@astryxdesign/core 0.7.2 → 0.7.3-canary.0bf23bd
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/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +8 -4
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +7 -0
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +19 -24
- package/dist/ClickableCard/ClickableCard.d.ts +2 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +11 -9
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +11 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +23 -5
- package/dist/DateInput/DateInput.d.ts +4 -4
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +27 -20
- package/dist/DateInput/NativeDateField.d.ts.map +1 -1
- package/dist/DateInput/NativeDateField.js +14 -8
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +14 -10
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +9 -4
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +52 -10
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +34 -1
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.js +15 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +21 -2
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +375 -42
- package/dist/DropdownMenu/menuRegionStops.d.ts +2 -2
- package/dist/DropdownMenu/menuRegionStops.js +2 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +14 -12
- package/dist/Link/Link.d.ts +2 -3
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +11 -19
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +48 -15
- package/dist/MultiSelector/MultiSelector.d.ts +4 -4
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.d.ts +2 -0
- package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.d.ts.map +1 -0
- package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.js +48 -0
- package/dist/MultiSelector/MultiSelector.js +25 -18
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +8 -4
- package/dist/Selector/Selector.d.ts +4 -4
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +23 -14
- package/dist/Selector/SelectorOption.d.ts.map +1 -1
- package/dist/Selector/SelectorOption.js +1 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +7 -14
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +25 -17
- package/dist/Switch/switch.markers.stylex.d.ts +2 -0
- package/dist/Switch/switch.markers.stylex.d.ts.map +1 -1
- package/dist/Switch/switch.markers.stylex.js +6 -0
- package/dist/TimeInput/TimeInput.d.ts +2 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +8 -3
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/Tooltip.js +36 -14
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +11 -2
- package/dist/TopNav/TopNav.d.ts.map +1 -1
- package/dist/TopNav/TopNav.js +2 -2
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +1 -0
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +14 -2
- package/dist/astryx.css +8 -2
- package/dist/hooks/useMenuPress.d.ts +11 -1
- package/dist/hooks/useMenuPress.d.ts.map +1 -1
- package/dist/hooks/useMenuPress.js +43 -5
- package/dist/utils/disabledInteraction.d.ts +21 -0
- package/dist/utils/disabledInteraction.d.ts.map +1 -0
- package/dist/utils/disabledInteraction.js +33 -0
- package/dist/utils/timeParser.d.ts +4 -0
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +9 -2
- package/package.json +4 -4
- package/scripts/agent-doc-state.mjs +35 -8
- package/src/Banner/Banner.spec.md +37 -32
- package/src/BottomSheet/BottomSheet.spec.md +13 -6
- package/src/BottomSheet/BottomSheet.test.tsx +29 -0
- package/src/BottomSheet/BottomSheet.tsx +8 -4
- package/src/BottomSheet/BottomSheetSwitcher.spec.md +121 -51
- package/src/BottomSheet/BottomSheetSwitcher.test.tsx +26 -0
- package/src/BottomSheet/BottomSheetSwitcher.tsx +6 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +44 -5
- package/src/CheckboxInput/CheckboxInput.tsx +16 -26
- package/src/CheckboxInput/__tests__/Checkbox.a11y.states.ts +3 -3
- package/src/CheckboxList/CheckboxList.test.tsx +9 -6
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
- package/src/ClickableCard/ClickableCard.test.tsx +5 -4
- package/src/ClickableCard/ClickableCard.tsx +9 -9
- package/src/CodeBlock/CodeBlock.highlightStyles.test.tsx +87 -0
- package/src/CodeBlock/CodeBlock.tsx +11 -1
- package/src/ComplexSelector/ComplexSelector.focusableDisabled.test.tsx +76 -0
- package/src/ComplexSelector/ComplexSelector.tsx +21 -4
- package/src/ContextMenu/ContextMenu.test.tsx +41 -0
- package/src/DateInput/DateInput.doc.mjs +9 -8
- package/src/DateInput/DateInput.test.tsx +88 -13
- package/src/DateInput/DateInput.tsx +49 -21
- package/src/DateInput/DateInputTouch.test.tsx +22 -1
- package/src/DateInput/NativeDateField.test.tsx +29 -3
- package/src/DateInput/NativeDateField.tsx +20 -7
- package/src/DateInput/TouchDateField.tsx +24 -9
- package/src/DateRangeInput/DateRangeInput.spec.md +13 -13
- package/src/Dialog/Dialog.test.tsx +39 -0
- package/src/Dialog/Dialog.tsx +9 -4
- package/src/DropdownMenu/DropdownMenu.spec.md +33 -2
- package/src/DropdownMenu/DropdownMenu.tsx +79 -8
- package/src/DropdownMenu/DropdownMenuContext.public.test.ts +22 -0
- package/src/DropdownMenu/DropdownMenuContext.tsx +39 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +16 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +623 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +556 -99
- package/src/DropdownMenu/__tests__/SubMenuHeaderFooter.a11y.chromium.spec.ts +267 -0
- package/src/DropdownMenu/menuRegionStops.ts +2 -2
- package/src/DropdownMenu/modules/useMenuPress.spec.md +9 -0
- package/src/FieldStatus/FieldStatus.spec.md +3 -2
- package/src/FileInput/FileInput.test.tsx +30 -7
- package/src/FileInput/FileInput.tsx +21 -11
- package/src/Link/Link.test.tsx +21 -7
- package/src/Link/Link.tsx +16 -24
- package/src/Link/__tests__/Link.a11y.states.ts +1 -1
- package/src/Markdown/Markdown.rerender.test.tsx +143 -0
- package/src/Markdown/Markdown.tsx +89 -35
- package/src/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.ts +71 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +5 -5
- package/src/MultiSelector/MultiSelector.focusableDisabled.test.tsx +121 -0
- package/src/MultiSelector/MultiSelector.test.tsx +49 -7
- package/src/MultiSelector/MultiSelector.tsx +53 -29
- package/src/Popover/Popover.test.tsx +15 -0
- package/src/Popover/Popover.tsx +19 -8
- package/src/PowerSearch/PowerSearchFilterEditor.test.tsx +3 -2
- package/src/PowerSearch/PowerSearchToken.test.tsx +7 -5
- package/src/Selector/Selector.doc.mjs +4 -4
- package/src/Selector/Selector.focusableDisabled.test.tsx +127 -0
- package/src/Selector/Selector.spec.md +11 -11
- package/src/Selector/Selector.test.tsx +64 -6
- package/src/Selector/Selector.tsx +51 -21
- package/src/Selector/SelectorOption.tsx +4 -0
- package/src/SideNav/SideNav.test.tsx +35 -0
- package/src/Slider/Slider.spec.md +11 -11
- package/src/Slider/Slider.test.tsx +3 -3
- package/src/Slider/Slider.tsx +8 -15
- package/src/Switch/Switch.test.tsx +85 -8
- package/src/Switch/Switch.tsx +26 -16
- package/src/Switch/__tests__/Switch.a11y.states.ts +2 -2
- package/src/Switch/switch.markers.stylex.ts +4 -0
- package/src/Table/Table.spec.md +2 -0
- package/src/Table/plugins/infiniteScroll/useTableInfiniteScroll.spec.md +244 -0
- package/src/Table/plugins/selection/useTableSelection.test.tsx +5 -3
- package/src/Table/plugins/virtualization/useTableVirtualization.spec.md +266 -0
- package/src/TimeInput/TimeInput.doc.mjs +5 -3
- package/src/TimeInput/TimeInput.test.tsx +20 -0
- package/src/TimeInput/TimeInput.tsx +2 -1
- package/src/Token/Token.test.tsx +26 -4
- package/src/Token/Token.tsx +6 -2
- package/src/Tokenizer/Tokenizer.spec.md +28 -28
- package/src/Tooltip/Tooltip.test.tsx +51 -6
- package/src/Tooltip/Tooltip.tsx +41 -18
- package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +129 -0
- package/src/Tooltip/__tests__/Tooltip.a11y.renders.tsx +86 -0
- package/src/Tooltip/__tests__/Tooltip.a11y.states.ts +132 -0
- package/src/Tooltip/__tests__/Tooltip.a11y.test.tsx +126 -0
- package/src/Tooltip/__tests__/TooltipHoverBridge.a11y.chromium.spec.ts +74 -0
- package/src/Tooltip/useTooltip.test.tsx +23 -0
- package/src/Tooltip/useTooltip.tsx +22 -9
- package/src/TopNav/TopNav.tsx +11 -1
- package/src/TopNav/TopNavHeading.tsx +1 -0
- package/src/TopNav/__tests__/TopNavMobileLongHeading.a11y.chromium.spec.ts +74 -0
- package/src/Typeahead/Typeahead.test.tsx +89 -0
- package/src/Typeahead/Typeahead.tsx +15 -2
- package/src/hooks/useMenuPress.ts +45 -7
- package/src/utils/disabledInteraction.ts +40 -0
- package/src/utils/timeParser.test.ts +11 -0
- package/src/utils/timeParser.ts +9 -2
|
@@ -36,7 +36,9 @@
|
|
|
36
36
|
*
|
|
37
37
|
* The menu root is marked `data-astryx-menu-press` so a nested flyout (a DOM
|
|
38
38
|
* descendant of its parent menu) can tell which level owns a press, and so a
|
|
39
|
-
* surface can be recognised as carrying this model.
|
|
39
|
+
* surface can be recognised as carrying this model. A menu the root renders
|
|
40
|
+
* beside itself names the root with `data-astryx-menu-press-surface` and counts
|
|
41
|
+
* as nested in it.
|
|
40
42
|
*
|
|
41
43
|
* SYNC: When modified, update:
|
|
42
44
|
* - /packages/core/src/hooks/index.ts
|
|
@@ -60,6 +62,14 @@ import {useLongPress, type UseLongPressHandlers} from './useLongPress';
|
|
|
60
62
|
/** Marks a menu root that carries this press model. */
|
|
61
63
|
export const MENU_PRESS_MARKER = 'data-astryx-menu-press';
|
|
62
64
|
const MENU_PRESS_ROOT_SELECTOR = `[${MENU_PRESS_MARKER}]`;
|
|
65
|
+
/**
|
|
66
|
+
* Carried by a menu root that another root renders beside itself rather than
|
|
67
|
+
* inside it, naming that root's `id`: the menu of a sub-menu with a header or
|
|
68
|
+
* footer, in a dialog beside the root's menu, is nested in that root for the
|
|
69
|
+
* press model, as a flyout inside the root's DOM is. Nothing else beside the
|
|
70
|
+
* root carries it, so a picker placed in a header or footer stays its own root.
|
|
71
|
+
*/
|
|
72
|
+
export const MENU_PRESS_SURFACE_ATTR = 'data-astryx-menu-press-surface';
|
|
63
73
|
|
|
64
74
|
/** How long after a tracked release the browser's click is still swallowed. */
|
|
65
75
|
export const MENU_PRESS_STRAY_CLICK_MS = 400;
|
|
@@ -246,16 +256,44 @@ function isRowFocusable(row: HTMLElement): boolean {
|
|
|
246
256
|
function getOutermostRoot(menu: HTMLElement): HTMLElement {
|
|
247
257
|
let root = menu;
|
|
248
258
|
for (;;) {
|
|
249
|
-
const parent =
|
|
250
|
-
MENU_PRESS_ROOT_SELECTOR
|
|
251
|
-
|
|
252
|
-
if (parent == null) {
|
|
259
|
+
const parent =
|
|
260
|
+
root.parentElement?.closest<HTMLElement>(MENU_PRESS_ROOT_SELECTOR) ??
|
|
261
|
+
getSurfaceOwner(root);
|
|
262
|
+
if (parent == null || parent === root) {
|
|
253
263
|
return root;
|
|
254
264
|
}
|
|
255
265
|
root = parent;
|
|
256
266
|
}
|
|
257
267
|
}
|
|
258
268
|
|
|
269
|
+
/**
|
|
270
|
+
* The menu root that renders `menu` beside itself, if any (see
|
|
271
|
+
* `MENU_PRESS_SURFACE_ATTR`). Read off the menu itself, never an ancestor, so
|
|
272
|
+
* a root placed in a region of that surface is not adopted.
|
|
273
|
+
*/
|
|
274
|
+
function getSurfaceOwner(menu: HTMLElement): HTMLElement | null {
|
|
275
|
+
const ownerId = menu.getAttribute(MENU_PRESS_SURFACE_ATTR);
|
|
276
|
+
if (!ownerId) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
const owner = menu.ownerDocument.getElementById(ownerId);
|
|
280
|
+
return owner?.matches(MENU_PRESS_ROOT_SELECTOR) === true ? owner : null;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Whether `element` is inside the menu tree whose outermost root is `root`:
|
|
285
|
+
* inside the root itself, or inside a menu nested in it through a surface
|
|
286
|
+
* the root renders beside itself. Anything else in such a surface (a header
|
|
287
|
+
* field, say) is outside the menu, as the root's own regions are.
|
|
288
|
+
*/
|
|
289
|
+
function isInMenuTree(element: Element, root: HTMLElement): boolean {
|
|
290
|
+
if (root.contains(element)) {
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
const owner = element.closest<HTMLElement>(MENU_PRESS_ROOT_SELECTOR);
|
|
294
|
+
return owner != null && getOutermostRoot(owner) === root;
|
|
295
|
+
}
|
|
296
|
+
|
|
259
297
|
interface ResolvedPoint {
|
|
260
298
|
row: HTMLElement | null;
|
|
261
299
|
isInMenu: boolean;
|
|
@@ -332,14 +370,14 @@ export function useMenuPress(options: UseMenuPressOptions): UseMenuPressReturn {
|
|
|
332
370
|
}
|
|
333
371
|
const root = menu == null ? null : getOutermostRoot(menu);
|
|
334
372
|
const isInMenu =
|
|
335
|
-
root != null && element != null &&
|
|
373
|
+
root != null && element != null && isInMenuTree(element, root);
|
|
336
374
|
const trigger = triggerRef?.current ?? null;
|
|
337
375
|
const isOnTrigger =
|
|
338
376
|
trigger != null && element != null && trigger.contains(element);
|
|
339
377
|
let row: HTMLElement | null = null;
|
|
340
378
|
if (isInMenu && element != null) {
|
|
341
379
|
row = element.closest<HTMLElement>(itemSelector);
|
|
342
|
-
if (row != null && !
|
|
380
|
+
if (row != null && !isInMenuTree(row, root)) {
|
|
343
381
|
row = null;
|
|
344
382
|
}
|
|
345
383
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file disabledInteraction.ts
|
|
5
|
+
* @input An optional caller keydown handler
|
|
6
|
+
* @output Event props that keep a focusable, aria-disabled control inert
|
|
7
|
+
* @position Shared by controls that replace native `disabled` with
|
|
8
|
+
* `aria-disabled` under spec:AST-085 (FR1, FR2)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {KeyboardEvent, KeyboardEventHandler, MouseEvent} from 'react';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Event props for a disabled control that stays focusable. Native `disabled`
|
|
15
|
+
* dispatched no click at all; without it, Enter and Space still synthesize a
|
|
16
|
+
* click that native listeners on the element (a wrapping Popover's trigger)
|
|
17
|
+
* receive. Cancelling those keys keeps the click from existing, and the click
|
|
18
|
+
* handler cancels pointer clicks and keeps them from reaching ancestors. Other
|
|
19
|
+
* keys still reach the caller's handler.
|
|
20
|
+
*/
|
|
21
|
+
export function disabledInteractionProps<T extends HTMLElement>(
|
|
22
|
+
onKeyDown?: KeyboardEventHandler<T>,
|
|
23
|
+
): {
|
|
24
|
+
onClick: (event: MouseEvent<T>) => void;
|
|
25
|
+
onKeyDown: (event: KeyboardEvent<T>) => void;
|
|
26
|
+
} {
|
|
27
|
+
return {
|
|
28
|
+
onClick: event => {
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
event.stopPropagation();
|
|
31
|
+
},
|
|
32
|
+
onKeyDown: event => {
|
|
33
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
} else {
|
|
36
|
+
onKeyDown?.(event);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -260,6 +260,17 @@ describe('adjustTime', () => {
|
|
|
260
260
|
expect(adjustTime('10:00' as ISOTimeString, NaN)).toBe('10:00');
|
|
261
261
|
});
|
|
262
262
|
|
|
263
|
+
it('returns the input unchanged for a fractional delta', () => {
|
|
264
|
+
// `increment` is documented as minutes and typed `number`, so a caller can
|
|
265
|
+
// hand ArrowUp a fraction. A fractional minute reaching formatISOTime is
|
|
266
|
+
// not rounded: it pads to "30.5" and the field is left holding a string
|
|
267
|
+
// that is no longer a parseable time.
|
|
268
|
+
expect(adjustTime('10:30' as ISOTimeString, 0.5)).toBe('10:30');
|
|
269
|
+
expect(adjustTime('10:30:45' as ISOTimeString, -0.5, true)).toBe(
|
|
270
|
+
'10:30:45',
|
|
271
|
+
);
|
|
272
|
+
});
|
|
273
|
+
|
|
263
274
|
it('wraps large negative deltas in constant time', () => {
|
|
264
275
|
expect(adjustTime('10:00' as ISOTimeString, -1440 * 1e7)).toBe('10:00');
|
|
265
276
|
expect(adjustTime('10:00' as ISOTimeString, -1440 * 1e7 - 30)).toBe(
|
package/src/utils/timeParser.ts
CHANGED
|
@@ -372,6 +372,10 @@ export function clampTime(
|
|
|
372
372
|
|
|
373
373
|
/**
|
|
374
374
|
* Adjusts a time by adding/subtracting minutes.
|
|
375
|
+
*
|
|
376
|
+
* `deltaMinutes` is a whole number of minutes. A fractional delta leaves the
|
|
377
|
+
* time unchanged rather than returning a value that is no longer a time —
|
|
378
|
+
* `HH:MM` has no place for a fraction of a minute.
|
|
375
379
|
*/
|
|
376
380
|
export function adjustTime(
|
|
377
381
|
time: ISOTimeString,
|
|
@@ -384,8 +388,11 @@ export function adjustTime(
|
|
|
384
388
|
}
|
|
385
389
|
|
|
386
390
|
// A non-finite delta would spin the wrap-around forever (-Infinity) or
|
|
387
|
-
// produce "NaN:NaN" (NaN)
|
|
388
|
-
|
|
391
|
+
// produce "NaN:NaN" (NaN), and a fractional one is never rounded on the way
|
|
392
|
+
// out — formatISOTime pads "30.5" to two characters and leaves it, so the
|
|
393
|
+
// caller gets back a value that is no longer a time. Steps are whole
|
|
394
|
+
// minutes: return the input unchanged instead.
|
|
395
|
+
if (!Number.isInteger(deltaMinutes)) {
|
|
389
396
|
return time;
|
|
390
397
|
}
|
|
391
398
|
|