Compare commits

...

29 Commits

Author SHA1 Message Date
cf2b8abc4b chore(deps): update dependency vite to v8
Some checks failed
continuous-integration/drone/pr Build is failing
2026-03-12 22:14:32 +00:00
92997cc7b4 Merge pull request 'chore(deps): update dependency globals to v17.4.0' (#25) from renovate/globals-17.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-11 15:26:17 +01:00
cad0842b41 chore(deps): update dependency globals to v17.4.0
All checks were successful
continuous-integration/drone/pr Build is passing
2026-03-11 14:10:51 +00:00
8f70ad1a20 Merge pull request 'chore(deps): update dependency storybook to v10.2.17' (#24) from renovate/storybook-10.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-11 12:28:29 +01:00
32d7e1645d Merge pull request 'chore(deps): update dependency postcss to v8.5.8' (#23) from renovate/postcss-8.x-lockfile into main
Some checks failed
continuous-integration/drone/push Build is failing
2026-03-11 12:27:01 +01:00
68f343d32a chore(deps): update dependency storybook to v10.2.17
All checks were successful
continuous-integration/drone/pr Build is passing
2026-03-11 06:09:38 +00:00
ec4f5b2d13 chore(deps): update dependency postcss to v8.5.8
All checks were successful
continuous-integration/drone/pr Build is passing
2026-03-11 06:09:22 +00:00
31a8304b73 chore(deps): update @storybook/react-vite to v10.2.17
All checks were successful
continuous-integration/drone/push Build is passing
Consolidates Renovate PR #22
2026-03-10 23:21:27 +01:00
4d799f8820 chore(deps): update lockfile — storybook 10.2.17, eslint 10.0.3, react-router-dom 7.13.1, @types/node 25.4.0, eslint-plugin-react-refresh 0.5.2
All checks were successful
continuous-integration/drone/push Build is passing
Consolidates Renovate PRs #3 #13 #16 #17 #18 #19 #20 #21
2026-03-10 23:17:55 +01:00
be9372c1ee Merge pull request 'Update dependency @storybook/react-vite to v10.2.16' (#10) from renovate/storybook-react-vite-10.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-09 19:05:24 +01:00
bea
377fb90536 Update dependency @storybook/react-vite to v10.2.16
All checks were successful
continuous-integration/drone/pr Build is passing
2026-03-09 18:55:21 +01:00
88ac53fa95 Merge pull request 'Update dependency @codemirror/language to v6.12.2' (#12) from renovate/codemirror-language-6.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-09 18:52:40 +01:00
2e775174a2 Merge pull request 'Update dependency @storybook/addon-a11y to v10.2.16' (#6) from renovate/storybook-addon-a11y-10.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-09 18:51:46 +01:00
f2fef1d3f1 Merge pull request 'Update dependency @storybook/addon-docs to v10.2.16' (#7) from renovate/storybook-addon-docs-10.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-09 18:51:44 +01:00
672661a5c8 Merge pull request 'Update dependency @storybook/react to v10.2.16' (#9) from renovate/storybook-react-10.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-09 18:48:58 +01:00
8323c8f301 Merge pull request 'Update dependency @storybook/addon-themes to v10.2.16' (#8) from renovate/storybook-addon-themes-10.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-09 18:47:35 +01:00
5c8ed35ec1 Merge pull request 'Update dependency storybook to v10.2.16' (#15) from renovate/storybook-10.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
2026-03-09 18:46:10 +01:00
a36586edd3 Update dependency storybook to v10.2.16
All checks were successful
continuous-integration/drone/pr Build is passing
2026-03-07 22:18:54 +00:00
efe4aaf0bd Update dependency @storybook/react to v10.2.16
All checks were successful
continuous-integration/drone/pr Build is passing
2026-03-07 22:18:05 +00:00
b1c77f60d2 Update dependency @storybook/addon-themes to v10.2.16
All checks were successful
continuous-integration/drone/pr Build is passing
2026-03-07 22:17:34 +00:00
e228c25e40 Update dependency @storybook/addon-docs to v10.2.16
Some checks failed
continuous-integration/drone/pr Build is failing
2026-03-07 22:17:19 +00:00
43c0eafa52 Update dependency @storybook/addon-a11y to v10.2.16
Some checks failed
continuous-integration/drone/pr Build is failing
2026-03-07 22:16:59 +00:00
e11eed83c5 Update dependency @codemirror/language to v6.12.2
Some checks failed
continuous-integration/drone/pr Build is failing
2026-03-02 22:16:53 +00:00
3e1857c49b Merge pull request 'Update dependency @types/node to v25.3.2' (#14) from renovate/node-25.x-lockfile into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #14
2026-03-01 22:57:17 +01:00
62310e80b0 Update dependency @types/node to v25.3.2
All checks were successful
continuous-integration/drone/pr Build is passing
2026-03-01 14:14:32 +00:00
dcda048b27 Merge pull request 'Update dependency eslint to v10.0.2' (#11) from renovate/eslint-10.x-lockfile into main
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #11
2026-03-01 03:02:18 +01:00
32f5e27a42 Update dependency eslint to v10.0.2
All checks were successful
continuous-integration/drone/pr Build is passing
2026-02-28 14:15:43 +00:00
1523f7be2c add unit tests
All checks were successful
continuous-integration/drone/push Build is passing
2026-02-24 17:55:26 +01:00
b664c99944 fix sonar issues
Some checks failed
continuous-integration/drone/push Build is failing
2026-02-24 16:27:53 +01:00
9 changed files with 1351 additions and 148 deletions

View File

@@ -87,7 +87,7 @@
"tailwindcss": "^3.4.16", "tailwindcss": "^3.4.16",
"typescript": "^5.6.2", "typescript": "^5.6.2",
"typescript-eslint": "^8.56.0", "typescript-eslint": "^8.56.0",
"vite": "^7.0.0", "vite": "^8.0.0",
"vitest": "^4.0.18", "vitest": "^4.0.18",
"yjs": "^13.6.24" "yjs": "^13.6.24"
}, },

View File

@@ -12,7 +12,6 @@ import {
type FocusEvent, type FocusEvent,
type FocusEventHandler, type FocusEventHandler,
type KeyboardEvent as ReactKeyboardEvent, type KeyboardEvent as ReactKeyboardEvent,
type MutableRefObject,
type ReactNode, type ReactNode,
type Ref, type Ref,
useCallback, useCallback,
@@ -143,7 +142,7 @@ function createDateTimeFromPickerValue(value: PickerValue): Date {
} }
function startOfDay(value: Date): Date { function startOfDay(value: Date): Date {
const candidate = new Date(value.getTime()); const candidate = new Date(value);
candidate.setHours(0, 0, 0, 0); candidate.setHours(0, 0, 0, 0);
return candidate; return candidate;
} }
@@ -256,7 +255,7 @@ function assignRef(ref: Ref<HTMLInputElement> | undefined, node: HTMLInputElemen
return; return;
} }
(ref as MutableRefObject<HTMLInputElement | null>).current = node; (ref as { current: HTMLInputElement | null }).current = node;
} }
function tokenizeFormat(format: string): RawFormatPart[] { function tokenizeFormat(format: string): RawFormatPart[] {
@@ -398,9 +397,11 @@ function buildFormatConfigOrNull(type: DatePickerKind, format: string): FormatCo
} }
const segments = parts.filter((part): part is FormatSegment => part.type === 'segment'); const segments = parts.filter((part): part is FormatSegment => part.type === 'segment');
/* c8 ignore start -- validated token counts always yield at least one segment. */
if (segments.length === 0) { if (segments.length === 0) {
return null; return null;
} }
/* c8 ignore stop */
return { return {
type, type,
@@ -421,9 +422,11 @@ function buildFormatConfig(type: DatePickerKind, requestedFormat?: string): Form
} }
const fallback = buildFormatConfigOrNull(type, DEFAULT_FORMAT[type]); const fallback = buildFormatConfigOrNull(type, DEFAULT_FORMAT[type]);
/* c8 ignore start -- static defaults are valid for all supported picker types. */
if (!fallback) { if (!fallback) {
throw new Error('Failed to initialize DatePicker format configuration.'); throw new Error('Failed to initialize DatePicker format configuration.');
} }
/* c8 ignore stop */
return fallback; return fallback;
} }
@@ -455,9 +458,11 @@ function parsePickerValueWithFormat(rawValue: string, config: FormatConfig): Pic
} }
const numeric = Number(chunk); const numeric = Number(chunk);
/* c8 ignore start -- numeric chunks are finite after /^\d+$/ validation. */
if (!Number.isFinite(numeric)) { if (!Number.isFinite(numeric)) {
return null; return null;
} }
/* c8 ignore stop */
if (part.kind === 'year') { if (part.kind === 'year') {
year = numeric; year = numeric;
@@ -473,12 +478,16 @@ function parsePickerValueWithFormat(rawValue: string, config: FormatConfig): Pic
} }
if (config.type !== 'time') { if (config.type !== 'time') {
/* c8 ignore start -- date/month/year segments are guaranteed for non-time validated formats. */
if (year == null || month == null || day == null) { if (year == null || month == null || day == null) {
return null; return null;
} }
/* c8 ignore stop */
/* c8 ignore start -- 'yyyy' token bounds parsed year to 0..9999. */
if (year < 0 || year > 9999) { if (year < 0 || year > 9999) {
return null; return null;
} }
/* c8 ignore stop */
const parsedDate = createValidatedDate(year, month, day); const parsedDate = createValidatedDate(year, month, day);
if (!parsedDate) { if (!parsedDate) {
@@ -493,9 +502,11 @@ function parsePickerValueWithFormat(rawValue: string, config: FormatConfig): Pic
}; };
} }
/* c8 ignore start -- date-time format validation guarantees hour/minute segments. */
if (hour == null || minute == null) { if (hour == null || minute == null) {
return null; return null;
} }
/* c8 ignore stop */
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
return null; return null;
@@ -508,9 +519,11 @@ function parsePickerValueWithFormat(rawValue: string, config: FormatConfig): Pic
}; };
} }
/* c8 ignore start -- time format validation guarantees hour/minute segments. */
if (hour == null || minute == null) { if (hour == null || minute == null) {
return null; return null;
} }
/* c8 ignore stop */
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
return null; return null;
@@ -616,7 +629,11 @@ function isWithinRange(
return true; return true;
} }
function applySegmentDigits(baseValue: PickerValue, kind: SegmentKind, digits: string): PickerValue { function applySegmentDigits(
baseValue: PickerValue,
kind: SegmentKind,
digits: string,
): PickerValue {
const parsedDigits = Number(digits); const parsedDigits = Number(digits);
if (!Number.isFinite(parsedDigits)) { if (!Number.isFinite(parsedDigits)) {
return clonePickerValue(baseValue); return clonePickerValue(baseValue);
@@ -644,7 +661,8 @@ function applySegmentDigits(baseValue: PickerValue, kind: SegmentKind, digits: s
const maxDayForCurrentMonth = daysInMonth(year, month); const maxDayForCurrentMonth = daysInMonth(year, month);
day = clampNumber(day, 1, maxDayForCurrentMonth); day = clampNumber(day, 1, maxDayForCurrentMonth);
const nextDate = createValidatedDate(year, month, day) ?? createDateAtLocalMidnight(year, month - 1, day); const nextDate =
createValidatedDate(year, month, day) ?? createDateAtLocalMidnight(year, month - 1, day);
return { return {
date: nextDate, date: nextDate,
hour, hour,
@@ -744,6 +762,39 @@ function isHourSelectableForRange(
return true; return true;
} }
// eslint-disable-next-line react-refresh/only-export-components -- test-only export of pure helpers.
export const __datePickerTestUtils = {
pad2,
pad4,
clampNumber,
createDateAtLocalMidnight,
createDateTimeFromPickerValue,
startOfDay,
startOfMonth,
isSameDay,
createValidatedDate,
daysInMonth,
clonePickerValue,
resolveLocale,
resolveWeekStart,
buildMonthGrid,
joinClassNames,
assignRef,
tokenizeFormat,
buildFormatConfigOrNull,
buildFormatConfig,
parsePickerValueWithFormat,
formatPickerValueWithFormat,
comparePickerValue,
normalizeRange,
clampPickerToRange,
isWithinRange,
applySegmentDigits,
findSegmentIndexByCaret,
isDateSelectableForRange,
isHourSelectableForRange,
} as const;
export function DatePicker({ export function DatePicker({
label, label,
placeholder = '', placeholder = '',
@@ -770,9 +821,11 @@ export function DatePicker({
const inputWrapperRef = useRef<HTMLDivElement | null>(null); const inputWrapperRef = useRef<HTMLDivElement | null>(null);
const popupRef = useRef<HTMLDivElement | null>(null); const popupRef = useRef<HTMLDivElement | null>(null);
const changeHandledRef = useRef(false); const changeHandledRef = useRef(false);
const bufferedDigitsRef = useRef<{ segmentIndex: number; digits: string; timestamp: number } | null>( const bufferedDigitsRef = useRef<{
null, segmentIndex: number;
); digits: string;
timestamp: number;
} | null>(null);
const activeSegmentIndexRef = useRef(0); const activeSegmentIndexRef = useRef(0);
const pendingSelectionTimerRef = useRef<number | null>(null); const pendingSelectionTimerRef = useRef<number | null>(null);
@@ -897,9 +950,11 @@ export function DatePicker({
const monthGrid = useMemo(() => buildMonthGrid(viewMonth, weekStart), [viewMonth, weekStart]); const monthGrid = useMemo(() => buildMonthGrid(viewMonth, weekStart), [viewMonth, weekStart]);
const recalculatePopupPosition = useCallback(() => { const recalculatePopupPosition = useCallback(() => {
if (!isOpen || !inputWrapperRef.current || !popupRef.current || typeof window === 'undefined') { /* c8 ignore start -- guard protects partial mount/layout states that are not deterministic to unit test. */
if (!isOpen || !inputWrapperRef.current || !popupRef.current || !globalThis.window) {
return; return;
} }
/* c8 ignore stop */
const anchorRect = inputWrapperRef.current.getBoundingClientRect(); const anchorRect = inputWrapperRef.current.getBoundingClientRect();
const popupRect = popupRef.current.getBoundingClientRect(); const popupRect = popupRef.current.getBoundingClientRect();
@@ -920,7 +975,10 @@ export function DatePicker({
? anchorRect.top - popupRect.height - POPUP_GAP ? anchorRect.top - popupRect.height - POPUP_GAP
: anchorRect.bottom + POPUP_GAP; : anchorRect.bottom + POPUP_GAP;
top = Math.max(POPUP_MARGIN, Math.min(top, viewportHeight - POPUP_MARGIN - popupRect.height)); top = Math.max(
POPUP_MARGIN,
Math.min(top, viewportHeight - POPUP_MARGIN - popupRect.height),
);
setPopupPosition({ setPopupPosition({
top, top,
@@ -937,9 +995,11 @@ export function DatePicker({
recalculatePopupPosition(); recalculatePopupPosition();
if (typeof window === 'undefined') { /* c8 ignore start -- browser/window is always present in jsdom runtime. */
if (!globalThis.window) {
return; return;
} }
/* c8 ignore stop */
const handleWindowChange = () => { const handleWindowChange = () => {
recalculatePopupPosition(); recalculatePopupPosition();
@@ -961,11 +1021,16 @@ export function DatePicker({
const handlePointerDown = (event: MouseEvent | TouchEvent) => { const handlePointerDown = (event: MouseEvent | TouchEvent) => {
const eventTarget = event.target as Node | null; const eventTarget = event.target as Node | null;
/* c8 ignore start -- pointer events always provide a target in browser runtimes. */
if (!eventTarget) { if (!eventTarget) {
return; return;
} }
/* c8 ignore stop */
if (popupRef.current?.contains(eventTarget) || inputWrapperRef.current?.contains(eventTarget)) { if (
popupRef.current?.contains(eventTarget) ||
inputWrapperRef.current?.contains(eventTarget)
) {
return; return;
} }
@@ -992,7 +1057,7 @@ export function DatePicker({
useEffect(() => { useEffect(() => {
return () => { return () => {
if (pendingSelectionTimerRef.current != null) { if (pendingSelectionTimerRef.current != null) {
window.clearTimeout(pendingSelectionTimerRef.current); globalThis.window.clearTimeout(pendingSelectionTimerRef.current);
} }
}; };
}, []); }, []);
@@ -1000,27 +1065,33 @@ export function DatePicker({
const selectSegment = useCallback( const selectSegment = useCallback(
(segmentIndex: number) => { (segmentIndex: number) => {
const segments = formatConfig.segments; const segments = formatConfig.segments;
/* c8 ignore start -- format configuration always includes at least one segment. */
if (segments.length === 0) { if (segments.length === 0) {
return; return;
} }
/* c8 ignore stop */
const clampedIndex = clampNumber(segmentIndex, 0, segments.length - 1); const clampedIndex = clampNumber(segmentIndex, 0, segments.length - 1);
activeSegmentIndexRef.current = clampedIndex; activeSegmentIndexRef.current = clampedIndex;
if (typeof window === 'undefined') { /* c8 ignore start -- browser/window is always present in jsdom runtime. */
if (!globalThis.window) {
return; return;
} }
/* c8 ignore stop */
if (pendingSelectionTimerRef.current != null) { if (pendingSelectionTimerRef.current != null) {
window.clearTimeout(pendingSelectionTimerRef.current); globalThis.window.clearTimeout(pendingSelectionTimerRef.current);
} }
pendingSelectionTimerRef.current = window.setTimeout(() => { pendingSelectionTimerRef.current = globalThis.window.setTimeout(() => {
const inputNode = internalInputRef.current; const inputNode = internalInputRef.current;
const targetSegment = segments[clampedIndex]; const targetSegment = segments[clampedIndex];
/* c8 ignore start -- input node and target segment are available while mounted. */
if (!inputNode || !targetSegment) { if (!inputNode || !targetSegment) {
return; return;
} }
/* c8 ignore stop */
inputNode.setSelectionRange(targetSegment.start, targetSegment.end); inputNode.setSelectionRange(targetSegment.start, targetSegment.end);
}, 0); }, 0);
@@ -1030,14 +1101,18 @@ export function DatePicker({
const resolveCurrentSegmentIndex = useCallback(() => { const resolveCurrentSegmentIndex = useCallback(() => {
const segments = formatConfig.segments; const segments = formatConfig.segments;
/* c8 ignore start -- format configuration always includes at least one segment. */
if (segments.length === 0) { if (segments.length === 0) {
return 0; return 0;
} }
/* c8 ignore stop */
const inputNode = internalInputRef.current; const inputNode = internalInputRef.current;
/* c8 ignore start -- interactions only run when input node is mounted. */
if (!inputNode) { if (!inputNode) {
return activeSegmentIndexRef.current; return activeSegmentIndexRef.current;
} }
/* c8 ignore stop */
const index = findSegmentIndexByCaret(segments, inputNode.selectionStart); const index = findSegmentIndexByCaret(segments, inputNode.selectionStart);
activeSegmentIndexRef.current = index; activeSegmentIndexRef.current = index;
@@ -1067,9 +1142,11 @@ export function DatePicker({
} }
const inputNode = internalInputRef.current; const inputNode = internalInputRef.current;
/* c8 ignore start -- commits run only from active mounted input interactions. */
if (!inputNode) { if (!inputNode) {
return; return;
} }
/* c8 ignore stop */
changeHandledRef.current = false; changeHandledRef.current = false;
@@ -1105,11 +1182,14 @@ export function DatePicker({
}, },
) => { ) => {
const segment = formatConfig.segments[segmentIndex]; const segment = formatConfig.segments[segmentIndex];
/* c8 ignore start -- segmentIndex is always resolved from known format segments. */
if (!segment) { if (!segment) {
return; return;
} }
/* c8 ignore stop */
const baseValue = parsePickerValueWithFormat(displayValue, formatConfig) ?? clampedSelectedValue; const baseValue =
parsePickerValueWithFormat(displayValue, formatConfig) ?? clampedSelectedValue;
const nextUnclamped = applySegmentDigits(baseValue, segment.kind, digits); const nextUnclamped = applySegmentDigits(baseValue, segment.kind, digits);
const nextClamped = clampPickerToRange( const nextClamped = clampPickerToRange(
nextUnclamped, nextUnclamped,
@@ -1145,7 +1225,7 @@ export function DatePicker({
(segmentIndex: number, moveToNext: boolean) => { (segmentIndex: number, moveToNext: boolean) => {
const buffered = bufferedDigitsRef.current; const buffered = bufferedDigitsRef.current;
const segment = formatConfig.segments[segmentIndex]; const segment = formatConfig.segments[segmentIndex];
if (!buffered || buffered.segmentIndex !== segmentIndex || !segment) { if (buffered?.segmentIndex !== segmentIndex || !segment) {
if (moveToNext) { if (moveToNext) {
selectSegment(segmentIndex + 1); selectSegment(segmentIndex + 1);
} }
@@ -1159,9 +1239,11 @@ export function DatePicker({
); );
const openPicker = useCallback(() => { const openPicker = useCallback(() => {
/* c8 ignore start -- disabled inputs cannot trigger picker open interactions. */
if (disabled) { if (disabled) {
return; return;
} }
/* c8 ignore stop */
if (type !== 'time') { if (type !== 'time') {
setViewMonth(startOfMonth(selectedDate)); setViewMonth(startOfMonth(selectedDate));
} }
@@ -1170,9 +1252,11 @@ export function DatePicker({
}, [disabled, selectedDate, type]); }, [disabled, selectedDate, type]);
const togglePicker = useCallback(() => { const togglePicker = useCallback(() => {
/* c8 ignore start -- disabled icon button cannot trigger click events. */
if (disabled) { if (disabled) {
return; return;
} }
/* c8 ignore stop */
if (isOpen) { if (isOpen) {
closePicker(); closePicker();
return; return;
@@ -1220,9 +1304,11 @@ export function DatePicker({
hour: 0, hour: 0,
minute: 0, minute: 0,
}; };
/* c8 ignore start -- out-of-range date cells are disabled in the calendar UI. */
if (!isWithinRange(candidate, normalizedMinValue, normalizedMaxValue, type)) { if (!isWithinRange(candidate, normalizedMinValue, normalizedMaxValue, type)) {
return; return;
} }
/* c8 ignore stop */
commitValue(formatPickerValueWithFormat(candidate, formatConfig)); commitValue(formatPickerValueWithFormat(candidate, formatConfig));
closePicker(); closePicker();
@@ -1234,7 +1320,12 @@ export function DatePicker({
hour: selectedHour, hour: selectedHour,
minute: selectedMinute, minute: selectedMinute,
}; };
const nextValue = clampPickerToRange(candidate, normalizedMinValue, normalizedMaxValue, type); const nextValue = clampPickerToRange(
candidate,
normalizedMinValue,
normalizedMaxValue,
type,
);
commitValue(formatPickerValueWithFormat(nextValue, formatConfig)); commitValue(formatPickerValueWithFormat(nextValue, formatConfig));
setViewMonth(startOfMonth(normalizedDate)); setViewMonth(startOfMonth(normalizedDate));
}, },
@@ -1313,17 +1404,21 @@ export function DatePicker({
}, [disabled, selectSegment]); }, [disabled, selectSegment]);
const handleInputMouseUp = useCallback(() => { const handleInputMouseUp = useCallback(() => {
/* c8 ignore start -- disabled inputs do not emit mouse interaction events. */
if (disabled) { if (disabled) {
return; return;
} }
/* c8 ignore stop */
selectSegment(resolveCurrentSegmentIndex()); selectSegment(resolveCurrentSegmentIndex());
}, [disabled, resolveCurrentSegmentIndex, selectSegment]); }, [disabled, resolveCurrentSegmentIndex, selectSegment]);
const handleInputClick = useCallback(() => { const handleInputClick = useCallback(() => {
/* c8 ignore start -- disabled inputs do not emit click interaction events. */
if (disabled) { if (disabled) {
return; return;
} }
/* c8 ignore stop */
selectSegment(resolveCurrentSegmentIndex()); selectSegment(resolveCurrentSegmentIndex());
}, [disabled, resolveCurrentSegmentIndex, selectSegment]); }, [disabled, resolveCurrentSegmentIndex, selectSegment]);
@@ -1341,7 +1436,12 @@ export function DatePicker({
return; return;
} }
const clamped = clampPickerToRange(parsed, normalizedMinValue, normalizedMaxValue, type); const clamped = clampPickerToRange(
parsed,
normalizedMinValue,
normalizedMaxValue,
type,
);
event.preventDefault(); event.preventDefault();
commitValue(formatPickerValueWithFormat(clamped, formatConfig)); commitValue(formatPickerValueWithFormat(clamped, formatConfig));
}, },
@@ -1368,9 +1468,11 @@ export function DatePicker({
} }
const segment = formatConfig.segments[segmentIndex]; const segment = formatConfig.segments[segmentIndex];
/* c8 ignore start -- segment index resolution always maps to a valid segment. */
if (!segment) { if (!segment) {
return; return;
} }
/* c8 ignore stop */
if (key === 'ArrowDown' && !isOpen) { if (key === 'ArrowDown' && !isOpen) {
event.preventDefault(); event.preventDefault();
@@ -1437,11 +1539,13 @@ export function DatePicker({
digits = buffered.digits; digits = buffered.digits;
} }
/* c8 ignore start -- buffered digits are reset on segment completion. */
if (digits.length >= segment.length) { if (digits.length >= segment.length) {
digits = key; digits = key;
} else { } else {
digits += key; digits += key;
} }
/* c8 ignore stop */
bufferedDigitsRef.current = { bufferedDigitsRef.current = {
segmentIndex, segmentIndex,
@@ -1663,7 +1767,11 @@ export function DatePicker({
<div className="datepicker-time-root"> <div className="datepicker-time-root">
<div className="datepicker-time-column"> <div className="datepicker-time-column">
<span className="datepicker-time-title">Hours</span> <span className="datepicker-time-title">Hours</span>
<div className="datepicker-time-list" role="listbox" aria-label="Hours"> <div
className="datepicker-time-list"
role="listbox"
aria-label="Hours"
>
{HOURS.map((hour) => { {HOURS.map((hour) => {
const hourDisabled = !isHourSelectableForRange( const hourDisabled = !isHourSelectableForRange(
selectedDate, selectedDate,
@@ -1717,7 +1825,8 @@ export function DatePicker({
type="button" type="button"
className={joinClassNames( className={joinClassNames(
'datepicker-time-option', 'datepicker-time-option',
minute === selectedMinute && 'is-selected', minute === selectedMinute &&
'is-selected',
)} )}
onClick={() => handleMinuteCommit(minute)} onClick={() => handleMinuteCommit(minute)}
disabled={minuteDisabled} disabled={minuteDisabled}

View File

@@ -21,6 +21,12 @@ describe('Button', () => {
expect(screen.getByRole('button', { name: 'Details' })).toHaveClass('btn-secondary'); expect(screen.getByRole('button', { name: 'Details' })).toHaveClass('btn-secondary');
}); });
it('uses explicit variant when provided', () => {
render(<Button label="Danger" type="outlined" variant="important" />);
expect(screen.getByRole('button', { name: 'Danger' })).toHaveClass('btn-important');
});
it('renders icon-only button and custom aria label', () => { it('renders icon-only button and custom aria label', () => {
render(<Button type="solid" icon={HomeIcon} ariaLabel="Open home" />); render(<Button type="solid" icon={HomeIcon} ariaLabel="Open home" />);

View File

@@ -51,4 +51,12 @@ describe('Chip', () => {
rerender(<Chip tone=" ">Blank</Chip>); rerender(<Chip tone=" ">Blank</Chip>);
expect(screen.getByText('Blank').getAttribute('style')).toBeNull(); expect(screen.getByText('Blank').getAttribute('style')).toBeNull();
}); });
it('ignores unresolved direct palettes and unknown shades', () => {
const { rerender } = render(<Chip tone="indigo">Palette token</Chip>);
expect(screen.getByText('Palette token').getAttribute('style')).toBeNull();
rerender(<Chip tone="indigo-999">Unknown shade</Chip>);
expect(screen.getByText('Unknown shade').getAttribute('style')).toBeNull();
});
}); });

View File

@@ -0,0 +1,428 @@
import { afterEach, describe, expect, it, vi } from 'vitest';
import { __datePickerTestUtils as utils } from '../../src/components/DatePicker';
type GlobalDescriptor = PropertyDescriptor | undefined;
function setGlobalProperty(name: string, descriptor: PropertyDescriptor): GlobalDescriptor {
const key = name as keyof typeof globalThis;
const original = Object.getOwnPropertyDescriptor(globalThis, key);
Object.defineProperty(globalThis, key, descriptor);
return original;
}
function restoreGlobalProperty(name: string, original: GlobalDescriptor): void {
const key = name as keyof typeof globalThis;
if (original) {
Object.defineProperty(globalThis, key, original);
return;
}
Reflect.deleteProperty(globalThis, key);
}
describe('DatePicker logic helpers', () => {
afterEach(() => {
vi.restoreAllMocks();
});
it('formats and clamps numeric values', () => {
expect(utils.pad2(3)).toBe('03');
expect(utils.pad4(12)).toBe('0012');
expect(utils.clampNumber(99, 0, 50)).toBe(50);
expect(utils.clampNumber(-1, 0, 50)).toBe(0);
});
it('validates calendar dates strictly', () => {
expect(utils.createValidatedDate(2026, 2, 29)).toBeNull();
expect(utils.createValidatedDate(2028, 2, 29)).toBeInstanceOf(Date);
});
it('resolves locale with and without navigator', () => {
const originalNavigator = setGlobalProperty('navigator', {
configurable: true,
value: undefined,
});
expect(utils.resolveLocale()).toBe('en-US');
restoreGlobalProperty('navigator', originalNavigator);
const locale = utils.resolveLocale();
expect(typeof locale).toBe('string');
expect(locale.length).toBeGreaterThan(0);
});
it('resolves week start across locale and fallback branches', () => {
const originalIntl = setGlobalProperty('Intl', {
configurable: true,
value: undefined,
});
expect(utils.resolveWeekStart('en-US')).toBe(0);
setGlobalProperty('Intl', {
configurable: true,
value: {
Locale: class MockLocale {
weekInfo = { firstDay: 2 };
},
},
});
expect(utils.resolveWeekStart('de-DE')).toBe(2);
setGlobalProperty('Intl', {
configurable: true,
value: {
Locale: class MockLocale {
weekInfo = { firstDay: 7 };
},
},
});
expect(utils.resolveWeekStart('en-US')).toBe(0);
setGlobalProperty('Intl', {
configurable: true,
value: {
Locale: class MockLocale {
weekInfo = { firstDay: 0 };
},
},
});
expect(utils.resolveWeekStart('en-US')).toBe(0);
setGlobalProperty('Intl', {
configurable: true,
value: {
Locale: class MockLocale {
weekInfo = { firstDay: 'x' as unknown as number };
},
},
});
expect(utils.resolveWeekStart('en-US')).toBe(0);
setGlobalProperty('Intl', {
configurable: true,
value: {
Locale: class MockLocale {
constructor() {
throw new Error('boom');
}
},
},
});
expect(utils.resolveWeekStart('en-US')).toBe(0);
restoreGlobalProperty('Intl', originalIntl);
});
it('builds and validates format configuration', () => {
expect(utils.buildFormatConfigOrNull('date-time', '')).toBeNull();
expect(utils.buildFormatConfigOrNull('date-time', 'yyyy/mm/dd HH')).toBeNull();
const config = utils.buildFormatConfigOrNull('date-time', 'dd/mm/yyyy HH:mm');
expect(config).not.toBeNull();
expect(config?.segments).toHaveLength(5);
expect(config?.totalLength).toBe(16);
});
it('falls back to default format when requested format is invalid', () => {
const config = utils.buildFormatConfig('date-time', 'yyyy/mm/dd');
expect(config.format).toBe('yyyy/mm/dd HH:mm');
});
it('parses valid values and rejects invalid input', () => {
const dateTimeConfig = utils.buildFormatConfig('date-time', 'dd/mm/yyyy HH:mm');
expect(utils.parsePickerValueWithFormat('22/02/2026 14:30', dateTimeConfig)).toEqual({
date: utils.createDateAtLocalMidnight(2026, 1, 22),
hour: 14,
minute: 30,
});
expect(utils.parsePickerValueWithFormat('2/2/2026 14:30', dateTimeConfig)).toBeNull();
expect(utils.parsePickerValueWithFormat('22-02-2026 14:30', dateTimeConfig)).toBeNull();
expect(utils.parsePickerValueWithFormat('aa/02/2026 14:30', dateTimeConfig)).toBeNull();
expect(utils.parsePickerValueWithFormat('31/02/2026 14:30', dateTimeConfig)).toBeNull();
expect(utils.parsePickerValueWithFormat('22/02/2026 24:30', dateTimeConfig)).toBeNull();
const timeConfig = utils.buildFormatConfig('time', 'HH:mm');
expect(utils.parsePickerValueWithFormat('09:00', timeConfig)).toEqual({
date: utils.startOfDay(new Date()),
hour: 9,
minute: 0,
});
expect(utils.parsePickerValueWithFormat('09:77', timeConfig)).toBeNull();
});
it('formats picker values with the chosen configuration', () => {
const config = utils.buildFormatConfig('date-time', 'dd/mm/yyyy HH:mm');
const text = utils.formatPickerValueWithFormat(
{
date: utils.createDateAtLocalMidnight(2027, 2, 11),
hour: 6,
minute: 5,
},
config,
);
expect(text).toBe('11/03/2027 06:05');
});
it('compares values by picker type', () => {
const date = utils.comparePickerValue(
{
date: utils.createDateAtLocalMidnight(2026, 1, 1),
hour: 23,
minute: 30,
},
{
date: utils.createDateAtLocalMidnight(2026, 1, 2),
hour: 1,
minute: 0,
},
'date',
);
expect(date).toBeLessThan(0);
const time = utils.comparePickerValue(
{
date: utils.createDateAtLocalMidnight(2026, 1, 1),
hour: 9,
minute: 0,
},
{
date: utils.createDateAtLocalMidnight(2026, 1, 1),
hour: 8,
minute: 59,
},
'time',
);
expect(time).toBeGreaterThan(0);
const dateTime = utils.comparePickerValue(
{
date: utils.createDateAtLocalMidnight(2026, 1, 1),
hour: 1,
minute: 0,
},
{
date: utils.createDateAtLocalMidnight(2026, 1, 1),
hour: 1,
minute: 1,
},
'date-time',
);
expect(dateTime).toBeLessThan(0);
});
it('normalizes and enforces picker ranges', () => {
const min = {
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 9,
minute: 0,
};
const max = {
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 10,
minute: 0,
};
const normalized = utils.normalizeRange(max, min, 'date-time');
expect(normalized.minValue).toEqual(min);
expect(normalized.maxValue).toEqual(max);
const below = utils.clampPickerToRange(
{
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 8,
minute: 0,
},
min,
max,
'date-time',
);
expect(below).toEqual(min);
const above = utils.clampPickerToRange(
{
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 10,
minute: 30,
},
min,
max,
'date-time',
);
expect(above).toEqual(max);
expect(utils.isWithinRange(min, min, max, 'date-time')).toBe(true);
expect(
utils.isWithinRange(
{
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 7,
minute: 59,
},
min,
max,
'date-time',
),
).toBe(false);
expect(
utils.isWithinRange(
{
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 10,
minute: 1,
},
min,
max,
'date-time',
),
).toBe(false);
});
it('applies segment edits across year, month, day, hour and minute', () => {
const base = {
date: utils.createDateAtLocalMidnight(2026, 1, 28),
hour: 14,
minute: 30,
};
expect(utils.applySegmentDigits(base, 'year', '0001').date.getFullYear()).toBe(1);
expect(utils.applySegmentDigits(base, 'month', '13').date.getMonth()).toBe(11);
expect(utils.applySegmentDigits(base, 'day', '99').date.getDate()).toBe(28);
expect(utils.applySegmentDigits(base, 'hour', '88').hour).toBe(23);
expect(utils.applySegmentDigits(base, 'minute', '99').minute).toBe(59);
const unchanged = utils.applySegmentDigits(base, 'day', 'not-a-number');
expect(unchanged).toEqual(base);
});
it('resolves segment index from caret position', () => {
const config = utils.buildFormatConfig('date-time', 'dd/mm/yyyy HH:mm');
expect(utils.findSegmentIndexByCaret([], 3)).toBe(0);
expect(utils.findSegmentIndexByCaret(config.segments, null)).toBe(0);
expect(utils.findSegmentIndexByCaret(config.segments, 0)).toBe(0);
expect(utils.findSegmentIndexByCaret(config.segments, 6)).toBe(2);
expect(utils.findSegmentIndexByCaret(config.segments, 99)).toBe(
config.segments[config.segments.length - 1].segmentIndex,
);
expect(utils.findSegmentIndexByCaret(config.segments, 2)).toBe(0);
const nonStandardSegments = [
{
type: 'segment',
kind: 'day',
token: 'dd',
length: 2,
start: 5,
end: 7,
segmentIndex: 0,
},
] as unknown as Parameters<typeof utils.findSegmentIndexByCaret>[0];
expect(utils.findSegmentIndexByCaret(nonStandardSegments, 1)).toBe(0);
});
it('checks date and hour selectability inside constrained ranges', () => {
const min = {
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 9,
minute: 30,
};
const max = {
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 10,
minute: 15,
};
expect(
utils.isDateSelectableForRange(
utils.createDateAtLocalMidnight(2026, 2, 9),
'date-time',
min,
max,
),
).toBe(false);
expect(
utils.isDateSelectableForRange(
utils.createDateAtLocalMidnight(2026, 2, 10),
'date-time',
min,
max,
),
).toBe(true);
expect(
utils.isDateSelectableForRange(
utils.createDateAtLocalMidnight(2026, 2, 11),
'date-time',
min,
max,
),
).toBe(false);
expect(
utils.isDateSelectableForRange(
utils.createDateAtLocalMidnight(2026, 2, 9),
'date',
{
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 0,
minute: 0,
},
{
date: utils.createDateAtLocalMidnight(2026, 2, 10),
hour: 0,
minute: 0,
},
),
).toBe(false);
expect(
utils.isHourSelectableForRange(
utils.createDateAtLocalMidnight(2026, 2, 10),
8,
'date-time',
min,
max,
),
).toBe(false);
expect(
utils.isHourSelectableForRange(
utils.createDateAtLocalMidnight(2026, 2, 10),
9,
'date-time',
min,
max,
),
).toBe(true);
expect(
utils.isHourSelectableForRange(
utils.createDateAtLocalMidnight(2026, 2, 10),
11,
'date-time',
min,
max,
),
).toBe(false);
});
it('builds month grids and joins class names', () => {
const month = utils.createDateAtLocalMidnight(2026, 2, 10);
const grid = utils.buildMonthGrid(month, 1);
expect(grid).toHaveLength(42);
expect(grid[0]).toBeInstanceOf(Date);
expect(grid[41]).toBeInstanceOf(Date);
expect(utils.joinClassNames('a', false, 'b', undefined, '', null, 'c')).toBe('a b c');
});
it('assigns refs for callback and object refs', () => {
const callback = vi.fn();
const objectRef = { current: null as HTMLInputElement | null };
const node = document.createElement('input');
utils.assignRef(callback, node);
utils.assignRef(objectRef, node);
utils.assignRef(undefined, node);
expect(callback).toHaveBeenCalledWith(node);
expect(objectRef.current).toBe(node);
});
});

View File

@@ -1,5 +1,5 @@
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react'; import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react';
import { useState } from 'react'; import { createRef, type FocusEvent as ReactFocusEvent, useState } from 'react';
import { describe, expect, it, vi } from 'vitest'; import { describe, expect, it, vi } from 'vitest';
import { DatePicker } from '../../src/components/DatePicker'; import { DatePicker } from '../../src/components/DatePicker';
@@ -10,6 +10,7 @@ type ControlledProps = {
min?: string; min?: string;
max?: string; max?: string;
onValueChange?: (value: string) => void; onValueChange?: (value: string) => void;
onBlur?: (event: ReactFocusEvent<HTMLInputElement>) => void;
disabled?: boolean; disabled?: boolean;
}; };
@@ -20,6 +21,7 @@ function ControlledDatePicker({
min, min,
max, max,
onValueChange, onValueChange,
onBlur,
disabled = false, disabled = false,
}: Readonly<ControlledProps>) { }: Readonly<ControlledProps>) {
const [value, setValue] = useState(initialValue); const [value, setValue] = useState(initialValue);
@@ -33,6 +35,7 @@ function ControlledDatePicker({
min={min} min={min}
max={max} max={max}
disabled={disabled} disabled={disabled}
onBlur={onBlur}
onChange={(event) => { onChange={(event) => {
setValue(event.target.value); setValue(event.target.value);
onValueChange?.(event.target.value); onValueChange?.(event.target.value);
@@ -64,6 +67,30 @@ function getCurrentMonthDayButton(label: string): HTMLButtonElement {
return targetButton; return targetButton;
} }
function createPasteEvent(text: string): Event {
const event = new Event('paste', { bubbles: true, cancelable: true });
Object.defineProperty(event, 'clipboardData', {
value: {
getData: () => text,
},
});
return event;
}
function createRect(left: number, top: number, width: number, height: number): DOMRect {
return {
x: left,
y: top,
left,
top,
width,
height,
right: left + width,
bottom: top + height,
toJSON: () => ({}),
} as DOMRect;
}
describe('DatePicker', () => { describe('DatePicker', () => {
it('opens popup from icon button and closes with Escape', () => { it('opens popup from icon button and closes with Escape', () => {
render(<DatePicker label="Schedule" type="date-time" value="2031/05/20 14:30" onChange={() => {}} />); render(<DatePicker label="Schedule" type="date-time" value="2031/05/20 14:30" onChange={() => {}} />);
@@ -80,6 +107,12 @@ describe('DatePicker', () => {
expect( expect(
screen.queryByRole('dialog', { name: 'Date and time picker popup' }), screen.queryByRole('dialog', { name: 'Date and time picker popup' }),
).not.toBeInTheDocument(); ).not.toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
fireEvent.click(screen.getByRole('button', { name: 'Close date picker' }));
expect(
screen.queryByRole('dialog', { name: 'Date and time picker popup' }),
).not.toBeInTheDocument();
}); });
it('supports segment-by-segment editing with custom format and auto-advance', async () => { it('supports segment-by-segment editing with custom format and auto-advance', async () => {
@@ -288,6 +321,25 @@ describe('DatePicker', () => {
expect(screen.queryByRole('dialog', { name: 'Date picker popup' })).not.toBeInTheDocument(); expect(screen.queryByRole('dialog', { name: 'Date picker popup' })).not.toBeInTheDocument();
}); });
it('commits calendar date changes in date-time mode without closing the popup', () => {
const onValueChange = vi.fn();
render(
<ControlledDatePicker
type="date-time"
initialValue="2031/05/20 14:30"
onValueChange={onValueChange}
/>,
);
fireEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
pickCurrentMonthDay('15');
const input = screen.getByLabelText('Schedule') as HTMLInputElement;
expect(input.value).toMatch(/^\d{4}\/\d{2}\/15 14:30$/);
expect(onValueChange).toHaveBeenCalled();
expect(screen.getByRole('dialog', { name: 'Date and time picker popup' })).toBeInTheDocument();
});
it('renders time mode selectors only and keeps popup open after selection', () => { it('renders time mode selectors only and keeps popup open after selection', () => {
const onValueChange = vi.fn(); const onValueChange = vi.fn();
render(<ControlledDatePicker type="time" initialValue="09:00" onValueChange={onValueChange} />); render(<ControlledDatePicker type="time" initialValue="09:00" onValueChange={onValueChange} />);
@@ -344,6 +396,37 @@ describe('DatePicker', () => {
expect(screen.getByText('Invalid date')).toBeInTheDocument(); expect(screen.getByText('Invalid date')).toBeInTheDocument();
}); });
it('forwards inputRef for callback and object refs', () => {
const callbackRef = vi.fn();
const objectRef = createRef<HTMLInputElement>();
const { rerender } = render(
<DatePicker
label="Schedule"
type="date-time"
value="2031/05/20 14:30"
onChange={() => {}}
inputRef={callbackRef}
/>,
);
expect(callbackRef).toHaveBeenCalled();
const callbackNode = callbackRef.mock.calls.find(([node]) => node instanceof HTMLInputElement)?.[0];
expect(callbackNode).toBeInstanceOf(HTMLInputElement);
rerender(
<DatePicker
label="Schedule"
type="date-time"
value="2031/05/20 14:30"
onChange={() => {}}
inputRef={objectRef}
/>,
);
expect(objectRef.current).toBeInstanceOf(HTMLInputElement);
});
it('supports inline layout', () => { it('supports inline layout', () => {
const { container } = render( const { container } = render(
<DatePicker label="Start time" type="time" value="09:00" onChange={() => {}} layout="inline" />, <DatePicker label="Start time" type="time" value="09:00" onChange={() => {}} layout="inline" />,
@@ -352,4 +435,306 @@ describe('DatePicker', () => {
expect(container.querySelector('label')).toHaveClass('inline-flex'); expect(container.querySelector('label')).toHaveClass('inline-flex');
expect(container.querySelector('label > div')).not.toHaveClass('mt-1'); expect(container.querySelector('label > div')).not.toHaveClass('mt-1');
}); });
it('handles outside vs inside pointer interactions for popup close behavior', () => {
render(<DatePicker label="Schedule" type="date-time" value="2031/05/20 14:30" onChange={() => {}} />);
fireEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
const dialog = screen.getByRole('dialog', { name: 'Date and time picker popup' });
fireEvent.mouseDown(dialog);
expect(screen.getByRole('dialog', { name: 'Date and time picker popup' })).toBeInTheDocument();
fireEvent.mouseDown(document.body);
expect(
screen.queryByRole('dialog', { name: 'Date and time picker popup' }),
).not.toBeInTheDocument();
});
it('supports month/year chooser interactions and month navigation buttons', async () => {
render(<DatePicker label="Schedule" type="date" value="2031/05/20" onChange={() => {}} />);
fireEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
fireEvent.click(screen.getByRole('button', { name: 'Previous month' }));
fireEvent.click(screen.getByRole('button', { name: 'Next month' }));
const chooserButtons = document.querySelectorAll('.datepicker-chooser-btn');
const monthChooserButton = chooserButtons[0] as HTMLButtonElement;
const yearChooserButton = chooserButtons[1] as HTMLButtonElement;
const initialMonthText = monthChooserButton.textContent;
fireEvent.click(monthChooserButton);
const monthList = screen.getByRole('listbox', { name: 'Choose month' });
const monthOptions = within(monthList).getAllByRole('button');
const nextMonth = monthOptions.find((option) => option.textContent !== initialMonthText) ?? monthOptions[0];
fireEvent.click(nextMonth);
await waitFor(() => {
expect(screen.queryByRole('listbox', { name: 'Choose month' })).not.toBeInTheDocument();
});
expect((document.querySelectorAll('.datepicker-chooser-btn')[0] as HTMLButtonElement).textContent).toBe(
nextMonth.textContent,
);
const initialYearText = yearChooserButton.textContent;
fireEvent.click(yearChooserButton);
const yearList = screen.getByRole('listbox', { name: 'Choose year' });
const yearOptions = within(yearList).getAllByRole('button');
const nextYear = yearOptions.find((option) => option.textContent !== initialYearText) ?? yearOptions[0];
fireEvent.click(nextYear);
await waitFor(() => {
expect(screen.queryByRole('listbox', { name: 'Choose year' })).not.toBeInTheDocument();
});
expect((document.querySelectorAll('.datepicker-chooser-btn')[1] as HTMLButtonElement).textContent).toBe(
nextYear.textContent,
);
});
it('guards month navigation at absolute calendar boundaries', () => {
const first = render(
<DatePicker label="Schedule" type="date" value="0000/01/15" onChange={() => {}} />,
);
fireEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
fireEvent.click(screen.getByRole('button', { name: 'Previous month' }));
const lowerYearButton = document.querySelectorAll('.datepicker-chooser-btn')[1] as HTMLButtonElement;
expect(lowerYearButton.textContent).toBe('0');
first.unmount();
render(<DatePicker label="Schedule" type="date" value="9999/12/15" onChange={() => {}} />);
fireEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
fireEvent.click(screen.getByRole('button', { name: 'Next month' }));
const upperYearButton = document.querySelectorAll('.datepicker-chooser-btn')[1] as HTMLButtonElement;
expect(upperYearButton.textContent).toBe('9999');
});
it('supports keyboard navigation commands and segment reset shortcuts', async () => {
const onBlur = vi.fn();
render(
<ControlledDatePicker
type="date-time"
format="dd/mm/yyyy HH:mm"
initialValue="22/02/2026 14:30"
onBlur={onBlur}
/>,
);
const input = screen.getByLabelText('Schedule') as HTMLInputElement;
fireEvent.focus(input);
await waitFor(() => {
expect(input.selectionStart).toBe(0);
expect(input.selectionEnd).toBe(2);
});
fireEvent.keyDown(input, { key: '1' });
fireEvent.keyDown(input, { key: 'ArrowRight' });
await waitFor(() => {
expect(input.value.startsWith('01/')).toBe(true);
expect(input.selectionStart).toBe(3);
});
fireEvent.mouseUp(input);
fireEvent.click(input);
fireEvent.keyDown(input, { key: 'ArrowDown' });
expect(screen.getByRole('dialog', { name: 'Date and time picker popup' })).toBeInTheDocument();
fireEvent.keyDown(input, { key: 'ArrowRight' });
await waitFor(() => expect(input.selectionStart).toBe(3));
fireEvent.keyDown(input, { key: 'ArrowLeft' });
await waitFor(() => expect((input.selectionStart ?? 0) <= 3).toBe(true));
fireEvent.keyDown(input, { key: 'Tab' });
await waitFor(() => expect((input.selectionStart ?? 0) >= 0).toBe(true));
fireEvent.keyDown(input, { key: 'Tab', shiftKey: true });
await waitFor(() => expect((input.selectionStart ?? 0) >= 0).toBe(true));
fireEvent.keyDown(input, { key: 'Backspace' });
await waitFor(() => {
expect(input.value.startsWith('01/')).toBe(true);
});
fireEvent.keyDown(input, { key: '/' });
await waitFor(() => expect(input.selectionStart).toBe(3));
fireEvent.keyDown(input, { key: 'Delete' });
await waitFor(() => {
expect(input.value.slice(3, 5)).toBe('01');
});
fireEvent.keyDown(input, { key: '/' });
await waitFor(() => expect(input.selectionStart).toBe(6));
fireEvent.keyDown(input, { key: 'Delete' });
fireEvent.keyDown(input, { key: ' ' });
fireEvent.keyDown(input, { key: 'Delete' });
await waitFor(() => {
expect(/\s00:|:00$/.test(input.value)).toBe(true);
});
fireEvent.keyDown(input, { key: 'Enter' });
fireEvent.keyDown(input, { key: 'x' });
fireEvent.blur(input);
expect(onBlur).toHaveBeenCalledTimes(1);
});
it('handles paste validation and value commits', async () => {
render(
<ControlledDatePicker
type="date-time"
format="dd/mm/yyyy HH:mm"
initialValue="22/02/2026 14:30"
/>,
);
const input = screen.getByLabelText('Schedule') as HTMLInputElement;
await act(async () => {
input.dispatchEvent(createPasteEvent('invalid value'));
});
expect(input.value).toBe('22/02/2026 14:30');
await act(async () => {
input.dispatchEvent(createPasteEvent('11/03/2027 16:45'));
});
expect(input.value).toBe('11/03/2027 16:45');
});
it('returns early from interaction handlers when disabled', () => {
render(
<DatePicker
label="Schedule"
type="date-time"
format="dd/mm/yyyy HH:mm"
value="22/02/2026 14:30"
disabled
onChange={() => {}}
/>,
);
const input = screen.getByLabelText('Schedule') as HTMLInputElement;
fireEvent.focus(input);
fireEvent.mouseUp(input);
fireEvent.click(input);
fireEvent.keyDown(input, { key: 'ArrowDown' });
const disabledPaste = createPasteEvent('11/03/2027 16:45');
input.dispatchEvent(disabledPaste);
expect(disabledPaste.defaultPrevented).toBe(false);
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
it('falls back to direct assignment and synthetic onChange when native dispatch is stubbed', async () => {
const onChange = vi.fn();
const originalGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
render(
<DatePicker
label="Schedule"
type="date-time"
format="dd/mm/yyyy HH:mm"
value="22/02/2026 14:30"
onChange={onChange}
/>,
);
const input = screen.getByLabelText('Schedule') as HTMLInputElement;
const nativeDispatchEvent = input.dispatchEvent.bind(input);
vi.spyOn(input, 'dispatchEvent').mockImplementation((event: Event) => {
if (event.type === 'change') {
return true;
}
return nativeDispatchEvent(event);
});
vi.spyOn(Object, 'getOwnPropertyDescriptor').mockImplementation((target, property) => {
if (target === HTMLInputElement.prototype && property === 'value') {
return {
configurable: true,
enumerable: true,
get: originalGetOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.get,
};
}
return originalGetOwnPropertyDescriptor(target, property);
});
fireEvent.focus(input);
input.setSelectionRange(0, 2);
fireEvent.keyDown(input, { key: '1' });
await waitFor(() => {
expect(onChange).toHaveBeenCalled();
});
});
it('safely handles pending segment selection during unmount', () => {
vi.useFakeTimers();
const { unmount } = render(
<DatePicker
label="Schedule"
type="date-time"
format="dd/mm/yyyy HH:mm"
value="22/02/2026 14:30"
onChange={() => {}}
/>,
);
const input = screen.getByLabelText('Schedule') as HTMLInputElement;
fireEvent.focus(input);
unmount();
expect(() => {
vi.runAllTimers();
}).not.toThrow();
});
it('recalculates popup position on window resize and scroll', async () => {
const originalInnerWidth = Object.getOwnPropertyDescriptor(window, 'innerWidth');
const originalInnerHeight = Object.getOwnPropertyDescriptor(window, 'innerHeight');
const rectSpy = vi
.spyOn(HTMLElement.prototype, 'getBoundingClientRect')
.mockImplementation(function mockRect(this: HTMLElement) {
if (this.classList.contains('datepicker-popup')) {
return createRect(0, 0, 300, 200);
}
if (this.classList.contains('relative') && this.querySelector('input')) {
return createRect(500, 80, 120, 40);
}
return createRect(0, 0, 100, 30);
});
Object.defineProperty(window, 'innerWidth', { configurable: true, value: 600 });
Object.defineProperty(window, 'innerHeight', { configurable: true, value: 480 });
render(<DatePicker label="Schedule" type="date-time" value="2031/05/20 14:30" onChange={() => {}} />);
fireEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
const dialog = screen.getByRole('dialog', { name: 'Date and time picker popup' });
expect(dialog).toBeInTheDocument();
await waitFor(() => {
expect(dialog.style.left).toBe('292px');
});
fireEvent(window, new Event('resize'));
fireEvent(window, new Event('scroll'));
expect(screen.getByRole('dialog', { name: 'Date and time picker popup' })).toBeInTheDocument();
expect(dialog.style.left).toBe('292px');
rectSpy.mockRestore();
if (originalInnerWidth) {
Object.defineProperty(window, 'innerWidth', originalInnerWidth);
}
if (originalInnerHeight) {
Object.defineProperty(window, 'innerHeight', originalInnerHeight);
}
});
}); });

View File

@@ -52,4 +52,9 @@ describe('Dropdown', () => {
expect(select).toHaveClass('custom-select'); expect(select).toHaveClass('custom-select');
expect(screen.getByText('Role').closest('label')).toHaveClass('custom-wrapper'); expect(screen.getByText('Role').closest('label')).toHaveClass('custom-wrapper');
}); });
it('supports rendering without a label', () => {
const { container } = render(<Dropdown value="USER" choices={choices} />);
expect(container.querySelector('label > span')).toBeNull();
});
}); });

View File

@@ -89,4 +89,9 @@ describe('InputField', () => {
expect(container.querySelector('label')).toHaveClass('inline-flex'); expect(container.querySelector('label')).toHaveClass('inline-flex');
expect(container.querySelector('label > div')).not.toHaveClass('mt-1'); expect(container.querySelector('label > div')).not.toHaveClass('mt-1');
}); });
it('supports rendering without a label', () => {
const { container } = render(<InputField type="text" value="" onChange={() => {}} />);
expect(container.querySelector('label > span')).toBeNull();
});
}); });

503
yarn.lock
View File

@@ -504,9 +504,9 @@
"@codemirror/legacy-modes" "^6.4.0" "@codemirror/legacy-modes" "^6.4.0"
"@codemirror/language@^6.0.0", "@codemirror/language@^6.11.3", "@codemirror/language@^6.3.0", "@codemirror/language@^6.3.2", "@codemirror/language@^6.4.0", "@codemirror/language@^6.6.0", "@codemirror/language@^6.8.0": "@codemirror/language@^6.0.0", "@codemirror/language@^6.11.3", "@codemirror/language@^6.3.0", "@codemirror/language@^6.3.2", "@codemirror/language@^6.4.0", "@codemirror/language@^6.6.0", "@codemirror/language@^6.8.0":
version "6.12.1" version "6.12.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@codemirror/language/-/language-6.12.1.tgz#d615f7b099a39248312feaaf0bfafce4418aac1b" resolved "https://nexus.beatrice.wtf/repository/npm-group/@codemirror/language/-/language-6.12.2.tgz#7db5a46757411cf251e8f450474c05710c27d42c"
integrity sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ== integrity sha512-jEPmz2nGGDxhRTg3lTpzmIyGKxz3Gp3SJES4b0nAuE5SWQoKdT5GoQ69cwMmFd+wvFUhYirtDTr0/DRHpQAyWg==
dependencies: dependencies:
"@codemirror/state" "^6.0.0" "@codemirror/state" "^6.0.0"
"@codemirror/view" "^6.23.0" "@codemirror/view" "^6.23.0"
@@ -558,7 +558,7 @@
dependencies: dependencies:
"@marijn/find-cluster-break" "^1.0.0" "@marijn/find-cluster-break" "^1.0.0"
"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0", "@codemirror/view@^6.37.0", "@codemirror/view@^6.7.1": "@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0", "@codemirror/view@^6.37.0", "@codemirror/view@^6.7.1":
version "6.39.15" version "6.39.15"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@codemirror/view/-/view-6.39.15.tgz#7665f465b7fad1a1cae15b2689ffee2b47b18246" resolved "https://nexus.beatrice.wtf/repository/npm-group/@codemirror/view/-/view-6.39.15.tgz#7665f465b7fad1a1cae15b2689ffee2b47b18246"
integrity sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg== integrity sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg==
@@ -568,6 +568,16 @@
style-mod "^4.1.0" style-mod "^4.1.0"
w3c-keyname "^2.2.4" w3c-keyname "^2.2.4"
"@codemirror/view@^6.23.0":
version "6.39.16"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@codemirror/view/-/view-6.39.16.tgz#e9d876aba20b31df7858abd7c2a845319c70b302"
integrity sha512-m6S22fFpKtOWhq8HuhzsI1WzUP/hB9THbDj0Tl5KX4gbO6Y91hwBl7Yky33NdvB6IffuRFiBxf1R8kJMyXmA4Q==
dependencies:
"@codemirror/state" "^6.5.0"
crelt "^1.0.6"
style-mod "^4.1.0"
w3c-keyname "^2.2.4"
"@codesandbox/nodebox@0.1.8": "@codesandbox/nodebox@0.1.8":
version "0.1.8" version "0.1.8"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@codesandbox/nodebox/-/nodebox-0.1.8.tgz#2dc701005cedefac386f17a69a4c9a4f38c2325d" resolved "https://nexus.beatrice.wtf/repository/npm-group/@codesandbox/nodebox/-/nodebox-0.1.8.tgz#2dc701005cedefac386f17a69a4c9a4f38c2325d"
@@ -646,6 +656,28 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz#798a33950d11226a0ebb6acafa60f5594424967f" resolved "https://nexus.beatrice.wtf/repository/npm-group/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz#798a33950d11226a0ebb6acafa60f5594424967f"
integrity sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA== integrity sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==
"@emnapi/core@^1.7.1":
version "1.9.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@emnapi/core/-/core-1.9.0.tgz#4a54213b208fcf288cce25076c74e0f7613e6100"
integrity sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==
dependencies:
"@emnapi/wasi-threads" "1.2.0"
tslib "^2.4.0"
"@emnapi/runtime@^1.7.1":
version "1.9.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@emnapi/runtime/-/runtime-1.9.0.tgz#91c54a6e77c36154c125e873409472e2b70efd5b"
integrity sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==
dependencies:
tslib "^2.4.0"
"@emnapi/wasi-threads@1.2.0":
version "1.2.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz#a19d9772cc3d195370bf6e2a805eec40aa75e18e"
integrity sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==
dependencies:
tslib "^2.4.0"
"@esbuild/aix-ppc64@0.27.3": "@esbuild/aix-ppc64@0.27.3":
version "0.27.3" version "0.27.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz#815b39267f9bffd3407ea6c376ac32946e24f8d2" resolved "https://nexus.beatrice.wtf/repository/npm-group/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz#815b39267f9bffd3407ea6c376ac32946e24f8d2"
@@ -788,26 +820,26 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b"
integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==
"@eslint/config-array@^0.23.2": "@eslint/config-array@^0.23.3":
version "0.23.2" version "0.23.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/config-array/-/config-array-0.23.2.tgz#db85beeff7facc685a5775caacb1c845669b9470" resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/config-array/-/config-array-0.23.3.tgz#3f4a93dd546169c09130cbd10f2415b13a20a219"
integrity sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A== integrity sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==
dependencies: dependencies:
"@eslint/object-schema" "^3.0.2" "@eslint/object-schema" "^3.0.3"
debug "^4.3.1" debug "^4.3.1"
minimatch "^10.2.1" minimatch "^10.2.4"
"@eslint/config-helpers@^0.5.2": "@eslint/config-helpers@^0.5.2":
version "0.5.2" version "0.5.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/config-helpers/-/config-helpers-0.5.2.tgz#314c7b03d02a371ad8c0a7f6821d5a8a8437ba9d" resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/config-helpers/-/config-helpers-0.5.3.tgz#721fe6bbb90d74b0c80d6ff2428e5bbcb002becb"
integrity sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ== integrity sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==
dependencies: dependencies:
"@eslint/core" "^1.1.0" "@eslint/core" "^1.1.1"
"@eslint/core@^1.1.0": "@eslint/core@^1.1.1":
version "1.1.0" version "1.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/core/-/core-1.1.0.tgz#51f5cd970e216fbdae6721ac84491f57f965836d" resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/core/-/core-1.1.1.tgz#450f3d2be2d463ccd51119544092256b4e88df32"
integrity sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw== integrity sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==
dependencies: dependencies:
"@types/json-schema" "^7.0.15" "@types/json-schema" "^7.0.15"
@@ -816,17 +848,17 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/js/-/js-10.0.1.tgz#1e8a876f50117af8ab67e47d5ad94d38d6622583" resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/js/-/js-10.0.1.tgz#1e8a876f50117af8ab67e47d5ad94d38d6622583"
integrity sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA== integrity sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==
"@eslint/object-schema@^3.0.2": "@eslint/object-schema@^3.0.3":
version "3.0.2" version "3.0.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/object-schema/-/object-schema-3.0.2.tgz#c59c6a94aa4b428ed7f1615b6a4495c0a21f7a22" resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/object-schema/-/object-schema-3.0.3.tgz#5bf671e52e382e4adc47a9906f2699374637db6b"
integrity sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw== integrity sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==
"@eslint/plugin-kit@^0.6.0": "@eslint/plugin-kit@^0.6.1":
version "0.6.0" version "0.6.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/plugin-kit/-/plugin-kit-0.6.0.tgz#e0cb12ec66719cb2211ad36499fb516f2a63899d" resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz#eb9e6689b56ce8bc1855bb33090e63f3fc115e8e"
integrity sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ== integrity sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==
dependencies: dependencies:
"@eslint/core" "^1.1.0" "@eslint/core" "^1.1.1"
levn "^0.4.1" levn "^0.4.1"
"@exodus/bytes@^1.11.0", "@exodus/bytes@^1.6.0": "@exodus/bytes@^1.11.0", "@exodus/bytes@^1.6.0":
@@ -1365,6 +1397,15 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@mdxeditor/gurx/-/gurx-1.2.4.tgz#b4d16141ee1f605dde754932087de17e2d73b919" resolved "https://nexus.beatrice.wtf/repository/npm-group/@mdxeditor/gurx/-/gurx-1.2.4.tgz#b4d16141ee1f605dde754932087de17e2d73b919"
integrity sha512-9ZykIFYhKaXaaSPCs1cuI+FvYDegJjbKwmA4ASE/zY+hJY6EYqvoye4esiO85CjhOw9aoD/izD/CU78/egVqmg== integrity sha512-9ZykIFYhKaXaaSPCs1cuI+FvYDegJjbKwmA4ASE/zY+hJY6EYqvoye4esiO85CjhOw9aoD/izD/CU78/egVqmg==
"@napi-rs/wasm-runtime@^1.1.1":
version "1.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz#c3705ab549d176b8dc5172723d6156c3dc426af2"
integrity sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==
dependencies:
"@emnapi/core" "^1.7.1"
"@emnapi/runtime" "^1.7.1"
"@tybys/wasm-util" "^0.10.1"
"@nodelib/fs.scandir@2.1.5": "@nodelib/fs.scandir@2.1.5":
version "2.1.5" version "2.1.5"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" resolved "https://nexus.beatrice.wtf/repository/npm-group/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@@ -1391,6 +1432,16 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" resolved "https://nexus.beatrice.wtf/repository/npm-group/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd"
integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==
"@oxc-project/runtime@0.115.0":
version "0.115.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@oxc-project/runtime/-/runtime-0.115.0.tgz#5e8350088964e1d8e0c73cfccfc1d71ca2e2f4a2"
integrity sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==
"@oxc-project/types@=0.115.0":
version "0.115.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@oxc-project/types/-/types-0.115.0.tgz#92a599543529bce45f8f2da77f40a124d63349dc"
integrity sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==
"@radix-ui/colors@^3.0.0": "@radix-ui/colors@^3.0.0":
version "3.0.0" version "3.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@radix-ui/colors/-/colors-3.0.0.tgz#e8a591a303c44e503bd1212cacf40a09511165e0" resolved "https://nexus.beatrice.wtf/repository/npm-group/@radix-ui/colors/-/colors-3.0.0.tgz#e8a591a303c44e503bd1212cacf40a09511165e0"
@@ -1740,11 +1791,93 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz#c06dac2d011f36d61259aa1c6df4f0d5e28bc55e" resolved "https://nexus.beatrice.wtf/repository/npm-group/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz#c06dac2d011f36d61259aa1c6df4f0d5e28bc55e"
integrity sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg== integrity sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg==
"@rolldown/binding-android-arm64@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.9.tgz#4bbd28868564948c2bf04b3ca117a6828f95626c"
integrity sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==
"@rolldown/binding-darwin-arm64@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.9.tgz#80864a6997404f264cc7a216cad221fe6148705d"
integrity sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ==
"@rolldown/binding-darwin-x64@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.9.tgz#747b698878b6f44d817f87e9e3cb197b16076d2a"
integrity sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg==
"@rolldown/binding-freebsd-x64@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.9.tgz#35c29d7c83aa75429c74d7d1ee9c7d3e61f4552c"
integrity sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q==
"@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.9.tgz#36d2bcbcf07f17f18fb2df727a62f16e5295c816"
integrity sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ==
"@rolldown/binding-linux-arm64-gnu@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.9.tgz#5b03c11f2b661a275f2d7628e4f456783e1b9f63"
integrity sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg==
"@rolldown/binding-linux-arm64-musl@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.9.tgz#d3cbd1b1760d34b5789af89f4bcc09a1446d3eb5"
integrity sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==
"@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.9.tgz#8e971e7f066b2c0876e20c9f6174d645f31efb84"
integrity sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==
"@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.9.tgz#e7283523780741f07a4441c7c8af5b2550faadf2"
integrity sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==
"@rolldown/binding-linux-x64-gnu@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.9.tgz#da2302e079bb5f3a98edf75608621e94f1fb550e"
integrity sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==
"@rolldown/binding-linux-x64-musl@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.9.tgz#3f27a620d56b93644fd1b6fad58fc2dbe93d5d71"
integrity sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==
"@rolldown/binding-openharmony-arm64@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.9.tgz#9c307777157d029aaf8db1a09221b9275dbe5547"
integrity sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==
"@rolldown/binding-wasm32-wasi@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.9.tgz#c3a82bef0ddd644efa74c050c26223f29f55039c"
integrity sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g==
dependencies:
"@napi-rs/wasm-runtime" "^1.1.1"
"@rolldown/binding-win32-arm64-msvc@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.9.tgz#27e23cbd53b7095d0b66191ef999327b4684a6cf"
integrity sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA==
"@rolldown/binding-win32-x64-msvc@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.9.tgz#96046309142b398c9c2a9a0a052e7355535e69c8"
integrity sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ==
"@rolldown/pluginutils@1.0.0-rc.3": "@rolldown/pluginutils@1.0.0-rc.3":
version "1.0.0-rc.3" version "1.0.0-rc.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz#8a88cc92a0f741befc7bc109cb1a4c6b9408e1c5" resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz#8a88cc92a0f741befc7bc109cb1a4c6b9408e1c5"
integrity sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q== integrity sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==
"@rolldown/pluginutils@1.0.0-rc.9":
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.9.tgz#ddb28c13602aea5a5edf03532c28bbfc37c4b5e0"
integrity sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==
"@rollup/pluginutils@^5.0.2": "@rollup/pluginutils@^5.0.2":
version "5.3.0" version "5.3.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@rollup/pluginutils/-/pluginutils-5.3.0.tgz#57ba1b0cbda8e7a3c597a4853c807b156e21a7b4" resolved "https://nexus.beatrice.wtf/repository/npm-group/@rollup/pluginutils/-/pluginutils-5.3.0.tgz#57ba1b0cbda8e7a3c597a4853c807b156e21a7b4"
@@ -1890,45 +2023,45 @@
integrity sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg== integrity sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg==
"@storybook/addon-a11y@^10.2.10": "@storybook/addon-a11y@^10.2.10":
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/addon-a11y/-/addon-a11y-10.2.10.tgz#8c80cdcce50eecc52aa7b0fec69dd2bcb92eef98" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/addon-a11y/-/addon-a11y-10.2.17.tgz#be6bdcb3b7a4af5c75c45ba22e20658965c538e6"
integrity sha512-1S9pDXgvbHhBStGarCvfJ3/rfcaiAcQHRhuM3Nk4WGSIYtC1LCSRuzYdDYU0aNRpdCbCrUA7kUCbqvIE3tH+3Q== integrity sha512-J0ogEc4/XFC+Ytz+X1we6TOKreEk/shgUs/mtxdsLa0xJ6bp2n2OQPSjNtQHH/nK4SRBSfHWPm8ztfcXTzeG9w==
dependencies: dependencies:
"@storybook/global" "^5.0.0" "@storybook/global" "^5.0.0"
axe-core "^4.2.0" axe-core "^4.2.0"
"@storybook/addon-docs@^10.2.10": "@storybook/addon-docs@^10.2.10":
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/addon-docs/-/addon-docs-10.2.10.tgz#22d1a8dae3b04d5e9e1e131ae7f97a8ab722e83d" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/addon-docs/-/addon-docs-10.2.17.tgz#845ee497dfaedac37703bc090aa013e542e88ddb"
integrity sha512-2wIYtdvZIzPbQ5194M5Igpy8faNbQ135nuO5ZaZ2VuttqGr+IJcGnDP42zYwbAsGs28G8ohpkbSgIzVyJWUhPQ== integrity sha512-c414xi7rxlaHn92qWOxtEkcOMm0/+cvBui0gUsgiWOZOM8dHChGZ/RjMuf1pPDyOrSsybLsPjZhP0WthsMDkdQ==
dependencies: dependencies:
"@mdx-js/react" "^3.0.0" "@mdx-js/react" "^3.0.0"
"@storybook/csf-plugin" "10.2.10" "@storybook/csf-plugin" "10.2.17"
"@storybook/icons" "^2.0.1" "@storybook/icons" "^2.0.1"
"@storybook/react-dom-shim" "10.2.10" "@storybook/react-dom-shim" "10.2.17"
react "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" react "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
react-dom "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" react-dom "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
ts-dedent "^2.0.0" ts-dedent "^2.0.0"
"@storybook/addon-themes@^10.2.10": "@storybook/addon-themes@^10.2.10":
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/addon-themes/-/addon-themes-10.2.10.tgz#2daefc26d1c9071ff49948d92805908b7d54caf5" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/addon-themes/-/addon-themes-10.2.17.tgz#33cbb5a443b0b5041cbdb891eebf8aae700ed051"
integrity sha512-j7ixCgzpWeTU7K4BkNHtEg3NdmRg9YW7ynvv0OjD3vaz4+FUVWOq7PPwb3SktLS1tOl4UA13IpApD8nSpBiY6A== integrity sha512-5AJ6h/i967CEDG3DNstfgKo9ysDNIOb1pnbn8VbcD/Fw8D2dZm7pLkTAQOnxu6lFQaIU10DIiVp7cviBMasDUg==
dependencies: dependencies:
ts-dedent "^2.0.0" ts-dedent "^2.0.0"
"@storybook/builder-vite@10.2.10": "@storybook/builder-vite@10.2.17":
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/builder-vite/-/builder-vite-10.2.10.tgz#0f9889873291a7b88857c45224d4063e204d3a62" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/builder-vite/-/builder-vite-10.2.17.tgz#87823a5289c3b2d6cc82f07676b52cfc41372599"
integrity sha512-Wd6CYL7LvRRNiXMz977x9u/qMm7nmMw/7Dow2BybQo+Xbfy1KhVjIoZ/gOiG515zpojSozctNrJUbM0+jH1jwg== integrity sha512-m/OBveTLm5ds/tUgHmmbKzgSi/oeCpQwm5rZa49vP2BpAd41Q7ER6TzkOoISzPoNNMAcbVmVc5vn7k6hdbPSHw==
dependencies: dependencies:
"@storybook/csf-plugin" "10.2.10" "@storybook/csf-plugin" "10.2.17"
ts-dedent "^2.0.0" ts-dedent "^2.0.0"
"@storybook/csf-plugin@10.2.10": "@storybook/csf-plugin@10.2.17":
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/csf-plugin/-/csf-plugin-10.2.10.tgz#038cd8e41884f2f437502504d02b8c0a24ed0b39" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/csf-plugin/-/csf-plugin-10.2.17.tgz#a3d1da13e67f7d6ce3cb0a4cfee9badc4411b37e"
integrity sha512-aFvgaNDAnKMjuyhPK5ialT22pPqMN0XfPBNPeeNVPYztngkdKBa8WFqF/umDd47HxAjebq+vn6uId1xHyOHH3g== integrity sha512-crHH8i/4mwzeXpWRPgwvwX2vjytW42zyzTRySUax5dTU8o9sjk4y+Z9hkGx3Nmu1TvqseS8v1Z20saZr/tQcWw==
dependencies: dependencies:
unplugin "^2.3.5" unplugin "^2.3.5"
@@ -1942,33 +2075,33 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/icons/-/icons-2.0.1.tgz#1bd351db1d33bfccbbafa7b64fb413168f1a6616" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/icons/-/icons-2.0.1.tgz#1bd351db1d33bfccbbafa7b64fb413168f1a6616"
integrity sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg== integrity sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg==
"@storybook/react-dom-shim@10.2.10": "@storybook/react-dom-shim@10.2.17":
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/react-dom-shim/-/react-dom-shim-10.2.10.tgz#ce1b439573fa01fc4fd461cff22bda23abf39a4a" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/react-dom-shim/-/react-dom-shim-10.2.17.tgz#9d7b3e600c190fa643b8d0ad92422df6bd26fc2c"
integrity sha512-TmBrhyLHn8B8rvDHKk5uW5BqzO1M1T+fqFNWg88NIAJOoyX4Uc90FIJjDuN1OJmWKGwB5vLmPwaKBYsTe1yS+w== integrity sha512-x9Kb7eUSZ1zGsEw/TtWrvs1LwWIdNp8qoOQCgPEjdB07reSJcE8R3+ASWHJThmd4eZf66ZALPJyerejake4Osw==
"@storybook/react-vite@^10.2.10": "@storybook/react-vite@^10.2.10":
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/react-vite/-/react-vite-10.2.10.tgz#cf1e970189167786fe1e314eeef025b50a49e4f1" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/react-vite/-/react-vite-10.2.17.tgz#54aa766c4254f8b1c7958ccc343033db08b88867"
integrity sha512-C652GhZHXURi+gFqqLKmZPskEq1FQto4VCf/eQea2exmdVS0nOB+FFWQZNCivX6mpkDHza8UxRZNFpDB0mWcJQ== integrity sha512-E/1hNmxVsjy9l3TuaNufSqkdz8saTJUGEs8GRCjKlF7be2wljIwewUxjAT3efk+bxOCw76ZmqGHk6MnRa3y7Gw==
dependencies: dependencies:
"@joshwooding/vite-plugin-react-docgen-typescript" "^0.6.4" "@joshwooding/vite-plugin-react-docgen-typescript" "^0.6.4"
"@rollup/pluginutils" "^5.0.2" "@rollup/pluginutils" "^5.0.2"
"@storybook/builder-vite" "10.2.10" "@storybook/builder-vite" "10.2.17"
"@storybook/react" "10.2.10" "@storybook/react" "10.2.17"
empathic "^2.0.0" empathic "^2.0.0"
magic-string "^0.30.0" magic-string "^0.30.0"
react-docgen "^8.0.0" react-docgen "^8.0.0"
resolve "^1.22.8" resolve "^1.22.8"
tsconfig-paths "^4.2.0" tsconfig-paths "^4.2.0"
"@storybook/react@10.2.10", "@storybook/react@^10.2.10": "@storybook/react@10.2.17", "@storybook/react@^10.2.10":
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/react/-/react-10.2.10.tgz#38116ead3e1bbb96acfa043db3545e36146cd32f" resolved "https://nexus.beatrice.wtf/repository/npm-group/@storybook/react/-/react-10.2.17.tgz#ec2788a4d163732dfb7a86f9dc878f448d5e3fd9"
integrity sha512-PcsChzPI8lhllB9exV7nFb96093i6sTwIl0jpPjaTFPQCRoueR9E/YeP3qSKQL9xt4cmii0cW7F0RUx25rW93Q== integrity sha512-875AVMYil2X9Civil6GFZ8koIzlKxcXbl2eJ7+/GPbhIonTNmwx0qbWPHttjZXUvFuQ4RRtb9KkBwy4TCb/LeA==
dependencies: dependencies:
"@storybook/global" "^5.0.0" "@storybook/global" "^5.0.0"
"@storybook/react-dom-shim" "10.2.10" "@storybook/react-dom-shim" "10.2.17"
react-docgen "^8.0.2" react-docgen "^8.0.2"
"@testing-library/dom@^10.4.1": "@testing-library/dom@^10.4.1":
@@ -2009,6 +2142,13 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@testing-library/user-event/-/user-event-14.6.1.tgz#13e09a32d7a8b7060fe38304788ebf4197cd2149" resolved "https://nexus.beatrice.wtf/repository/npm-group/@testing-library/user-event/-/user-event-14.6.1.tgz#13e09a32d7a8b7060fe38304788ebf4197cd2149"
integrity sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw== integrity sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==
"@tybys/wasm-util@^0.10.1":
version "0.10.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414"
integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==
dependencies:
tslib "^2.4.0"
"@types/aria-query@^5.0.1": "@types/aria-query@^5.0.1":
version "5.0.4" version "5.0.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708"
@@ -2119,9 +2259,9 @@
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
"@types/node@^25.3.0": "@types/node@^25.3.0":
version "25.3.0" version "25.4.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/node/-/node-25.3.0.tgz#749b1bd4058e51b72e22bd41e9eab6ebd0180470" resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/node/-/node-25.4.0.tgz#f25d8467984d6667cc4c1be1e2f79593834aaedb"
integrity sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A== integrity sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==
dependencies: dependencies:
undici-types "~7.18.0" undici-types "~7.18.0"
@@ -2383,7 +2523,7 @@ agent-base@^7.1.0, agent-base@^7.1.2:
resolved "https://nexus.beatrice.wtf/repository/npm-group/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" resolved "https://nexus.beatrice.wtf/repository/npm-group/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8"
integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==
ajv@^6.12.4: ajv@^6.14.0:
version "6.14.0" version "6.14.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" resolved "https://nexus.beatrice.wtf/repository/npm-group/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a"
integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw== integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==
@@ -2504,9 +2644,9 @@ binary-extensions@^2.0.0:
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
brace-expansion@^5.0.2: brace-expansion@^5.0.2:
version "5.0.3" version "5.0.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/brace-expansion/-/brace-expansion-5.0.3.tgz#6a9c6c268f85b53959ec527aeafe0f7300258eef" resolved "https://nexus.beatrice.wtf/repository/npm-group/brace-expansion/-/brace-expansion-5.0.4.tgz#614daaecd0a688f660bbbc909a8748c3d80d4336"
integrity sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA== integrity sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==
dependencies: dependencies:
balanced-match "^4.0.2" balanced-match "^4.0.2"
@@ -2549,9 +2689,9 @@ camelcase-css@^2.0.1:
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
caniuse-lite@^1.0.30001759: caniuse-lite@^1.0.30001759:
version "1.0.30001774" version "1.0.30001777"
resolved "https://nexus.beatrice.wtf/repository/npm-group/caniuse-lite/-/caniuse-lite-1.0.30001774.tgz#0e576b6f374063abcd499d202b9ba1301be29b70" resolved "https://nexus.beatrice.wtf/repository/npm-group/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz#028f21e4b2718d138b55e692583e6810ccf60691"
integrity sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA== integrity sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==
ccount@^2.0.0: ccount@^2.0.0:
version "2.0.1" version "2.0.1"
@@ -2777,6 +2917,11 @@ dequal@^2.0.0, dequal@^2.0.2, dequal@^2.0.3:
resolved "https://nexus.beatrice.wtf/repository/npm-group/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" resolved "https://nexus.beatrice.wtf/repository/npm-group/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
detect-libc@^2.0.3:
version "2.1.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad"
integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==
detect-node-es@^1.1.0: detect-node-es@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" resolved "https://nexus.beatrice.wtf/repository/npm-group/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
@@ -2838,9 +2983,9 @@ downshift@^7.6.0:
tslib "^2.3.0" tslib "^2.3.0"
electron-to-chromium@^1.5.263: electron-to-chromium@^1.5.263:
version "1.5.302" version "1.5.307"
resolved "https://nexus.beatrice.wtf/repository/npm-group/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz#032a5802b31f7119269959c69fe2015d8dad5edb" resolved "https://nexus.beatrice.wtf/repository/npm-group/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz#09f8973100c39fb0d003b890393cd1d58932b1c8"
integrity sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg== integrity sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==
empathic@^2.0.0: empathic@^2.0.0:
version "2.0.0" version "2.0.0"
@@ -2948,14 +3093,14 @@ eslint-plugin-react-hooks@^7.1.0-canary-ab18f33d-20260220:
zod-validation-error "^3.5.0 || ^4.0.0" zod-validation-error "^3.5.0 || ^4.0.0"
eslint-plugin-react-refresh@^0.5.1: eslint-plugin-react-refresh@^0.5.1:
version "0.5.1" version "0.5.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.1.tgz#d13f1cfea4718a108060a41219d1849287278adc" resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz#39e11021be10e1cd9adab2bdeabc65b17222409f"
integrity sha512-Y5sJsreCUdGcF4mLD70iJNa47Z6CX4MsqJoJBARDC/fBhmacSby7k73UuValr0F9M7GfWKpEqS4NMsniWkVxQw== integrity sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==
eslint-scope@^9.1.1: eslint-scope@^9.1.2:
version "9.1.1" version "9.1.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-scope/-/eslint-scope-9.1.1.tgz#f6a209486e38bd28356b5feb07d445cc99c89967" resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-scope/-/eslint-scope-9.1.2.tgz#b9de6ace2fab1cff24d2e58d85b74c8fcea39802"
integrity sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw== integrity sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==
dependencies: dependencies:
"@types/esrecurse" "^4.3.1" "@types/esrecurse" "^4.3.1"
"@types/estree" "^1.0.8" "@types/estree" "^1.0.8"
@@ -2973,25 +3118,25 @@ eslint-visitor-keys@^5.0.0, eslint-visitor-keys@^5.0.1:
integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA== integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==
eslint@^10: eslint@^10:
version "10.0.1" version "10.0.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint/-/eslint-10.0.1.tgz#b5c5f7706782a21590ba6451e7a30d2947273c2d" resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint/-/eslint-10.0.3.tgz#360a7de7f2706eb8a32caa17ca983f0089efe694"
integrity sha512-20MV9SUdeN6Jd84xESsKhRly+/vxI+hwvpBMA93s+9dAcjdCuCojn4IqUGS3lvVaqjVYGYHSRMCpeFtF2rQYxQ== integrity sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==
dependencies: dependencies:
"@eslint-community/eslint-utils" "^4.8.0" "@eslint-community/eslint-utils" "^4.8.0"
"@eslint-community/regexpp" "^4.12.2" "@eslint-community/regexpp" "^4.12.2"
"@eslint/config-array" "^0.23.2" "@eslint/config-array" "^0.23.3"
"@eslint/config-helpers" "^0.5.2" "@eslint/config-helpers" "^0.5.2"
"@eslint/core" "^1.1.0" "@eslint/core" "^1.1.1"
"@eslint/plugin-kit" "^0.6.0" "@eslint/plugin-kit" "^0.6.1"
"@humanfs/node" "^0.16.6" "@humanfs/node" "^0.16.6"
"@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/module-importer" "^1.0.1"
"@humanwhocodes/retry" "^0.4.2" "@humanwhocodes/retry" "^0.4.2"
"@types/estree" "^1.0.6" "@types/estree" "^1.0.6"
ajv "^6.12.4" ajv "^6.14.0"
cross-spawn "^7.0.6" cross-spawn "^7.0.6"
debug "^4.3.2" debug "^4.3.2"
escape-string-regexp "^4.0.0" escape-string-regexp "^4.0.0"
eslint-scope "^9.1.1" eslint-scope "^9.1.2"
eslint-visitor-keys "^5.0.1" eslint-visitor-keys "^5.0.1"
espree "^11.1.1" espree "^11.1.1"
esquery "^1.7.0" esquery "^1.7.0"
@@ -3004,7 +3149,7 @@ eslint@^10:
imurmurhash "^0.1.4" imurmurhash "^0.1.4"
is-glob "^4.0.0" is-glob "^4.0.0"
json-stable-stringify-without-jsonify "^1.0.1" json-stable-stringify-without-jsonify "^1.0.1"
minimatch "^10.2.1" minimatch "^10.2.4"
natural-compare "^1.4.0" natural-compare "^1.4.0"
optionator "^0.9.3" optionator "^0.9.3"
@@ -3019,9 +3164,9 @@ esniff@^2.0.1:
type "^2.7.2" type "^2.7.2"
espree@^11.1.1: espree@^11.1.1:
version "11.1.1" version "11.2.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/espree/-/espree-11.1.1.tgz#866f6bc9ccccd6f28876b7a6463abb281b9cb847" resolved "https://nexus.beatrice.wtf/repository/npm-group/espree/-/espree-11.2.0.tgz#01d5e47dc332aaba3059008362454a8cc34ccaa5"
integrity sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ== integrity sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==
dependencies: dependencies:
acorn "^8.16.0" acorn "^8.16.0"
acorn-jsx "^5.3.2" acorn-jsx "^5.3.2"
@@ -3177,9 +3322,9 @@ flat-cache@^4.0.0:
keyv "^4.5.4" keyv "^4.5.4"
flatted@^3.2.9: flatted@^3.2.9:
version "3.3.3" version "3.4.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" resolved "https://nexus.beatrice.wtf/repository/npm-group/flatted/-/flatted-3.4.1.tgz#84ccd9579e76e9cc0d246c11d8be0beb019143e6"
integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== integrity sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==
format@^0.2.0: format@^0.2.0:
version "0.2.2" version "0.2.2"
@@ -3230,9 +3375,9 @@ glob@^13.0.1:
path-scurry "^2.0.2" path-scurry "^2.0.2"
globals@^17.3.0: globals@^17.3.0:
version "17.3.0" version "17.4.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/globals/-/globals-17.3.0.tgz#8b96544c2fa91afada02747cc9731c002a96f3b9" resolved "https://nexus.beatrice.wtf/repository/npm-group/globals/-/globals-17.4.0.tgz#33d7d297ed1536b388a0e2f4bcd0ff19c8ff91b5"
integrity sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw== integrity sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==
has-flag@^4.0.0: has-flag@^4.0.0:
version "4.0.0" version "4.0.0"
@@ -3532,6 +3677,80 @@ lib0@^0.2.99:
dependencies: dependencies:
isomorphic.js "^0.2.4" isomorphic.js "^0.2.4"
lightningcss-android-arm64@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz#f033885116dfefd9c6f54787523e3514b61e1968"
integrity sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==
lightningcss-darwin-arm64@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz#50b71871b01c8199584b649e292547faea7af9b5"
integrity sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==
lightningcss-darwin-x64@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz#35f3e97332d130b9ca181e11b568ded6aebc6d5e"
integrity sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==
lightningcss-freebsd-x64@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz#9777a76472b64ed6ff94342ad64c7bafd794a575"
integrity sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==
lightningcss-linux-arm-gnueabihf@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz#13ae652e1ab73b9135d7b7da172f666c410ad53d"
integrity sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==
lightningcss-linux-arm64-gnu@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz#417858795a94592f680123a1b1f9da8a0e1ef335"
integrity sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==
lightningcss-linux-arm64-musl@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz#6be36692e810b718040802fd809623cffe732133"
integrity sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==
lightningcss-linux-x64-gnu@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz#0b7803af4eb21cfd38dd39fe2abbb53c7dd091f6"
integrity sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==
lightningcss-linux-x64-musl@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz#88dc8ba865ddddb1ac5ef04b0f161804418c163b"
integrity sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==
lightningcss-win32-arm64-msvc@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz#4f30ba3fa5e925f5b79f945e8cc0d176c3b1ab38"
integrity sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==
lightningcss-win32-x64-msvc@1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz#141aa5605645064928902bb4af045fa7d9f4220a"
integrity sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==
lightningcss@^1.32.0:
version "1.32.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lightningcss/-/lightningcss-1.32.0.tgz#b85aae96486dcb1bf49a7c8571221273f4f1e4a9"
integrity sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==
dependencies:
detect-libc "^2.0.3"
optionalDependencies:
lightningcss-android-arm64 "1.32.0"
lightningcss-darwin-arm64 "1.32.0"
lightningcss-darwin-x64 "1.32.0"
lightningcss-freebsd-x64 "1.32.0"
lightningcss-linux-arm-gnueabihf "1.32.0"
lightningcss-linux-arm64-gnu "1.32.0"
lightningcss-linux-arm64-musl "1.32.0"
lightningcss-linux-x64-gnu "1.32.0"
lightningcss-linux-x64-musl "1.32.0"
lightningcss-win32-arm64-msvc "1.32.0"
lightningcss-win32-x64-msvc "1.32.0"
lilconfig@^3.1.1, lilconfig@^3.1.3: lilconfig@^3.1.1, lilconfig@^3.1.3:
version "3.1.3" version "3.1.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" resolved "https://nexus.beatrice.wtf/repository/npm-group/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4"
@@ -4161,10 +4380,10 @@ min-indent@^1.0.0:
resolved "https://nexus.beatrice.wtf/repository/npm-group/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" resolved "https://nexus.beatrice.wtf/repository/npm-group/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
minimatch@^10.2.1, minimatch@^10.2.2: minimatch@^10.2.2, minimatch@^10.2.4:
version "10.2.2" version "10.2.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/minimatch/-/minimatch-10.2.2.tgz#361603ee323cfb83496fea2ae17cc44ea4e1f99f" resolved "https://nexus.beatrice.wtf/repository/npm-group/minimatch/-/minimatch-10.2.4.tgz#465b3accbd0218b8281f5301e27cedc697f96fde"
integrity sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw== integrity sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==
dependencies: dependencies:
brace-expansion "^5.0.2" brace-expansion "^5.0.2"
@@ -4220,9 +4439,9 @@ next-tick@^1.1.0:
integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
node-releases@^2.0.27: node-releases@^2.0.27:
version "2.0.27" version "2.0.36"
resolved "https://nexus.beatrice.wtf/repository/npm-group/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" resolved "https://nexus.beatrice.wtf/repository/npm-group/node-releases/-/node-releases-2.0.36.tgz#99fd6552aaeda9e17c4713b57a63964a2e325e9d"
integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== integrity sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==
normalize-path@^3.0.0, normalize-path@~3.0.0: normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0" version "3.0.0"
@@ -4411,10 +4630,10 @@ postcss-value-parser@^4.0.0:
resolved "https://nexus.beatrice.wtf/repository/npm-group/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" resolved "https://nexus.beatrice.wtf/repository/npm-group/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.4.47, postcss@^8.4.49, postcss@^8.5.6: postcss@^8.4.47, postcss@^8.4.49, postcss@^8.5.6, postcss@^8.5.8:
version "8.5.6" version "8.5.8"
resolved "https://nexus.beatrice.wtf/repository/npm-group/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" resolved "https://nexus.beatrice.wtf/repository/npm-group/postcss/-/postcss-8.5.8.tgz#6230ecc8fb02e7a0f6982e53990937857e13f399"
integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== integrity sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==
dependencies: dependencies:
nanoid "^3.3.11" nanoid "^3.3.11"
picocolors "^1.1.1" picocolors "^1.1.1"
@@ -4545,16 +4764,16 @@ react-remove-scroll@^2.6.3:
use-sidecar "^1.1.3" use-sidecar "^1.1.3"
react-router-dom@^7.0.0: react-router-dom@^7.0.0:
version "7.13.0" version "7.13.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/react-router-dom/-/react-router-dom-7.13.0.tgz#8b5f7204fadca680f0e94f207c163f0dcd1cfdf5" resolved "https://nexus.beatrice.wtf/repository/npm-group/react-router-dom/-/react-router-dom-7.13.1.tgz#74c045acc333ca94612b889cd1b1e1ee9534dead"
integrity sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g== integrity sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==
dependencies: dependencies:
react-router "7.13.0" react-router "7.13.1"
react-router@7.13.0: react-router@7.13.1:
version "7.13.0" version "7.13.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/react-router/-/react-router-7.13.0.tgz#de9484aee764f4f65b93275836ff5944d7f5bd3b" resolved "https://nexus.beatrice.wtf/repository/npm-group/react-router/-/react-router-7.13.1.tgz#5e2b3ebafd6c78d9775e135474bf5060645077f7"
integrity sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw== integrity sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==
dependencies: dependencies:
cookie "^1.0.1" cookie "^1.0.1"
set-cookie-parser "^2.6.0" set-cookie-parser "^2.6.0"
@@ -4624,6 +4843,30 @@ reusify@^1.0.4:
resolved "https://nexus.beatrice.wtf/repository/npm-group/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" resolved "https://nexus.beatrice.wtf/repository/npm-group/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f"
integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==
rolldown@1.0.0-rc.9:
version "1.0.0-rc.9"
resolved "https://nexus.beatrice.wtf/repository/npm-group/rolldown/-/rolldown-1.0.0-rc.9.tgz#5a0d3e194f2bcc7a134870b174042fcaed463689"
integrity sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q==
dependencies:
"@oxc-project/types" "=0.115.0"
"@rolldown/pluginutils" "1.0.0-rc.9"
optionalDependencies:
"@rolldown/binding-android-arm64" "1.0.0-rc.9"
"@rolldown/binding-darwin-arm64" "1.0.0-rc.9"
"@rolldown/binding-darwin-x64" "1.0.0-rc.9"
"@rolldown/binding-freebsd-x64" "1.0.0-rc.9"
"@rolldown/binding-linux-arm-gnueabihf" "1.0.0-rc.9"
"@rolldown/binding-linux-arm64-gnu" "1.0.0-rc.9"
"@rolldown/binding-linux-arm64-musl" "1.0.0-rc.9"
"@rolldown/binding-linux-ppc64-gnu" "1.0.0-rc.9"
"@rolldown/binding-linux-s390x-gnu" "1.0.0-rc.9"
"@rolldown/binding-linux-x64-gnu" "1.0.0-rc.9"
"@rolldown/binding-linux-x64-musl" "1.0.0-rc.9"
"@rolldown/binding-openharmony-arm64" "1.0.0-rc.9"
"@rolldown/binding-wasm32-wasi" "1.0.0-rc.9"
"@rolldown/binding-win32-arm64-msvc" "1.0.0-rc.9"
"@rolldown/binding-win32-x64-msvc" "1.0.0-rc.9"
rollup@^4.43.0: rollup@^4.43.0:
version "4.59.0" version "4.59.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/rollup/-/rollup-4.59.0.tgz#cf74edac17c1486f562d728a4d923a694abdf06f" resolved "https://nexus.beatrice.wtf/repository/npm-group/rollup/-/rollup-4.59.0.tgz#cf74edac17c1486f562d728a4d923a694abdf06f"
@@ -4752,9 +4995,9 @@ std-env@^3.10.0:
integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==
storybook@^10.2.10: storybook@^10.2.10:
version "10.2.10" version "10.2.17"
resolved "https://nexus.beatrice.wtf/repository/npm-group/storybook/-/storybook-10.2.10.tgz#b0a008c239690889fc52ae95a35305d4c64b4306" resolved "https://nexus.beatrice.wtf/repository/npm-group/storybook/-/storybook-10.2.17.tgz#32ac551d7c47e9a1d71d4caedabe638fa03bc2ea"
integrity sha512-N4U42qKgzMHS7DjqLz5bY4P7rnvJtYkWFCyKspZr3FhPUuy6CWOae3aYC2BjXkHrdug0Jyta6VxFTuB1tYUKhg== integrity sha512-yueTpl5YJqLzQqs3CanxNdAAfFU23iP0j+JVJURE4ghfEtRmWfWoZWLGkVcyjmgum7UmjwAlqRuOjQDNvH89kw==
dependencies: dependencies:
"@storybook/global" "^5.0.0" "@storybook/global" "^5.0.0"
"@storybook/icons" "^2.0.1" "@storybook/icons" "^2.0.1"
@@ -4976,7 +5219,7 @@ tsconfig-paths@^4.2.0:
minimist "^1.2.6" minimist "^1.2.6"
strip-bom "^3.0.0" strip-bom "^3.0.0"
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.0: tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0:
version "2.8.1" version "2.8.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" resolved "https://nexus.beatrice.wtf/repository/npm-group/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -5131,7 +5374,7 @@ vfile-message@^4.0.0:
"@types/unist" "^3.0.0" "@types/unist" "^3.0.0"
unist-util-stringify-position "^4.0.0" unist-util-stringify-position "^4.0.0"
"vite@^6.0.0 || ^7.0.0", vite@^7.0.0: "vite@^6.0.0 || ^7.0.0":
version "7.3.1" version "7.3.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507" resolved "https://nexus.beatrice.wtf/repository/npm-group/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507"
integrity sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA== integrity sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==
@@ -5145,6 +5388,20 @@ vfile-message@^4.0.0:
optionalDependencies: optionalDependencies:
fsevents "~2.3.3" fsevents "~2.3.3"
vite@^8.0.0:
version "8.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/vite/-/vite-8.0.0.tgz#d749f9bf5be196635982bc16ec0c6faf2b31f3a4"
integrity sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q==
dependencies:
"@oxc-project/runtime" "0.115.0"
lightningcss "^1.32.0"
picomatch "^4.0.3"
postcss "^8.5.8"
rolldown "1.0.0-rc.9"
tinyglobby "^0.2.15"
optionalDependencies:
fsevents "~2.3.3"
vitest@^4.0.18: vitest@^4.0.18:
version "4.0.18" version "4.0.18"
resolved "https://nexus.beatrice.wtf/repository/npm-group/vitest/-/vitest-4.0.18.tgz#56f966353eca0b50f4df7540cd4350ca6d454a05" resolved "https://nexus.beatrice.wtf/repository/npm-group/vitest/-/vitest-4.0.18.tgz#56f966353eca0b50f4df7540cd4350ca6d454a05"