@dashforge/tw 0.11.0-beta → 1.1.0
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/CHANGELOG.md +234 -12
- package/COVERAGE.md +2 -2
- package/PARITY.md +7 -9
- package/PERFORMANCE.md +3 -4
- package/README.md +74 -15
- package/THEME-AUDIT.md +3 -4
- package/dashforge-tw-1.0.0.tgz +0 -0
- package/dist/index.esm.js +3127 -748
- package/dist/src/components/Alert/Alert.d.ts +65 -0
- package/dist/src/components/Alert/Alert.d.ts.map +1 -0
- package/dist/src/components/Alert/alert.types.d.ts +130 -0
- package/dist/src/components/Alert/alert.types.d.ts.map +1 -0
- package/dist/src/components/Alert/alert.variants.d.ts +85 -0
- package/dist/src/components/Alert/alert.variants.d.ts.map +1 -0
- package/dist/src/components/Avatar/Avatar.d.ts +48 -0
- package/dist/src/components/Avatar/Avatar.d.ts.map +1 -0
- package/dist/src/components/Avatar/avatar.types.d.ts +162 -0
- package/dist/src/components/Avatar/avatar.types.d.ts.map +1 -0
- package/dist/src/components/Avatar/avatar.variants.d.ts +208 -0
- package/dist/src/components/Avatar/avatar.variants.d.ts.map +1 -0
- package/dist/src/components/Badge/Badge.d.ts +63 -0
- package/dist/src/components/Badge/Badge.d.ts.map +1 -0
- package/dist/src/components/Badge/badge.types.d.ts +124 -0
- package/dist/src/components/Badge/badge.types.d.ts.map +1 -0
- package/dist/src/components/Badge/badge.variants.d.ts +262 -0
- package/dist/src/components/Badge/badge.variants.d.ts.map +1 -0
- package/dist/src/components/Box/Box.d.ts.map +1 -1
- package/dist/src/components/Box/box.types.d.ts +53 -0
- package/dist/src/components/Box/box.types.d.ts.map +1 -1
- package/dist/src/components/Button/Button.d.ts.map +1 -1
- package/dist/src/components/Button/button.types.d.ts +35 -0
- package/dist/src/components/Button/button.types.d.ts.map +1 -1
- package/dist/src/components/Card/Card.d.ts +107 -0
- package/dist/src/components/Card/Card.d.ts.map +1 -0
- package/dist/src/components/Card/card.types.d.ts +119 -0
- package/dist/src/components/Card/card.types.d.ts.map +1 -0
- package/dist/src/components/Chip/Chip.d.ts +67 -0
- package/dist/src/components/Chip/Chip.d.ts.map +1 -0
- package/dist/src/components/Chip/chip.types.d.ts +113 -0
- package/dist/src/components/Chip/chip.types.d.ts.map +1 -0
- package/dist/src/components/Chip/chip.variants.d.ts +155 -0
- package/dist/src/components/Chip/chip.variants.d.ts.map +1 -0
- package/dist/src/components/IconButton/IconButton.d.ts +57 -0
- package/dist/src/components/IconButton/IconButton.d.ts.map +1 -0
- package/dist/src/components/IconButton/iconButton.types.d.ts +96 -0
- package/dist/src/components/IconButton/iconButton.types.d.ts.map +1 -0
- package/dist/src/components/IconButton/iconButton.variants.d.ts +26 -0
- package/dist/src/components/IconButton/iconButton.variants.d.ts.map +1 -0
- package/dist/src/components/Menu/Menu.d.ts +118 -0
- package/dist/src/components/Menu/Menu.d.ts.map +1 -0
- package/dist/src/components/Menu/menu.types.d.ts +179 -0
- package/dist/src/components/Menu/menu.types.d.ts.map +1 -0
- package/dist/src/components/Menu/menu.variants.d.ts +129 -0
- package/dist/src/components/Menu/menu.variants.d.ts.map +1 -0
- package/dist/src/components/Snackbar/Snackbar.d.ts.map +1 -1
- package/dist/src/components/Snackbar/snackbar.types.d.ts +40 -3
- package/dist/src/components/Snackbar/snackbar.types.d.ts.map +1 -1
- package/dist/src/components/Snackbar/snackbar.variants.d.ts +12 -57
- package/dist/src/components/Snackbar/snackbar.variants.d.ts.map +1 -1
- package/dist/src/components/Spinner/Spinner.d.ts +44 -0
- package/dist/src/components/Spinner/Spinner.d.ts.map +1 -0
- package/dist/src/components/Spinner/spinner.types.d.ts +89 -0
- package/dist/src/components/Spinner/spinner.types.d.ts.map +1 -0
- package/dist/src/components/Spinner/spinner.variants.d.ts +111 -0
- package/dist/src/components/Spinner/spinner.variants.d.ts.map +1 -0
- package/dist/src/components/Table/cells/RenderChip.d.ts +15 -72
- package/dist/src/components/Table/cells/RenderChip.d.ts.map +1 -1
- package/dist/src/components/_shared/severity/index.d.ts +21 -0
- package/dist/src/components/_shared/severity/index.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severity.types.d.ts +48 -0
- package/dist/src/components/_shared/severity/severity.types.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severityIcons.d.ts +45 -0
- package/dist/src/components/_shared/severity/severityIcons.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severityVariants.d.ts +22 -0
- package/dist/src/components/_shared/severity/severityVariants.d.ts.map +1 -0
- package/dist/src/index.d.ts +27 -2
- package/dist/src/index.d.ts.map +1 -1
- package/package.json +8 -7
- package/src/components/Alert/Alert.test.tsx +302 -0
- package/src/components/Alert/Alert.tsx +186 -0
- package/src/components/Alert/alert.types.ts +144 -0
- package/src/components/Alert/alert.variants.ts +71 -0
- package/src/components/Autocomplete/autocomplete.variants.ts +1 -1
- package/src/components/Avatar/Avatar.test.tsx +287 -0
- package/src/components/Avatar/Avatar.tsx +304 -0
- package/src/components/Avatar/avatar.types.ts +205 -0
- package/src/components/Avatar/avatar.variants.ts +194 -0
- package/src/components/Badge/Badge.test.tsx +385 -0
- package/src/components/Badge/Badge.tsx +174 -0
- package/src/components/Badge/badge.types.ts +154 -0
- package/src/components/Badge/badge.variants.ts +161 -0
- package/src/components/Box/Box.test.tsx +21 -0
- package/src/components/Box/Box.tsx +32 -3
- package/src/components/Box/box.types.ts +55 -0
- package/src/components/Button/Button.test.tsx +21 -0
- package/src/components/Button/Button.tsx +28 -27
- package/src/components/Button/button.types.ts +36 -0
- package/src/components/Card/Card.test.tsx +291 -0
- package/src/components/Card/Card.tsx +241 -0
- package/src/components/Card/card.types.ts +132 -0
- package/src/components/Chip/Chip.test.tsx +316 -0
- package/src/components/Chip/Chip.tsx +224 -0
- package/src/components/Chip/chip.types.ts +128 -0
- package/src/components/Chip/chip.variants.ts +173 -0
- package/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx +1 -1
- package/src/components/IconButton/IconButton.test.tsx +367 -0
- package/src/components/IconButton/IconButton.tsx +159 -0
- package/src/components/IconButton/iconButton.types.ts +106 -0
- package/src/components/IconButton/iconButton.variants.ts +31 -0
- package/src/components/LeftNav/leftNav.variants.ts +2 -2
- package/src/components/Menu/Menu.test.tsx +408 -0
- package/src/components/Menu/Menu.tsx +335 -0
- package/src/components/Menu/menu.types.ts +221 -0
- package/src/components/Menu/menu.variants.ts +132 -0
- package/src/components/Pagination/pagination.variants.ts +1 -1
- package/src/components/Snackbar/Snackbar.tsx +46 -28
- package/src/components/Snackbar/snackbar.types.ts +47 -3
- package/src/components/Snackbar/snackbar.variants.ts +29 -22
- package/src/components/Spinner/Spinner.test.tsx +199 -0
- package/src/components/Spinner/Spinner.tsx +158 -0
- package/src/components/Spinner/spinner.types.ts +113 -0
- package/src/components/Spinner/spinner.variants.ts +83 -0
- package/src/components/Table/cells/RenderChip.tsx +24 -87
- package/src/components/Table/cells/RowActionsMenu.tsx +1 -1
- package/src/components/TextField/TextField.test.tsx +5 -1
- package/src/components/_shared/severity/index.ts +33 -0
- package/src/components/_shared/severity/severity.types.ts +50 -0
- package/src/components/_shared/severity/severityIcons.tsx +104 -0
- package/src/components/_shared/severity/severityVariants.test.ts +136 -0
- package/src/components/_shared/severity/severityVariants.ts +115 -0
- package/src/index.ts +163 -1
- package/vite.config.ts +8 -0
- package/vitest.config.mts +8 -1
- package/LICENSE +0 -21
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
2
|
+
/**
|
|
3
|
+
* Tailwind-variants recipe for `<Chip>` — promoted from the internal
|
|
4
|
+
* `Table/cells/RenderChip` (Sprint 4.4). The visual treatment is
|
|
5
|
+
* preserved byte-identical: the same 3 × 7 compound matrix
|
|
6
|
+
* (variant × color) emitted by RenderChip is now the single source
|
|
7
|
+
* of truth, consumed by both the public `<Chip>` and (via thin
|
|
8
|
+
* wrapper) the legacy `RenderChip` internal.
|
|
9
|
+
*
|
|
10
|
+
* Slots (only `root` slot used by the public Chip; sub-slots
|
|
11
|
+
* surfaced via separate inline classes in `Chip.tsx`):
|
|
12
|
+
* - `root` — outer chip surface
|
|
13
|
+
*
|
|
14
|
+
* Variants axis (3 × 7, plus orthogonal `size`):
|
|
15
|
+
* - `color`: 7 intents (`neutral / primary / secondary / success /
|
|
16
|
+
* warning / danger / info`)
|
|
17
|
+
* - `variant`: `soft` (default) / `solid` / `outline`
|
|
18
|
+
* - `size`: `sm` (default) / `md`
|
|
19
|
+
*
|
|
20
|
+
* Token-driven: every Tailwind utility resolves through
|
|
21
|
+
* `dashforgePreset()` → CSS variables. No hardcoded hex.
|
|
22
|
+
*
|
|
23
|
+
* `dark:` variants on color palettes (lines 49-77 of legacy
|
|
24
|
+
* RenderChip, preserved here) are INTENTIONAL — color palettes do not
|
|
25
|
+
* auto-invert via the CSS-var swap (only the `neutral` palette does),
|
|
26
|
+
* so the `dark:` shift is a deliberate design choice (darker bg +
|
|
27
|
+
* lighter text in dark mode for visual cohesion). `dark:` on the
|
|
28
|
+
* `neutral` row is AVOIDED — that would double-invert.
|
|
29
|
+
*/
|
|
30
|
+
export declare const chipVariants: import("tailwind-variants").TVReturnType<{
|
|
31
|
+
color: {
|
|
32
|
+
neutral: string;
|
|
33
|
+
primary: string;
|
|
34
|
+
secondary: string;
|
|
35
|
+
success: string;
|
|
36
|
+
warning: string;
|
|
37
|
+
danger: string;
|
|
38
|
+
info: string;
|
|
39
|
+
};
|
|
40
|
+
variant: {
|
|
41
|
+
soft: string;
|
|
42
|
+
solid: string;
|
|
43
|
+
outline: string;
|
|
44
|
+
};
|
|
45
|
+
size: {
|
|
46
|
+
sm: string;
|
|
47
|
+
md: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Clickable state — adds focus ring + hover transition. Applied
|
|
51
|
+
* when the chip renders as `<button>` (i.e. `onClick` or
|
|
52
|
+
* explicit `clickable` is set).
|
|
53
|
+
*/
|
|
54
|
+
clickable: {
|
|
55
|
+
true: string[];
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Selected state — used on filter chips to indicate active
|
|
59
|
+
* selection. Visually shifts the chip to a heavier emphasis
|
|
60
|
+
* (one step up the elevation ladder of its current variant).
|
|
61
|
+
* Compound rules below apply the actual shift per (variant, color)
|
|
62
|
+
* cell.
|
|
63
|
+
*/
|
|
64
|
+
selected: {
|
|
65
|
+
true: string;
|
|
66
|
+
};
|
|
67
|
+
/** Disabled state for clickable chips. */
|
|
68
|
+
disabled: {
|
|
69
|
+
true: string;
|
|
70
|
+
};
|
|
71
|
+
}, undefined, string[], {
|
|
72
|
+
color: {
|
|
73
|
+
neutral: string;
|
|
74
|
+
primary: string;
|
|
75
|
+
secondary: string;
|
|
76
|
+
success: string;
|
|
77
|
+
warning: string;
|
|
78
|
+
danger: string;
|
|
79
|
+
info: string;
|
|
80
|
+
};
|
|
81
|
+
variant: {
|
|
82
|
+
soft: string;
|
|
83
|
+
solid: string;
|
|
84
|
+
outline: string;
|
|
85
|
+
};
|
|
86
|
+
size: {
|
|
87
|
+
sm: string;
|
|
88
|
+
md: string;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Clickable state — adds focus ring + hover transition. Applied
|
|
92
|
+
* when the chip renders as `<button>` (i.e. `onClick` or
|
|
93
|
+
* explicit `clickable` is set).
|
|
94
|
+
*/
|
|
95
|
+
clickable: {
|
|
96
|
+
true: string[];
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Selected state — used on filter chips to indicate active
|
|
100
|
+
* selection. Visually shifts the chip to a heavier emphasis
|
|
101
|
+
* (one step up the elevation ladder of its current variant).
|
|
102
|
+
* Compound rules below apply the actual shift per (variant, color)
|
|
103
|
+
* cell.
|
|
104
|
+
*/
|
|
105
|
+
selected: {
|
|
106
|
+
true: string;
|
|
107
|
+
};
|
|
108
|
+
/** Disabled state for clickable chips. */
|
|
109
|
+
disabled: {
|
|
110
|
+
true: string;
|
|
111
|
+
};
|
|
112
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
113
|
+
color: {
|
|
114
|
+
neutral: string;
|
|
115
|
+
primary: string;
|
|
116
|
+
secondary: string;
|
|
117
|
+
success: string;
|
|
118
|
+
warning: string;
|
|
119
|
+
danger: string;
|
|
120
|
+
info: string;
|
|
121
|
+
};
|
|
122
|
+
variant: {
|
|
123
|
+
soft: string;
|
|
124
|
+
solid: string;
|
|
125
|
+
outline: string;
|
|
126
|
+
};
|
|
127
|
+
size: {
|
|
128
|
+
sm: string;
|
|
129
|
+
md: string;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Clickable state — adds focus ring + hover transition. Applied
|
|
133
|
+
* when the chip renders as `<button>` (i.e. `onClick` or
|
|
134
|
+
* explicit `clickable` is set).
|
|
135
|
+
*/
|
|
136
|
+
clickable: {
|
|
137
|
+
true: string[];
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Selected state — used on filter chips to indicate active
|
|
141
|
+
* selection. Visually shifts the chip to a heavier emphasis
|
|
142
|
+
* (one step up the elevation ladder of its current variant).
|
|
143
|
+
* Compound rules below apply the actual shift per (variant, color)
|
|
144
|
+
* cell.
|
|
145
|
+
*/
|
|
146
|
+
selected: {
|
|
147
|
+
true: string;
|
|
148
|
+
};
|
|
149
|
+
/** Disabled state for clickable chips. */
|
|
150
|
+
disabled: {
|
|
151
|
+
true: string;
|
|
152
|
+
};
|
|
153
|
+
}, undefined, string[], unknown, unknown, undefined>>;
|
|
154
|
+
export type ChipVariants = VariantProps<typeof chipVariants>;
|
|
155
|
+
//# sourceMappingURL=chip.variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chip.variants.d.ts","sourceRoot":"","sources":["../../../../src/components/Chip/chip.variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;IA2BrB;;;;OAIG;;;;IAOH;;;;;;OAMG;;;;IAIH,0CAA0C;;;;;;;;;;;;;;;;;;;;;;;IArB1C;;;;OAIG;;;;IAOH;;;;;;OAMG;;;;IAIH,0CAA0C;;;;;;;;;;;;;;;;;;;;;;;IArB1C;;;;OAIG;;;;IAOH;;;;;;OAMG;;;;IAIH,0CAA0C;;;;qDA4F5C,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { IconButtonProps } from './iconButton.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Dashforge TW IconButton — square, icon-only action button.
|
|
4
|
+
*
|
|
5
|
+
* Reuses `buttonVariants` 1:1 (same `variant` / `color` / `size` /
|
|
6
|
+
* `loading` axes) so every `<Button>` style maps to the equivalent
|
|
7
|
+
* `<IconButton>` with zero code duplication. The ONLY additions are:
|
|
8
|
+
*
|
|
9
|
+
* - `ICON_BUTTON_SIZE_OVERRIDES` — forces `w-N + px-0` so the button
|
|
10
|
+
* is square at every size token
|
|
11
|
+
* - `ICON_BUTTON_BASE` — `aspect-square inline-flex items-center
|
|
12
|
+
* justify-center` for layout
|
|
13
|
+
*
|
|
14
|
+
* Both additions are token-driven (spacing) or layout-primitive
|
|
15
|
+
* (geometry) — no hardcoded hex, no `dark:` variants.
|
|
16
|
+
*
|
|
17
|
+
* **`aria-label` is REQUIRED** at the type level — icon-only buttons
|
|
18
|
+
* are invisible to assistive tech without an explicit accessible
|
|
19
|
+
* name. The TypeScript compiler enforces this rather than relying on
|
|
20
|
+
* runtime warnings.
|
|
21
|
+
*
|
|
22
|
+
* RBAC integration mirrors `<Button>`: `access` with
|
|
23
|
+
* `onUnauthorized: 'hide' | 'disable' | 'readonly'`. No `visibleWhen`
|
|
24
|
+
* (mirror Button — buttons should disable, not hide, on
|
|
25
|
+
* state-driven unavailability; permission-driven hiding is `access`).
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* import { Trash2 } from 'lucide-react';
|
|
30
|
+
*
|
|
31
|
+
* <IconButton aria-label="Delete row" color="danger" onClick={onDelete}>
|
|
32
|
+
* <Trash2 size={20} />
|
|
33
|
+
* </IconButton>
|
|
34
|
+
*
|
|
35
|
+
* // Polymorphism via Radix Slot
|
|
36
|
+
* <IconButton asChild aria-label="Open settings" variant="ghost">
|
|
37
|
+
* <Link to="/settings"><SettingsIcon size={20} /></Link>
|
|
38
|
+
* </IconButton>
|
|
39
|
+
*
|
|
40
|
+
* // RBAC-gated
|
|
41
|
+
* <IconButton
|
|
42
|
+
* aria-label="Publish article"
|
|
43
|
+
* variant="solid"
|
|
44
|
+
* color="primary"
|
|
45
|
+
* access={{ resource: 'article', action: 'publish', onUnauthorized: 'disable' }}
|
|
46
|
+
* >
|
|
47
|
+
* <PublishIcon size={20} />
|
|
48
|
+
* </IconButton>
|
|
49
|
+
*
|
|
50
|
+
* // Loading swap
|
|
51
|
+
* <IconButton aria-label="Save" loading={isSaving}>
|
|
52
|
+
* <SaveIcon size={20} />
|
|
53
|
+
* </IconButton>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare const IconButton: import("react").ForwardRefExoticComponent<IconButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
57
|
+
//# sourceMappingURL=IconButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconButton.d.ts","sourceRoot":"","sources":["../../../../src/components/IconButton/IconButton.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAY7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,eAAO,MAAM,UAAU,+GAgFtB,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import type { ClassValue } from 'tailwind-variants';
|
|
3
|
+
import type { Engine } from '@dashforge/ui-core';
|
|
4
|
+
import type { AccessRequirement } from '@dashforge/rbac';
|
|
5
|
+
import type { ButtonVariants } from '../Button/button.variants.js';
|
|
6
|
+
/**
|
|
7
|
+
* Props for `<IconButton>`.
|
|
8
|
+
*
|
|
9
|
+
* IconButton is the **icon-only variant of `<Button>`** — it reuses
|
|
10
|
+
* `buttonVariants` 1:1 (same `variant` × `color` × `size` × `loading`
|
|
11
|
+
* compound matrix) and adds:
|
|
12
|
+
*
|
|
13
|
+
* - Square geometry (width = height = size token, `aspect-square`)
|
|
14
|
+
* - Zero horizontal padding (no text to pad around)
|
|
15
|
+
* - **`aria-label` REQUIRED** at the type level — icon-only buttons
|
|
16
|
+
* are invisible to screen readers without an explicit label, so we
|
|
17
|
+
* enforce it via TypeScript rather than runtime warning.
|
|
18
|
+
*
|
|
19
|
+
* Notes on excluded props (deliberate parity with `<Button>`):
|
|
20
|
+
* - **No `slotProps`** — IconButton renders a single DOM element
|
|
21
|
+
* (`<button>` plus a transient loading swap); `className` + `sx`
|
|
22
|
+
* cover the override surface fully, matching Button.
|
|
23
|
+
* - **No `fullWidth`** — meaningless on an icon-sized button.
|
|
24
|
+
*
|
|
25
|
+
* As of 1.1.0 (Sprint 4.4 alignment), IconButton + Button both
|
|
26
|
+
* support `visibleWhen` — see prop docs below.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* import { TrashIcon } from 'lucide-react';
|
|
31
|
+
*
|
|
32
|
+
* <IconButton aria-label="Delete row" color="danger" onClick={onDelete}>
|
|
33
|
+
* <TrashIcon size={20} />
|
|
34
|
+
* </IconButton>
|
|
35
|
+
*
|
|
36
|
+
* // Polymorphism via Radix Slot — wrap a router Link without nesting
|
|
37
|
+
* // a button inside an anchor.
|
|
38
|
+
* <IconButton asChild aria-label="Open settings" variant="ghost">
|
|
39
|
+
* <Link to="/settings"><SettingsIcon size={20} /></Link>
|
|
40
|
+
* </IconButton>
|
|
41
|
+
*
|
|
42
|
+
* // RBAC-gated
|
|
43
|
+
* <IconButton
|
|
44
|
+
* aria-label="Publish article"
|
|
45
|
+
* variant="solid"
|
|
46
|
+
* color="primary"
|
|
47
|
+
* access={{ resource: 'article', action: 'publish', onUnauthorized: 'disable' }}
|
|
48
|
+
* >
|
|
49
|
+
* <PublishIcon size={20} />
|
|
50
|
+
* </IconButton>
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export interface IconButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'color' | 'children'>, Pick<ButtonVariants, 'variant' | 'color' | 'size' | 'loading'> {
|
|
54
|
+
/**
|
|
55
|
+
* The icon — typically an SVG element from the consumer's icon
|
|
56
|
+
* library (Lucide / Phosphor / Tabler / inline SVG). A single
|
|
57
|
+
* `ReactNode` is expected.
|
|
58
|
+
*/
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
/**
|
|
61
|
+
* Required at the type level — icon-only buttons MUST have an
|
|
62
|
+
* accessible name. Pass a short verb phrase describing the action
|
|
63
|
+
* (e.g. `"Delete row"`, `"Open settings"`, NOT `"Trash icon"`).
|
|
64
|
+
*/
|
|
65
|
+
'aria-label': string;
|
|
66
|
+
/**
|
|
67
|
+
* Render-as-child via Radix Slot — the resolved IconButton
|
|
68
|
+
* className is forwarded to the immediate child element, no
|
|
69
|
+
* `<button>` DOM is emitted. Useful for router `<Link>`s.
|
|
70
|
+
* Same contract as `<Button asChild>`.
|
|
71
|
+
*/
|
|
72
|
+
asChild?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* RBAC requirement. When the current subject doesn't satisfy the
|
|
75
|
+
* requirement, the button is hidden / disabled / read-only per
|
|
76
|
+
* `onUnauthorized`. Same contract as `<Button access>`.
|
|
77
|
+
*/
|
|
78
|
+
access?: AccessRequirement;
|
|
79
|
+
/**
|
|
80
|
+
* Reactive visibility predicate — same contract as `<Button>` and
|
|
81
|
+
* `<Chip>`. When the predicate returns `false`, the component
|
|
82
|
+
* renders `null`. Inside a `<DashForm>` it subscribes to engine
|
|
83
|
+
* state and re-evaluates on every change; outside a form, it's
|
|
84
|
+
* called with `null` engine (capture external state in closure).
|
|
85
|
+
*
|
|
86
|
+
* Added in 1.1.0 (Sprint 4.4 alignment) to keep IconButton in
|
|
87
|
+
* lockstep with Button.
|
|
88
|
+
*/
|
|
89
|
+
visibleWhen?: (engine: Engine) => boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Root-element class shortcut (string or `clsx`-compatible value).
|
|
92
|
+
* Last-wins via `tailwind-merge` inside `cn()`.
|
|
93
|
+
*/
|
|
94
|
+
sx?: ClassValue;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=iconButton.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iconButton.types.d.ts","sourceRoot":"","sources":["../../../../src/components/IconButton/iconButton.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,WAAW,eACf,SAAQ,IAAI,CACR,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,OAAO,GAAG,UAAU,CACrB,EACD,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAChE;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;OAIG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAE1C;;;OAGG;IACH,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ButtonVariants } from '../Button/button.variants.js';
|
|
2
|
+
/**
|
|
3
|
+
* IconButton size overrides — applied ON TOP of `buttonVariants(...)`.
|
|
4
|
+
*
|
|
5
|
+
* Button's `size` axis sets `h-X` + `px-Y` (rectangular). For
|
|
6
|
+
* IconButton we need a SQUARE shape, so we:
|
|
7
|
+
* - zero out the horizontal padding (`px-0`)
|
|
8
|
+
* - set an explicit width that matches the height (`w-N` mirrors the
|
|
9
|
+
* `h-N` from Button's size variant)
|
|
10
|
+
*
|
|
11
|
+
* The `aspect-square` utility provides belt-and-braces in the edge
|
|
12
|
+
* case where Tailwind purges the explicit `w-N` (e.g., when the user
|
|
13
|
+
* passes `size` dynamically and the JIT can't statically see all
|
|
14
|
+
* combinations).
|
|
15
|
+
*
|
|
16
|
+
* Token propagation: `w-N` resolves to `var(--df-tw-spacing-N)`
|
|
17
|
+
* through `dashforgePreset()`, identical to how `h-N` works for
|
|
18
|
+
* Button. `patchTheme({ spacing: { 10: '2.75rem' } })` patches both
|
|
19
|
+
* Button height and IconButton size in lockstep.
|
|
20
|
+
*/
|
|
21
|
+
type IconButtonSize = NonNullable<ButtonVariants['size']>;
|
|
22
|
+
export declare const ICON_BUTTON_SIZE_OVERRIDES: Record<IconButtonSize, string>;
|
|
23
|
+
/** Always-applied layout primitives — not token-driven (geometric CSS). */
|
|
24
|
+
export declare const ICON_BUTTON_BASE = "aspect-square inline-flex items-center justify-center";
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=iconButton.variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iconButton.variants.d.ts","sourceRoot":"","sources":["../../../../src/components/IconButton/iconButton.variants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;GAkBG;AACH,KAAK,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;AAE1D,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAIrE,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,0DAA0D,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { MenuContentProps, MenuItemProps, MenuLabelProps, MenuProps, MenuSeparatorProps, MenuSkeletonProps, MenuTriggerProps } from './menu.types.js';
|
|
3
|
+
/**
|
|
4
|
+
* `<Menu>` — top-level provider that wraps Radix `DropdownMenu.Root`.
|
|
5
|
+
*
|
|
6
|
+
* Compound API:
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <Menu>
|
|
9
|
+
* <MenuTrigger>
|
|
10
|
+
* <IconButton aria-label="Actions"><MoreIcon /></IconButton>
|
|
11
|
+
* </MenuTrigger>
|
|
12
|
+
* <MenuContent>
|
|
13
|
+
* <MenuLabel>Actions</MenuLabel>
|
|
14
|
+
* <MenuItem onClick={onEdit}>Edit</MenuItem>
|
|
15
|
+
* <MenuSeparator />
|
|
16
|
+
* <MenuItem color="danger" onClick={onDelete}>Delete</MenuItem>
|
|
17
|
+
* </MenuContent>
|
|
18
|
+
* </Menu>
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Built on `@radix-ui/react-dropdown-menu` (purpose-built menu
|
|
22
|
+
* primitive with full WAI-ARIA menu pattern + keyboard nav
|
|
23
|
+
* + type-ahead + portal mount).
|
|
24
|
+
*
|
|
25
|
+
* Sub-menus and controlled selection mode are deliberately out of
|
|
26
|
+
* scope for v1 (Sprint 4.4) — composable via Radix primitives if
|
|
27
|
+
* needed via explicit sub-component opt-in (future).
|
|
28
|
+
*/
|
|
29
|
+
export declare function Menu({ children, open, defaultOpen, onOpenChange, closeOnItemClick, modal, }: MenuProps): import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
/**
|
|
31
|
+
* `<MenuTrigger>` — the element that opens the menu.
|
|
32
|
+
*
|
|
33
|
+
* Always renders the immediate child via Radix Slot (`asChild`) — the
|
|
34
|
+
* child receives the click handler + `aria-haspopup="menu"` +
|
|
35
|
+
* `aria-expanded` reactive to open state. Pass any interactive
|
|
36
|
+
* component as the child (`<IconButton>`, `<Button>`, `<Avatar>`,
|
|
37
|
+
* custom).
|
|
38
|
+
*/
|
|
39
|
+
export declare function MenuTrigger({ children }: MenuTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
/**
|
|
41
|
+
* `<MenuContent>` — the floating panel.
|
|
42
|
+
*
|
|
43
|
+
* Lazy-mounted via Radix Portal — zero DOM cost when the menu is
|
|
44
|
+
* closed (one of the perf properties we inherit from Radix +
|
|
45
|
+
* Atlaskit-style menus).
|
|
46
|
+
*
|
|
47
|
+
* Placement / sideOffset are read from the parent `<Menu>` via
|
|
48
|
+
* Radix context — we re-pull the `<Menu>` props via the
|
|
49
|
+
* `MenuContext` here.
|
|
50
|
+
*
|
|
51
|
+
* NB: placement is read from PARENT MENU PROPS, not from
|
|
52
|
+
* `<MenuContent>` directly — keeps the floating-positioning API on
|
|
53
|
+
* the provider where it belongs.
|
|
54
|
+
*/
|
|
55
|
+
export declare const MenuContent: import("react").ForwardRefExoticComponent<MenuContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
56
|
+
/**
|
|
57
|
+
* `<MenuItem>` — clickable row inside the menu.
|
|
58
|
+
*
|
|
59
|
+
* Memoized via `React.memo` for performance — re-renders only when
|
|
60
|
+
* its own props change, not when sibling items mutate. Pattern
|
|
61
|
+
* inspired by Atlaskit's `ButtonItem` optimization (one of the
|
|
62
|
+
* reasons Atlaskit menus stay responsive on large item lists).
|
|
63
|
+
*
|
|
64
|
+
* Bridge integration:
|
|
65
|
+
* - `access` — hides / disables the item per RBAC
|
|
66
|
+
* - `visibleWhen` — engine-reactive predicate
|
|
67
|
+
*
|
|
68
|
+
* Both gates fold into the visible/disabled state; when the
|
|
69
|
+
* predicate returns `false` OR `access` denies visibility, the
|
|
70
|
+
* item renders `null` (does NOT occupy a row in the menu, vs
|
|
71
|
+
* disabled which renders dimmed-but-present).
|
|
72
|
+
*/
|
|
73
|
+
declare function MenuItemImpl(props: MenuItemProps): import("react/jsx-runtime").JSX.Element | null;
|
|
74
|
+
export declare const MenuItem: import("react").MemoExoticComponent<typeof MenuItemImpl>;
|
|
75
|
+
/**
|
|
76
|
+
* `<MenuLabel>` — non-interactive group heading.
|
|
77
|
+
*
|
|
78
|
+
* Renders via Radix `DropdownMenu.Label` which carries the right
|
|
79
|
+
* ARIA semantics (`role="presentation"` — not announced as a
|
|
80
|
+
* `menuitem` by screen readers).
|
|
81
|
+
*/
|
|
82
|
+
export declare function MenuLabel({ children, className }: MenuLabelProps): import("react/jsx-runtime").JSX.Element;
|
|
83
|
+
/**
|
|
84
|
+
* `<MenuSeparator>` — horizontal divider between items.
|
|
85
|
+
*
|
|
86
|
+
* Renders via Radix `DropdownMenu.Separator` — semantically correct
|
|
87
|
+
* `role="separator"` for screen readers navigating the menu.
|
|
88
|
+
*/
|
|
89
|
+
export declare function MenuSeparator({ className }: MenuSeparatorProps): import("react/jsx-runtime").JSX.Element;
|
|
90
|
+
/**
|
|
91
|
+
* `<MenuSkeleton>` — Atlaskit-style loading state.
|
|
92
|
+
*
|
|
93
|
+
* Renders `count` placeholder rows (default 3) inside the menu while
|
|
94
|
+
* real items are being fetched. Each row matches the geometry of a
|
|
95
|
+
* real `<MenuItem>` (height, padding, icon slot) so the layout
|
|
96
|
+
* doesn't jump when the real data arrives.
|
|
97
|
+
*
|
|
98
|
+
* `withHeading=true` adds a skeleton heading at the top, mimicking a
|
|
99
|
+
* `<MenuLabel>` — useful when the real menu starts with a section
|
|
100
|
+
* label.
|
|
101
|
+
*
|
|
102
|
+
* Pure visual — no animation overhead beyond Tailwind's
|
|
103
|
+
* `animate-pulse` (motion-reduce-safe).
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```tsx
|
|
107
|
+
* <MenuContent>
|
|
108
|
+
* {isLoading ? (
|
|
109
|
+
* <MenuSkeleton count={5} withHeading />
|
|
110
|
+
* ) : (
|
|
111
|
+
* items.map((it) => <MenuItem key={it.id}>{it.label}</MenuItem>)
|
|
112
|
+
* )}
|
|
113
|
+
* </MenuContent>
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function MenuSkeleton({ count, withHeading, className, }: MenuSkeletonProps): import("react/jsx-runtime").JSX.Element;
|
|
117
|
+
export type { ReactNode };
|
|
118
|
+
//# sourceMappingURL=Menu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../../src/components/Menu/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAMf,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,iBAAiB,CAAC;AAmBzB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,gBAAuB,EACvB,KAAa,GACd,EAAE,SAAS,2CAaX;AAID;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CAEzD;AAID;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,6GAqCvB,CAAC;AAMF;;;;;;;;;;;;;;;;GAgBG;AACH,iBAAS,YAAY,CAAC,KAAK,EAAE,aAAa,kDAkDzC;AAED,eAAO,MAAM,QAAQ,0DAAqB,CAAC;AAK3C;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,cAAc,2CAOhE;AAID;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,EAAE,kBAAkB,2CAG9D;AAID;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAS,EACT,WAAmB,EACnB,SAAS,GACV,EAAE,iBAAiB,2CAkBnB;AAmBD,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ClassValue } from 'tailwind-variants';
|
|
3
|
+
import type { Engine } from '@dashforge/ui-core';
|
|
4
|
+
import type { AccessRequirement } from '@dashforge/rbac';
|
|
5
|
+
/**
|
|
6
|
+
* Placement of the menu content relative to the trigger. Maps 1:1 to
|
|
7
|
+
* Radix DropdownMenu's `side` + `align` pair via the internal
|
|
8
|
+
* helpers in Menu.tsx.
|
|
9
|
+
*/
|
|
10
|
+
export type MenuPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end';
|
|
11
|
+
/**
|
|
12
|
+
* Props for the top-level `<Menu>` provider.
|
|
13
|
+
*
|
|
14
|
+
* Wraps Radix `DropdownMenu.Root`. Provides open-state coordination
|
|
15
|
+
* + closeOnItemClick context for descendant `<MenuItem>`s.
|
|
16
|
+
*/
|
|
17
|
+
export interface MenuProps {
|
|
18
|
+
/** Compound children: `<MenuTrigger>` + `<MenuContent>`. */
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
/** Controlled open state. */
|
|
21
|
+
open?: boolean;
|
|
22
|
+
/** Default open state for uncontrolled mode. @default false */
|
|
23
|
+
defaultOpen?: boolean;
|
|
24
|
+
/** Open/close callback (controlled). */
|
|
25
|
+
onOpenChange?: (open: boolean) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Close the menu when an item is clicked. Set to `false` for
|
|
28
|
+
* filter-style menus where item clicks should NOT dismiss (e.g.,
|
|
29
|
+
* multi-select checkbox menus, sticky filter pills).
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
closeOnItemClick?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Placement of the content relative to the trigger.
|
|
35
|
+
* @default 'bottom-start'
|
|
36
|
+
*/
|
|
37
|
+
placement?: MenuPlacement;
|
|
38
|
+
/**
|
|
39
|
+
* Pixel offset between trigger and content along the perpendicular
|
|
40
|
+
* axis (e.g., for `placement='bottom-*'`, the vertical gap).
|
|
41
|
+
* @default 6
|
|
42
|
+
*/
|
|
43
|
+
sideOffset?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Modal mode (Radix). When `true`, the menu blocks interaction with
|
|
46
|
+
* the rest of the page (focus trap + outside scroll lock). When
|
|
47
|
+
* `false`, dismissal is automatic on outside-click but the page
|
|
48
|
+
* remains interactive. Default false matches the "lightweight
|
|
49
|
+
* action menu" pattern.
|
|
50
|
+
* @default false
|
|
51
|
+
*/
|
|
52
|
+
modal?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Props for `<MenuTrigger>` — the element that opens the menu.
|
|
56
|
+
*
|
|
57
|
+
* Always renders via Radix Slot — the immediate child element
|
|
58
|
+
* (typically `<IconButton>`, `<Button>`, or a custom interactive
|
|
59
|
+
* component) receives the click handler, `aria-haspopup="menu"`,
|
|
60
|
+
* and `aria-expanded` reactive to open state.
|
|
61
|
+
*/
|
|
62
|
+
export interface MenuTriggerProps {
|
|
63
|
+
/** The trigger element. */
|
|
64
|
+
children: ReactNode;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Props for `<MenuContent>` — the floating panel.
|
|
68
|
+
*
|
|
69
|
+
* Rendered through Radix `DropdownMenu.Portal`, lazily mounted only
|
|
70
|
+
* when the menu is open (cost zero in DOM when closed).
|
|
71
|
+
*/
|
|
72
|
+
export interface MenuContentProps {
|
|
73
|
+
/** Items + labels + separators + skeletons. */
|
|
74
|
+
children: ReactNode;
|
|
75
|
+
/** CSS min-width for the menu panel. */
|
|
76
|
+
minWidth?: number | string;
|
|
77
|
+
/** Standard className — appended to the root via `cn()`. */
|
|
78
|
+
className?: string;
|
|
79
|
+
/** Root-element class shortcut. */
|
|
80
|
+
sx?: ClassValue;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Visual / semantic color of a `<MenuItem>`. `'danger'` highlights
|
|
84
|
+
* destructive actions with a red hover state.
|
|
85
|
+
*/
|
|
86
|
+
export type MenuItemColor = 'default' | 'danger';
|
|
87
|
+
/**
|
|
88
|
+
* Props for `<MenuItem>` — a clickable row inside the menu.
|
|
89
|
+
*
|
|
90
|
+
* Memoized (`React.memo`) for perf — re-renders only on prop change.
|
|
91
|
+
* Pattern inspired by Atlaskit's ButtonItem optimization.
|
|
92
|
+
*/
|
|
93
|
+
export interface MenuItemProps {
|
|
94
|
+
/** Item label / content. */
|
|
95
|
+
children: ReactNode;
|
|
96
|
+
/**
|
|
97
|
+
* Click handler. After firing, the menu closes (unless the parent
|
|
98
|
+
* `<Menu closeOnItemClick={false}>` opts out).
|
|
99
|
+
*/
|
|
100
|
+
onClick?: () => void;
|
|
101
|
+
/** Leading icon slot. */
|
|
102
|
+
icon?: ReactNode;
|
|
103
|
+
/**
|
|
104
|
+
* Trailing slot — typically a keyboard shortcut (`"⌘K"`), a
|
|
105
|
+
* status hint, or a sub-menu chevron (when sub-menus arrive).
|
|
106
|
+
*/
|
|
107
|
+
endIcon?: ReactNode;
|
|
108
|
+
/** Disabled state — suppresses click + dims the item. */
|
|
109
|
+
disabled?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Visual hint of "active option" — for menus that show current
|
|
112
|
+
* selection (e.g., theme picker). No controlled selection state
|
|
113
|
+
* by design (v1) — purely visual.
|
|
114
|
+
*/
|
|
115
|
+
selected?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Color intent. `'danger'` highlights destructive actions
|
|
118
|
+
* (Delete, Remove, Sign out) with a red hover tint.
|
|
119
|
+
* @default 'default'
|
|
120
|
+
*/
|
|
121
|
+
color?: MenuItemColor;
|
|
122
|
+
/**
|
|
123
|
+
* RBAC requirement. When the current subject doesn't satisfy it,
|
|
124
|
+
* the item is hidden (or disabled per `onUnauthorized`).
|
|
125
|
+
*/
|
|
126
|
+
access?: AccessRequirement;
|
|
127
|
+
/**
|
|
128
|
+
* Reactive visibility predicate. When `false`, the item renders
|
|
129
|
+
* `null`. Use for state-driven menu items (e.g., "Restore" only
|
|
130
|
+
* when an item was just deleted).
|
|
131
|
+
*/
|
|
132
|
+
visibleWhen?: (engine: Engine) => boolean;
|
|
133
|
+
/** Standard className. */
|
|
134
|
+
className?: string;
|
|
135
|
+
/** Root-element class shortcut. */
|
|
136
|
+
sx?: ClassValue;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Props for `<MenuLabel>` — non-interactive group heading.
|
|
140
|
+
*
|
|
141
|
+
* Rendered as `role="presentation"` so screen readers don't
|
|
142
|
+
* announce it as a menuitem. Typical use: section dividers inside
|
|
143
|
+
* a menu ("Workspace", "Account", "Help").
|
|
144
|
+
*/
|
|
145
|
+
export interface MenuLabelProps {
|
|
146
|
+
children: ReactNode;
|
|
147
|
+
className?: string;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Props for `<MenuSeparator>` — horizontal divider between items.
|
|
151
|
+
*/
|
|
152
|
+
export interface MenuSeparatorProps {
|
|
153
|
+
className?: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Props for `<MenuSkeleton>` — Atlaskit-style loading state.
|
|
157
|
+
*
|
|
158
|
+
* Renders N placeholder rows that mimic the menu's item geometry,
|
|
159
|
+
* giving the user immediate visual feedback while the real items
|
|
160
|
+
* are being fetched (e.g., "Recent files" pulled from an API).
|
|
161
|
+
* Strictly perceived-performance UX: no animation overhead beyond
|
|
162
|
+
* Tailwind's `animate-pulse`.
|
|
163
|
+
*/
|
|
164
|
+
export interface MenuSkeletonProps {
|
|
165
|
+
/**
|
|
166
|
+
* Number of skeleton item rows to render.
|
|
167
|
+
* @default 3
|
|
168
|
+
*/
|
|
169
|
+
count?: number;
|
|
170
|
+
/**
|
|
171
|
+
* Show a skeleton heading at the top of the list (matches the
|
|
172
|
+
* height + indent of a real `<MenuLabel>`).
|
|
173
|
+
* @default false
|
|
174
|
+
*/
|
|
175
|
+
withHeading?: boolean;
|
|
176
|
+
/** Standard className. */
|
|
177
|
+
className?: string;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=menu.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Menu/menu.types.ts"],"names":[],"mappings":"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"}
|