@astryxdesign/core 0.7.2-canary.caec7ca → 0.7.2-canary.cbb7fa3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AspectRatio/AspectRatio.d.ts +6 -8
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +44 -3
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +5 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +3 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +37 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +5 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +20 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +46 -3
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -0
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.js +21 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +15 -4
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +4 -10
- package/dist/Field/Field.d.ts +1 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +8 -4
- package/dist/Grid/GridSpan.d.ts.map +1 -1
- package/dist/Grid/GridSpan.js +1 -0
- package/dist/List/List.d.ts +46 -19
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +28 -10
- package/dist/List/ListContext.d.ts +8 -3
- package/dist/List/ListContext.d.ts.map +1 -1
- package/dist/List/ListContext.js +7 -2
- package/dist/List/ListItem.d.ts +4 -3
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +19 -8
- package/dist/List/index.d.ts +1 -1
- package/dist/List/index.d.ts.map +1 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +8 -1
- package/dist/MetadataList/MetadataList.d.ts.map +1 -1
- package/dist/MetadataList/MetadataList.js +5 -1
- package/dist/MetadataList/MetadataListContext.d.ts +1 -1
- package/dist/MetadataList/MetadataListContext.d.ts.map +1 -1
- package/dist/RadioList/RadioList.d.ts +1 -1
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +6 -2
- package/dist/ToggleButton/ToggleButton.d.ts +3 -2
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +12 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +1 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +2 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +57 -9
- package/dist/astryx.css +16 -3
- package/dist/hooks/useMenuHover.d.ts.map +1 -1
- package/dist/hooks/useMenuHover.js +18 -13
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +15 -9
- package/package.json +3 -3
- package/src/AspectRatio/AspectRatio.test.tsx +44 -43
- package/src/AspectRatio/AspectRatio.tsx +38 -18
- package/src/AspectRatio/__tests__/AspectRatioFitLayers.a11y.browser.spec.ts +157 -0
- package/src/Avatar/Avatar.doc.mjs +5 -3
- package/src/AvatarGroup/AvatarGroup.doc.mjs +3 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +4 -1
- package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +3 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
- package/src/CheckboxInput/CheckboxInput.tsx +3 -1
- package/src/CommandPalette/CommandPaletteInput.test.tsx +53 -4
- package/src/CommandPalette/CommandPaletteInput.tsx +33 -3
- package/src/CommandPalette/__tests__/CommandPaletteInputAudit.a11y.chromium.spec.ts +335 -0
- package/src/ContextMenu/ContextMenu.tsx +4 -1
- package/src/Dialog/Dialog.test.tsx +46 -0
- package/src/Dialog/Dialog.tsx +20 -7
- package/src/Dialog/__tests__/Dialog.a11y.known-failures.ts +0 -14
- package/src/DropdownMenu/DropdownMenu.tsx +45 -2
- package/src/DropdownMenu/DropdownMenuContext.tsx +24 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +185 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +17 -3
- package/src/EmptyState/EmptyState.doc.mjs +3 -2
- package/src/EmptyState/EmptyState.spec.md +189 -0
- package/src/EmptyState/EmptyState.test.tsx +74 -3
- package/src/EmptyState/EmptyState.tsx +4 -8
- package/src/Field/Field.doc.mjs +14 -8
- package/src/Field/Field.spec.md +217 -0
- package/src/Field/Field.test.tsx +60 -2
- package/src/Field/Field.tsx +17 -8
- package/src/Grid/GridSpan.tsx +3 -0
- package/src/Item/Item.doc.mjs +1 -1
- package/src/Item/Item.tsx +1 -1
- package/src/List/List.doc.mjs +14 -1
- package/src/List/List.spec.md +129 -77
- package/src/List/List.test.tsx +144 -94
- package/src/List/List.tsx +74 -18
- package/src/List/ListContext.tsx +9 -3
- package/src/List/ListItem.tsx +46 -26
- package/src/List/index.ts +1 -1
- package/src/Markdown/Markdown.tsx +14 -1
- package/src/MetadataList/MetadataList.doc.mjs +2 -2
- package/src/MetadataList/MetadataList.test.tsx +38 -0
- package/src/MetadataList/MetadataList.tsx +8 -1
- package/src/MetadataList/MetadataListContext.tsx +1 -1
- package/src/RadioList/RadioList.fr10.test.tsx +45 -2
- package/src/RadioList/RadioList.tsx +4 -1
- package/src/Slider/Slider.spec.md +39 -18
- package/src/TabList/TabList.spec.md +57 -44
- package/src/TimeInput/TimeInput.fr10.test.tsx +15 -0
- package/src/ToggleButton/ToggleButton.test.tsx +95 -0
- package/src/ToggleButton/ToggleButton.tsx +12 -1
- package/src/TreeList/TreeList.doc.mjs +1 -0
- package/src/TreeList/TreeList.test.tsx +327 -6
- package/src/TreeList/TreeList.tsx +5 -1
- package/src/TreeList/TreeListBranches.tsx +6 -0
- package/src/TreeList/TreeListItem.tsx +88 -13
- package/src/docPropLiterals.test.ts +36 -10
- package/src/hooks/useMenuHover.ts +18 -13
- package/src/reset.css +0 -29
- package/src/theme/derivedVarRegistry.test.ts +7 -0
- package/src/utils/plainDate.test.ts +37 -1
- package/src/utils/plainDate.ts +15 -5
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
4
4
|
/**
|
|
5
5
|
* @file Guards doc prop types against opaque named unions (#1645).
|
|
6
|
-
* @input Every {Name}.doc.mjs plus the TypeScript sources they describe
|
|
6
|
+
* @input Every {Name}.doc.mjs plus the TypeScript sources they describe,
|
|
7
|
+
* including same-file private aliases used by exported literal unions.
|
|
7
8
|
* @output Fails when a documented prop type hides its legal literal values.
|
|
8
9
|
* @position Repo-wide doc-shape guard, sibling of docPropReferences.test.ts.
|
|
9
10
|
*
|
|
@@ -188,18 +189,34 @@ for (const file of findFiles(SRC_DIR, ['.ts', '.tsx'])) {
|
|
|
188
189
|
// markers the comment-stripped `src` has already removed.
|
|
189
190
|
const rawTypeRhs = new Map<string, string>();
|
|
190
191
|
for (const m of raw.matchAll(
|
|
191
|
-
|
|
192
|
+
/\btype ([A-Z][A-Za-z0-9]*)(?:<[^>]*>)?\s*=\s*([^;]+);/g,
|
|
192
193
|
)) {
|
|
193
194
|
rawTypeRhs.set(m[1], m[2]);
|
|
194
195
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
196
|
+
const declarations = [
|
|
197
|
+
...src.matchAll(
|
|
198
|
+
/\b(export )?type ([A-Z][A-Za-z0-9]*)(?:<[^>]*>)?\s*=\s*([^;]+);/g,
|
|
199
|
+
),
|
|
200
|
+
];
|
|
201
|
+
// Resolve same-file literal aliases before registering exported types.
|
|
202
|
+
// Repeat until no new literal unions are found.
|
|
203
|
+
const fileLiterals = new Map<string, string>();
|
|
204
|
+
let previousSize: number;
|
|
205
|
+
do {
|
|
206
|
+
previousSize = fileLiterals.size;
|
|
207
|
+
for (const [, , name, rhsRaw] of declarations) {
|
|
208
|
+
const rhs = rhsRaw
|
|
209
|
+
.replace(/\s+/g, ' ')
|
|
210
|
+
.trim()
|
|
211
|
+
.split('|')
|
|
212
|
+
.map(part => fileLiterals.get(part.trim()) ?? part.trim())
|
|
213
|
+
.join(' | ');
|
|
214
|
+
|
|
215
|
+
if (!LITERAL_UNION.test(rhs)) {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
201
218
|
const deprecated = deprecatedLiteralMembers(rawTypeRhs.get(name) ?? '');
|
|
202
|
-
|
|
219
|
+
fileLiterals.set(
|
|
203
220
|
name,
|
|
204
221
|
rhs
|
|
205
222
|
.replace(/^\|\s*/, '')
|
|
@@ -209,8 +226,17 @@ for (const file of findFiles(SRC_DIR, ['.ts', '.tsx'])) {
|
|
|
209
226
|
.filter(member => !deprecated.has(member))
|
|
210
227
|
.join(' | '),
|
|
211
228
|
);
|
|
229
|
+
}
|
|
230
|
+
} while (fileLiterals.size !== previousSize);
|
|
231
|
+
for (const [, exported, name, rhsRaw] of declarations) {
|
|
232
|
+
if (!exported) {
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const literals = fileLiterals.get(name);
|
|
236
|
+
if (literals !== undefined) {
|
|
237
|
+
literalUnions.set(name, literals);
|
|
212
238
|
} else {
|
|
213
|
-
namedBodies.set(name,
|
|
239
|
+
namedBodies.set(name, rhsRaw.replace(/\s+/g, ' ').trim());
|
|
214
240
|
}
|
|
215
241
|
}
|
|
216
242
|
for (const m of src.matchAll(
|
|
@@ -230,19 +230,6 @@ export function useMenuHover<T extends HTMLElement = HTMLElement>(
|
|
|
230
230
|
const hoverOpenedAtRef = useRef(0);
|
|
231
231
|
const prevIsOpenRef = useRef(isOpen);
|
|
232
232
|
|
|
233
|
-
// Catches every close, whatever caused it. A layout effect, not render: it
|
|
234
|
-
// must land before the browser hit-tests the vanished panel and fires the
|
|
235
|
-
// mouseenter REOPEN_SUPPRESS_MS exists to swallow.
|
|
236
|
-
useIsomorphicLayoutEffect(() => {
|
|
237
|
-
const wasOpen = prevIsOpenRef.current;
|
|
238
|
-
prevIsOpenRef.current = isOpen;
|
|
239
|
-
if (wasOpen && !isOpen) {
|
|
240
|
-
hoverModeRef.current = false;
|
|
241
|
-
hoverOpenedAtRef.current = 0;
|
|
242
|
-
closedAtRef.current = Date.now();
|
|
243
|
-
}
|
|
244
|
-
}, [isOpen]);
|
|
245
|
-
|
|
246
233
|
const clearTimeouts = useCallback(() => {
|
|
247
234
|
if (showTimerRef.current) {
|
|
248
235
|
clearTimeout(showTimerRef.current);
|
|
@@ -256,6 +243,24 @@ export function useMenuHover<T extends HTMLElement = HTMLElement>(
|
|
|
256
243
|
safeTriangleCleanupRef.current = null;
|
|
257
244
|
}, []);
|
|
258
245
|
|
|
246
|
+
// Catches every close, whatever caused it. A layout effect, not render: it
|
|
247
|
+
// must land before the browser hit-tests the vanished panel and fires the
|
|
248
|
+
// mouseenter REOPEN_SUPPRESS_MS exists to swallow.
|
|
249
|
+
useIsomorphicLayoutEffect(() => {
|
|
250
|
+
const wasOpen = prevIsOpenRef.current;
|
|
251
|
+
prevIsOpenRef.current = isOpen;
|
|
252
|
+
if (wasOpen && !isOpen) {
|
|
253
|
+
// A hover-open scheduled before the close must not fire afterwards and
|
|
254
|
+
// reopen what just closed from elsewhere — e.g. the root menu's light
|
|
255
|
+
// dismiss closing a submenu flyout mid hover-intent (#6893). A fresh
|
|
256
|
+
// mouseenter still opens; only the stale timer is cancelled.
|
|
257
|
+
clearTimeouts();
|
|
258
|
+
hoverModeRef.current = false;
|
|
259
|
+
hoverOpenedAtRef.current = 0;
|
|
260
|
+
closedAtRef.current = Date.now();
|
|
261
|
+
}
|
|
262
|
+
}, [isOpen, clearTimeouts]);
|
|
263
|
+
|
|
259
264
|
// useListFocus needs an onEscape that is defined in terms of its own listRef;
|
|
260
265
|
// the indirection avoids the use-before-declare.
|
|
261
266
|
const escapeHandlerRef = useRef<() => void>(() => {});
|
package/src/reset.css
CHANGED
|
@@ -203,35 +203,6 @@
|
|
|
203
203
|
height: auto;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
/* ===========================================================================
|
|
207
|
-
AspectRatio Fit Baseline
|
|
208
|
-
=========================================================================== */
|
|
209
|
-
|
|
210
|
-
/*
|
|
211
|
-
* Child sizing for AspectRatio's `fit` prop — the component marks the
|
|
212
|
-
* child's direct parent with `data-astryx-aspect-ratio-override` (carrying
|
|
213
|
-
* the fit value), and these direct-child rules size the child, so
|
|
214
|
-
* consumers don't hand-write width/height/object-fit on every media child.
|
|
215
|
-
* The marker sits on the parent itself, so the rules don't depend on
|
|
216
|
-
* AspectRatio's internal element structure or its theming surface. As with
|
|
217
|
-
* the [data-astryx-media] baseline below, the rules are zero-specificity
|
|
218
|
-
* and any styling the child sets itself still wins. `fit="center"` needs
|
|
219
|
-
* no rules here — the component centers the child from its own wrapper.
|
|
220
|
-
*/
|
|
221
|
-
:where([data-astryx-aspect-ratio-override="cover"], [data-astryx-aspect-ratio-override="contain"])
|
|
222
|
-
> :where(*) {
|
|
223
|
-
width: 100%;
|
|
224
|
-
height: 100%;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
:where([data-astryx-aspect-ratio-override="cover"]) > :where(img, video) {
|
|
228
|
-
object-fit: cover;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
:where([data-astryx-aspect-ratio-override="contain"]) > :where(img, video) {
|
|
232
|
-
object-fit: contain;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
206
|
/* ===========================================================================
|
|
236
207
|
Forms
|
|
237
208
|
=========================================================================== */
|
|
@@ -261,6 +261,9 @@ const CROSS_COMPONENT_VARS: Record<string, string[]> = {
|
|
|
261
261
|
// The destructive item variant recolors the Item it renders; Item owns,
|
|
262
262
|
// documents and reads both slots.
|
|
263
263
|
DropdownMenu: ['--_item-label-color', '--_item-description-color'],
|
|
264
|
+
// List's edge="flush" zeroes the inline inset of the Item each ListItem
|
|
265
|
+
// renders; Item owns, documents and reads it.
|
|
266
|
+
List: ['--_item-inset-inline'],
|
|
264
267
|
// A layer content root stops an outer Stepper's connector gap; Stepper owns,
|
|
265
268
|
// documents and reads it.
|
|
266
269
|
Layer: ['--step-connector-gap'],
|
|
@@ -316,6 +319,10 @@ const VARS_WITHOUT_DERIVED_MAPPING = new Set([
|
|
|
316
319
|
'--tree-list-indent',
|
|
317
320
|
'--_tree-indent',
|
|
318
321
|
'--tree-list-row-gap',
|
|
322
|
+
// Published by each treeitem while it has keyboard focus and read as its
|
|
323
|
+
// row's z-index, so the focused row paints above the guide lines. Focus
|
|
324
|
+
// state, not a value a theme author sets.
|
|
325
|
+
'--_tree-focus-z',
|
|
319
326
|
// Clipped on the ONE side each on-track connector segment faces the
|
|
320
327
|
// indicator from — trailing above the node, leading below it, mirrored
|
|
321
328
|
// again per axis. No standard property maps onto this purpose-based seam:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
|
-
import {describe, it, expect} from 'vitest';
|
|
3
|
+
import {describe, it, expect, afterEach} from 'vitest';
|
|
4
4
|
import {
|
|
5
5
|
type PlainDate,
|
|
6
6
|
plainDateCreate,
|
|
@@ -711,6 +711,42 @@ describe('plainDateGetWeekNumber', () => {
|
|
|
711
711
|
expect(plainDateGetWeekNumber({year: 2026, month: 1, day: 4})).toBe(1);
|
|
712
712
|
});
|
|
713
713
|
|
|
714
|
+
// Regression: the week number must not depend on the host timezone's DST
|
|
715
|
+
// offset. Zones whose DST ends after New Year (southern hemisphere) used to
|
|
716
|
+
// add a phantom hour to the Thursday-vs-Jan-1 day count, and in years whose
|
|
717
|
+
// Jan 1 is a Friday that hour rounded a whole week up.
|
|
718
|
+
describe('DST independence', () => {
|
|
719
|
+
const originalTZ = process.env.TZ;
|
|
720
|
+
|
|
721
|
+
afterEach(() => {
|
|
722
|
+
if (originalTZ === undefined) {
|
|
723
|
+
delete process.env.TZ;
|
|
724
|
+
} else {
|
|
725
|
+
process.env.TZ = originalTZ;
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
it.each(['Australia/Sydney', 'Pacific/Auckland', 'America/Santiago'])(
|
|
730
|
+
'does not round week 14 up to 15 in %s (DST ends after New Year)',
|
|
731
|
+
zone => {
|
|
732
|
+
process.env.TZ = zone;
|
|
733
|
+
// 2021-01-01 is a Friday, so every ISO Thursday falls on a whole
|
|
734
|
+
// multiple of 7 days into the year. 2021-04-05..11 is ISO week 14.
|
|
735
|
+
expect(plainDateGetWeekNumber({year: 2021, month: 4, day: 5})).toBe(14);
|
|
736
|
+
expect(plainDateGetWeekNumber({year: 2021, month: 4, day: 8})).toBe(14);
|
|
737
|
+
expect(plainDateGetWeekNumber({year: 2021, month: 4, day: 11})).toBe(
|
|
738
|
+
14,
|
|
739
|
+
);
|
|
740
|
+
},
|
|
741
|
+
);
|
|
742
|
+
|
|
743
|
+
it('keeps late-December weeks correct in Australia/Sydney', () => {
|
|
744
|
+
process.env.TZ = 'Australia/Sydney';
|
|
745
|
+
// 2027-12-30 (Thursday) is ISO week 52, not 53.
|
|
746
|
+
expect(plainDateGetWeekNumber({year: 2027, month: 12, day: 30})).toBe(52);
|
|
747
|
+
});
|
|
748
|
+
});
|
|
749
|
+
|
|
714
750
|
it('keeps years 1-99 instead of mapping them to 1900-1999', () => {
|
|
715
751
|
// 0004-01-01 is a Thursday (ISO week 1); 1904-01-01 was a Friday.
|
|
716
752
|
expect(plainDateGetWeekNumber({year: 4, month: 1, day: 1})).toBe(1);
|
package/src/utils/plainDate.ts
CHANGED
|
@@ -282,11 +282,21 @@ export function plainDateSetEndOfWeekExclusive(
|
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
export function plainDateGetWeekNumber(pd: PlainDate): number {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
285
|
+
// ISO week number: ceil(day-of-year of the week's Thursday / 7). Computed
|
|
286
|
+
// entirely on UTC anchors — the same DST immunity plainDateDiffDays relies
|
|
287
|
+
// on — because mixing local-time instants leaks the host zone's DST offset
|
|
288
|
+
// into the day count. When Jan 1 is a Friday (so every Thursday's day-of-year
|
|
289
|
+
// is an exact multiple of 7), a one-hour offset from a zone whose DST ends
|
|
290
|
+
// after New Year rounds a whole week up: Sydney, Auckland and Santiago users
|
|
291
|
+
// saw week 15 for the week that is ISO week 14. utcTime keeps years 1-99
|
|
292
|
+
// as given, like the other Calendar date helpers.
|
|
293
|
+
const msPerDay = 24 * 60 * 60 * 1000;
|
|
294
|
+
const utcMidnight = utcTime(pd.year, pd.month - 1, pd.day);
|
|
295
|
+
const dayNum = new Date(utcMidnight).getUTCDay() || 7;
|
|
296
|
+
const thursday = utcMidnight + (4 - dayNum) * msPerDay;
|
|
297
|
+
const yearStart = utcTime(new Date(thursday).getUTCFullYear(), 0, 1);
|
|
298
|
+
const dayOfYear = (thursday - yearStart) / msPerDay + 1;
|
|
299
|
+
return Math.ceil(dayOfYear / 7);
|
|
290
300
|
}
|
|
291
301
|
|
|
292
302
|
// e.g. "Wednesday, May 21, 2026" (locale-dependent)
|