@shadow-js/ui 0.0.0-stage → 1.0.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 +24 -0
- package/LICENSE +21 -0
- package/README.md +598 -2
- package/dist/cli.mjs +2293 -0
- package/dist/dev/cli/schema.d.ts +73 -0
- package/dist/dev/index.d.ts +6 -0
- package/dist/dev/index.js +5 -0
- package/dist/dev/locales/ar.d.ts +141 -0
- package/dist/dev/locales/ar.js +128 -0
- package/dist/dev/locales/ar.js.map +1 -0
- package/dist/dev/locales/en.d.ts +141 -0
- package/dist/dev/locales/en.js +128 -0
- package/dist/dev/locales/en.js.map +1 -0
- package/dist/dev/registry/utils/utils.d.ts +29 -0
- package/dist/dev/registry/utils/utils.js +27 -0
- package/dist/dev/registry/utils/utils.js.map +1 -0
- package/dist/dev/theme/theme-logic.d.ts +187 -0
- package/dist/dev/theme/theme-logic.js +184 -0
- package/dist/dev/theme/theme-logic.js.map +1 -0
- package/dist/dev/theme/theme-provider.d.ts +90 -0
- package/dist/dev/theme/theme-provider.js +150 -0
- package/dist/dev/theme/theme-provider.js.map +1 -0
- package/dist/prod/index.js +1 -0
- package/dist/prod/locales/ar.js +2 -0
- package/dist/prod/locales/ar.js.map +1 -0
- package/dist/prod/locales/en.js +2 -0
- package/dist/prod/locales/en.js.map +1 -0
- package/dist/prod/registry/utils/utils.js +2 -0
- package/dist/prod/registry/utils/utils.js.map +1 -0
- package/dist/prod/theme/theme-logic.js +2 -0
- package/dist/prod/theme/theme-logic.js.map +1 -0
- package/dist/prod/theme/theme-provider.js +2 -0
- package/dist/prod/theme/theme-provider.js.map +1 -0
- package/package.json +102 -4
- package/registry/accordion/accordion.tsx +210 -0
- package/registry/accordion/item.json +4 -0
- package/registry/alert/alert.tsx +200 -0
- package/registry/alert/item.json +4 -0
- package/registry/alert-dialog/alert-dialog.tsx +530 -0
- package/registry/alert-dialog/item.json +4 -0
- package/registry/aspect-ratio/aspect-ratio.tsx +71 -0
- package/registry/aspect-ratio/item.json +4 -0
- package/registry/attachment/attachment.tsx +459 -0
- package/registry/attachment/item.json +4 -0
- package/registry/avatar/avatar.tsx +385 -0
- package/registry/avatar/item.json +4 -0
- package/registry/badge/badge.tsx +108 -0
- package/registry/badge/item.json +4 -0
- package/registry/breadcrumb/breadcrumb.tsx +354 -0
- package/registry/breadcrumb/item.json +4 -0
- package/registry/bubble/bubble.tsx +260 -0
- package/registry/bubble/item.json +4 -0
- package/registry/button/button.tsx +125 -0
- package/registry/button/item.json +4 -0
- package/registry/button-group/button-group.tsx +189 -0
- package/registry/button-group/item.json +4 -0
- package/registry/calendar/calendar.tsx +348 -0
- package/registry/calendar/item.json +4 -0
- package/registry/card/card.tsx +311 -0
- package/registry/card/item.json +4 -0
- package/registry/carousel/carousel.tsx +851 -0
- package/registry/carousel/item.json +4 -0
- package/registry/chart/chart.tsx +1956 -0
- package/registry/chart/item.json +4 -0
- package/registry/chart-scale/chart-scale.ts +670 -0
- package/registry/chart-scale/item.json +5 -0
- package/registry/checkbox/checkbox.tsx +79 -0
- package/registry/checkbox/item.json +4 -0
- package/registry/code-block/code-block.tsx +470 -0
- package/registry/code-block/item.json +4 -0
- package/registry/collapsible/collapsible.tsx +117 -0
- package/registry/collapsible/item.json +4 -0
- package/registry/combobox/combobox.tsx +977 -0
- package/registry/combobox/item.json +4 -0
- package/registry/command/command.tsx +757 -0
- package/registry/command/item.json +4 -0
- package/registry/context-menu/context-menu.tsx +697 -0
- package/registry/context-menu/item.json +4 -0
- package/registry/data-table/data-table.tsx +437 -0
- package/registry/data-table/item.json +4 -0
- package/registry/date-picker/date-picker.tsx +349 -0
- package/registry/date-picker/item.json +4 -0
- package/registry/dialog/dialog.tsx +412 -0
- package/registry/dialog/item.json +4 -0
- package/registry/direction/direction.tsx +88 -0
- package/registry/direction/item.json +4 -0
- package/registry/drawer/drawer.tsx +787 -0
- package/registry/drawer/item.json +4 -0
- package/registry/dropdown-menu/dropdown-menu.tsx +692 -0
- package/registry/dropdown-menu/item.json +4 -0
- package/registry/empty/empty.tsx +240 -0
- package/registry/empty/item.json +4 -0
- package/registry/field/field.tsx +624 -0
- package/registry/field/item.json +4 -0
- package/registry/form/form.tsx +1112 -0
- package/registry/form/item.json +4 -0
- package/registry/hover-card/hover-card.tsx +144 -0
- package/registry/hover-card/item.json +4 -0
- package/registry/icons/icons.tsx +1691 -0
- package/registry/icons/item.json +4 -0
- package/registry/input/input.tsx +43 -0
- package/registry/input/item.json +4 -0
- package/registry/input-group/input-group.tsx +315 -0
- package/registry/input-group/item.json +4 -0
- package/registry/input-otp/input-otp.tsx +329 -0
- package/registry/input-otp/item.json +4 -0
- package/registry/item/item.json +4 -0
- package/registry/item/item.tsx +439 -0
- package/registry/kbd/item.json +4 -0
- package/registry/kbd/kbd.tsx +65 -0
- package/registry/label/item.json +4 -0
- package/registry/label/label.tsx +60 -0
- package/registry/marker/item.json +4 -0
- package/registry/marker/marker.tsx +175 -0
- package/registry/menubar/item.json +4 -0
- package/registry/menubar/menubar.tsx +694 -0
- package/registry/message/item.json +4 -0
- package/registry/message/message.tsx +280 -0
- package/registry/message-scroller/item.json +4 -0
- package/registry/message-scroller/message-scroller.tsx +262 -0
- package/registry/native-select/item.json +4 -0
- package/registry/native-select/native-select.tsx +113 -0
- package/registry/navigation-menu/item.json +4 -0
- package/registry/navigation-menu/navigation-menu.tsx +362 -0
- package/registry/pagination/item.json +4 -0
- package/registry/pagination/pagination.tsx +460 -0
- package/registry/password-input/item.json +5 -0
- package/registry/password-input/password-input.tsx +494 -0
- package/registry/popover/item.json +4 -0
- package/registry/popover/popover.tsx +284 -0
- package/registry/progress/item.json +4 -0
- package/registry/progress/progress.tsx +190 -0
- package/registry/questionnaire/item.json +4 -0
- package/registry/questionnaire/questionnaire.tsx +569 -0
- package/registry/radio-group/item.json +4 -0
- package/registry/radio-group/radio-group.tsx +101 -0
- package/registry/resizable/item.json +4 -0
- package/registry/resizable/resizable.tsx +455 -0
- package/registry/scroll-area/item.json +4 -0
- package/registry/scroll-area/scroll-area.tsx +149 -0
- package/registry/select/item.json +4 -0
- package/registry/select/select.tsx +571 -0
- package/registry/separator/item.json +4 -0
- package/registry/separator/separator.tsx +52 -0
- package/registry/sheet/item.json +4 -0
- package/registry/sheet/sheet.tsx +476 -0
- package/registry/sidebar/item.json +4 -0
- package/registry/sidebar/sidebar.tsx +1870 -0
- package/registry/skeleton/item.json +4 -0
- package/registry/skeleton/skeleton.tsx +47 -0
- package/registry/slider/item.json +4 -0
- package/registry/slider/slider.tsx +149 -0
- package/registry/spinner/item.json +4 -0
- package/registry/spinner/spinner.tsx +51 -0
- package/registry/switch/item.json +4 -0
- package/registry/switch/switch.tsx +93 -0
- package/registry/table/item.json +4 -0
- package/registry/table/table.tsx +373 -0
- package/registry/tabs/item.json +4 -0
- package/registry/tabs/tabs.tsx +209 -0
- package/registry/textarea/item.json +4 -0
- package/registry/textarea/textarea.tsx +51 -0
- package/registry/toast/item.json +4 -0
- package/registry/toast/toast.tsx +949 -0
- package/registry/toggle/item.json +4 -0
- package/registry/toggle/toggle.tsx +110 -0
- package/registry/toggle-group/item.json +4 -0
- package/registry/toggle-group/toggle-group.tsx +189 -0
- package/registry/tooltip/item.json +4 -0
- package/registry/tooltip/tooltip.tsx +169 -0
- package/registry/trace/item.json +4 -0
- package/registry/trace/trace.tsx +356 -0
- package/registry/ui-strings/item.json +5 -0
- package/registry/ui-strings/ui-strings.tsx +454 -0
- package/registry/use-highlighted-code/item.json +5 -0
- package/registry/use-highlighted-code/use-highlighted-code.tsx +145 -0
- package/registry/use-mobile/item.json +5 -0
- package/registry/use-mobile/use-mobile.ts +46 -0
- package/registry/utils/item.json +5 -0
- package/registry/utils/utils.ts +38 -0
- package/registry.json +3274 -0
- package/styles/animations.css +321 -0
- package/styles/theme-core.css +55 -0
- package/styles/theme.css +12 -0
- package/styles/themes/gray.css +69 -0
- package/styles/themes/neutral.css +69 -0
- package/styles/themes/slate.css +69 -0
- package/styles/themes/stone.css +69 -0
- package/styles/themes/zinc.css +69 -0
- package/styles/typeset.css +251 -0
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
import { splitProps } from "@shadow-js/core";
|
|
2
|
+
import {
|
|
3
|
+
DropdownMenu as DropdownMenuPrimitive,
|
|
4
|
+
type DropdownMenuProps,
|
|
5
|
+
type DropdownMenuTriggerProps,
|
|
6
|
+
type MenuCheckboxItemProps,
|
|
7
|
+
type MenuContentProps,
|
|
8
|
+
type MenuGroupProps,
|
|
9
|
+
type MenuItemOwnProps,
|
|
10
|
+
type MenuLabelProps,
|
|
11
|
+
type MenuPortalProps,
|
|
12
|
+
type MenuRadioGroupProps,
|
|
13
|
+
type MenuRadioItemProps,
|
|
14
|
+
type MenuSeparatorProps,
|
|
15
|
+
type MenuSubContentProps,
|
|
16
|
+
type MenuSubProps,
|
|
17
|
+
type MenuSubTriggerProps,
|
|
18
|
+
type PolymorphicProps,
|
|
19
|
+
type PolymorphicTarget,
|
|
20
|
+
} from "@shadow-js/primitives";
|
|
21
|
+
import type { ComponentProps, JSX } from "@shadow-js/web";
|
|
22
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from "@/components/ui/icons";
|
|
23
|
+
import { type ClassValue, cn } from "@/lib/utils";
|
|
24
|
+
|
|
25
|
+
/** The props as the implementation sees them: the typed own props plus whatever the target takes. */
|
|
26
|
+
type Loose = {
|
|
27
|
+
readonly as?: PolymorphicTarget;
|
|
28
|
+
readonly class?: ClassValue;
|
|
29
|
+
readonly inset?: boolean | undefined;
|
|
30
|
+
readonly variant?: "default" | "destructive" | undefined;
|
|
31
|
+
readonly children?: JSX.Element | undefined;
|
|
32
|
+
readonly [prop: string]: unknown;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** The placement and entrance animation shared by the menu panels. */
|
|
36
|
+
const PANEL =
|
|
37
|
+
"z-50 min-w-[8rem] origin-(--primitives-transform-origin) rounded-md border bg-popover p-1 text-popover-foreground outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95";
|
|
38
|
+
|
|
39
|
+
/** What every selectable row shares. */
|
|
40
|
+
const ROW =
|
|
41
|
+
"relative flex cursor-default items-center gap-2 rounded-sm text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 forced-colors:focus:bg-[Highlight] forced-colors:focus:text-[HighlightText] forced-colors:data-[disabled]:text-[GrayText] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A menu opened from a button, such as a user menu or a row's actions. It is controlled with `open` and
|
|
45
|
+
* `onOpenChange`, or uncontrolled with `defaultOpen`. `dir="rtl"` mirrors the arrow keys and the side
|
|
46
|
+
* of submenus.
|
|
47
|
+
*
|
|
48
|
+
* Keyboard and ARIA: this follows the WAI-ARIA menu button pattern. Enter and Space on the trigger
|
|
49
|
+
* toggle the menu, and opening it focuses the first item. ArrowDown opens it with the first item
|
|
50
|
+
* focused, and ArrowUp with the last. In the menu, the arrow keys, Home, End, PageUp, PageDown and
|
|
51
|
+
* typeahead move between items, and Enter or Space selects the focused item. Escape or Tab closes the
|
|
52
|
+
* menu and returns focus to the trigger. The trigger has `aria-haspopup="menu"`, `aria-expanded`, and
|
|
53
|
+
* `aria-controls` while the menu is open. The content is a `role="menu"` of `menuitem`,
|
|
54
|
+
* `menuitemcheckbox` and `menuitemradio` items, labeled by the trigger. A disabled item is skipped by
|
|
55
|
+
* the arrow keys and cannot be selected.
|
|
56
|
+
*
|
|
57
|
+
* shadcn/ui differences: `as` replaces `asChild` on the trigger and on items. The prop is `class`, not `className`, and every part has a `data-slot`.
|
|
58
|
+
*
|
|
59
|
+
* @param props The menu props: see {@link DropdownMenuProps}.
|
|
60
|
+
* @returns The menu. It renders no element of its own.
|
|
61
|
+
* @example
|
|
62
|
+
* import { Button } from "@/components/ui/button";
|
|
63
|
+
* import {
|
|
64
|
+
* DropdownMenu,
|
|
65
|
+
* DropdownMenuContent,
|
|
66
|
+
* DropdownMenuItem,
|
|
67
|
+
* DropdownMenuLabel,
|
|
68
|
+
* DropdownMenuSeparator,
|
|
69
|
+
* DropdownMenuTrigger,
|
|
70
|
+
* } from "@/components/ui/dropdown-menu";
|
|
71
|
+
*
|
|
72
|
+
* export function AccountMenu() {
|
|
73
|
+
* return (
|
|
74
|
+
* <DropdownMenu>
|
|
75
|
+
* <DropdownMenuTrigger as={Button} variant="outline">
|
|
76
|
+
* Open
|
|
77
|
+
* </DropdownMenuTrigger>
|
|
78
|
+
* <DropdownMenuContent>
|
|
79
|
+
* <DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
80
|
+
* <DropdownMenuSeparator />
|
|
81
|
+
* <DropdownMenuItem>Profile</DropdownMenuItem>
|
|
82
|
+
* </DropdownMenuContent>
|
|
83
|
+
* </DropdownMenu>
|
|
84
|
+
* );
|
|
85
|
+
* }
|
|
86
|
+
* @see {@link DropdownMenuTrigger}
|
|
87
|
+
* @see {@link DropdownMenuContent}
|
|
88
|
+
* @since 1.0.0
|
|
89
|
+
*/
|
|
90
|
+
function DropdownMenu(props: DropdownMenuProps): JSX.Element {
|
|
91
|
+
return <DropdownMenuPrimitive {...props} />;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Renders the menu into `document.body`, or into the `container` you pass, while it is open. Nothing is
|
|
96
|
+
* rendered on the server. {@link DropdownMenuContent} already portals itself, so use this only to choose
|
|
97
|
+
* another container.
|
|
98
|
+
*
|
|
99
|
+
* @param props The portal props: `container` and `forceMount`.
|
|
100
|
+
* @returns The portal, or nothing while the menu is closed.
|
|
101
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
102
|
+
* @example
|
|
103
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuPortal, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
104
|
+
*
|
|
105
|
+
* export function Portaled() {
|
|
106
|
+
* return (
|
|
107
|
+
* <DropdownMenu>
|
|
108
|
+
* <DropdownMenuTrigger>Open</DropdownMenuTrigger>
|
|
109
|
+
* <DropdownMenuPortal>
|
|
110
|
+
* <DropdownMenuContent>
|
|
111
|
+
* <DropdownMenuItem>Profile</DropdownMenuItem>
|
|
112
|
+
* </DropdownMenuContent>
|
|
113
|
+
* </DropdownMenuPortal>
|
|
114
|
+
* </DropdownMenu>
|
|
115
|
+
* );
|
|
116
|
+
* }
|
|
117
|
+
* @see {@link DropdownMenuContent}
|
|
118
|
+
* @since 1.0.0
|
|
119
|
+
*/
|
|
120
|
+
function DropdownMenuPortal(props: MenuPortalProps): JSX.Element {
|
|
121
|
+
return <DropdownMenuPrimitive.Portal {...props} />;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The button that opens the menu and anchors it. It is a native button by default; `as` renders another
|
|
126
|
+
* element, such as the shadcn `Button`. The keys are described on {@link DropdownMenu}.
|
|
127
|
+
*
|
|
128
|
+
* @param props The trigger props: the attributes of the rendered element, and `as`.
|
|
129
|
+
* @returns The trigger.
|
|
130
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
131
|
+
* @example
|
|
132
|
+
* import { Button } from "@/components/ui/button";
|
|
133
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
134
|
+
*
|
|
135
|
+
* export function OpenMenu() {
|
|
136
|
+
* return (
|
|
137
|
+
* <DropdownMenu>
|
|
138
|
+
* <DropdownMenuTrigger as={Button}>Open</DropdownMenuTrigger>
|
|
139
|
+
* <DropdownMenuContent>
|
|
140
|
+
* <DropdownMenuItem>Profile</DropdownMenuItem>
|
|
141
|
+
* </DropdownMenuContent>
|
|
142
|
+
* </DropdownMenu>
|
|
143
|
+
* );
|
|
144
|
+
* }
|
|
145
|
+
* @see {@link DropdownMenu}
|
|
146
|
+
* @since 1.0.0
|
|
147
|
+
*/
|
|
148
|
+
function DropdownMenuTrigger<T extends PolymorphicTarget = "button">(
|
|
149
|
+
props: DropdownMenuTriggerProps<T>,
|
|
150
|
+
): JSX.Element {
|
|
151
|
+
return <DropdownMenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The menu panel. It is rendered in `document.body`, placed against the trigger, and takes focus when it
|
|
156
|
+
* opens. The gap between the trigger and the panel is 4 px unless you pass `sideOffset`.
|
|
157
|
+
*
|
|
158
|
+
* @param props The panel props: the placement options (such as `align`), `sideOffset`, `class` and the
|
|
159
|
+
* attributes of the rendered `div`.
|
|
160
|
+
* @returns The panel, rendered in a portal while the menu is open.
|
|
161
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
162
|
+
* @example
|
|
163
|
+
* import { Button } from "@/components/ui/button";
|
|
164
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
165
|
+
*
|
|
166
|
+
* export function Actions() {
|
|
167
|
+
* return (
|
|
168
|
+
* <DropdownMenu>
|
|
169
|
+
* <DropdownMenuTrigger as={Button} variant="outline">
|
|
170
|
+
* Actions
|
|
171
|
+
* </DropdownMenuTrigger>
|
|
172
|
+
* <DropdownMenuContent align="end" class="w-56">
|
|
173
|
+
* <DropdownMenuItem>Duplicate</DropdownMenuItem>
|
|
174
|
+
* </DropdownMenuContent>
|
|
175
|
+
* </DropdownMenu>
|
|
176
|
+
* );
|
|
177
|
+
* }
|
|
178
|
+
* @see {@link DropdownMenuTrigger}
|
|
179
|
+
* @since 1.0.0
|
|
180
|
+
*/
|
|
181
|
+
function DropdownMenuContent(props: MenuContentProps): JSX.Element {
|
|
182
|
+
const [local, rest] = splitProps(props, ["class", "sideOffset"]);
|
|
183
|
+
return (
|
|
184
|
+
<DropdownMenuPortal>
|
|
185
|
+
<DropdownMenuPrimitive.Content
|
|
186
|
+
data-slot="dropdown-menu-content"
|
|
187
|
+
sideOffset={local.sideOffset ?? 4}
|
|
188
|
+
class={cn(
|
|
189
|
+
PANEL,
|
|
190
|
+
"max-h-(--primitives-available-height) overflow-x-hidden overflow-y-auto shadow-md",
|
|
191
|
+
local.class,
|
|
192
|
+
)}
|
|
193
|
+
{...rest}
|
|
194
|
+
/>
|
|
195
|
+
</DropdownMenuPortal>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* A group of related items, announced as a `role="group"`. The arrow keys skip it.
|
|
201
|
+
*
|
|
202
|
+
* @param props The group props: the attributes of the rendered `div`.
|
|
203
|
+
* @returns The group.
|
|
204
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
205
|
+
* @example
|
|
206
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
207
|
+
*
|
|
208
|
+
* export function Account() {
|
|
209
|
+
* return (
|
|
210
|
+
* <DropdownMenu>
|
|
211
|
+
* <DropdownMenuTrigger>Open</DropdownMenuTrigger>
|
|
212
|
+
* <DropdownMenuContent>
|
|
213
|
+
* <DropdownMenuGroup>
|
|
214
|
+
* <DropdownMenuItem>Profile</DropdownMenuItem>
|
|
215
|
+
* </DropdownMenuGroup>
|
|
216
|
+
* </DropdownMenuContent>
|
|
217
|
+
* </DropdownMenu>
|
|
218
|
+
* );
|
|
219
|
+
* }
|
|
220
|
+
* @see {@link DropdownMenuItem}
|
|
221
|
+
* @since 1.0.0
|
|
222
|
+
*/
|
|
223
|
+
function DropdownMenuGroup(props: MenuGroupProps): JSX.Element {
|
|
224
|
+
return <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Own props of {@link DropdownMenuItem}: the extra parts the item adds to the menu item props.
|
|
229
|
+
* @see {@link DropdownMenuItem}
|
|
230
|
+
* @since 1.0.0
|
|
231
|
+
*/
|
|
232
|
+
export interface DropdownMenuItemExtraProps {
|
|
233
|
+
/**
|
|
234
|
+
* Indents the item so it lines up with items that have an indicator.
|
|
235
|
+
* @default false
|
|
236
|
+
*/
|
|
237
|
+
readonly inset?: boolean | undefined;
|
|
238
|
+
/**
|
|
239
|
+
* Colors the item for a dangerous action when `destructive`.
|
|
240
|
+
* @default "default"
|
|
241
|
+
*/
|
|
242
|
+
readonly variant?: "default" | "destructive" | undefined;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Props of {@link DropdownMenuItem}: `onSelect` (called when the item is picked, and `preventDefault()`
|
|
247
|
+
* keeps the menu open), `disabled`, `inset`, `variant` and every attribute of the chosen element.
|
|
248
|
+
* @see {@link DropdownMenuItem}
|
|
249
|
+
* @since 1.0.0
|
|
250
|
+
*/
|
|
251
|
+
export type DropdownMenuItemProps<T extends PolymorphicTarget = "div"> = PolymorphicProps<
|
|
252
|
+
"div",
|
|
253
|
+
MenuItemOwnProps & DropdownMenuItemExtraProps,
|
|
254
|
+
T
|
|
255
|
+
>;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* An action in the menu. Selecting it, by a click, Enter or Space, closes the menu unless `onSelect`
|
|
259
|
+
* calls `event.preventDefault()`. A disabled item is skipped by the arrow keys and cannot be selected.
|
|
260
|
+
* It is a `role="menuitem"` with `tabindex="-1"`, and it has `data-highlighted` while it has focus.
|
|
261
|
+
* shadcn's `asChild` is the `as` prop here: `<DropdownMenuItem as="a" href="/settings">`.
|
|
262
|
+
*
|
|
263
|
+
* @param props The item props: see {@link DropdownMenuItemProps}.
|
|
264
|
+
* @returns The menu item.
|
|
265
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
266
|
+
* @example
|
|
267
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
268
|
+
*
|
|
269
|
+
* export function Delete() {
|
|
270
|
+
* const remove = (): void => {
|
|
271
|
+
* // Delete the item here.
|
|
272
|
+
* };
|
|
273
|
+
* return (
|
|
274
|
+
* <DropdownMenu>
|
|
275
|
+
* <DropdownMenuTrigger>Open</DropdownMenuTrigger>
|
|
276
|
+
* <DropdownMenuContent>
|
|
277
|
+
* <DropdownMenuItem variant="destructive" onSelect={remove}>
|
|
278
|
+
* Delete
|
|
279
|
+
* </DropdownMenuItem>
|
|
280
|
+
* </DropdownMenuContent>
|
|
281
|
+
* </DropdownMenu>
|
|
282
|
+
* );
|
|
283
|
+
* }
|
|
284
|
+
* @see {@link DropdownMenuContent}
|
|
285
|
+
* @since 1.0.0
|
|
286
|
+
*/
|
|
287
|
+
function DropdownMenuItem<T extends PolymorphicTarget = "div">(
|
|
288
|
+
props: DropdownMenuItemProps<T>,
|
|
289
|
+
): JSX.Element {
|
|
290
|
+
const [local, rest] = splitProps(props as unknown as Loose, ["class", "inset", "variant"]);
|
|
291
|
+
return (
|
|
292
|
+
<DropdownMenuPrimitive.Item
|
|
293
|
+
data-slot="dropdown-menu-item"
|
|
294
|
+
data-inset={local.inset === true ? "" : undefined}
|
|
295
|
+
data-variant={local.variant ?? "default"}
|
|
296
|
+
class={cn(
|
|
297
|
+
ROW,
|
|
298
|
+
"px-2 py-1.5 data-[inset]:ps-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive! [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
299
|
+
local.class,
|
|
300
|
+
)}
|
|
301
|
+
{...rest}
|
|
302
|
+
/>
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* An item that toggles a boolean and shows a check mark while it is checked. Enter, Space and a click
|
|
308
|
+
* toggle it, and it has `role="menuitemcheckbox"` with `aria-checked` (`"mixed"` while indeterminate).
|
|
309
|
+
* The state changes even when `onSelect` keeps the menu open.
|
|
310
|
+
*
|
|
311
|
+
* @param props The item props: `checked` (`true`, `false` or `"indeterminate"`), `onCheckedChange`, and
|
|
312
|
+
* the attributes of the item.
|
|
313
|
+
* @returns The checkbox item.
|
|
314
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
315
|
+
* @example
|
|
316
|
+
* import { useSignal } from "@shadow-js/core";
|
|
317
|
+
* import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
318
|
+
*
|
|
319
|
+
* export function View() {
|
|
320
|
+
* const [bookmarks, setBookmarks] = useSignal(true);
|
|
321
|
+
* return (
|
|
322
|
+
* <DropdownMenu>
|
|
323
|
+
* <DropdownMenuTrigger>View</DropdownMenuTrigger>
|
|
324
|
+
* <DropdownMenuContent>
|
|
325
|
+
* <DropdownMenuCheckboxItem checked={bookmarks()} onCheckedChange={setBookmarks}>
|
|
326
|
+
* Show bookmarks
|
|
327
|
+
* </DropdownMenuCheckboxItem>
|
|
328
|
+
* </DropdownMenuContent>
|
|
329
|
+
* </DropdownMenu>
|
|
330
|
+
* );
|
|
331
|
+
* }
|
|
332
|
+
* @see {@link DropdownMenuRadioGroup}
|
|
333
|
+
* @since 1.0.0
|
|
334
|
+
*/
|
|
335
|
+
function DropdownMenuCheckboxItem(props: MenuCheckboxItemProps): JSX.Element {
|
|
336
|
+
const [local, rest] = splitProps(props, ["class", "children"]);
|
|
337
|
+
return (
|
|
338
|
+
<DropdownMenuPrimitive.CheckboxItem
|
|
339
|
+
data-slot="dropdown-menu-checkbox-item"
|
|
340
|
+
class={cn(ROW, "py-1.5 ps-8 pe-2", local.class)}
|
|
341
|
+
{...rest}
|
|
342
|
+
>
|
|
343
|
+
<span class="pointer-events-none absolute start-2 flex size-3.5 items-center justify-center">
|
|
344
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
345
|
+
<CheckIcon class="size-4" />
|
|
346
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
347
|
+
</span>
|
|
348
|
+
{local.children}
|
|
349
|
+
</DropdownMenuPrimitive.CheckboxItem>
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* A group of mutually exclusive {@link DropdownMenuRadioItem}s. It is a `role="group"` and handles no
|
|
355
|
+
* keys itself; the items are navigated like any other menu item.
|
|
356
|
+
*
|
|
357
|
+
* @param props The group props: `value` (the selected item's value), `onValueChange`, and the
|
|
358
|
+
* attributes of the rendered `div`.
|
|
359
|
+
* @returns The group.
|
|
360
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
361
|
+
* @example
|
|
362
|
+
* import { useSignal } from "@shadow-js/core";
|
|
363
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
364
|
+
*
|
|
365
|
+
* export function Position() {
|
|
366
|
+
* const [position, setPosition] = useSignal("bottom");
|
|
367
|
+
* return (
|
|
368
|
+
* <DropdownMenu>
|
|
369
|
+
* <DropdownMenuTrigger>Position</DropdownMenuTrigger>
|
|
370
|
+
* <DropdownMenuContent>
|
|
371
|
+
* <DropdownMenuRadioGroup value={position()} onValueChange={setPosition}>
|
|
372
|
+
* <DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
|
|
373
|
+
* <DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
|
|
374
|
+
* </DropdownMenuRadioGroup>
|
|
375
|
+
* </DropdownMenuContent>
|
|
376
|
+
* </DropdownMenu>
|
|
377
|
+
* );
|
|
378
|
+
* }
|
|
379
|
+
* @see {@link DropdownMenuRadioItem}
|
|
380
|
+
* @since 1.0.0
|
|
381
|
+
*/
|
|
382
|
+
function DropdownMenuRadioGroup(props: MenuRadioGroupProps): JSX.Element {
|
|
383
|
+
return <DropdownMenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* An item of a {@link DropdownMenuRadioGroup}, with a dot while it is the selected one. It is a
|
|
388
|
+
* `role="menuitemradio"` with `aria-checked`. Enter, Space and a click select it, even when `onSelect`
|
|
389
|
+
* keeps the menu open.
|
|
390
|
+
*
|
|
391
|
+
* @param props The item props: `value` and the attributes of the item.
|
|
392
|
+
* @returns The radio item.
|
|
393
|
+
* @throws Error when rendered outside a {@link DropdownMenuRadioGroup}.
|
|
394
|
+
* @example
|
|
395
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
396
|
+
*
|
|
397
|
+
* export function Density() {
|
|
398
|
+
* return (
|
|
399
|
+
* <DropdownMenu>
|
|
400
|
+
* <DropdownMenuTrigger>Density</DropdownMenuTrigger>
|
|
401
|
+
* <DropdownMenuContent>
|
|
402
|
+
* <DropdownMenuRadioGroup value="compact">
|
|
403
|
+
* <DropdownMenuRadioItem value="compact">Compact</DropdownMenuRadioItem>
|
|
404
|
+
* </DropdownMenuRadioGroup>
|
|
405
|
+
* </DropdownMenuContent>
|
|
406
|
+
* </DropdownMenu>
|
|
407
|
+
* );
|
|
408
|
+
* }
|
|
409
|
+
* @see {@link DropdownMenuRadioGroup}
|
|
410
|
+
* @since 1.0.0
|
|
411
|
+
*/
|
|
412
|
+
function DropdownMenuRadioItem(props: MenuRadioItemProps): JSX.Element {
|
|
413
|
+
const [local, rest] = splitProps(props, ["class", "children"]);
|
|
414
|
+
return (
|
|
415
|
+
<DropdownMenuPrimitive.RadioItem
|
|
416
|
+
data-slot="dropdown-menu-radio-item"
|
|
417
|
+
class={cn(ROW, "py-1.5 ps-8 pe-2", local.class)}
|
|
418
|
+
{...rest}
|
|
419
|
+
>
|
|
420
|
+
<span class="pointer-events-none absolute start-2 flex size-3.5 items-center justify-center">
|
|
421
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
422
|
+
<CircleIcon class="size-2 fill-current" />
|
|
423
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
424
|
+
</span>
|
|
425
|
+
{local.children}
|
|
426
|
+
</DropdownMenuPrimitive.RadioItem>
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Props of {@link DropdownMenuLabel}: the attributes of the rendered `div` and `inset`, which indents the
|
|
432
|
+
* heading to line up with indented items.
|
|
433
|
+
* @see {@link DropdownMenuLabel}
|
|
434
|
+
* @since 1.0.0
|
|
435
|
+
*/
|
|
436
|
+
export type DropdownMenuLabelProps = MenuLabelProps & {
|
|
437
|
+
/**
|
|
438
|
+
* Indents the heading to line up with items that have an indicator.
|
|
439
|
+
* @default false
|
|
440
|
+
*/
|
|
441
|
+
readonly inset?: boolean | undefined;
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* A heading for a group of items. It has no role, is not focusable, and the arrow keys skip it.
|
|
446
|
+
*
|
|
447
|
+
* @param props The heading props: see {@link DropdownMenuLabelProps}.
|
|
448
|
+
* @returns The heading.
|
|
449
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
450
|
+
* @example
|
|
451
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
452
|
+
*
|
|
453
|
+
* export function AccountMenu() {
|
|
454
|
+
* return (
|
|
455
|
+
* <DropdownMenu>
|
|
456
|
+
* <DropdownMenuTrigger>Account</DropdownMenuTrigger>
|
|
457
|
+
* <DropdownMenuContent>
|
|
458
|
+
* <DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
459
|
+
* <DropdownMenuItem>Profile</DropdownMenuItem>
|
|
460
|
+
* </DropdownMenuContent>
|
|
461
|
+
* </DropdownMenu>
|
|
462
|
+
* );
|
|
463
|
+
* }
|
|
464
|
+
* @see {@link DropdownMenuGroup}
|
|
465
|
+
* @since 1.0.0
|
|
466
|
+
*/
|
|
467
|
+
function DropdownMenuLabel(props: DropdownMenuLabelProps): JSX.Element {
|
|
468
|
+
const [local, rest] = splitProps(props, ["class", "inset"]);
|
|
469
|
+
return (
|
|
470
|
+
<DropdownMenuPrimitive.Label
|
|
471
|
+
data-slot="dropdown-menu-label"
|
|
472
|
+
data-inset={local.inset === true ? "" : undefined}
|
|
473
|
+
class={cn("px-2 py-1.5 text-sm font-medium data-[inset]:ps-8", local.class)}
|
|
474
|
+
{...rest}
|
|
475
|
+
/>
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* A divider between groups of items. It is a `role="separator"` with a horizontal orientation.
|
|
481
|
+
*
|
|
482
|
+
* @param props The separator props: the attributes of the rendered `div`.
|
|
483
|
+
* @returns The separator.
|
|
484
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
485
|
+
* @example
|
|
486
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
487
|
+
*
|
|
488
|
+
* export function Divided() {
|
|
489
|
+
* return (
|
|
490
|
+
* <DropdownMenu>
|
|
491
|
+
* <DropdownMenuTrigger>Open</DropdownMenuTrigger>
|
|
492
|
+
* <DropdownMenuContent>
|
|
493
|
+
* <DropdownMenuItem>Back</DropdownMenuItem>
|
|
494
|
+
* <DropdownMenuSeparator />
|
|
495
|
+
* <DropdownMenuItem>Delete</DropdownMenuItem>
|
|
496
|
+
* </DropdownMenuContent>
|
|
497
|
+
* </DropdownMenu>
|
|
498
|
+
* );
|
|
499
|
+
* }
|
|
500
|
+
* @see {@link DropdownMenuGroup}
|
|
501
|
+
* @since 1.0.0
|
|
502
|
+
*/
|
|
503
|
+
function DropdownMenuSeparator(props: MenuSeparatorProps): JSX.Element {
|
|
504
|
+
const [local, rest] = splitProps(props, ["class"]);
|
|
505
|
+
return (
|
|
506
|
+
<DropdownMenuPrimitive.Separator
|
|
507
|
+
data-slot="dropdown-menu-separator"
|
|
508
|
+
class={cn("-mx-1 my-1 h-px bg-border", local.class)}
|
|
509
|
+
{...rest}
|
|
510
|
+
/>
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* A keyboard shortcut hint at the end of an item. It is decorative: it does not add a key binding.
|
|
516
|
+
*
|
|
517
|
+
* @param props The hint props: the attributes of the rendered `span`, and `children` (the shortcut text).
|
|
518
|
+
* @returns The hint.
|
|
519
|
+
* @example
|
|
520
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuShortcut, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
521
|
+
*
|
|
522
|
+
* export function Editing() {
|
|
523
|
+
* return (
|
|
524
|
+
* <DropdownMenu>
|
|
525
|
+
* <DropdownMenuTrigger>Edit</DropdownMenuTrigger>
|
|
526
|
+
* <DropdownMenuContent>
|
|
527
|
+
* <DropdownMenuItem>
|
|
528
|
+
* Save
|
|
529
|
+
* <DropdownMenuShortcut>Ctrl+S</DropdownMenuShortcut>
|
|
530
|
+
* </DropdownMenuItem>
|
|
531
|
+
* </DropdownMenuContent>
|
|
532
|
+
* </DropdownMenu>
|
|
533
|
+
* );
|
|
534
|
+
* }
|
|
535
|
+
* @see {@link DropdownMenuItem}
|
|
536
|
+
* @since 1.0.0
|
|
537
|
+
*/
|
|
538
|
+
function DropdownMenuShortcut(props: ComponentProps<"span">): JSX.Element {
|
|
539
|
+
const [local, rest] = splitProps(props, ["class"]);
|
|
540
|
+
return (
|
|
541
|
+
<span
|
|
542
|
+
data-slot="dropdown-menu-shortcut"
|
|
543
|
+
class={cn("ms-auto text-xs tracking-widest text-muted-foreground", local.class)}
|
|
544
|
+
{...rest}
|
|
545
|
+
/>
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* The root of a submenu. It renders no element; place a {@link DropdownMenuSubTrigger} and a
|
|
551
|
+
* {@link DropdownMenuSubContent} in it, inside a {@link DropdownMenuContent}. The submenu closes when its
|
|
552
|
+
* menu does.
|
|
553
|
+
*
|
|
554
|
+
* @param props The submenu props: `open`, `defaultOpen` and `onOpenChange` of the submenu.
|
|
555
|
+
* @returns The submenu's context around its children.
|
|
556
|
+
* @throws Error when rendered outside a {@link DropdownMenu}.
|
|
557
|
+
* @example
|
|
558
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
559
|
+
*
|
|
560
|
+
* export function Share() {
|
|
561
|
+
* return (
|
|
562
|
+
* <DropdownMenu>
|
|
563
|
+
* <DropdownMenuTrigger>Share</DropdownMenuTrigger>
|
|
564
|
+
* <DropdownMenuContent>
|
|
565
|
+
* <DropdownMenuSub>
|
|
566
|
+
* <DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
|
|
567
|
+
* <DropdownMenuSubContent>
|
|
568
|
+
* <DropdownMenuItem>Email</DropdownMenuItem>
|
|
569
|
+
* </DropdownMenuSubContent>
|
|
570
|
+
* </DropdownMenuSub>
|
|
571
|
+
* </DropdownMenuContent>
|
|
572
|
+
* </DropdownMenu>
|
|
573
|
+
* );
|
|
574
|
+
* }
|
|
575
|
+
* @see {@link DropdownMenuSubTrigger}
|
|
576
|
+
* @see {@link DropdownMenuSubContent}
|
|
577
|
+
* @since 1.0.0
|
|
578
|
+
*/
|
|
579
|
+
function DropdownMenuSub(props: MenuSubProps): JSX.Element {
|
|
580
|
+
return <DropdownMenuPrimitive.Sub {...props} />;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* The item that opens a submenu, with a chevron that points the other way in right-to-left layouts. It is
|
|
585
|
+
* a `role="menuitem"` with `aria-haspopup="menu"` and `aria-expanded`. ArrowRight opens the submenu
|
|
586
|
+
* (ArrowLeft in right-to-left layouts).
|
|
587
|
+
*
|
|
588
|
+
* @param props The trigger props: the attributes of the rendered `div`, `inset`, and `children`.
|
|
589
|
+
* @returns The submenu trigger.
|
|
590
|
+
* @throws Error when rendered outside a {@link DropdownMenuSub}.
|
|
591
|
+
* @example
|
|
592
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
593
|
+
*
|
|
594
|
+
* export function Invite() {
|
|
595
|
+
* return (
|
|
596
|
+
* <DropdownMenu>
|
|
597
|
+
* <DropdownMenuTrigger>Share</DropdownMenuTrigger>
|
|
598
|
+
* <DropdownMenuContent>
|
|
599
|
+
* <DropdownMenuSub>
|
|
600
|
+
* <DropdownMenuSubTrigger inset>Invite users</DropdownMenuSubTrigger>
|
|
601
|
+
* <DropdownMenuSubContent>
|
|
602
|
+
* <DropdownMenuItem>Email</DropdownMenuItem>
|
|
603
|
+
* </DropdownMenuSubContent>
|
|
604
|
+
* </DropdownMenuSub>
|
|
605
|
+
* </DropdownMenuContent>
|
|
606
|
+
* </DropdownMenu>
|
|
607
|
+
* );
|
|
608
|
+
* }
|
|
609
|
+
* @see {@link DropdownMenuSub}
|
|
610
|
+
* @since 1.0.0
|
|
611
|
+
*/
|
|
612
|
+
function DropdownMenuSubTrigger<T extends PolymorphicTarget = "div">(
|
|
613
|
+
props: MenuSubTriggerProps<T> & { readonly inset?: boolean | undefined },
|
|
614
|
+
): JSX.Element {
|
|
615
|
+
const [local, rest] = splitProps(props as unknown as Loose, ["class", "inset", "children"]);
|
|
616
|
+
return (
|
|
617
|
+
<DropdownMenuPrimitive.SubTrigger
|
|
618
|
+
data-slot="dropdown-menu-sub-trigger"
|
|
619
|
+
data-inset={local.inset === true ? "" : undefined}
|
|
620
|
+
class={cn(
|
|
621
|
+
ROW,
|
|
622
|
+
"px-2 py-1.5 data-[inset]:ps-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground forced-colors:data-[state=open]:bg-[Highlight] forced-colors:data-[state=open]:text-[HighlightText] [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
623
|
+
local.class,
|
|
624
|
+
)}
|
|
625
|
+
{...rest}
|
|
626
|
+
>
|
|
627
|
+
{local.children}
|
|
628
|
+
<ChevronRightIcon class="ms-auto size-4 rtl:rotate-180" />
|
|
629
|
+
</DropdownMenuPrimitive.SubTrigger>
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* The submenu panel, placed beside its trigger. It is a `role="menu"` labeled by its trigger. ArrowLeft
|
|
635
|
+
* (ArrowRight in right-to-left layouts) and Escape close it and return focus to the trigger.
|
|
636
|
+
*
|
|
637
|
+
* @param props The panel props: the attributes of the rendered `div` and `class`.
|
|
638
|
+
* @returns The submenu panel.
|
|
639
|
+
* @throws Error when rendered outside a {@link DropdownMenuSub}.
|
|
640
|
+
* @example
|
|
641
|
+
* import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
642
|
+
*
|
|
643
|
+
* export function Share() {
|
|
644
|
+
* return (
|
|
645
|
+
* <DropdownMenu>
|
|
646
|
+
* <DropdownMenuTrigger>Share</DropdownMenuTrigger>
|
|
647
|
+
* <DropdownMenuContent>
|
|
648
|
+
* <DropdownMenuSub>
|
|
649
|
+
* <DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
|
|
650
|
+
* <DropdownMenuSubContent class="w-44">
|
|
651
|
+
* <DropdownMenuItem>Email</DropdownMenuItem>
|
|
652
|
+
* </DropdownMenuSubContent>
|
|
653
|
+
* </DropdownMenuSub>
|
|
654
|
+
* </DropdownMenuContent>
|
|
655
|
+
* </DropdownMenu>
|
|
656
|
+
* );
|
|
657
|
+
* }
|
|
658
|
+
* @see {@link DropdownMenuSubTrigger}
|
|
659
|
+
* @since 1.0.0
|
|
660
|
+
*/
|
|
661
|
+
function DropdownMenuSubContent(props: MenuSubContentProps): JSX.Element {
|
|
662
|
+
const [local, rest] = splitProps(props, ["class"]);
|
|
663
|
+
return (
|
|
664
|
+
<DropdownMenuPrimitive.SubContent
|
|
665
|
+
data-slot="dropdown-menu-sub-content"
|
|
666
|
+
class={cn(
|
|
667
|
+
PANEL,
|
|
668
|
+
"max-h-(--primitives-available-height) overflow-x-hidden overflow-y-auto shadow-lg",
|
|
669
|
+
local.class,
|
|
670
|
+
)}
|
|
671
|
+
{...rest}
|
|
672
|
+
/>
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
export {
|
|
677
|
+
DropdownMenu,
|
|
678
|
+
DropdownMenuCheckboxItem,
|
|
679
|
+
DropdownMenuContent,
|
|
680
|
+
DropdownMenuGroup,
|
|
681
|
+
DropdownMenuItem,
|
|
682
|
+
DropdownMenuLabel,
|
|
683
|
+
DropdownMenuPortal,
|
|
684
|
+
DropdownMenuRadioGroup,
|
|
685
|
+
DropdownMenuRadioItem,
|
|
686
|
+
DropdownMenuSeparator,
|
|
687
|
+
DropdownMenuShortcut,
|
|
688
|
+
DropdownMenuSub,
|
|
689
|
+
DropdownMenuSubContent,
|
|
690
|
+
DropdownMenuSubTrigger,
|
|
691
|
+
DropdownMenuTrigger,
|
|
692
|
+
};
|