@astryxdesign/core 0.1.7-canary.eb8e07b → 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/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/astryx.css +1 -15
- package/dist/astryx.umd.js +46 -46
- package/dist/astryx.umd.js.map +4 -4
- package/package.json +1 -1
- 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 -10
- package/src/DropdownMenu/DropdownMenu.tsx +6 -11
- package/src/DropdownMenu/DropdownMenuContext.tsx +1 -29
- package/src/DropdownMenu/index.ts +3 -23
- package/src/Icon/Icon.test.tsx +0 -46
- package/src/Icon/Icon.tsx +24 -37
- 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/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/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",
|
|
@@ -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';
|
|
@@ -12,16 +12,6 @@ export const docs = {
|
|
|
12
12
|
targets: [
|
|
13
13
|
{className: 'astryx-dropdown-menu'},
|
|
14
14
|
{className: 'astryx-dropdown-menu-item', visualProps: ['size']},
|
|
15
|
-
{
|
|
16
|
-
className: 'astryx-dropdown-menu-checkbox',
|
|
17
|
-
visualProps: ['size'],
|
|
18
|
-
states: ['checked', 'disabled'],
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
className: 'astryx-dropdown-menu-radio',
|
|
22
|
-
visualProps: ['size'],
|
|
23
|
-
states: ['checked', 'disabled'],
|
|
24
|
-
},
|
|
25
15
|
],
|
|
26
16
|
vars: [
|
|
27
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;
|
|
@@ -14,14 +14,11 @@
|
|
|
14
14
|
|
|
15
15
|
import {createContext, use} from 'react';
|
|
16
16
|
|
|
17
|
-
/** Menu size, derived from the trigger button size. */
|
|
18
|
-
export type DropdownMenuSize = 'sm' | 'md' | 'lg';
|
|
19
|
-
|
|
20
17
|
export interface DropdownMenuContextValue {
|
|
21
18
|
/** Close the menu and return focus to trigger */
|
|
22
19
|
closeMenu: () => void;
|
|
23
20
|
/** Menu size derived from button size */
|
|
24
|
-
menuSize:
|
|
21
|
+
menuSize: 'sm' | 'md' | 'lg';
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
export const DropdownMenuContext =
|
|
@@ -35,28 +32,3 @@ DropdownMenuContext.displayName = 'DropdownMenuContext';
|
|
|
35
32
|
export function useDropdownMenuContext(): DropdownMenuContextValue | null {
|
|
36
33
|
return use(DropdownMenuContext);
|
|
37
34
|
}
|
|
38
|
-
|
|
39
|
-
// =============================================================================
|
|
40
|
-
// Radio group coordination
|
|
41
|
-
// =============================================================================
|
|
42
|
-
|
|
43
|
-
export interface DropdownMenuRadioGroupContextValue {
|
|
44
|
-
/** The currently selected value in the group. */
|
|
45
|
-
value: string | undefined;
|
|
46
|
-
/** Select a value. Called by a DropdownMenuRadioItem on activation. */
|
|
47
|
-
onChange: (value: string) => void;
|
|
48
|
-
/** Whether selecting an item should close the menu. @default true */
|
|
49
|
-
hasCloseOnSelect: boolean;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const DropdownMenuRadioGroupContext =
|
|
53
|
-
createContext<DropdownMenuRadioGroupContextValue | null>(null);
|
|
54
|
-
DropdownMenuRadioGroupContext.displayName = 'DropdownMenuRadioGroupContext';
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Read the enclosing radio group's selection state.
|
|
58
|
-
* Returns null when used outside a DropdownMenuRadioGroup.
|
|
59
|
-
*/
|
|
60
|
-
export function useDropdownMenuRadioGroupContext(): DropdownMenuRadioGroupContextValue | null {
|
|
61
|
-
return use(DropdownMenuRadioGroupContext);
|
|
62
|
-
}
|
|
@@ -18,27 +18,7 @@ export {
|
|
|
18
18
|
type DropdownMenuOption,
|
|
19
19
|
} from './DropdownMenu';
|
|
20
20
|
|
|
21
|
-
export {DropdownMenuItem, type DropdownMenuItemProps} from './DropdownMenuItem';
|
|
22
|
-
|
|
23
|
-
// Selectable items — checkbox (independent) and radio (single-select group).
|
|
24
|
-
export {
|
|
25
|
-
DropdownMenuCheckboxItem,
|
|
26
|
-
type DropdownMenuCheckboxItemProps,
|
|
27
|
-
} from './DropdownMenuCheckboxItem';
|
|
28
|
-
export {
|
|
29
|
-
DropdownMenuRadioGroup,
|
|
30
|
-
type DropdownMenuRadioGroupProps,
|
|
31
|
-
} from './DropdownMenuRadioGroup';
|
|
32
|
-
export {
|
|
33
|
-
DropdownMenuRadioItem,
|
|
34
|
-
type DropdownMenuRadioItemProps,
|
|
35
|
-
} from './DropdownMenuRadioItem';
|
|
36
|
-
|
|
37
|
-
// Menu-coordination context — public so consumers can build custom menu items
|
|
38
|
-
// that read the menu size / close the menu.
|
|
39
21
|
export {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
type DropdownMenuSize,
|
|
44
|
-
} from './DropdownMenuContext';
|
|
22
|
+
DropdownMenuItem,
|
|
23
|
+
type DropdownMenuItemProps,
|
|
24
|
+
} from './DropdownMenuItem';
|
package/src/Icon/Icon.test.tsx
CHANGED
|
@@ -96,52 +96,6 @@ describe('Icon', () => {
|
|
|
96
96
|
expect(screen.getByTestId('icon')).toBeInTheDocument();
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
it('sizes component-mode icons in rem so they scale with root font-size', () => {
|
|
100
|
-
const sizes = {
|
|
101
|
-
xsm: '0.75rem',
|
|
102
|
-
sm: '1rem',
|
|
103
|
-
md: '1.25rem',
|
|
104
|
-
lg: '1.5rem',
|
|
105
|
-
} as const;
|
|
106
|
-
for (const [size, expected] of Object.entries(sizes)) {
|
|
107
|
-
const {unmount} = render(
|
|
108
|
-
<Icon
|
|
109
|
-
icon={TestIcon}
|
|
110
|
-
size={size as keyof typeof sizes}
|
|
111
|
-
data-testid="icon"
|
|
112
|
-
/>,
|
|
113
|
-
);
|
|
114
|
-
const style = getComputedStyle(screen.getByTestId('icon'));
|
|
115
|
-
expect(style.width).toBe(expected);
|
|
116
|
-
expect(style.height).toBe(expected);
|
|
117
|
-
unmount();
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('sizes registry (string-mode) icons in rem, including fontSize', () => {
|
|
122
|
-
const sizes = {
|
|
123
|
-
xsm: '0.75rem',
|
|
124
|
-
sm: '1rem',
|
|
125
|
-
md: '1.25rem',
|
|
126
|
-
lg: '1.5rem',
|
|
127
|
-
} as const;
|
|
128
|
-
for (const [size, expected] of Object.entries(sizes)) {
|
|
129
|
-
const {unmount} = render(
|
|
130
|
-
<Icon
|
|
131
|
-
icon="check"
|
|
132
|
-
size={size as keyof typeof sizes}
|
|
133
|
-
data-testid="icon"
|
|
134
|
-
/>,
|
|
135
|
-
);
|
|
136
|
-
const style = getComputedStyle(screen.getByTestId('icon'));
|
|
137
|
-
expect(style.width).toBe(expected);
|
|
138
|
-
expect(style.height).toBe(expected);
|
|
139
|
-
// fontSize is expressed in rem so 1em-based registry icons scale too.
|
|
140
|
-
expect(style.fontSize).toBe(expected);
|
|
141
|
-
unmount();
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
|
|
145
99
|
it('forwards ref correctly', () => {
|
|
146
100
|
const ref = vi.fn();
|
|
147
101
|
render(<Icon icon={TestIcon} ref={ref} />);
|
package/src/Icon/Icon.tsx
CHANGED
|
@@ -111,64 +111,51 @@ const colorStyles = stylex.create({
|
|
|
111
111
|
/**
|
|
112
112
|
* Size styles for direct SVG icon components.
|
|
113
113
|
* Uses width/height only — SVG components handle their own viewBox scaling.
|
|
114
|
-
*
|
|
115
|
-
* Sizes are expressed in `rem` (relative to the root font-size) so icons scale
|
|
116
|
-
* in step with text when the document font-size changes, matching the rest of
|
|
117
|
-
* the design system's rem-based type scale. Values are the px-equivalents at a
|
|
118
|
-
* 16px root: 12px → 0.75rem, 16px → 1rem, 20px → 1.25rem, 24px → 1.5rem.
|
|
119
114
|
*/
|
|
120
115
|
const sizeStyles = stylex.create({
|
|
121
116
|
xsm: {
|
|
122
|
-
width:
|
|
123
|
-
height:
|
|
117
|
+
width: 12,
|
|
118
|
+
height: 12,
|
|
124
119
|
},
|
|
125
120
|
sm: {
|
|
126
|
-
width:
|
|
127
|
-
height:
|
|
121
|
+
width: 16,
|
|
122
|
+
height: 16,
|
|
128
123
|
},
|
|
129
124
|
md: {
|
|
130
|
-
width:
|
|
131
|
-
height:
|
|
125
|
+
width: 20,
|
|
126
|
+
height: 20,
|
|
132
127
|
},
|
|
133
128
|
lg: {
|
|
134
|
-
width:
|
|
135
|
-
height:
|
|
129
|
+
width: 24,
|
|
130
|
+
height: 24,
|
|
136
131
|
},
|
|
137
132
|
});
|
|
138
133
|
|
|
139
134
|
/**
|
|
140
135
|
* Size styles for string-based (registry) icons.
|
|
141
136
|
* Includes fontSize so that 1em-based icons from the registry scale correctly.
|
|
142
|
-
*
|
|
143
|
-
* Expressed in `rem` for the same reason as {@link sizeStyles} — icons track the
|
|
144
|
-
* root font-size instead of being locked to absolute pixels.
|
|
145
137
|
*/
|
|
146
138
|
const spanSizeStyles = stylex.create({
|
|
147
|
-
/* eslint-disable @astryx/no-hardcoded-styles -- fontSize here sizes 1em-based
|
|
148
|
-
registry SVGs to the icon box; icons use their own 12/16/20/24 scale, not
|
|
149
|
-
the 14px-anchored textSizeVars type scale. Values are rem so icons track
|
|
150
|
-
the root font-size. */
|
|
151
139
|
xsm: {
|
|
152
|
-
width:
|
|
153
|
-
height:
|
|
154
|
-
fontSize:
|
|
140
|
+
width: 12,
|
|
141
|
+
height: 12,
|
|
142
|
+
fontSize: 12,
|
|
155
143
|
},
|
|
156
144
|
sm: {
|
|
157
|
-
width:
|
|
158
|
-
height:
|
|
159
|
-
fontSize:
|
|
145
|
+
width: 16,
|
|
146
|
+
height: 16,
|
|
147
|
+
fontSize: 16,
|
|
160
148
|
},
|
|
161
149
|
md: {
|
|
162
|
-
width:
|
|
163
|
-
height:
|
|
164
|
-
fontSize:
|
|
150
|
+
width: 20,
|
|
151
|
+
height: 20,
|
|
152
|
+
fontSize: 20,
|
|
165
153
|
},
|
|
166
154
|
lg: {
|
|
167
|
-
width:
|
|
168
|
-
height:
|
|
169
|
-
fontSize:
|
|
155
|
+
width: 24,
|
|
156
|
+
height: 24,
|
|
157
|
+
fontSize: 24,
|
|
170
158
|
},
|
|
171
|
-
/* eslint-enable @astryx/no-hardcoded-styles */
|
|
172
159
|
});
|
|
173
160
|
|
|
174
161
|
// =============================================================================
|
|
@@ -207,10 +194,10 @@ export interface IconProps extends Omit<
|
|
|
207
194
|
color?: IconColor;
|
|
208
195
|
/**
|
|
209
196
|
* The size of the icon.
|
|
210
|
-
* - 'xsm':
|
|
211
|
-
* - 'sm':
|
|
212
|
-
* - 'md':
|
|
213
|
-
* - 'lg':
|
|
197
|
+
* - 'xsm': 12px
|
|
198
|
+
* - 'sm': 16px
|
|
199
|
+
* - 'md': 20px
|
|
200
|
+
* - 'lg': 24px
|
|
214
201
|
* @default 'md'
|
|
215
202
|
*/
|
|
216
203
|
size?: IconSize;
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file DropdownMenuCheckboxItem.tsx
|
|
3
|
-
* @input React, stylex, Item + Icon + DropdownMenu context + tokens from core
|
|
4
|
-
* @output DropdownMenuCheckboxItem — a standalone checkable menu item.
|
|
5
|
-
* @position Sub-component; used inside DropdownMenu.
|
|
6
|
-
*
|
|
7
|
-
* A menu item that toggles an independent boolean (role="menuitemcheckbox").
|
|
8
|
-
* Unlike CheckboxInput, there is no nested native <input>: the row itself owns
|
|
9
|
-
* the role and aria-checked, per the WAI-ARIA menuitemcheckbox pattern.
|
|
10
|
-
* Keyboard navigation (arrows/typeahead) and Enter/Space activation come from
|
|
11
|
-
* the parent DropdownMenu's useListFocus + activation path, which matches
|
|
12
|
-
* menuitemcheckbox alongside plain menuitem rows.
|
|
13
|
-
*
|
|
14
|
-
* The square checkbox visual is decorative (aria-hidden) — the row owns the
|
|
15
|
-
* checked state. Its size is derived from the menu's item size (a `sm` menu
|
|
16
|
-
* gets the compact control; `md`/`lg` get the standard one) and it swaps to the
|
|
17
|
-
* inline-end of the row on coarse-pointer (touch) devices via CSS `order`, so
|
|
18
|
-
* it lands where selection toggles are conventionally placed on mobile. The
|
|
19
|
-
* checkmark uses the `check` icon from the active theme's icon registry.
|
|
20
|
-
*/
|
|
21
|
-
import { type ReactNode } from 'react';
|
|
22
|
-
import { type IconType } from '../Icon';
|
|
23
|
-
import type { BaseProps } from '../BaseProps';
|
|
24
|
-
export interface DropdownMenuCheckboxItemProps extends Omit<BaseProps, 'onChange' | 'role' | 'aria-checked' | 'tabIndex'> {
|
|
25
|
-
/**
|
|
26
|
-
* Primary label text identifying the item.
|
|
27
|
-
*/
|
|
28
|
-
label: ReactNode;
|
|
29
|
-
/**
|
|
30
|
-
* Secondary description text displayed below the label.
|
|
31
|
-
*/
|
|
32
|
-
description?: ReactNode;
|
|
33
|
-
/**
|
|
34
|
-
* Icon to display before the label. Accepts a semantic icon name (see
|
|
35
|
-
* `npx astryx docs icons`) or a rendered node.
|
|
36
|
-
*/
|
|
37
|
-
icon?: ReactNode | IconType;
|
|
38
|
-
/**
|
|
39
|
-
* Whether the item is checked. Controlled — pair with `onChange`.
|
|
40
|
-
*/
|
|
41
|
-
value: boolean;
|
|
42
|
-
/**
|
|
43
|
-
* Callback fired with the next checked state when the item is toggled.
|
|
44
|
-
*/
|
|
45
|
-
onChange?: (checked: boolean) => void;
|
|
46
|
-
/**
|
|
47
|
-
* Whether the item is disabled. Disabled items stay focusable (via
|
|
48
|
-
* `aria-disabled`) so they remain discoverable by keyboard and assistive
|
|
49
|
-
* technology, but activation is blocked.
|
|
50
|
-
* @default false
|
|
51
|
-
*/
|
|
52
|
-
isDisabled?: boolean;
|
|
53
|
-
/**
|
|
54
|
-
* Whether toggling the item closes the menu. Checkbox items default to
|
|
55
|
-
* staying open so several can be toggled in a single session, unlike radio
|
|
56
|
-
* items which default to closing on selection.
|
|
57
|
-
* @default false
|
|
58
|
-
*/
|
|
59
|
-
hasCloseOnSelect?: boolean;
|
|
60
|
-
/**
|
|
61
|
-
* Content to render after the label and description, such as a keyboard
|
|
62
|
-
* shortcut hint or badge.
|
|
63
|
-
*/
|
|
64
|
-
endContent?: ReactNode;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* A checkable dropdown menu item (role="menuitemcheckbox").
|
|
68
|
-
*
|
|
69
|
-
* Must be used inside a DropdownMenu. Toggles an independent boolean; for a
|
|
70
|
-
* one-of-N choice use DropdownMenuRadioGroup + DropdownMenuRadioItem instead.
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```
|
|
74
|
-
* * import {DropdownMenuCheckboxItem} from '@astryxdesign/core/DropdownMenu';
|
|
75
|
-
*
|
|
76
|
-
* <DropdownMenu button={{label: 'View'}}>
|
|
77
|
-
* <DropdownMenuCheckboxItem
|
|
78
|
-
* label="Show archived"
|
|
79
|
-
* value={showArchived}
|
|
80
|
-
* onChange={setShowArchived}
|
|
81
|
-
* />
|
|
82
|
-
* </DropdownMenu>
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
85
|
-
export declare function DropdownMenuCheckboxItem({ label, description, icon, value, onChange, isDisabled, hasCloseOnSelect, endContent, xstyle, className, style, ...rest }: DropdownMenuCheckboxItemProps): import("react").JSX.Element;
|
|
86
|
-
export declare namespace DropdownMenuCheckboxItem {
|
|
87
|
-
var displayName: string;
|
|
88
|
-
}
|
|
89
|
-
//# sourceMappingURL=DropdownMenuCheckboxItem.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMenuCheckboxItem.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenuCheckboxItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAc,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAElD,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAY5D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA6D5C,MAAM,WAAW,6BAA8B,SAAQ,IAAI,CACzD,SAAS,EACT,UAAU,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,CAClD;IACC;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,WAAW,EACX,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,UAAkB,EAClB,gBAAwB,EACxB,UAAU,EACV,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,6BAA6B,+BAwD/B;yBArEe,wBAAwB"}
|