@vvedantb/ui 0.17.0 → 0.18.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/README.md +253 -3
- package/package.json +13 -5
- package/shell/src/SidebarResize.tsx +1 -4
- package/src/ai-elements/__snapshots__/queue.test.tsx.snap +11 -0
- package/src/ai-elements/activity-question-utils.ts +26 -0
- package/src/ai-elements/activity-question.tsx +159 -0
- package/src/ai-elements/activity-shared.tsx +459 -0
- package/src/ai-elements/activity-step-detail.tsx +115 -0
- package/src/ai-elements/activity-step-label.ts +981 -0
- package/src/ai-elements/activity-tasks-utils.ts +199 -0
- package/src/ai-elements/activity-tasks.tsx +770 -0
- package/src/ai-elements/artifact.tsx +162 -52
- package/src/ai-elements/attachments.tsx +62 -32
- package/src/ai-elements/code-block.tsx +76 -22
- package/src/ai-elements/context.tsx +370 -0
- package/src/ai-elements/conversation.tsx +186 -62
- package/src/ai-elements/file-chip.tsx +53 -0
- package/src/ai-elements/message.tsx +161 -50
- package/src/ai-elements/model-picker-content.tsx +505 -0
- package/src/ai-elements/model-picker-types.ts +56 -0
- package/src/ai-elements/model-picker.tsx +301 -0
- package/src/ai-elements/model-selector.tsx +102 -21
- package/src/ai-elements/plan.tsx +130 -0
- package/src/ai-elements/prompt-input-settings.tsx +144 -0
- package/src/ai-elements/prompt-input-speech.tsx +189 -0
- package/src/ai-elements/prompt-input-traits.tsx +281 -0
- package/src/ai-elements/prompt-input.tsx +320 -134
- package/src/ai-elements/provider-icon.tsx +133 -0
- package/src/ai-elements/queue.tsx +293 -9
- package/src/ai-elements/shimmer.tsx +72 -1
- package/src/ai-elements/simple-model-ladder.tsx +108 -0
- package/src/ai-elements/test-results.tsx +510 -0
- package/src/ai-elements/trace.tsx +243 -0
- package/src/ai-elements/use-streaming-disclosure.ts +50 -0
- package/src/ai-elements/web-preview.tsx +349 -0
- package/src/composer/input-area/ComposerSlashMenu.tsx +1 -1
- package/src/index.ts +66 -12
- package/src/kibo/avatar-stack.tsx +40 -0
- package/src/kibo/contribution-graph.tsx +539 -0
- package/src/kibo/cursor.tsx +72 -0
- package/src/kibo/gantt-features.tsx +439 -0
- package/src/kibo/gantt-header.tsx +181 -0
- package/src/kibo/gantt-provider.tsx +657 -0
- package/src/kibo/gantt-sidebar.tsx +157 -0
- package/src/kibo/gantt-timeline.tsx +154 -0
- package/src/kibo/index.ts +151 -0
- package/src/kibo/kanban.tsx +338 -0
- package/src/kibo/kanbanDropTarget.ts +25 -0
- package/src/kibo/list.tsx +162 -0
- package/src/kibo/theme-switcher.tsx +109 -0
- package/src/kibo/video-player.tsx +237 -0
- package/src/markdown/Markdown.tsx +112 -0
- package/src/markdown/MarkdownBlockquote.tsx +45 -0
- package/src/markdown/MarkdownCodeBlock.tsx +197 -0
- package/src/markdown/MarkdownInlineCode.tsx +40 -0
- package/src/markdown/MarkdownLink.tsx +92 -0
- package/src/markdown/codeFence.ts +57 -0
- package/src/markdown/codeHighlight.ts +138 -0
- package/src/markdown/incrementalBlocks.ts +182 -0
- package/src/markdown/index.ts +3 -0
- package/src/markdown/markdownClipboard.ts +178 -0
- package/src/markdown/mermaid.ts +155 -0
- package/src/markdown/rehypeGithubAlerts.ts +80 -0
- package/src/motion/presets.ts +24 -0
- package/src/ui/__snapshots__/alt-wrappers.test.tsx.snap +19 -0
- package/src/ui/__snapshots__/sonner-dom.test.tsx.snap +5 -0
- package/src/ui/_menu-parts.tsx +29 -0
- package/src/ui/accordion.alt.tsx +46 -53
- package/src/ui/accordion.tsx +59 -10
- package/src/ui/avatar.tsx +56 -0
- package/src/ui/badge.tsx +45 -21
- package/src/ui/border-beam.tsx +97 -0
- package/src/ui/button-group.tsx +50 -21
- package/src/ui/button.tsx +67 -45
- package/src/ui/calendar.tsx +48 -5
- package/src/ui/card.tsx +77 -8
- package/src/ui/carousel.tsx +60 -0
- package/src/ui/centered-spinner.tsx +30 -0
- package/src/ui/checkbox.tsx +34 -16
- package/src/ui/clear-input.alt.tsx +33 -75
- package/src/ui/clear-input.tsx +140 -15
- package/src/ui/collapsible.tsx +40 -2
- package/src/ui/command.tsx +143 -70
- package/src/ui/context-menu.tsx +159 -93
- package/src/ui/crossfade-icon.tsx +123 -0
- package/src/ui/dialog.tsx +154 -70
- package/src/ui/dropdown-menu.tsx +177 -117
- package/src/ui/hover-card.tsx +59 -17
- package/src/ui/input-group.alt.tsx +83 -83
- package/src/ui/input-group.tsx +129 -58
- package/src/ui/input.tsx +13 -4
- package/src/ui/label.tsx +11 -8
- package/src/ui/list-row.tsx +232 -0
- package/src/ui/loading-state.tsx +215 -0
- package/src/ui/popover.tsx +56 -23
- package/src/ui/progress.tsx +28 -16
- package/src/ui/refresh-spin-icon.tsx +41 -0
- package/src/ui/search-input.tsx +66 -15
- package/src/ui/select.tsx +171 -100
- package/src/ui/separator.tsx +23 -14
- package/src/ui/slider.tsx +21 -7
- package/src/ui/sonner.tsx +68 -30
- package/src/ui/spinner.tsx +229 -11
- package/src/ui/status-dot.tsx +84 -0
- package/src/ui/surface.tsx +49 -0
- package/src/ui/switch.tsx +29 -15
- package/src/ui/table.tsx +38 -16
- package/src/ui/tabs.tsx +123 -35
- package/src/ui/tabsSliding.ts +33 -1
- package/src/ui/textarea.tsx +13 -4
- package/src/ui/tooltip.tsx +50 -14
- package/src/ui/ui-config.tsx +149 -0
- package/src/utils/cat-color.ts +123 -0
- package/src/utils/dayjs.ts +6 -0
- package/src/utils/gesture.ts +59 -0
- package/src/utils/runtimeVisibility.ts +167 -0
- package/src/utils/sharedClock.ts +96 -0
- package/src/utils/surface-radius.ts +16 -0
- package/src/utils/useDragSensors.ts +58 -0
- package/tokens/examples/tokens-moved/Fixture.tsx +283 -0
- package/tokens/examples/tokens-moved/README.md +20 -0
- package/tokens/examples/tokens-moved/index.html +12 -0
- package/tokens/examples/tokens-moved/main.tsx +6 -0
- package/tokens/examples/tokens-moved/package.json +14 -0
- package/tokens/examples/tokens-moved/styles.css +12 -0
- package/tokens/examples/tokens-moved/tsconfig.json +14 -0
- package/tokens/examples/tokens-moved/vite.config.ts +11 -0
- package/tokens/src/css/border-beam.css +116 -0
- package/tokens/src/css/compat-shadcn-rgb.css +6 -0
- package/tokens/src/css/markdown.css +318 -0
package/src/ui/command.tsx
CHANGED
|
@@ -8,21 +8,53 @@ import {
|
|
|
8
8
|
DialogHeader,
|
|
9
9
|
DialogTitle,
|
|
10
10
|
} from "./dialog";
|
|
11
|
-
import {
|
|
11
|
+
import { useCn, useUiConfig } from "./ui-config";
|
|
12
|
+
|
|
13
|
+
/** App defaults for `Command*` (see `UiConfigProvider`). */
|
|
14
|
+
export interface CommandConfig {
|
|
15
|
+
/** Replaces the built-in classes of a part. */
|
|
16
|
+
classes?: {
|
|
17
|
+
root?: string;
|
|
18
|
+
/** `CommandDialog` content. */
|
|
19
|
+
dialogContent?: string;
|
|
20
|
+
/** The `Command` inside `CommandDialog`, for every `listLayout`. */
|
|
21
|
+
dialogCommand?: string;
|
|
22
|
+
inputWrapper?: string;
|
|
23
|
+
input?: string;
|
|
24
|
+
list?: string;
|
|
25
|
+
empty?: string;
|
|
26
|
+
group?: string;
|
|
27
|
+
separator?: string;
|
|
28
|
+
item?: string;
|
|
29
|
+
shortcut?: string;
|
|
30
|
+
};
|
|
31
|
+
/** Replace the built-in icons. */
|
|
32
|
+
icons?: {
|
|
33
|
+
/** `CommandInput` search icon. */
|
|
34
|
+
search?: React.ReactNode;
|
|
35
|
+
};
|
|
36
|
+
/** A `className` on `CommandEmpty` replaces its classes instead of merging with them. */
|
|
37
|
+
emptyClassNameReplaces?: boolean;
|
|
38
|
+
}
|
|
12
39
|
|
|
13
40
|
const Command = React.forwardRef<
|
|
14
41
|
React.ComponentRef<typeof CommandPrimitive>,
|
|
15
42
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
|
16
|
-
>(({ className, ...props }, ref) =>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
43
|
+
>(({ className, ...props }, ref) => {
|
|
44
|
+
const root = useUiConfig("Command")?.classes?.root;
|
|
45
|
+
const merge = useCn();
|
|
46
|
+
return (
|
|
47
|
+
<CommandPrimitive
|
|
48
|
+
ref={ref}
|
|
49
|
+
className={merge(
|
|
50
|
+
root ??
|
|
51
|
+
"flex h-full w-full flex-col overflow-hidden rounded-lg bg-overlay text-overlay-foreground",
|
|
52
|
+
className,
|
|
53
|
+
)}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
26
58
|
Command.displayName = CommandPrimitive.displayName;
|
|
27
59
|
|
|
28
60
|
// The list is pinned rather than `max-h`: a palette that resizes on every
|
|
@@ -56,9 +88,11 @@ function CommandDialog({
|
|
|
56
88
|
listLayout = "pinned",
|
|
57
89
|
...props
|
|
58
90
|
}: CommandDialogProps) {
|
|
91
|
+
const classes = useUiConfig("Command")?.classes;
|
|
92
|
+
const merge = useCn();
|
|
59
93
|
return (
|
|
60
94
|
<Dialog {...props}>
|
|
61
|
-
<DialogContent className={
|
|
95
|
+
<DialogContent className={merge(classes?.dialogContent ?? "overflow-hidden p-0 sm:max-w-xl", className)}>
|
|
62
96
|
{title !== undefined || description !== undefined ? (
|
|
63
97
|
<DialogHeader className="sr-only">
|
|
64
98
|
<DialogTitle>{title}</DialogTitle>
|
|
@@ -67,7 +101,10 @@ function CommandDialog({
|
|
|
67
101
|
) : null}
|
|
68
102
|
<Command
|
|
69
103
|
shouldFilter={shouldFilter}
|
|
70
|
-
className={
|
|
104
|
+
className={
|
|
105
|
+
classes?.dialogCommand ??
|
|
106
|
+
(listLayout === "auto" ? commandDialogAutoClass : commandDialogPinnedClass)
|
|
107
|
+
}
|
|
71
108
|
>
|
|
72
109
|
{children}
|
|
73
110
|
</Command>
|
|
@@ -79,97 +116,133 @@ function CommandDialog({
|
|
|
79
116
|
const CommandInput = React.forwardRef<
|
|
80
117
|
React.ComponentRef<typeof CommandPrimitive.Input>,
|
|
81
118
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
|
82
|
-
>(({ className, ...props }, ref) =>
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
"
|
|
92
|
-
className,
|
|
119
|
+
>(({ className, ...props }, ref) => {
|
|
120
|
+
const config = useUiConfig("Command");
|
|
121
|
+
const merge = useCn();
|
|
122
|
+
return (
|
|
123
|
+
<div
|
|
124
|
+
className={config?.classes?.inputWrapper ?? "flex items-center border-b border-separator px-3.5"}
|
|
125
|
+
cmdk-input-wrapper=""
|
|
126
|
+
>
|
|
127
|
+
{config?.icons?.search ?? (
|
|
128
|
+
<IconSearch className="mr-2 h-4 w-4 shrink-0 opacity-50" stroke={1.5} />
|
|
93
129
|
)}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
130
|
+
<CommandPrimitive.Input
|
|
131
|
+
ref={ref}
|
|
132
|
+
className={merge(
|
|
133
|
+
config?.classes?.input ??
|
|
134
|
+
"flex h-11 w-full max-sm:min-w-0 bg-transparent text-base sm:text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
135
|
+
className,
|
|
136
|
+
)}
|
|
137
|
+
{...props}
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
});
|
|
98
142
|
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
|
99
143
|
|
|
100
144
|
const CommandList = React.forwardRef<
|
|
101
145
|
React.ComponentRef<typeof CommandPrimitive.List>,
|
|
102
146
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
|
103
|
-
>(({ className, ...props }, ref) =>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
)
|
|
147
|
+
>(({ className, ...props }, ref) => {
|
|
148
|
+
const list = useUiConfig("Command")?.classes?.list;
|
|
149
|
+
const merge = useCn();
|
|
150
|
+
return (
|
|
151
|
+
<CommandPrimitive.List
|
|
152
|
+
ref={ref}
|
|
153
|
+
className={merge(list ?? "max-h-80 overflow-y-auto overflow-x-hidden pb-2", className)}
|
|
154
|
+
{...props}
|
|
155
|
+
/>
|
|
156
|
+
);
|
|
157
|
+
});
|
|
110
158
|
CommandList.displayName = CommandPrimitive.List.displayName;
|
|
111
159
|
|
|
112
160
|
const CommandEmpty = React.forwardRef<
|
|
113
161
|
React.ComponentRef<typeof CommandPrimitive.Empty>,
|
|
114
162
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
|
115
|
-
>(({ className, ...props }, ref) =>
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
163
|
+
>(({ className, ...props }, ref) => {
|
|
164
|
+
const config = useUiConfig("Command");
|
|
165
|
+
const merge = useCn();
|
|
166
|
+
const classes = config?.classes?.empty ?? "py-8 text-center text-sm text-muted-foreground";
|
|
167
|
+
return (
|
|
168
|
+
<CommandPrimitive.Empty
|
|
169
|
+
ref={ref}
|
|
170
|
+
className={
|
|
171
|
+
config?.emptyClassNameReplaces && className !== undefined
|
|
172
|
+
? className
|
|
173
|
+
: merge(classes, className)
|
|
174
|
+
}
|
|
175
|
+
{...props}
|
|
176
|
+
/>
|
|
177
|
+
);
|
|
178
|
+
});
|
|
122
179
|
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
|
123
180
|
|
|
124
181
|
const CommandGroup = React.forwardRef<
|
|
125
182
|
React.ComponentRef<typeof CommandPrimitive.Group>,
|
|
126
183
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
|
127
|
-
>(({ className, ...props }, ref) =>
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
184
|
+
>(({ className, ...props }, ref) => {
|
|
185
|
+
const group = useUiConfig("Command")?.classes?.group;
|
|
186
|
+
const merge = useCn();
|
|
187
|
+
return (
|
|
188
|
+
<CommandPrimitive.Group
|
|
189
|
+
ref={ref}
|
|
190
|
+
className={merge(
|
|
191
|
+
group ??
|
|
192
|
+
"overflow-hidden p-1.5 text-foreground [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-widest [&_[cmdk-group-heading]]:text-muted-foreground",
|
|
193
|
+
className,
|
|
194
|
+
)}
|
|
195
|
+
{...props}
|
|
196
|
+
/>
|
|
197
|
+
);
|
|
198
|
+
});
|
|
137
199
|
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
|
138
200
|
|
|
139
201
|
const CommandSeparator = React.forwardRef<
|
|
140
202
|
React.ComponentRef<typeof CommandPrimitive.Separator>,
|
|
141
203
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
|
142
|
-
>(({ className, ...props }, ref) =>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
204
|
+
>(({ className, ...props }, ref) => {
|
|
205
|
+
const separator = useUiConfig("Command")?.classes?.separator;
|
|
206
|
+
const merge = useCn();
|
|
207
|
+
return (
|
|
208
|
+
<CommandPrimitive.Separator
|
|
209
|
+
ref={ref}
|
|
210
|
+
className={merge(separator ?? "-mx-1.5 h-px bg-separator", className)}
|
|
211
|
+
{...props}
|
|
212
|
+
/>
|
|
213
|
+
);
|
|
214
|
+
});
|
|
149
215
|
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
|
150
216
|
|
|
151
217
|
const CommandItem = React.forwardRef<
|
|
152
218
|
React.ComponentRef<typeof CommandPrimitive.Item>,
|
|
153
219
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
|
154
|
-
>(({ className, ...props }, ref) =>
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
220
|
+
>(({ className, ...props }, ref) => {
|
|
221
|
+
const item = useUiConfig("Command")?.classes?.item;
|
|
222
|
+
const merge = useCn();
|
|
223
|
+
return (
|
|
224
|
+
<CommandPrimitive.Item
|
|
225
|
+
ref={ref}
|
|
226
|
+
className={merge(
|
|
227
|
+
item ??
|
|
228
|
+
"relative flex cursor-default gap-2 select-none items-center rounded-menu-item px-2.5 py-2 text-sm outline-none transition-colors data-[disabled=true]:pointer-events-none data-[selected=true]:bg-surface-tertiary/80 data-[selected=true]:text-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
229
|
+
className,
|
|
230
|
+
)}
|
|
231
|
+
{...props}
|
|
232
|
+
/>
|
|
233
|
+
);
|
|
234
|
+
});
|
|
164
235
|
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
|
165
236
|
|
|
166
237
|
function CommandShortcut({
|
|
167
238
|
className,
|
|
168
239
|
...props
|
|
169
240
|
}: React.HTMLAttributes<HTMLSpanElement>) {
|
|
241
|
+
const shortcut = useUiConfig("Command")?.classes?.shortcut;
|
|
242
|
+
const merge = useCn();
|
|
170
243
|
return (
|
|
171
244
|
<span
|
|
172
|
-
className={
|
|
245
|
+
className={merge(shortcut ?? "ml-auto text-xs tracking-wide text-muted-foreground/90", className)}
|
|
173
246
|
{...props}
|
|
174
247
|
/>
|
|
175
248
|
);
|
package/src/ui/context-menu.tsx
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
IconChevronRight,
|
|
6
6
|
IconCircleFilled,
|
|
7
7
|
} from "@tabler/icons-react";
|
|
8
|
-
import { cn } from "../utils/cn";
|
|
9
8
|
import {
|
|
10
9
|
menuCheckboxRadioItemClass,
|
|
11
10
|
menuContentClass,
|
|
@@ -15,10 +14,34 @@ import {
|
|
|
15
14
|
menuShortcutClass,
|
|
16
15
|
menuSubTriggerClass,
|
|
17
16
|
} from "./_menu-classes";
|
|
18
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
type MenuConfig,
|
|
19
|
+
MenuItemRow,
|
|
20
|
+
SubTriggerRow,
|
|
21
|
+
suppressAltKeyDown,
|
|
22
|
+
} from "./_menu-parts";
|
|
23
|
+
import { useCn, useUiConfig } from "./ui-config";
|
|
24
|
+
|
|
25
|
+
/** App defaults for `ContextMenu*` (see `UiConfigProvider`). */
|
|
26
|
+
export interface ContextMenuConfig extends MenuConfig {
|
|
27
|
+
/** Default for `ContextMenuSubContent` `portal`. */
|
|
28
|
+
subContentPortal?: boolean;
|
|
29
|
+
}
|
|
19
30
|
|
|
20
31
|
const ContextMenu = ContextMenuPrimitive.Root;
|
|
21
|
-
const ContextMenuTrigger =
|
|
32
|
+
const ContextMenuTrigger = React.forwardRef<
|
|
33
|
+
React.ComponentRef<typeof ContextMenuPrimitive.Trigger>,
|
|
34
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Trigger>
|
|
35
|
+
>((props, ref) => {
|
|
36
|
+
const trigger = useUiConfig("ContextMenu")?.classes?.trigger;
|
|
37
|
+
const merge = useCn();
|
|
38
|
+
// Without config, pass props untouched: Radix's Slot turns an explicit
|
|
39
|
+
// `className={undefined}` into `class=""`.
|
|
40
|
+
if (trigger === undefined) return <ContextMenuPrimitive.Trigger ref={ref} {...props} />;
|
|
41
|
+
const { className, ...rest } = props;
|
|
42
|
+
return <ContextMenuPrimitive.Trigger ref={ref} className={merge(trigger, className)} {...rest} />;
|
|
43
|
+
});
|
|
44
|
+
ContextMenuTrigger.displayName = ContextMenuPrimitive.Trigger.displayName;
|
|
22
45
|
const ContextMenuGroup = ContextMenuPrimitive.Group;
|
|
23
46
|
const ContextMenuPortal = ContextMenuPrimitive.Portal;
|
|
24
47
|
const ContextMenuSub = ContextMenuPrimitive.Sub;
|
|
@@ -31,30 +54,46 @@ const ContextMenuSubTrigger = React.forwardRef<
|
|
|
31
54
|
/** Leading icon or mark. The label then fills the row. */
|
|
32
55
|
startContent?: React.ReactNode;
|
|
33
56
|
}
|
|
34
|
-
>(({ className, inset, startContent, children, ...props }, ref) =>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
)
|
|
57
|
+
>(({ className, inset, startContent, children, ...props }, ref) => {
|
|
58
|
+
const classes = useUiConfig("ContextMenu")?.classes;
|
|
59
|
+
const merge = useCn();
|
|
60
|
+
return (
|
|
61
|
+
<ContextMenuPrimitive.SubTrigger
|
|
62
|
+
ref={ref}
|
|
63
|
+
className={merge(classes?.subTrigger ?? menuSubTriggerClass, inset && "pl-8", className)}
|
|
64
|
+
{...props}
|
|
65
|
+
>
|
|
66
|
+
{startContent === undefined ? children : (
|
|
67
|
+
<SubTriggerRow startContent={startContent}>{children}</SubTriggerRow>
|
|
68
|
+
)}
|
|
69
|
+
<IconChevronRight className="ml-auto" />
|
|
70
|
+
</ContextMenuPrimitive.SubTrigger>
|
|
71
|
+
);
|
|
72
|
+
});
|
|
46
73
|
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
|
47
74
|
|
|
48
75
|
const ContextMenuSubContent = React.forwardRef<
|
|
49
76
|
React.ComponentRef<typeof ContextMenuPrimitive.SubContent>,
|
|
50
|
-
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
77
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent> & {
|
|
78
|
+
/** Render into `document.body` so a clipping parent cannot cut it off. */
|
|
79
|
+
portal?: boolean;
|
|
80
|
+
}
|
|
81
|
+
>(({ className, portal, ...props }, ref) => {
|
|
82
|
+
const config = useUiConfig("ContextMenu");
|
|
83
|
+
const merge = useCn();
|
|
84
|
+
const content = (
|
|
85
|
+
<ContextMenuPrimitive.SubContent
|
|
86
|
+
ref={ref}
|
|
87
|
+
className={merge(config?.classes?.subContent ?? [menuContentClass, "w-40"], className)}
|
|
88
|
+
{...props}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
return (portal ?? config?.subContentPortal) ? (
|
|
92
|
+
<ContextMenuPrimitive.Portal>{content}</ContextMenuPrimitive.Portal>
|
|
93
|
+
) : (
|
|
94
|
+
content
|
|
95
|
+
);
|
|
96
|
+
});
|
|
58
97
|
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
|
59
98
|
|
|
60
99
|
const ContextMenuContent = React.forwardRef<
|
|
@@ -63,16 +102,21 @@ const ContextMenuContent = React.forwardRef<
|
|
|
63
102
|
/** Stop a bare Alt press from moving focus (e.g. into the browser menu bar). */
|
|
64
103
|
suppressAltKey?: boolean;
|
|
65
104
|
}
|
|
66
|
-
>(({ className, suppressAltKey, onKeyDown, ...props }, ref) =>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)
|
|
105
|
+
>(({ className, suppressAltKey, collisionPadding, onKeyDown, ...props }, ref) => {
|
|
106
|
+
const config = useUiConfig("ContextMenu");
|
|
107
|
+
const merge = useCn();
|
|
108
|
+
return (
|
|
109
|
+
<ContextMenuPrimitive.Portal>
|
|
110
|
+
<ContextMenuPrimitive.Content
|
|
111
|
+
ref={ref}
|
|
112
|
+
collisionPadding={collisionPadding ?? config?.collisionPadding}
|
|
113
|
+
className={merge(config?.classes?.content ?? [menuContentClass, "w-40"], className)}
|
|
114
|
+
onKeyDown={suppressAltKey ? suppressAltKeyDown(onKeyDown) : onKeyDown}
|
|
115
|
+
{...props}
|
|
116
|
+
/>
|
|
117
|
+
</ContextMenuPrimitive.Portal>
|
|
118
|
+
);
|
|
119
|
+
});
|
|
76
120
|
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
|
77
121
|
|
|
78
122
|
const ContextMenuItem = React.forwardRef<
|
|
@@ -90,63 +134,75 @@ const ContextMenuItem = React.forwardRef<
|
|
|
90
134
|
(
|
|
91
135
|
{ className, inset, startContent, description, endContent, children, asChild, ...props },
|
|
92
136
|
ref,
|
|
93
|
-
) =>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
137
|
+
) => {
|
|
138
|
+
const item = useUiConfig("ContextMenu")?.classes?.item;
|
|
139
|
+
const merge = useCn();
|
|
140
|
+
return (
|
|
141
|
+
<ContextMenuPrimitive.Item
|
|
142
|
+
ref={ref}
|
|
143
|
+
asChild={asChild}
|
|
144
|
+
className={merge(item ?? menuItemClass, inset && "pl-8", className)}
|
|
145
|
+
{...props}
|
|
146
|
+
>
|
|
147
|
+
{asChild || (startContent === undefined && description === undefined && endContent === undefined) ? (
|
|
148
|
+
children
|
|
149
|
+
) : (
|
|
150
|
+
<MenuItemRow startContent={startContent} description={description} endContent={endContent}>
|
|
151
|
+
{children}
|
|
152
|
+
</MenuItemRow>
|
|
153
|
+
)}
|
|
154
|
+
</ContextMenuPrimitive.Item>
|
|
155
|
+
);
|
|
156
|
+
},
|
|
109
157
|
);
|
|
110
158
|
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
|
111
159
|
|
|
112
160
|
const ContextMenuCheckboxItem = React.forwardRef<
|
|
113
161
|
React.ComponentRef<typeof ContextMenuPrimitive.CheckboxItem>,
|
|
114
162
|
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>
|
|
115
|
-
>(({ className, children, checked, ...props }, ref) =>
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
163
|
+
>(({ className, children, checked, ...props }, ref) => {
|
|
164
|
+
const config = useUiConfig("ContextMenu");
|
|
165
|
+
const merge = useCn();
|
|
166
|
+
return (
|
|
167
|
+
<ContextMenuPrimitive.CheckboxItem
|
|
168
|
+
ref={ref}
|
|
169
|
+
className={merge(config?.classes?.checkboxItem ?? menuCheckboxRadioItemClass, className)}
|
|
170
|
+
checked={checked}
|
|
171
|
+
{...props}
|
|
172
|
+
>
|
|
173
|
+
<span className="absolute left-2.5 flex h-3.5 w-3.5 items-center justify-center">
|
|
174
|
+
<ContextMenuPrimitive.ItemIndicator>
|
|
175
|
+
{config?.icons?.check ?? <IconCheck className="h-4 w-4" />}
|
|
176
|
+
</ContextMenuPrimitive.ItemIndicator>
|
|
177
|
+
</span>
|
|
178
|
+
{children}
|
|
179
|
+
</ContextMenuPrimitive.CheckboxItem>
|
|
180
|
+
);
|
|
181
|
+
});
|
|
130
182
|
ContextMenuCheckboxItem.displayName =
|
|
131
183
|
ContextMenuPrimitive.CheckboxItem.displayName;
|
|
132
184
|
|
|
133
185
|
const ContextMenuRadioItem = React.forwardRef<
|
|
134
186
|
React.ComponentRef<typeof ContextMenuPrimitive.RadioItem>,
|
|
135
187
|
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>
|
|
136
|
-
>(({ className, children, ...props }, ref) =>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
188
|
+
>(({ className, children, ...props }, ref) => {
|
|
189
|
+
const config = useUiConfig("ContextMenu");
|
|
190
|
+
const merge = useCn();
|
|
191
|
+
return (
|
|
192
|
+
<ContextMenuPrimitive.RadioItem
|
|
193
|
+
ref={ref}
|
|
194
|
+
className={merge(config?.classes?.radioItem ?? menuCheckboxRadioItemClass, className)}
|
|
195
|
+
{...props}
|
|
196
|
+
>
|
|
197
|
+
<span className="absolute left-2.5 flex h-3.5 w-3.5 items-center justify-center">
|
|
198
|
+
<ContextMenuPrimitive.ItemIndicator>
|
|
199
|
+
{config?.icons?.radio ?? <IconCircleFilled className="h-2 w-2 fill-current" />}
|
|
200
|
+
</ContextMenuPrimitive.ItemIndicator>
|
|
201
|
+
</span>
|
|
202
|
+
{children}
|
|
203
|
+
</ContextMenuPrimitive.RadioItem>
|
|
204
|
+
);
|
|
205
|
+
});
|
|
150
206
|
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
|
151
207
|
|
|
152
208
|
const ContextMenuLabel = React.forwardRef<
|
|
@@ -154,32 +210,42 @@ const ContextMenuLabel = React.forwardRef<
|
|
|
154
210
|
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
|
|
155
211
|
inset?: boolean;
|
|
156
212
|
}
|
|
157
|
-
>(({ className, inset, ...props }, ref) =>
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
)
|
|
213
|
+
>(({ className, inset, ...props }, ref) => {
|
|
214
|
+
const label = useUiConfig("ContextMenu")?.classes?.label;
|
|
215
|
+
const merge = useCn();
|
|
216
|
+
return (
|
|
217
|
+
<ContextMenuPrimitive.Label
|
|
218
|
+
ref={ref}
|
|
219
|
+
className={merge(label ?? menuLabelClass, inset && "pl-8", className)}
|
|
220
|
+
{...props}
|
|
221
|
+
/>
|
|
222
|
+
);
|
|
223
|
+
});
|
|
164
224
|
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
|
165
225
|
|
|
166
226
|
const ContextMenuSeparator = React.forwardRef<
|
|
167
227
|
React.ComponentRef<typeof ContextMenuPrimitive.Separator>,
|
|
168
228
|
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
|
|
169
|
-
>(({ className, ...props }, ref) =>
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
)
|
|
229
|
+
>(({ className, ...props }, ref) => {
|
|
230
|
+
const separator = useUiConfig("ContextMenu")?.classes?.separator;
|
|
231
|
+
const merge = useCn();
|
|
232
|
+
return (
|
|
233
|
+
<ContextMenuPrimitive.Separator
|
|
234
|
+
ref={ref}
|
|
235
|
+
className={merge(separator ?? menuSeparatorClass, className)}
|
|
236
|
+
{...props}
|
|
237
|
+
/>
|
|
238
|
+
);
|
|
239
|
+
});
|
|
176
240
|
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
|
|
177
241
|
|
|
178
242
|
const ContextMenuShortcut = ({
|
|
179
243
|
className,
|
|
180
244
|
...props
|
|
181
245
|
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
182
|
-
|
|
246
|
+
const shortcut = useUiConfig("ContextMenu")?.classes?.shortcut;
|
|
247
|
+
const merge = useCn();
|
|
248
|
+
return <span className={merge(shortcut ?? menuShortcutClass, className)} {...props} />;
|
|
183
249
|
};
|
|
184
250
|
ContextMenuShortcut.displayName = "ContextMenuShortcut";
|
|
185
251
|
|