@astryxdesign/core 0.1.7-canary.fb9c68c → 0.1.7
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/README.md +15 -24
- package/dist/Collapsible/Collapsible.d.ts +1 -11
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +4 -36
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +3 -4
- package/dist/ContextMenu/index.d.ts +0 -3
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +1 -7
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +4 -8
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +1 -17
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.js +0 -18
- package/dist/DropdownMenu/index.d.ts +1 -5
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +1 -10
- package/dist/Icon/Icon.d.ts +12 -17
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +20 -28
- package/dist/Outline/Outline.d.ts +3 -69
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +26 -129
- package/dist/Outline/useScrollSpy.d.ts +7 -27
- package/dist/Outline/useScrollSpy.d.ts.map +1 -1
- package/dist/Outline/useScrollSpy.js +70 -202
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +0 -2
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/index.d.ts +0 -2
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +0 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +2 -24
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +7 -18
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +3 -6
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +1 -8
- package/dist/astryx.css +2 -18
- package/dist/astryx.umd.js +48 -48
- package/dist/astryx.umd.js.map +4 -4
- package/dist/theme/Theme.js +1 -1
- package/dist/theme/defineTheme.d.ts +1 -1
- package/dist/theme/defineTheme.js +1 -1
- package/dist/theme/hct.d.ts +1 -0
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +3 -0
- package/locales/en.json +0 -28
- package/locales/pseudo.json +0 -21
- package/package.json +1 -3
- package/src/CheckboxInput/CheckboxInput.doc.mjs +1 -1
- package/src/Collapsible/Collapsible.doc.mjs +0 -7
- package/src/Collapsible/Collapsible.test.tsx +0 -80
- package/src/Collapsible/Collapsible.tsx +5 -58
- package/src/ContextMenu/ContextMenu.test.tsx +1 -75
- package/src/ContextMenu/ContextMenu.tsx +5 -10
- package/src/ContextMenu/index.ts +0 -15
- package/src/DropdownMenu/DropdownMenu.doc.mjs +0 -23
- package/src/DropdownMenu/DropdownMenu.tsx +6 -11
- package/src/DropdownMenu/DropdownMenuContext.tsx +1 -29
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +1 -7
- package/src/DropdownMenu/index.ts +3 -23
- package/src/Field/Field.doc.mjs +1 -1
- package/src/Field/FieldLabel.doc.mjs +1 -1
- package/src/Icon/Icon.test.tsx +0 -46
- package/src/Icon/Icon.tsx +24 -37
- package/src/NumberInput/NumberInput.doc.mjs +2 -2
- package/src/Outline/Outline.doc.mjs +3 -123
- package/src/Outline/Outline.test.tsx +0 -735
- package/src/Outline/Outline.tsx +33 -184
- package/src/Outline/useScrollSpy.ts +72 -248
- package/src/Selector/SelectorOption.doc.mjs +1 -1
- package/src/SideNav/SideNavItem.doc.mjs +2 -2
- package/src/Switch/Switch.doc.mjs +1 -1
- package/src/TabList/Tab.tsx +1 -5
- package/src/TabList/TabList.doc.mjs +3 -3
- package/src/TabList/TabList.test.tsx +0 -66
- package/src/TabList/TabList.tsx +0 -8
- package/src/TabList/TabMenu.tsx +1 -4
- package/src/Table/Table.doc.mjs +0 -2
- package/src/Table/index.ts +0 -7
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +1 -90
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +5 -37
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +9 -95
- package/src/Table/plugins/sortable/useTableSortable.tsx +7 -23
- package/src/Table/useBaseTablePlugins.ts +2 -6
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/Toolbar/Toolbar.tsx +3 -10
- package/src/theme/Theme.doc.mjs +4 -4
- package/src/theme/Theme.tsx +1 -1
- package/src/theme/defineTheme.ts +1 -1
- package/src/theme/hct.ts +4 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +0 -89
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +0 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +0 -170
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +0 -69
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +0 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +0 -70
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +0 -69
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +0 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +0 -178
- package/dist/DropdownMenu/menuItemRoles.d.ts +0 -13
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +0 -1
- package/dist/DropdownMenu/menuItemRoles.js +0 -15
- package/dist/Table/plugins/tree/index.d.ts +0 -5
- package/dist/Table/plugins/tree/index.d.ts.map +0 -1
- package/dist/Table/plugins/tree/index.js +0 -4
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +0 -38
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +0 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +0 -358
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +0 -51
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +0 -1
- package/dist/Table/plugins/tree/useTableTreeState.js +0 -175
- package/scripts/postinstall.mjs +0 -93
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +0 -95
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +0 -237
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +0 -80
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +0 -119
- package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +0 -80
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +0 -232
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +0 -163
- package/src/DropdownMenu/menuItemRoles.ts +0 -22
- package/src/Table/plugins/tree/index.ts +0 -12
- package/src/Table/plugins/tree/useTableTreeData-perf.test.tsx +0 -163
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +0 -594
- package/src/Table/plugins/tree/useTableTreeData.tsx +0 -495
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +0 -636
- package/src/Table/plugins/tree/useTableTreeState.tsx +0 -253
- package/src/Table/useTableTreeData.doc.mjs +0 -75
- package/src/Table/useTableTreeState.doc.mjs +0 -98
- package/src/postinstall.test.mjs +0 -71
package/dist/theme/Theme.js
CHANGED
|
@@ -115,7 +115,7 @@ function useThemeStyleInjection(theme) {
|
|
|
115
115
|
// One-time perf hint per theme
|
|
116
116
|
if (!warnedThemes.has(theme.name)) {
|
|
117
117
|
warnedThemes.add(theme.name);
|
|
118
|
-
console.warn(`[Astryx] Theme "${theme.name}" is using runtime style injection. ` + `For better performance, use the pre-built theme:\n\n` + ` import {${theme.name}Theme} from '@astryxdesign/theme-${theme.name}/built';\n` + ` import '@astryxdesign/theme-${theme.name}/theme.css';\n\n` + `For custom themes, run \`npx
|
|
118
|
+
console.warn(`[Astryx] Theme "${theme.name}" is using runtime style injection. ` + `For better performance, use the pre-built theme:\n\n` + ` import {${theme.name}Theme} from '@astryxdesign/theme-${theme.name}/built';\n` + ` import '@astryxdesign/theme-${theme.name}/theme.css';\n\n` + `For custom themes, run \`npx astryx theme build <file>\` to generate ` + `the built artifacts.`);
|
|
119
119
|
}
|
|
120
120
|
const {
|
|
121
121
|
prose,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Two distribution modes:
|
|
5
5
|
* - Unbuilt: Theme generates CSS and injects a <style> tag at runtime
|
|
6
|
-
* - Built: `astryx theme build` pre-compiles to a CSS file; Theme just
|
|
6
|
+
* - Built: `npx astryx theme build` pre-compiles to a CSS file; Theme just
|
|
7
7
|
* sets the data-astryx-theme attribute
|
|
8
8
|
*
|
|
9
9
|
* Token values can be:
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Two distribution modes:
|
|
7
7
|
* - Unbuilt: Theme generates CSS and injects a <style> tag at runtime
|
|
8
|
-
* - Built: `astryx theme build` pre-compiles to a CSS file; Theme just
|
|
8
|
+
* - Built: `npx astryx theme build` pre-compiles to a CSS file; Theme just
|
|
9
9
|
* sets the data-astryx-theme attribute
|
|
10
10
|
*
|
|
11
11
|
* Token values can be:
|
package/dist/theme/hct.d.ts
CHANGED
package/dist/theme/hct.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hct.d.ts","sourceRoot":"","sources":["../../src/theme/hct.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAoFD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAkBD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAkBzC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CA8BzC;AAkDD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMxB;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAM/D"}
|
|
1
|
+
{"version":3,"file":"hct.d.ts","sourceRoot":"","sources":["../../src/theme/hct.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAoFD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAkBD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAkBzC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CA8BzC;AAkDD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMxB;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAM/D"}
|
package/dist/theme/hct.js
CHANGED
|
@@ -79,6 +79,9 @@ function labToXyz(L, a, b) {
|
|
|
79
79
|
export function toneToY(tone) {
|
|
80
80
|
return labFInv((tone + 16) / 116);
|
|
81
81
|
}
|
|
82
|
+
export function yToTone(y) {
|
|
83
|
+
return 116 * labF(y) - 16;
|
|
84
|
+
}
|
|
82
85
|
|
|
83
86
|
// =============================================================================
|
|
84
87
|
// Hex <-> RGB
|
package/locales/en.json
CHANGED
|
@@ -423,26 +423,6 @@
|
|
|
423
423
|
"defaultMessage": "Clear sort",
|
|
424
424
|
"description": "Aria label for a Table column header when clicking it will clear the current sort."
|
|
425
425
|
},
|
|
426
|
-
"@astryx.table.sort.direction.ascending": {
|
|
427
|
-
"defaultMessage": "ascending",
|
|
428
|
-
"description": "Localized direction word interpolated as `direction` into @astryx.table.sort.sortedBy and @astryx.table.sort.sortedByWithPriority."
|
|
429
|
-
},
|
|
430
|
-
"@astryx.table.sort.direction.descending": {
|
|
431
|
-
"defaultMessage": "descending",
|
|
432
|
-
"description": "Localized direction word interpolated as `direction` into @astryx.table.sort.sortedBy and @astryx.table.sort.sortedByWithPriority."
|
|
433
|
-
},
|
|
434
|
-
"@astryx.table.sort.sortBy": {
|
|
435
|
-
"defaultMessage": "Sort by {label}",
|
|
436
|
-
"description": "Aria label for a sortable Table header button when the column is unsorted. `label` is the column header text."
|
|
437
|
-
},
|
|
438
|
-
"@astryx.table.sort.sortedBy": {
|
|
439
|
-
"defaultMessage": "Sort by {label}, sorted {direction}",
|
|
440
|
-
"description": "Aria label for a sorted Table header button. `direction` is the localized direction word from @astryx.table.sort.direction.*."
|
|
441
|
-
},
|
|
442
|
-
"@astryx.table.sort.sortedByWithPriority": {
|
|
443
|
-
"defaultMessage": "Sort by {label}, sorted {direction}, priority {rank, number} of {total, number}",
|
|
444
|
-
"description": "Aria label for a sorted Table header button in multi-sort. `rank` is the 1-based position of this column in the sort order; `total` is the number of sorted columns."
|
|
445
|
-
},
|
|
446
426
|
"@astryx.toast.dismiss": {
|
|
447
427
|
"defaultMessage": "Dismiss notification",
|
|
448
428
|
"description": "Aria label for the dismiss button on a Toast."
|
|
@@ -743,14 +723,6 @@
|
|
|
743
723
|
"defaultMessage": "Expand all rows",
|
|
744
724
|
"description": "Aria label for the Table expand-all / collapse-all header button when not all rows are currently expanded."
|
|
745
725
|
},
|
|
746
|
-
"@astryx.tableTree.collapseRow": {
|
|
747
|
-
"defaultMessage": "Collapse row",
|
|
748
|
-
"description": "Aria label for the Table tree-data expander chevron when the row is currently expanded."
|
|
749
|
-
},
|
|
750
|
-
"@astryx.tableTree.expandRow": {
|
|
751
|
-
"defaultMessage": "Expand row",
|
|
752
|
-
"description": "Aria label for the Table tree-data expander chevron when the row is currently collapsed."
|
|
753
|
-
},
|
|
754
726
|
"@astryx.textInput.clearLabel": {
|
|
755
727
|
"defaultMessage": "Clear {label}",
|
|
756
728
|
"description": "Aria label for the TextInput clear button. `label` is the input's own visible label."
|
package/locales/pseudo.json
CHANGED
|
@@ -317,21 +317,6 @@
|
|
|
317
317
|
"@astryx.table.sort.clear": {
|
|
318
318
|
"defaultMessage": "⟦Çłéàř šóřţ⟧"
|
|
319
319
|
},
|
|
320
|
-
"@astryx.table.sort.direction.ascending": {
|
|
321
|
-
"defaultMessage": "⟦àšçéñðíñĝ⟧"
|
|
322
|
-
},
|
|
323
|
-
"@astryx.table.sort.direction.descending": {
|
|
324
|
-
"defaultMessage": "⟦ðéšçéñðíñĝ⟧"
|
|
325
|
-
},
|
|
326
|
-
"@astryx.table.sort.sortBy": {
|
|
327
|
-
"defaultMessage": "⟦Šóřţ ƀý {label}⟧"
|
|
328
|
-
},
|
|
329
|
-
"@astryx.table.sort.sortedBy": {
|
|
330
|
-
"defaultMessage": "⟦Šóřţ ƀý {label}, šóřţéð {direction}⟧"
|
|
331
|
-
},
|
|
332
|
-
"@astryx.table.sort.sortedByWithPriority": {
|
|
333
|
-
"defaultMessage": "⟦Šóřţ ƀý {label}, šóřţéð {direction}, þříóříţý {rank, number} óƒ {total, number}⟧"
|
|
334
|
-
},
|
|
335
320
|
"@astryx.toast.dismiss": {
|
|
336
321
|
"defaultMessage": "⟦Ðíšɱíšš ñóţíƒíçàţíóñ⟧"
|
|
337
322
|
},
|
|
@@ -557,12 +542,6 @@
|
|
|
557
542
|
"@astryx.tableRowExpansion.expandAllRows": {
|
|
558
543
|
"defaultMessage": "⟦Éẋþàñð àłł řóŵš⟧"
|
|
559
544
|
},
|
|
560
|
-
"@astryx.tableTree.collapseRow": {
|
|
561
|
-
"defaultMessage": "⟦Çółłàþšé řóŵ⟧"
|
|
562
|
-
},
|
|
563
|
-
"@astryx.tableTree.expandRow": {
|
|
564
|
-
"defaultMessage": "⟦Éẋþàñð řóŵ⟧"
|
|
565
|
-
},
|
|
566
545
|
"@astryx.textInput.clearLabel": {
|
|
567
546
|
"defaultMessage": "⟦Çłéàř {label}⟧"
|
|
568
547
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.1.7
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -636,7 +636,6 @@
|
|
|
636
636
|
"files": [
|
|
637
637
|
"dist",
|
|
638
638
|
"src",
|
|
639
|
-
"scripts/postinstall.mjs",
|
|
640
639
|
"locales",
|
|
641
640
|
"docs.mjs",
|
|
642
641
|
"groups.doc.mjs",
|
|
@@ -663,7 +662,6 @@
|
|
|
663
662
|
"intl-messageformat": "^11.2.9"
|
|
664
663
|
},
|
|
665
664
|
"scripts": {
|
|
666
|
-
"postinstall": "node scripts/postinstall.mjs",
|
|
667
665
|
"build": "rimraf dist && pnpm build:i18n && pnpm build:esm && tsc --project tsconfig.build.json && pnpm build:css && pnpm build:umd && node ../../scripts/check-no-dev-jsx.mjs",
|
|
668
666
|
"build:i18n": "node scripts/build-pseudo-locale.mjs",
|
|
669
667
|
"build:esm": "babel src --out-dir dist --extensions .ts,.tsx --out-file-extension .js --ignore \"**/*.test.ts,**/*.test.tsx,**/__tests__/**,**/*.perf.test.*,**/*.doc.mjs,**/*.d.ts,**/*.css,**/*.css.d.ts\" --config-file ./babel.config.json",
|
|
@@ -113,7 +113,7 @@ export const docs = {
|
|
|
113
113
|
{
|
|
114
114
|
name: 'labelIcon',
|
|
115
115
|
type: 'IconType',
|
|
116
|
-
description: 'Icon to display before the label text. See `astryx docs icons` for valid semantic names.',
|
|
116
|
+
description: 'Icon to display before the label text. See `npx astryx docs icons` for valid semantic names.',
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
name: 'status',
|
|
@@ -17,7 +17,6 @@ export const docs = {
|
|
|
17
17
|
theming: {
|
|
18
18
|
targets: [
|
|
19
19
|
{className: 'astryx-collapsible', visualProps: ['density']},
|
|
20
|
-
{className: 'astryx-collapsible-content', visualProps: ['density']},
|
|
21
20
|
{className: 'astryx-collapsible-group', visualProps: ['density']},
|
|
22
21
|
],
|
|
23
22
|
},
|
|
@@ -54,12 +53,6 @@ export const docs = {
|
|
|
54
53
|
type: 'boolean',
|
|
55
54
|
description: 'Controlled open state.',
|
|
56
55
|
},
|
|
57
|
-
{
|
|
58
|
-
name: 'isDisabled',
|
|
59
|
-
type: 'boolean',
|
|
60
|
-
description: "Disable the item so its trigger can't be toggled (dimmed, aria-disabled, and out of the tab order). Doesn't collapse an already-open item.",
|
|
61
|
-
default: 'false',
|
|
62
|
-
},
|
|
63
56
|
{
|
|
64
57
|
name: 'onOpenChange',
|
|
65
58
|
type: '(isOpen: boolean) => void',
|
|
@@ -72,12 +72,6 @@ describe('Collapsible', () => {
|
|
|
72
72
|
expect(screen.getByTestId('root')).toHaveClass('astryx-collapsible');
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
it('renders the stable astryx-collapsible-content class on the content area', () => {
|
|
76
|
-
render(<Collapsible trigger="T">c</Collapsible>);
|
|
77
|
-
const content = contentFor(screen.getByRole('button'));
|
|
78
|
-
expect(content).toHaveClass('astryx-collapsible-content');
|
|
79
|
-
});
|
|
80
|
-
|
|
81
75
|
it('renders a ReactNode trigger, not just a string', () => {
|
|
82
76
|
render(
|
|
83
77
|
<Collapsible trigger={<span data-testid="rich">Rich</span>}>
|
|
@@ -246,80 +240,6 @@ describe('Collapsible', () => {
|
|
|
246
240
|
});
|
|
247
241
|
});
|
|
248
242
|
|
|
249
|
-
describe('disabled state', () => {
|
|
250
|
-
it('marks the trigger aria-disabled and drops it from the tab order', () => {
|
|
251
|
-
render(
|
|
252
|
-
<Collapsible trigger="T" isDisabled>
|
|
253
|
-
Body
|
|
254
|
-
</Collapsible>,
|
|
255
|
-
);
|
|
256
|
-
const button = screen.getByRole('button');
|
|
257
|
-
expect(button).toHaveAttribute('aria-disabled', 'true');
|
|
258
|
-
expect(button).toHaveAttribute('tabindex', '-1');
|
|
259
|
-
// Never the native disabled attribute — it stays focusable/perceivable.
|
|
260
|
-
expect(button).not.toBeDisabled();
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it('is enabled by default (no aria-disabled, stays in tab order)', () => {
|
|
264
|
-
render(<Collapsible trigger="T">Body</Collapsible>);
|
|
265
|
-
const button = screen.getByRole('button');
|
|
266
|
-
expect(button).not.toHaveAttribute('aria-disabled');
|
|
267
|
-
expect(button).not.toHaveAttribute('tabindex', '-1');
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
it('does not toggle when the trigger is clicked while disabled', async () => {
|
|
271
|
-
const user = userEvent.setup();
|
|
272
|
-
render(
|
|
273
|
-
<Collapsible trigger="T" isDisabled defaultIsOpen>
|
|
274
|
-
Body
|
|
275
|
-
</Collapsible>,
|
|
276
|
-
);
|
|
277
|
-
const button = screen.getByRole('button');
|
|
278
|
-
expect(button).toHaveAttribute('aria-expanded', 'true');
|
|
279
|
-
await user.click(button);
|
|
280
|
-
expect(button).toHaveAttribute('aria-expanded', 'true');
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
it('does not fire onOpenChange while disabled', async () => {
|
|
284
|
-
const user = userEvent.setup();
|
|
285
|
-
const onOpenChange = vi.fn();
|
|
286
|
-
render(
|
|
287
|
-
<Collapsible trigger="T" isDisabled onOpenChange={onOpenChange}>
|
|
288
|
-
Body
|
|
289
|
-
</Collapsible>,
|
|
290
|
-
);
|
|
291
|
-
await user.click(screen.getByRole('button'));
|
|
292
|
-
expect(onOpenChange).not.toHaveBeenCalled();
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
it('does not collapse an already-open item — content stays visible', () => {
|
|
296
|
-
render(
|
|
297
|
-
<Collapsible trigger="T" isDisabled defaultIsOpen>
|
|
298
|
-
Body
|
|
299
|
-
</Collapsible>,
|
|
300
|
-
);
|
|
301
|
-
const content = contentFor(screen.getByRole('button'));
|
|
302
|
-
expect(content).not.toHaveStyle({display: 'none'});
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
it('does not toggle its group item when disabled', async () => {
|
|
306
|
-
const user = userEvent.setup();
|
|
307
|
-
render(
|
|
308
|
-
<CollapsibleGroup type="single">
|
|
309
|
-
<Collapsible trigger="A" value="a" isDisabled>
|
|
310
|
-
Body A
|
|
311
|
-
</Collapsible>
|
|
312
|
-
<Collapsible trigger="B" value="b">
|
|
313
|
-
Body B
|
|
314
|
-
</Collapsible>
|
|
315
|
-
</CollapsibleGroup>,
|
|
316
|
-
);
|
|
317
|
-
const triggerA = screen.getByRole('button', {name: /A/});
|
|
318
|
-
await user.click(triggerA);
|
|
319
|
-
expect(triggerA).toHaveAttribute('aria-expanded', 'false');
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
|
|
323
243
|
describe('prop forwarding', () => {
|
|
324
244
|
it('forwards a ref to the root element', () => {
|
|
325
245
|
const ref = vi.fn();
|
|
@@ -39,7 +39,6 @@ import {
|
|
|
39
39
|
durationVars,
|
|
40
40
|
easeVars,
|
|
41
41
|
} from '../theme/tokens.stylex';
|
|
42
|
-
|
|
43
42
|
import {useCollapsible} from './useCollapsible';
|
|
44
43
|
import {CollapsibleGroupPresentationContext} from './CollapsibleGroupContext';
|
|
45
44
|
import {getIcon} from '../Icon/globalIconRegistry';
|
|
@@ -82,13 +81,6 @@ const styles = stylex.create({
|
|
|
82
81
|
textBoxEdge: 'cap alphabetic',
|
|
83
82
|
textBoxTrim: 'trim-both',
|
|
84
83
|
},
|
|
85
|
-
// Disabled trigger — non-interactive, dimmed. Native `disabled` on the
|
|
86
|
-
// button blocks click + keyboard activation; these styles restore the
|
|
87
|
-
// visual affordance that `all: unset` wipes.
|
|
88
|
-
triggerDisabled: {
|
|
89
|
-
cursor: 'not-allowed',
|
|
90
|
-
opacity: 0.5,
|
|
91
|
-
},
|
|
92
84
|
// Chevron indicator
|
|
93
85
|
chevron: {
|
|
94
86
|
display: 'inline-flex',
|
|
@@ -110,17 +102,8 @@ const styles = stylex.create({
|
|
|
110
102
|
contentHidden: {
|
|
111
103
|
display: 'none',
|
|
112
104
|
},
|
|
113
|
-
// Anchors body typography so revealed text renders at the system's body
|
|
114
|
-
// scale (family/size/weight/leading) instead of inheriting from wherever
|
|
115
|
-
// the Collapsible is placed. External themes override via the
|
|
116
|
-
// `astryx-collapsible-content` target.
|
|
117
105
|
content: {
|
|
118
106
|
paddingBlockStart: spacingVars['--spacing-1'],
|
|
119
|
-
fontFamily: typographyVars['--font-family-body'],
|
|
120
|
-
fontSize: typeScaleVars['--text-body-size'],
|
|
121
|
-
fontWeight: typeScaleVars['--text-body-weight'],
|
|
122
|
-
lineHeight: typeScaleVars['--text-body-leading'],
|
|
123
|
-
color: colorVars['--color-text-primary'],
|
|
124
107
|
},
|
|
125
108
|
// Group divider chrome — a hairline above every item except the first.
|
|
126
109
|
// The group's wrapper (or 'all' mode) owns the outer edges.
|
|
@@ -183,17 +166,6 @@ export interface CollapsibleProps extends BaseProps {
|
|
|
183
166
|
*/
|
|
184
167
|
isOpen?: boolean;
|
|
185
168
|
|
|
186
|
-
/**
|
|
187
|
-
* Whether the collapsible is disabled. A disabled item can't be toggled —
|
|
188
|
-
* its trigger is non-interactive and dimmed. Following the system-wide
|
|
189
|
-
* disabled convention, the trigger uses `aria-disabled` (not the native
|
|
190
|
-
* `disabled` attribute) and drops out of the tab order, staying perceivable
|
|
191
|
-
* to assistive tech. The content stays in whatever open state it was;
|
|
192
|
-
* disabling doesn't collapse an already-open item.
|
|
193
|
-
* @default false
|
|
194
|
-
*/
|
|
195
|
-
isDisabled?: boolean;
|
|
196
|
-
|
|
197
169
|
/**
|
|
198
170
|
* Callback when the open state changes.
|
|
199
171
|
*/
|
|
@@ -253,7 +225,6 @@ export function Collapsible({
|
|
|
253
225
|
children,
|
|
254
226
|
defaultIsOpen,
|
|
255
227
|
isOpen: controlledIsOpen,
|
|
256
|
-
isDisabled = false,
|
|
257
228
|
onOpenChange,
|
|
258
229
|
value,
|
|
259
230
|
ref,
|
|
@@ -273,17 +244,6 @@ export function Collapsible({
|
|
|
273
244
|
value,
|
|
274
245
|
});
|
|
275
246
|
|
|
276
|
-
// Activation is blocked by this guard rather than the native `disabled`
|
|
277
|
-
// attribute, so the trigger keeps `aria-disabled` semantics and stays
|
|
278
|
-
// discoverable. A native `disabled` button would silently swallow events
|
|
279
|
-
// (e.g. a wrapping tooltip's hover) — the system-wide disabled convention.
|
|
280
|
-
const handleToggle = () => {
|
|
281
|
-
if (isDisabled) {
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
toggle();
|
|
285
|
-
};
|
|
286
|
-
|
|
287
247
|
const presentation = use(CollapsibleGroupPresentationContext);
|
|
288
248
|
const isDivided = presentation?.hasDividers ?? false;
|
|
289
249
|
const density = presentation?.density ?? null;
|
|
@@ -308,20 +268,12 @@ export function Collapsible({
|
|
|
308
268
|
{...props}>
|
|
309
269
|
<button
|
|
310
270
|
type="button"
|
|
311
|
-
onClick={
|
|
312
|
-
aria-disabled={isDisabled || undefined}
|
|
271
|
+
onClick={toggle}
|
|
313
272
|
aria-expanded={isOpen}
|
|
314
273
|
aria-controls={contentId}
|
|
315
|
-
// A disabled trigger drops out of the tab order so it isn't a silently
|
|
316
|
-
// dead tab stop; activation stays blocked by the handleToggle guard,
|
|
317
|
-
// and aria-disabled keeps the state perceivable to assistive tech —
|
|
318
|
-
// the system-wide disabled convention (never native `disabled`, which
|
|
319
|
-
// would swallow events like a wrapping tooltip's hover).
|
|
320
|
-
tabIndex={isDisabled ? -1 : undefined}
|
|
321
274
|
{...stylex.props(
|
|
322
275
|
styles.trigger,
|
|
323
276
|
density != null && triggerDensity[density],
|
|
324
|
-
isDisabled && styles.triggerDisabled,
|
|
325
277
|
)}>
|
|
326
278
|
<span {...stylex.props(styles.triggerLabel)}>{trigger}</span>
|
|
327
279
|
<span
|
|
@@ -334,15 +286,10 @@ export function Collapsible({
|
|
|
334
286
|
</button>
|
|
335
287
|
<div
|
|
336
288
|
id={contentId}
|
|
337
|
-
{...
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
stylex.props(
|
|
342
|
-
styles.content,
|
|
343
|
-
density != null && contentDensity[density],
|
|
344
|
-
!isOpen && styles.contentHidden,
|
|
345
|
-
),
|
|
289
|
+
{...stylex.props(
|
|
290
|
+
styles.content,
|
|
291
|
+
density != null && contentDensity[density],
|
|
292
|
+
!isOpen && styles.contentHidden,
|
|
346
293
|
)}>
|
|
347
294
|
{presentation != null ? (
|
|
348
295
|
<CollapsibleGroupPresentationContext value={null}>
|
|
@@ -12,12 +12,7 @@ import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
|
12
12
|
import {render, screen, fireEvent, act} from '@testing-library/react';
|
|
13
13
|
import userEvent from '@testing-library/user-event';
|
|
14
14
|
import {ContextMenu} from './ContextMenu';
|
|
15
|
-
import {
|
|
16
|
-
ContextMenuItem,
|
|
17
|
-
ContextMenuCheckboxItem,
|
|
18
|
-
ContextMenuRadioGroup,
|
|
19
|
-
ContextMenuRadioItem,
|
|
20
|
-
} from './index';
|
|
15
|
+
import {ContextMenuItem} from './index';
|
|
21
16
|
import {DropdownMenuItem} from '../DropdownMenu/DropdownMenuItem';
|
|
22
17
|
import {Divider} from '../Divider';
|
|
23
18
|
|
|
@@ -542,72 +537,3 @@ describe('ContextMenu compound mode', () => {
|
|
|
542
537
|
});
|
|
543
538
|
});
|
|
544
539
|
});
|
|
545
|
-
|
|
546
|
-
describe('ContextMenu selectable items', () => {
|
|
547
|
-
it('renders checkbox and radio items with correct roles and state', () => {
|
|
548
|
-
render(
|
|
549
|
-
<ContextMenu
|
|
550
|
-
menuContent={
|
|
551
|
-
<>
|
|
552
|
-
<ContextMenuRadioGroup
|
|
553
|
-
value="name"
|
|
554
|
-
onChange={() => {}}
|
|
555
|
-
aria-label="Sort by">
|
|
556
|
-
<ContextMenuRadioItem value="name" label="Sort by name" />
|
|
557
|
-
<ContextMenuRadioItem value="date" label="Sort by date" />
|
|
558
|
-
</ContextMenuRadioGroup>
|
|
559
|
-
<ContextMenuCheckboxItem label="Show hidden" value={true} />
|
|
560
|
-
</>
|
|
561
|
-
}>
|
|
562
|
-
<div>Right-click me</div>
|
|
563
|
-
</ContextMenu>,
|
|
564
|
-
);
|
|
565
|
-
expect(
|
|
566
|
-
screen.getByRole('menuitemradio', {name: 'Sort by name', hidden: true}),
|
|
567
|
-
).toHaveAttribute('aria-checked', 'true');
|
|
568
|
-
expect(
|
|
569
|
-
screen.getByRole('menuitemradio', {name: 'Sort by date', hidden: true}),
|
|
570
|
-
).toHaveAttribute('aria-checked', 'false');
|
|
571
|
-
expect(
|
|
572
|
-
screen.getByRole('menuitemcheckbox', {name: 'Show hidden', hidden: true}),
|
|
573
|
-
).toHaveAttribute('aria-checked', 'true');
|
|
574
|
-
expect(
|
|
575
|
-
screen.getByRole('group', {name: 'Sort by', hidden: true}),
|
|
576
|
-
).toBeInTheDocument();
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
it('fires onChange for radio and checkbox items', async () => {
|
|
580
|
-
const user = userEvent.setup();
|
|
581
|
-
const onSort = vi.fn();
|
|
582
|
-
const onToggle = vi.fn();
|
|
583
|
-
render(
|
|
584
|
-
<ContextMenu
|
|
585
|
-
menuContent={
|
|
586
|
-
<>
|
|
587
|
-
<ContextMenuRadioGroup
|
|
588
|
-
value="name"
|
|
589
|
-
onChange={onSort}
|
|
590
|
-
aria-label="Sort by">
|
|
591
|
-
<ContextMenuRadioItem value="name" label="Sort by name" />
|
|
592
|
-
<ContextMenuRadioItem value="date" label="Sort by date" />
|
|
593
|
-
</ContextMenuRadioGroup>
|
|
594
|
-
<ContextMenuCheckboxItem
|
|
595
|
-
label="Show hidden"
|
|
596
|
-
value={false}
|
|
597
|
-
onChange={onToggle}
|
|
598
|
-
/>
|
|
599
|
-
</>
|
|
600
|
-
}>
|
|
601
|
-
<div>Right-click me</div>
|
|
602
|
-
</ContextMenu>,
|
|
603
|
-
);
|
|
604
|
-
await user.click(
|
|
605
|
-
screen.getByRole('menuitemradio', {name: 'Sort by date', hidden: true}),
|
|
606
|
-
);
|
|
607
|
-
expect(onSort).toHaveBeenCalledWith('date');
|
|
608
|
-
await user.click(
|
|
609
|
-
screen.getByRole('menuitemcheckbox', {name: 'Show hidden', hidden: true}),
|
|
610
|
-
);
|
|
611
|
-
expect(onToggle).toHaveBeenCalledWith(true);
|
|
612
|
-
});
|
|
613
|
-
});
|
|
@@ -46,10 +46,6 @@ import {
|
|
|
46
46
|
DropdownMenuContext,
|
|
47
47
|
type DropdownMenuContextValue,
|
|
48
48
|
} from '../DropdownMenu/DropdownMenuContext';
|
|
49
|
-
import {
|
|
50
|
-
MENU_ITEM_ROLES,
|
|
51
|
-
MENU_ITEM_SELECTOR,
|
|
52
|
-
} from '../DropdownMenu/menuItemRoles';
|
|
53
49
|
import {useListFocus} from '../hooks/useListFocus';
|
|
54
50
|
import {useTypeahead} from '../hooks/useTypeahead';
|
|
55
51
|
import {useLongPress} from '../hooks/useLongPress';
|
|
@@ -269,7 +265,7 @@ export function ContextMenu({
|
|
|
269
265
|
focusFirst,
|
|
270
266
|
focusItem,
|
|
271
267
|
} = useListFocus<HTMLDivElement>({
|
|
272
|
-
itemSelector:
|
|
268
|
+
itemSelector: '[role="menuitem"]:not([aria-disabled="true"])',
|
|
273
269
|
wrap: false,
|
|
274
270
|
onEscape: closeMenu,
|
|
275
271
|
});
|
|
@@ -279,7 +275,9 @@ export function ContextMenu({
|
|
|
279
275
|
(): HTMLElement[] =>
|
|
280
276
|
listRef.current
|
|
281
277
|
? Array.from(
|
|
282
|
-
listRef.current.querySelectorAll<HTMLElement>(
|
|
278
|
+
listRef.current.querySelectorAll<HTMLElement>(
|
|
279
|
+
'[role="menuitem"]:not([aria-disabled="true"])',
|
|
280
|
+
),
|
|
283
281
|
)
|
|
284
282
|
: [],
|
|
285
283
|
[listRef],
|
|
@@ -343,10 +341,7 @@ export function ContextMenu({
|
|
|
343
341
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
344
342
|
e.preventDefault();
|
|
345
343
|
const focused = document.activeElement as HTMLElement | null;
|
|
346
|
-
if (
|
|
347
|
-
focused &&
|
|
348
|
-
MENU_ITEM_ROLES.has(focused.getAttribute('role') ?? '')
|
|
349
|
-
) {
|
|
344
|
+
if (focused?.getAttribute('role') === 'menuitem') {
|
|
350
345
|
focused.click();
|
|
351
346
|
}
|
|
352
347
|
return;
|
package/src/ContextMenu/index.ts
CHANGED
|
@@ -20,18 +20,3 @@ export {
|
|
|
20
20
|
DropdownMenuItem as ContextMenuItem,
|
|
21
21
|
type DropdownMenuItemProps as ContextMenuItemProps,
|
|
22
22
|
} from '../DropdownMenu/DropdownMenuItem';
|
|
23
|
-
|
|
24
|
-
// Selectable items work inside a ContextMenu too — re-exported under the
|
|
25
|
-
// ContextMenu name for a coherent API.
|
|
26
|
-
export {
|
|
27
|
-
DropdownMenuCheckboxItem as ContextMenuCheckboxItem,
|
|
28
|
-
type DropdownMenuCheckboxItemProps as ContextMenuCheckboxItemProps,
|
|
29
|
-
} from '../DropdownMenu/DropdownMenuCheckboxItem';
|
|
30
|
-
export {
|
|
31
|
-
DropdownMenuRadioGroup as ContextMenuRadioGroup,
|
|
32
|
-
type DropdownMenuRadioGroupProps as ContextMenuRadioGroupProps,
|
|
33
|
-
} from '../DropdownMenu/DropdownMenuRadioGroup';
|
|
34
|
-
export {
|
|
35
|
-
DropdownMenuRadioItem as ContextMenuRadioItem,
|
|
36
|
-
type DropdownMenuRadioItemProps as ContextMenuRadioItemProps,
|
|
37
|
-
} from '../DropdownMenu/DropdownMenuRadioItem';
|
|
@@ -8,33 +8,10 @@ export const docs = {
|
|
|
8
8
|
group: 'DropdownMenu',
|
|
9
9
|
category: 'Action',
|
|
10
10
|
keywords: ["dropdown","menu","popover","select","actions","contextmenu","overflow","kebab","menubutton"],
|
|
11
|
-
playground: {
|
|
12
|
-
// `items` is required; without seeded entries the properties-tab preview
|
|
13
|
-
// renders an empty trigger button. Provide a few actions so the preview
|
|
14
|
-
// is meaningful.
|
|
15
|
-
defaults: {
|
|
16
|
-
button: {label: 'Actions'},
|
|
17
|
-
items: [
|
|
18
|
-
{label: 'Edit'},
|
|
19
|
-
{label: 'Duplicate'},
|
|
20
|
-
{label: 'Delete'},
|
|
21
|
-
],
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
11
|
theming: {
|
|
25
12
|
targets: [
|
|
26
13
|
{className: 'astryx-dropdown-menu'},
|
|
27
14
|
{className: 'astryx-dropdown-menu-item', visualProps: ['size']},
|
|
28
|
-
{
|
|
29
|
-
className: 'astryx-dropdown-menu-checkbox',
|
|
30
|
-
visualProps: ['size'],
|
|
31
|
-
states: ['checked', 'disabled'],
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
className: 'astryx-dropdown-menu-radio',
|
|
35
|
-
visualProps: ['size'],
|
|
36
|
-
states: ['checked', 'disabled'],
|
|
37
|
-
},
|
|
38
15
|
],
|
|
39
16
|
vars: [
|
|
40
17
|
{name: '--_dropdown-menu-radius', description: 'Border radius of the menu popup', default: 'var(--radius-element)', private: true},
|
|
@@ -38,7 +38,6 @@ import {Icon} from '../Icon';
|
|
|
38
38
|
import type {IconType} from '../Icon';
|
|
39
39
|
|
|
40
40
|
import {renderDropdownItems} from './renderDropdownItems';
|
|
41
|
-
import {MENU_ITEM_ROLES, MENU_ITEM_SELECTOR} from './menuItemRoles';
|
|
42
41
|
import {
|
|
43
42
|
DropdownMenuContext,
|
|
44
43
|
type DropdownMenuContextValue,
|
|
@@ -256,17 +255,14 @@ export function DropdownMenu({
|
|
|
256
255
|
popover.hide();
|
|
257
256
|
}, [popover]);
|
|
258
257
|
|
|
259
|
-
// Single keyboard navigation path for both modes
|
|
260
|
-
// The selector matches plain items plus selectable items
|
|
261
|
-
// (menuitemradio/menuitemcheckbox) so lab checkbox/radio rows are reachable
|
|
262
|
-
// and roved to alongside plain items — not just role="menuitem".
|
|
258
|
+
// Single keyboard navigation path for both modes
|
|
263
259
|
const {
|
|
264
260
|
listRef,
|
|
265
261
|
handleKeyDown: listNavKeyDown,
|
|
266
262
|
focusFirst,
|
|
267
263
|
focusItem,
|
|
268
264
|
} = useListFocus<HTMLDivElement>({
|
|
269
|
-
itemSelector:
|
|
265
|
+
itemSelector: '[role="menuitem"]:not([aria-disabled="true"])',
|
|
270
266
|
wrap: false,
|
|
271
267
|
onEscape: closeMenu,
|
|
272
268
|
});
|
|
@@ -277,7 +273,9 @@ export function DropdownMenu({
|
|
|
277
273
|
(): HTMLElement[] =>
|
|
278
274
|
listRef.current
|
|
279
275
|
? Array.from(
|
|
280
|
-
listRef.current.querySelectorAll<HTMLElement>(
|
|
276
|
+
listRef.current.querySelectorAll<HTMLElement>(
|
|
277
|
+
'[role="menuitem"]:not([aria-disabled="true"])',
|
|
278
|
+
),
|
|
281
279
|
)
|
|
282
280
|
: [],
|
|
283
281
|
[listRef],
|
|
@@ -310,10 +308,7 @@ export function DropdownMenu({
|
|
|
310
308
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
311
309
|
e.preventDefault();
|
|
312
310
|
const focused = document.activeElement as HTMLElement | null;
|
|
313
|
-
if (
|
|
314
|
-
focused &&
|
|
315
|
-
MENU_ITEM_ROLES.has(focused.getAttribute('role') ?? '')
|
|
316
|
-
) {
|
|
311
|
+
if (focused?.getAttribute('role') === 'menuitem') {
|
|
317
312
|
focused.click();
|
|
318
313
|
}
|
|
319
314
|
return;
|