@streamsai/ui 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +57 -2
- package/dist/components/ui/agent-avatar.d.ts +50 -0
- package/dist/components/ui/agent-avatar.js +38 -0
- package/dist/components/ui/alert-dialog.d.ts +12 -0
- package/dist/components/ui/alert-dialog.js +37 -0
- package/dist/components/ui/alert.d.ts +10 -0
- package/dist/components/ui/alert.js +28 -0
- package/dist/components/ui/assets/loader.json.js +1 -0
- package/dist/components/ui/avatar-frame.d.ts +11 -0
- package/dist/components/ui/avatar-frame.js +20 -0
- package/dist/components/ui/avatar.d.ts +23 -0
- package/dist/components/ui/avatar.js +54 -0
- package/dist/components/ui/badge.d.ts +7 -0
- package/dist/components/ui/badge.js +36 -0
- package/dist/components/ui/bar-list.d.ts +40 -0
- package/dist/components/ui/bar-list.js +37 -0
- package/dist/components/ui/breadcrumb.d.ts +8 -0
- package/dist/components/ui/breadcrumb.js +21 -0
- package/dist/components/ui/button-group.d.ts +10 -0
- package/dist/components/ui/button-group.js +41 -0
- package/dist/components/ui/button.d.ts +9 -0
- package/dist/components/ui/button.js +39 -0
- package/dist/components/ui/card.d.ts +9 -0
- package/dist/components/ui/card.js +25 -0
- package/dist/components/ui/checkbox.d.ts +3 -0
- package/dist/components/ui/checkbox.js +16 -0
- package/dist/components/ui/chip.d.ts +13 -0
- package/dist/components/ui/chip.js +22 -0
- package/dist/components/ui/clickable.d.ts +27 -0
- package/dist/components/ui/clickable.js +54 -0
- package/dist/components/ui/code-block.d.ts +68 -0
- package/dist/components/ui/code-block.js +112 -0
- package/dist/components/ui/code-view.d.ts +21 -0
- package/dist/components/ui/code-view.js +20 -0
- package/dist/components/ui/collapsible.d.ts +6 -0
- package/dist/components/ui/collapsible.js +18 -0
- package/dist/components/ui/combobox.d.ts +14 -0
- package/dist/components/ui/combobox.js +37 -0
- package/dist/components/ui/command.d.ts +15 -0
- package/dist/components/ui/command.js +34 -0
- package/dist/components/ui/context-menu.d.ts +21 -0
- package/dist/components/ui/context-menu.js +60 -0
- package/dist/components/ui/counter.d.ts +11 -0
- package/dist/components/ui/counter.js +20 -0
- package/dist/components/ui/dialog.d.ts +17 -0
- package/dist/components/ui/dialog.js +41 -0
- package/dist/components/ui/disabled-reason.d.ts +22 -0
- package/dist/components/ui/disabled-reason.js +16 -0
- package/dist/components/ui/dropdown-menu.d.ts +33 -0
- package/dist/components/ui/dropdown-menu.js +58 -0
- package/dist/components/ui/editable-text.d.ts +95 -0
- package/dist/components/ui/editable-text.js +191 -0
- package/dist/components/ui/heading.d.ts +24 -0
- package/dist/components/ui/heading.js +92 -0
- package/dist/components/ui/hover-card.d.ts +9 -0
- package/dist/components/ui/hover-card.js +16 -0
- package/dist/components/ui/icon-button.d.ts +23 -0
- package/dist/components/ui/icon-button.js +32 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.js +8 -0
- package/dist/components/ui/kbd.d.ts +12 -0
- package/dist/components/ui/kbd.js +12 -0
- package/dist/components/ui/label.d.ts +3 -0
- package/dist/components/ui/label.js +7 -0
- package/dist/components/ui/loader.d.ts +19 -0
- package/dist/components/ui/loader.js +157 -0
- package/dist/components/ui/message-toolbar.d.ts +20 -0
- package/dist/components/ui/message-toolbar.js +17 -0
- package/dist/components/ui/modal.d.ts +30 -0
- package/dist/components/ui/modal.js +41 -0
- package/dist/components/ui/nav-item.d.ts +25 -0
- package/dist/components/ui/nav-item.js +66 -0
- package/dist/components/ui/panel-section.d.ts +22 -0
- package/dist/components/ui/panel-section.js +26 -0
- package/dist/components/ui/popover.d.ts +14 -0
- package/dist/components/ui/popover.js +30 -0
- package/dist/components/ui/progress.d.ts +5 -0
- package/dist/components/ui/progress.js +16 -0
- package/dist/components/ui/provider-badge.d.ts +22 -0
- package/dist/components/ui/provider-badge.js +38 -0
- package/dist/components/ui/radio-group.d.ts +5 -0
- package/dist/components/ui/radio-group.js +21 -0
- package/dist/components/ui/reply-summary.d.ts +16 -0
- package/dist/components/ui/reply-summary.js +8 -0
- package/dist/components/ui/resizable.d.ts +8 -0
- package/dist/components/ui/resizable.js +15 -0
- package/dist/components/ui/rich-text-editor.d.ts +447 -0
- package/dist/components/ui/rich-text-editor.js +2419 -0
- package/dist/components/ui/running-indicator.d.ts +17 -0
- package/dist/components/ui/running-indicator.js +34 -0
- package/dist/components/ui/sandboxed-frame.d.ts +29 -0
- package/dist/components/ui/sandboxed-frame.js +77 -0
- package/dist/components/ui/scroll-area.d.ts +14 -0
- package/dist/components/ui/scroll-area.js +17 -0
- package/dist/components/ui/section-header.d.ts +12 -0
- package/dist/components/ui/section-header.js +12 -0
- package/dist/components/ui/select.d.ts +15 -0
- package/dist/components/ui/select.js +40 -0
- package/dist/components/ui/separator.d.ts +3 -0
- package/dist/components/ui/separator.js +13 -0
- package/dist/components/ui/sheet.d.ts +23 -0
- package/dist/components/ui/sheet.js +48 -0
- package/dist/components/ui/shimmer-text.d.ts +26 -0
- package/dist/components/ui/shimmer-text.js +32 -0
- package/dist/components/ui/sidebar.d.ts +63 -0
- package/dist/components/ui/sidebar.js +283 -0
- package/dist/components/ui/skeleton.d.ts +14 -0
- package/dist/components/ui/skeleton.js +12 -0
- package/dist/components/ui/sonner.d.ts +4 -0
- package/dist/components/ui/sonner.js +14 -0
- package/dist/components/ui/spark-bars.d.ts +29 -0
- package/dist/components/ui/spark-bars.js +24 -0
- package/dist/components/ui/spinner.d.ts +16 -0
- package/dist/components/ui/spinner.js +26 -0
- package/dist/components/ui/stacked-bar.d.ts +37 -0
- package/dist/components/ui/stacked-bar.js +56 -0
- package/dist/components/ui/status-dot.d.ts +16 -0
- package/dist/components/ui/status-dot.js +32 -0
- package/dist/components/ui/switch.d.ts +5 -0
- package/dist/components/ui/switch.js +13 -0
- package/dist/components/ui/tabs.d.ts +14 -0
- package/dist/components/ui/tabs.js +55 -0
- package/dist/components/ui/text.d.ts +27 -0
- package/dist/components/ui/text.js +100 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.js +7 -0
- package/dist/components/ui/theme-toggle.d.ts +21 -0
- package/dist/components/ui/theme-toggle.js +17 -0
- package/dist/components/ui/toggle-group.d.ts +6 -0
- package/dist/components/ui/toggle-group.js +12 -0
- package/dist/components/ui/tooltip.d.ts +11 -0
- package/dist/components/ui/tooltip.js +21 -0
- package/dist/components/ui/trace.d.ts +24 -0
- package/dist/components/ui/trace.js +57 -0
- package/dist/components/ui/trend-line.d.ts +93 -0
- package/dist/components/ui/trend-line.js +215 -0
- package/dist/components/ui/truncate.d.ts +30 -0
- package/dist/components/ui/truncate.js +54 -0
- package/dist/components/ui/viewer-shell.d.ts +55 -0
- package/dist/components/ui/viewer-shell.js +15 -0
- package/dist/components/ui/virtual-list.d.ts +91 -0
- package/dist/components/ui/virtual-list.js +406 -0
- package/dist/components/ui/visually-hidden.d.ts +15 -0
- package/dist/components/ui/visually-hidden.js +19 -0
- package/dist/direction/index.d.ts +19 -0
- package/dist/direction/index.js +32 -0
- package/dist/hooks/use-code-highlighting.d.ts +22 -0
- package/dist/hooks/use-code-highlighting.js +47 -0
- package/dist/hooks/use-is-truncated.d.ts +7 -0
- package/dist/hooks/use-is-truncated.js +23 -0
- package/dist/hooks/use-mobile.d.ts +2 -0
- package/dist/hooks/use-mobile.js +15 -0
- package/dist/icons/custom.d.ts +29 -0
- package/dist/icons/custom.js +48 -0
- package/dist/icons/index.d.ts +49 -0
- package/dist/icons/index.js +50 -0
- package/dist/icons/provider-logos.d.ts +17 -0
- package/dist/icons/provider-logos.js +28 -0
- package/dist/icons/providers.d.ts +9 -0
- package/dist/icons/providers.js +51 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.js +124 -0
- package/dist/lib/code-highlighter.d.ts +9 -0
- package/dist/lib/code-highlighter.js +65 -0
- package/dist/lib/code-language.d.ts +13 -0
- package/dist/lib/code-language.js +103 -0
- package/dist/lib/code-tokens.d.ts +9 -0
- package/dist/lib/code-tokens.js +27 -0
- package/dist/lib/copy-text.d.ts +6 -0
- package/dist/lib/copy-text.js +46 -0
- package/dist/lib/home-tile.d.ts +12 -0
- package/dist/lib/home-tile.js +45 -0
- package/dist/lib/reveal-mask.d.ts +9 -0
- package/dist/lib/reveal-mask.js +16 -0
- package/dist/lib/text-direction.d.ts +28 -0
- package/dist/lib/text-direction.js +119 -0
- package/dist/lib/utils.d.ts +11 -0
- package/dist/lib/utils.js +30 -0
- package/dist/motion/components.d.ts +184 -0
- package/dist/motion/components.js +211 -0
- package/dist/motion/config.d.ts +849 -0
- package/dist/motion/config.js +429 -0
- package/dist/motion/index.d.ts +8 -0
- package/dist/motion/index.js +8 -0
- package/dist/motion/modal-presence.d.ts +5 -0
- package/dist/motion/modal-presence.js +27 -0
- package/dist/motion/popup.d.ts +77 -0
- package/dist/motion/popup.js +103 -0
- package/dist/platform/index.d.ts +29 -0
- package/dist/platform/index.js +63 -0
- package/dist/styles/base.css +319 -0
- package/dist/styles/fonts/Figtree-Variable.woff2 +0 -0
- package/dist/styles/fonts/OFL.txt +93 -0
- package/dist/styles/fonts/Poppins-Medium.woff2 +0 -0
- package/dist/styles/fonts/Poppins-Regular.woff2 +0 -0
- package/dist/styles/fonts/Poppins-SemiBold.woff2 +0 -0
- package/dist/styles/fonts.css +28 -0
- package/dist/styles/globals.css +8 -0
- package/dist/styles/mcp-host.css +76 -0
- package/dist/styles/tokens.css +387 -0
- package/dist/styles/tokens.d.mts +57 -0
- package/dist/styles/tokens.mjs +59 -0
- package/dist/theme/index.d.ts +28 -0
- package/dist/theme/index.js +65 -0
- package/package.json +136 -3
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Collapsible as CollapsiblePrimitive } from '@base-ui/react/collapsible';
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
import { MotionCollapsePanel } from '../../motion/popup.js';
|
|
5
|
+
function Collapsible({ ...props }) {
|
|
6
|
+
return _jsx(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
|
|
7
|
+
}
|
|
8
|
+
function CollapsibleTrigger({ className, ...props }) {
|
|
9
|
+
return (_jsx(CollapsiblePrimitive.Trigger, { "data-slot": "collapsible-trigger", className: cn('flex w-full items-center justify-between', className), ...props }));
|
|
10
|
+
}
|
|
11
|
+
function renderCollapsePanel(props, state) {
|
|
12
|
+
return _jsx(MotionCollapsePanel, { ...props, open: state.open });
|
|
13
|
+
}
|
|
14
|
+
/** Animates open and shut with `presets.collapse` (motion), so callers never add their own. */
|
|
15
|
+
function CollapsibleContent({ className, ...props }) {
|
|
16
|
+
return (_jsx(CollapsiblePrimitive.Panel, { "data-slot": "collapsible-content", keepMounted: true, render: renderCollapsePanel, className: cn(className), ...props }));
|
|
17
|
+
}
|
|
18
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Combobox as ComboboxPrimitive } from '@base-ui/react/combobox';
|
|
3
|
+
declare function Combobox<Value, Multiple extends boolean | undefined = false, Item = Value>({ actionsRef, onOpenChange, ...props }: ComboboxPrimitive.Root.Props<Value, Multiple, Item>): React.JSX.Element;
|
|
4
|
+
/** The field itself: an editable text input (the select trigger look) that opens the list when pressed. */
|
|
5
|
+
declare function ComboboxInput({ className, ...props }: ComboboxPrimitive.Input.Props): React.JSX.Element;
|
|
6
|
+
declare function ComboboxContent({ className, children, side, sideOffset, align, ...props }: ComboboxPrimitive.Popup.Props & Pick<ComboboxPrimitive.Positioner.Props, 'align' | 'side' | 'sideOffset'>): React.JSX.Element;
|
|
7
|
+
/** The scroll area. Group labels stick to its top edge, so it carries no top padding of its own. */
|
|
8
|
+
declare function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props): React.JSX.Element;
|
|
9
|
+
declare function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props): React.JSX.Element;
|
|
10
|
+
declare function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props): React.JSX.Element;
|
|
11
|
+
/** Pinned to the top of the scroll area until the next group's label pushes it away. */
|
|
12
|
+
declare function ComboboxGroupLabel({ className, ...props }: ComboboxPrimitive.GroupLabel.Props): React.JSX.Element;
|
|
13
|
+
declare function ComboboxItem({ className, children, ...props }: ComboboxPrimitive.Item.Props): React.JSX.Element;
|
|
14
|
+
export { Combobox, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxList, };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Combobox as ComboboxPrimitive } from '@base-ui/react/combobox';
|
|
5
|
+
import { cn } from '../../lib/utils.js';
|
|
6
|
+
import { PopupExitContext, usePopupExit, usePopupRender } from '../../motion/popup.js';
|
|
7
|
+
import { Check as CheckIcon, ChevronDown as ChevronDownIcon } from '../../icons/index.js';
|
|
8
|
+
function Combobox({ actionsRef, onOpenChange, ...props }) {
|
|
9
|
+
const exit = usePopupExit(actionsRef, onOpenChange);
|
|
10
|
+
return (_jsx(PopupExitContext, { value: exit.unmount, children: _jsx(ComboboxPrimitive.Root, { ...props, actionsRef: exit.actionsRef, onOpenChange: exit.onOpenChange }) }));
|
|
11
|
+
}
|
|
12
|
+
/** The field itself: an editable text input (the select trigger look) that opens the list when pressed. */
|
|
13
|
+
function ComboboxInput({ className, ...props }) {
|
|
14
|
+
return (_jsxs("div", { "data-slot": "combobox-input-wrapper", className: "relative w-full", children: [_jsx(ComboboxPrimitive.Input, { "data-slot": "combobox-input", className: cn('h-8 w-full truncate rounded-lg border border-input bg-transparent py-2 pr-8 pl-2.5 text-sm transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40', className), ...props }), _jsx(ChevronDownIcon, { "aria-hidden": true, className: "pointer-events-none absolute top-1/2 right-2 size-4 -translate-y-1/2 text-muted-foreground" })] }));
|
|
15
|
+
}
|
|
16
|
+
function ComboboxContent({ className, children, side = 'bottom', sideOffset = 4, align = 'start', ...props }) {
|
|
17
|
+
const renderPopup = usePopupRender();
|
|
18
|
+
return (_jsx(ComboboxPrimitive.Portal, { children: _jsx(ComboboxPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, className: "isolate z-(--z-dropdown)", children: _jsx(ComboboxPrimitive.Popup, { render: renderPopup, "data-slot": "combobox-content", className: cn('relative isolate z-(--z-dropdown) w-(--anchor-width) min-w-56 origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10', className), ...props, children: children }) }) }));
|
|
19
|
+
}
|
|
20
|
+
/** The scroll area. Group labels stick to its top edge, so it carries no top padding of its own. */
|
|
21
|
+
function ComboboxList({ className, ...props }) {
|
|
22
|
+
return (_jsx(ComboboxPrimitive.List, { "data-slot": "combobox-list", className: cn('max-h-72 overflow-x-hidden overflow-y-auto px-1 pb-1', className), ...props }));
|
|
23
|
+
}
|
|
24
|
+
function ComboboxEmpty({ className, ...props }) {
|
|
25
|
+
return (_jsx(ComboboxPrimitive.Empty, { "data-slot": "combobox-empty", className: cn('px-2 py-2 text-center text-sm text-muted-foreground empty:hidden', className), ...props }));
|
|
26
|
+
}
|
|
27
|
+
function ComboboxGroup({ className, ...props }) {
|
|
28
|
+
return _jsx(ComboboxPrimitive.Group, { "data-slot": "combobox-group", className: className, ...props });
|
|
29
|
+
}
|
|
30
|
+
/** Pinned to the top of the scroll area until the next group's label pushes it away. */
|
|
31
|
+
function ComboboxGroupLabel({ className, ...props }) {
|
|
32
|
+
return (_jsx(ComboboxPrimitive.GroupLabel, { "data-slot": "combobox-group-label", className: cn('sticky top-0 z-10 bg-popover px-2 py-1.5 text-xs font-medium text-muted-foreground', className), ...props }));
|
|
33
|
+
}
|
|
34
|
+
function ComboboxItem({ className, children, ...props }) {
|
|
35
|
+
return (_jsxs(ComboboxPrimitive.Item, { "data-slot": "combobox-item", className: cn('relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50', className), ...props, children: [children, _jsx(ComboboxPrimitive.ItemIndicator, { render: _jsx("span", { className: "flex size-4 shrink-0 items-center justify-center" }), children: _jsx(CheckIcon, { "aria-hidden": true, className: "size-4" }) })] }));
|
|
36
|
+
}
|
|
37
|
+
export { Combobox, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxList, };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Command as CommandPrimitive } from 'cmdk';
|
|
3
|
+
import { Dialog } from './dialog.js';
|
|
4
|
+
declare function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>): React.JSX.Element;
|
|
5
|
+
declare function CommandInput({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Input>): React.JSX.Element;
|
|
6
|
+
declare function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>): React.JSX.Element;
|
|
7
|
+
declare function CommandEmpty({ ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>): React.JSX.Element;
|
|
8
|
+
declare function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>): React.JSX.Element;
|
|
9
|
+
declare function CommandSeparator({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Separator>): React.JSX.Element;
|
|
10
|
+
declare function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>): React.JSX.Element;
|
|
11
|
+
declare function CommandShortcut({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
|
|
12
|
+
declare function CommandDialog({ children, ...props }: Omit<React.ComponentProps<typeof Dialog>, 'children'> & {
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
}): React.JSX.Element;
|
|
15
|
+
export { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut, CommandDialog, };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Command as CommandPrimitive } from 'cmdk';
|
|
4
|
+
import { Search as SearchIcon } from '../../icons/index.js';
|
|
5
|
+
import { cn } from '../../lib/utils.js';
|
|
6
|
+
import { Dialog, DialogContent } from './dialog.js';
|
|
7
|
+
function Command({ className, ...props }) {
|
|
8
|
+
return (_jsx(CommandPrimitive, { "data-slot": "command", className: cn('flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground', className), ...props }));
|
|
9
|
+
}
|
|
10
|
+
function CommandInput({ className, ...props }) {
|
|
11
|
+
return (_jsxs("div", { "data-slot": "command-input-wrapper", className: "flex items-center border-b px-3", children: [_jsx(SearchIcon, { className: "mr-2 size-4 shrink-0 opacity-50" }), _jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50', className), ...props })] }));
|
|
12
|
+
}
|
|
13
|
+
function CommandList({ className, ...props }) {
|
|
14
|
+
return (_jsx(CommandPrimitive.List, { "data-slot": "command-list", className: cn('max-h-72 overflow-y-auto overflow-x-hidden', className), ...props }));
|
|
15
|
+
}
|
|
16
|
+
function CommandEmpty({ ...props }) {
|
|
17
|
+
return (_jsx(CommandPrimitive.Empty, { "data-slot": "command-empty", className: "py-6 text-center text-sm", ...props }));
|
|
18
|
+
}
|
|
19
|
+
function CommandGroup({ className, ...props }) {
|
|
20
|
+
return (_jsx(CommandPrimitive.Group, { "data-slot": "command-group", className: cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', className), ...props }));
|
|
21
|
+
}
|
|
22
|
+
function CommandSeparator({ className, ...props }) {
|
|
23
|
+
return (_jsx(CommandPrimitive.Separator, { "data-slot": "command-separator", className: cn('-mx-1 h-px bg-border', className), ...props }));
|
|
24
|
+
}
|
|
25
|
+
function CommandItem({ className, ...props }) {
|
|
26
|
+
return (_jsx(CommandPrimitive.Item, { "data-slot": "command-item", className: cn('relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50', className), ...props }));
|
|
27
|
+
}
|
|
28
|
+
function CommandShortcut({ className, ...props }) {
|
|
29
|
+
return (_jsx("span", { "data-slot": "command-shortcut", className: cn('ml-auto text-xs tracking-widest text-muted-foreground', className), ...props }));
|
|
30
|
+
}
|
|
31
|
+
function CommandDialog({ children, ...props }) {
|
|
32
|
+
return (_jsx(Dialog, { ...props, children: _jsx(DialogContent, { className: "overflow-hidden p-0 shadow-lg", showCloseButton: false, children: _jsx(Command, { className: "[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:size-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:size-5", children: children }) }) }));
|
|
33
|
+
}
|
|
34
|
+
export { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut, CommandDialog, };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ContextMenu as ContextMenuPrimitive } from '@base-ui/react/context-menu';
|
|
3
|
+
declare function ContextMenu({ actionsRef, onOpenChange, ...props }: ContextMenuPrimitive.Root.Props): React.JSX.Element;
|
|
4
|
+
declare function ContextMenuTrigger({ className, ...props }: ContextMenuPrimitive.Trigger.Props): React.JSX.Element;
|
|
5
|
+
declare function ContextMenuContent({ className, ...props }: ContextMenuPrimitive.Popup.Props): React.JSX.Element;
|
|
6
|
+
declare function ContextMenuItem({ className, variant, disabled, disabledReason, ...props }: ContextMenuPrimitive.Item.Props & {
|
|
7
|
+
variant?: 'default' | 'destructive';
|
|
8
|
+
/** Disables the item and explains why on hover. Leave empty when the item is enabled. */
|
|
9
|
+
disabledReason?: React.ReactNode;
|
|
10
|
+
}): React.JSX.Element;
|
|
11
|
+
declare function ContextMenuCheckboxItem({ className, children, ...props }: ContextMenuPrimitive.CheckboxItem.Props): React.JSX.Element;
|
|
12
|
+
declare function ContextMenuRadioGroup({ ...props }: ContextMenuPrimitive.RadioGroup.Props): React.JSX.Element;
|
|
13
|
+
declare function ContextMenuRadioItem({ className, children, ...props }: ContextMenuPrimitive.RadioItem.Props): React.JSX.Element;
|
|
14
|
+
declare function ContextMenuLabel({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
15
|
+
declare function ContextMenuSeparator({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
16
|
+
declare function ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
|
|
17
|
+
declare function ContextMenuGroup({ ...props }: ContextMenuPrimitive.Group.Props): React.JSX.Element;
|
|
18
|
+
declare function ContextMenuSub({ actionsRef, onOpenChange, ...props }: ContextMenuPrimitive.SubmenuRoot.Props): React.JSX.Element;
|
|
19
|
+
declare function ContextMenuSubTrigger({ className, children, ...props }: ContextMenuPrimitive.SubmenuTrigger.Props): React.JSX.Element;
|
|
20
|
+
declare function ContextMenuSubContent({ className, ...props }: ContextMenuPrimitive.Popup.Props): React.JSX.Element;
|
|
21
|
+
export { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuGroup, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { ContextMenu as ContextMenuPrimitive } from '@base-ui/react/context-menu';
|
|
4
|
+
import { ChevronRight as ChevronRightIcon } from '../../icons/index.js';
|
|
5
|
+
import { cn } from '../../lib/utils.js';
|
|
6
|
+
import { DisabledReason } from './disabled-reason.js';
|
|
7
|
+
import { PopupExitContext, usePopupExit, usePopupRender } from '../../motion/popup.js';
|
|
8
|
+
function ContextMenu({ actionsRef, onOpenChange, ...props }) {
|
|
9
|
+
const exit = usePopupExit(actionsRef, onOpenChange);
|
|
10
|
+
return (_jsx(PopupExitContext, { value: exit.unmount, children: _jsx(ContextMenuPrimitive.Root, { "data-slot": "context-menu", ...props, actionsRef: exit.actionsRef, onOpenChange: exit.onOpenChange }) }));
|
|
11
|
+
}
|
|
12
|
+
// A touch long press is also how a webview starts a text selection or shows its callout, and it
|
|
13
|
+
// starts first, so on touch devices the trigger must not be selectable.
|
|
14
|
+
const TOUCH_PRESS_CLASS = 'pointer-coarse:select-none pointer-coarse:[-webkit-touch-callout:none]';
|
|
15
|
+
function ContextMenuTrigger({ className, ...props }) {
|
|
16
|
+
return (_jsx(ContextMenuPrimitive.Trigger, { "data-slot": "context-menu-trigger", className: typeof className === 'function'
|
|
17
|
+
? (state) => cn(TOUCH_PRESS_CLASS, className(state))
|
|
18
|
+
: cn(TOUCH_PRESS_CLASS, className), ...props }));
|
|
19
|
+
}
|
|
20
|
+
function ContextMenuContent({ className, ...props }) {
|
|
21
|
+
const renderPopup = usePopupRender();
|
|
22
|
+
return (_jsx(ContextMenuPrimitive.Portal, { children: _jsx(ContextMenuPrimitive.Positioner, { className: "isolate z-(--z-dropdown) outline-none", children: _jsx(ContextMenuPrimitive.Popup, { render: renderPopup, "data-slot": "context-menu-content", className: cn('z-(--z-dropdown) min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground in-data-[platform=mobile]:flex in-data-[platform=mobile]:flex-col in-data-[platform=mobile]:gap-0.5 shadow-md', className), ...props }) }) }));
|
|
23
|
+
}
|
|
24
|
+
function ContextMenuItem({ className, variant = 'default', disabled, disabledReason, ...props }) {
|
|
25
|
+
const item = (_jsx(ContextMenuPrimitive.Item, { "data-slot": "context-menu-item", "data-variant": variant, disabled: disabled || Boolean(disabledReason), className: cn('relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm in-data-[platform=mobile]:text-base outline-none focus:bg-accent focus:text-accent-foreground 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 data-disabled:pointer-events-none data-disabled:opacity-50', className), ...props }));
|
|
26
|
+
return disabledReason ? (_jsx(DisabledReason, { reason: disabledReason, side: "inline-end", focusable: false, className: "flex rounded-sm", children: item })) : (item);
|
|
27
|
+
}
|
|
28
|
+
function ContextMenuCheckboxItem({ className, children, ...props }) {
|
|
29
|
+
return (_jsx(ContextMenuPrimitive.CheckboxItem, { "data-slot": "context-menu-checkbox-item", className: cn('relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm in-data-[platform=mobile]:text-base outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50', className), ...props, children: children }));
|
|
30
|
+
}
|
|
31
|
+
function ContextMenuRadioGroup({ ...props }) {
|
|
32
|
+
return _jsx(ContextMenuPrimitive.RadioGroup, { "data-slot": "context-menu-radio-group", ...props });
|
|
33
|
+
}
|
|
34
|
+
function ContextMenuRadioItem({ className, children, ...props }) {
|
|
35
|
+
return (_jsx(ContextMenuPrimitive.RadioItem, { "data-slot": "context-menu-radio-item", className: cn('relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm in-data-[platform=mobile]:text-base outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50', className), ...props, children: children }));
|
|
36
|
+
}
|
|
37
|
+
function ContextMenuLabel({ className, ...props }) {
|
|
38
|
+
return (_jsx("div", { "data-slot": "context-menu-label", className: cn('px-2 py-1.5 text-xs font-semibold text-muted-foreground', className), ...props }));
|
|
39
|
+
}
|
|
40
|
+
function ContextMenuSeparator({ className, ...props }) {
|
|
41
|
+
return (_jsx("div", { "data-slot": "context-menu-separator", role: "separator", className: cn('-mx-1 my-1 h-px bg-border', className), ...props }));
|
|
42
|
+
}
|
|
43
|
+
function ContextMenuShortcut({ className, ...props }) {
|
|
44
|
+
return (_jsx("span", { "data-slot": "context-menu-shortcut", className: cn('ml-auto text-xs tracking-widest text-muted-foreground', className), ...props }));
|
|
45
|
+
}
|
|
46
|
+
function ContextMenuGroup({ ...props }) {
|
|
47
|
+
return _jsx(ContextMenuPrimitive.Group, { "data-slot": "context-menu-group", ...props });
|
|
48
|
+
}
|
|
49
|
+
function ContextMenuSub({ actionsRef, onOpenChange, ...props }) {
|
|
50
|
+
const exit = usePopupExit(actionsRef, onOpenChange);
|
|
51
|
+
return (_jsx(PopupExitContext, { value: exit.unmount, children: _jsx(ContextMenuPrimitive.SubmenuRoot, { "data-slot": "context-menu-sub", ...props, actionsRef: exit.actionsRef, onOpenChange: exit.onOpenChange }) }));
|
|
52
|
+
}
|
|
53
|
+
function ContextMenuSubTrigger({ className, children, ...props }) {
|
|
54
|
+
return (_jsxs(ContextMenuPrimitive.SubmenuTrigger, { "data-slot": "context-menu-sub-trigger", className: cn('flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm in-data-[platform=mobile]:text-base outline-none focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*="size-"])]:size-4', className), ...props, children: [children, _jsx(ChevronRightIcon, { className: "ml-auto" })] }));
|
|
55
|
+
}
|
|
56
|
+
function ContextMenuSubContent({ className, ...props }) {
|
|
57
|
+
const renderPopup = usePopupRender();
|
|
58
|
+
return (_jsx(ContextMenuPrimitive.Portal, { children: _jsx(ContextMenuPrimitive.Positioner, { className: "isolate z-(--z-dropdown) outline-none", children: _jsx(ContextMenuPrimitive.Popup, { render: renderPopup, "data-slot": "context-menu-sub-content", className: cn('z-(--z-dropdown) min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground in-data-[platform=mobile]:flex in-data-[platform=mobile]:flex-col in-data-[platform=mobile]:gap-0.5 shadow-lg', className), ...props }) }) }));
|
|
59
|
+
}
|
|
60
|
+
export { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuGroup, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
2
|
+
declare const counterVariants: (props?: ({
|
|
3
|
+
variant?: "default" | "primary" | null | undefined;
|
|
4
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
5
|
+
interface CounterProps extends VariantProps<typeof counterVariants> {
|
|
6
|
+
count: number;
|
|
7
|
+
max?: number;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function Counter({ count, max, variant, className }: CounterProps): import("react").JSX.Element | null;
|
|
11
|
+
export { Counter, counterVariants, type CounterProps };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cva } from 'class-variance-authority';
|
|
3
|
+
import { Swap } from '../../motion/index.js';
|
|
4
|
+
import { cn } from '../../lib/utils.js';
|
|
5
|
+
const counterVariants = cva('inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-body-3 font-semibold tabular-nums', {
|
|
6
|
+
variants: {
|
|
7
|
+
variant: {
|
|
8
|
+
default: 'bg-secondary text-secondary-foreground',
|
|
9
|
+
primary: 'bg-primary text-primary-foreground',
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
defaultVariants: { variant: 'default' },
|
|
13
|
+
});
|
|
14
|
+
function Counter({ count, max = 99, variant, className }) {
|
|
15
|
+
if (count <= 0)
|
|
16
|
+
return null;
|
|
17
|
+
const text = count > max ? `${max}+` : String(count);
|
|
18
|
+
return (_jsx("span", { "data-slot": "counter", className: cn(counterVariants({ variant }), className), children: _jsx(Swap, { swapKey: text, inline: true, children: text }) }));
|
|
19
|
+
}
|
|
20
|
+
export { Counter, counterVariants };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
|
|
3
|
+
declare function Dialog({ actionsRef, onOpenChange, ...props }: DialogPrimitive.Root.Props): React.JSX.Element;
|
|
4
|
+
declare function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props): React.JSX.Element;
|
|
5
|
+
declare function DialogPortal({ ...props }: DialogPrimitive.Portal.Props): React.JSX.Element;
|
|
6
|
+
declare function DialogClose({ ...props }: DialogPrimitive.Close.Props): React.JSX.Element;
|
|
7
|
+
declare function DialogOverlay({ className, ...props }: DialogPrimitive.Backdrop.Props): React.JSX.Element;
|
|
8
|
+
declare function DialogContent({ className, children, showCloseButton, ...props }: DialogPrimitive.Popup.Props & {
|
|
9
|
+
showCloseButton?: boolean;
|
|
10
|
+
}): React.JSX.Element;
|
|
11
|
+
declare function DialogHeader({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
12
|
+
declare function DialogFooter({ className, showCloseButton, children, ...props }: React.ComponentProps<'div'> & {
|
|
13
|
+
showCloseButton?: boolean;
|
|
14
|
+
}): React.JSX.Element;
|
|
15
|
+
declare function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props): React.JSX.Element;
|
|
16
|
+
declare function DialogDescription({ className, ...props }: DialogPrimitive.Description.Props): React.JSX.Element;
|
|
17
|
+
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
|
|
4
|
+
import { cn } from '../../lib/utils.js';
|
|
5
|
+
import { PopupExitContext, renderBackdrop, useModalRender, usePopupExit } from '../../motion/popup.js';
|
|
6
|
+
import { presets } from '../../motion/config.js';
|
|
7
|
+
import { Button } from './button.js';
|
|
8
|
+
import { X as XIcon } from '../../icons/index.js';
|
|
9
|
+
function Dialog({ actionsRef, onOpenChange, ...props }) {
|
|
10
|
+
const exit = usePopupExit(actionsRef, onOpenChange);
|
|
11
|
+
return (_jsx(PopupExitContext, { value: exit.unmount, children: _jsx(DialogPrimitive.Root, { "data-slot": "dialog", ...props, actionsRef: exit.actionsRef, onOpenChange: exit.onOpenChange }) }));
|
|
12
|
+
}
|
|
13
|
+
function DialogTrigger({ ...props }) {
|
|
14
|
+
return _jsx(DialogPrimitive.Trigger, { "data-slot": "dialog-trigger", ...props });
|
|
15
|
+
}
|
|
16
|
+
function DialogPortal({ ...props }) {
|
|
17
|
+
return _jsx(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
|
|
18
|
+
}
|
|
19
|
+
function DialogClose({ ...props }) {
|
|
20
|
+
return _jsx(DialogPrimitive.Close, { "data-slot": "dialog-close", ...props });
|
|
21
|
+
}
|
|
22
|
+
function DialogOverlay({ className, ...props }) {
|
|
23
|
+
return (_jsx(DialogPrimitive.Backdrop, { render: renderBackdrop, "data-slot": "dialog-overlay", className: cn('fixed inset-y-0 left-[var(--overlay-inset-left,0px)] right-[var(--overlay-inset-right,0px)] isolate z-(--z-modal) bg-black/10 supports-backdrop-filter:backdrop-blur-xs', className), ...props }));
|
|
24
|
+
}
|
|
25
|
+
function DialogContent({ className, children, showCloseButton = true, ...props }) {
|
|
26
|
+
const renderPopup = useModalRender(presets.dialog);
|
|
27
|
+
return (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Popup, { render: renderPopup, "data-slot": "dialog-content", className: cn('fixed top-1/2 left-[var(--overlay-inset-left,0px)] right-[var(--overlay-inset-right,0px)] mx-auto z-(--z-modal) grid w-[calc(100%-var(--overlay-inset-left,0px)-var(--overlay-inset-right,0px)-var(--modal-gutter,2rem))]! -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 outline-none sm:max-w-sm', className), ...props, children: [children, showCloseButton && (_jsxs(DialogPrimitive.Close, { "data-slot": "dialog-close", render: _jsx(Button, { variant: "ghost", className: "absolute top-2 right-2", size: "icon-sm" }), children: [_jsx(XIcon, {}), _jsx("span", { className: "sr-only", children: "Close" })] }))] })] }));
|
|
28
|
+
}
|
|
29
|
+
function DialogHeader({ className, ...props }) {
|
|
30
|
+
return (_jsx("div", { "data-slot": "dialog-header", className: cn('flex flex-col gap-2', className), ...props }));
|
|
31
|
+
}
|
|
32
|
+
function DialogFooter({ className, showCloseButton = false, children, ...props }) {
|
|
33
|
+
return (_jsxs("div", { "data-slot": "dialog-footer", className: cn('-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end', className), ...props, children: [children, showCloseButton && (_jsx(DialogPrimitive.Close, { render: _jsx(Button, { variant: "outline" }), children: "Close" }))] }));
|
|
34
|
+
}
|
|
35
|
+
function DialogTitle({ className, ...props }) {
|
|
36
|
+
return (_jsx(DialogPrimitive.Title, { "data-slot": "dialog-title", className: cn('text-base leading-none font-medium', className), ...props }));
|
|
37
|
+
}
|
|
38
|
+
function DialogDescription({ className, ...props }) {
|
|
39
|
+
return (_jsx(DialogPrimitive.Description, { "data-slot": "dialog-description", className: cn('text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground', className), ...props }));
|
|
40
|
+
}
|
|
41
|
+
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
type DisabledReasonProps = {
|
|
3
|
+
/** Why the wrapped control is disabled. Empty means it is enabled: no tooltip, not focusable. */
|
|
4
|
+
reason?: ReactNode;
|
|
5
|
+
/** The disabled control. It still sets its own `disabled`; this only explains it. */
|
|
6
|
+
children: ReactElement;
|
|
7
|
+
side?: 'top' | 'bottom' | 'left' | 'right' | 'inline-start' | 'inline-end';
|
|
8
|
+
/**
|
|
9
|
+
* Makes the wrapper a tab stop so keyboard users can reach the explanation, because a disabled
|
|
10
|
+
* control is skipped by Tab. Turn it off inside menus, which own their keyboard navigation.
|
|
11
|
+
*/
|
|
12
|
+
focusable?: boolean;
|
|
13
|
+
className?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Hover and focus explanation for a disabled control. A disabled control takes no pointer events
|
|
17
|
+
* (`pointer-events-none`, and no native `title`), so a tooltip or `title` on the control itself
|
|
18
|
+
* never opens; the wrapper receives the hover instead.
|
|
19
|
+
*/
|
|
20
|
+
declare function DisabledReason({ reason, children, side, focusable, className, }: DisabledReasonProps): import("react").JSX.Element;
|
|
21
|
+
export { DisabledReason };
|
|
22
|
+
export type { DisabledReasonProps };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from './tooltip.js';
|
|
5
|
+
/**
|
|
6
|
+
* Hover and focus explanation for a disabled control. A disabled control takes no pointer events
|
|
7
|
+
* (`pointer-events-none`, and no native `title`), so a tooltip or `title` on the control itself
|
|
8
|
+
* never opens; the wrapper receives the hover instead.
|
|
9
|
+
*/
|
|
10
|
+
function DisabledReason({ reason, children, side = 'top', focusable = true, className, }) {
|
|
11
|
+
const active = Boolean(reason);
|
|
12
|
+
// The wrapper stays mounted while `reason` toggles: swapping the tree would remount the control
|
|
13
|
+
// (dropping focus and in-flight clicks) every time it flips between enabled and disabled.
|
|
14
|
+
return (_jsxs(Tooltip, { disabled: !active, children: [_jsx(TooltipTrigger, { render: _jsx("span", { "data-slot": "disabled-reason", tabIndex: active && focusable ? 0 : undefined, className: cn('inline-flex rounded-lg outline-none focus-visible:ring-3 focus-visible:ring-ring/50', className) }), children: children }), active ? _jsx(TooltipContent, { side: side, children: reason }) : null] }));
|
|
15
|
+
}
|
|
16
|
+
export { DisabledReason };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Menu as MenuPrimitive } from '@base-ui/react/menu';
|
|
3
|
+
declare function DropdownMenu({ actionsRef, onOpenChange, ...props }: MenuPrimitive.Root.Props): React.JSX.Element;
|
|
4
|
+
declare function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props): React.JSX.Element;
|
|
5
|
+
declare function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props): React.JSX.Element;
|
|
6
|
+
declare function DropdownMenuContent({ align, alignOffset, side, sideOffset, className, ...props }: MenuPrimitive.Popup.Props & Pick<MenuPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>): React.JSX.Element;
|
|
7
|
+
declare function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props): React.JSX.Element;
|
|
8
|
+
declare function DropdownMenuLabel({ className, inset, ...props }: MenuPrimitive.GroupLabel.Props & {
|
|
9
|
+
inset?: boolean;
|
|
10
|
+
}): React.JSX.Element;
|
|
11
|
+
declare function DropdownMenuItem({ className, inset, variant, disabled, disabledReason, ...props }: MenuPrimitive.Item.Props & {
|
|
12
|
+
inset?: boolean;
|
|
13
|
+
variant?: 'default' | 'destructive';
|
|
14
|
+
/** Disables the item and explains why on hover. Leave empty when the item is enabled. */
|
|
15
|
+
disabledReason?: React.ReactNode;
|
|
16
|
+
}): React.JSX.Element;
|
|
17
|
+
declare function DropdownMenuSub({ actionsRef, onOpenChange, ...props }: MenuPrimitive.SubmenuRoot.Props): React.JSX.Element;
|
|
18
|
+
declare function DropdownMenuSubTrigger({ className, inset, children, ...props }: MenuPrimitive.SubmenuTrigger.Props & {
|
|
19
|
+
inset?: boolean;
|
|
20
|
+
}): React.JSX.Element;
|
|
21
|
+
declare function DropdownMenuSubContent({ align, alignOffset, side, sideOffset, className, ...props }: React.ComponentProps<typeof DropdownMenuContent>): React.JSX.Element;
|
|
22
|
+
declare function DropdownMenuCheckboxItem({ className, children, checked, inset, ...props }: MenuPrimitive.CheckboxItem.Props & {
|
|
23
|
+
inset?: boolean;
|
|
24
|
+
}): React.JSX.Element;
|
|
25
|
+
declare function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props): React.JSX.Element;
|
|
26
|
+
declare function DropdownMenuRadioItem({ className, children, inset, disabled, disabledReason, ...props }: MenuPrimitive.RadioItem.Props & {
|
|
27
|
+
inset?: boolean;
|
|
28
|
+
/** Disables the item and explains why on hover. Leave empty when the item is enabled. */
|
|
29
|
+
disabledReason?: React.ReactNode;
|
|
30
|
+
}): React.JSX.Element;
|
|
31
|
+
declare function DropdownMenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props): React.JSX.Element;
|
|
32
|
+
declare function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
|
|
33
|
+
export { DropdownMenu, DropdownMenuPortal, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Menu as MenuPrimitive } from '@base-ui/react/menu';
|
|
4
|
+
import { cn } from '../../lib/utils.js';
|
|
5
|
+
import { PopupExitContext, usePopupExit, usePopupRender } from '../../motion/popup.js';
|
|
6
|
+
import { DisabledReason } from './disabled-reason.js';
|
|
7
|
+
import { Check as CheckIcon, ChevronRight as ChevronRightIcon } from '../../icons/index.js';
|
|
8
|
+
function DropdownMenu({ actionsRef, onOpenChange, ...props }) {
|
|
9
|
+
const exit = usePopupExit(actionsRef, onOpenChange);
|
|
10
|
+
return (_jsx(PopupExitContext, { value: exit.unmount, children: _jsx(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props, actionsRef: exit.actionsRef, onOpenChange: exit.onOpenChange }) }));
|
|
11
|
+
}
|
|
12
|
+
function DropdownMenuPortal({ ...props }) {
|
|
13
|
+
return _jsx(MenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
|
|
14
|
+
}
|
|
15
|
+
function DropdownMenuTrigger({ ...props }) {
|
|
16
|
+
return _jsx(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
17
|
+
}
|
|
18
|
+
function DropdownMenuContent({ align = 'start', alignOffset = 0, side = 'bottom', sideOffset = 4, className, ...props }) {
|
|
19
|
+
const renderPopup = usePopupRender();
|
|
20
|
+
return (_jsx(MenuPrimitive.Portal, { children: _jsx(MenuPrimitive.Positioner, { className: "isolate z-(--z-dropdown) outline-none", align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, children: _jsx(MenuPrimitive.Popup, { render: renderPopup, "data-slot": "dropdown-menu-content", className: cn('z-(--z-dropdown) max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground in-data-[platform=mobile]:flex in-data-[platform=mobile]:flex-col in-data-[platform=mobile]:gap-0.5 shadow-md ring-1 ring-foreground/10 outline-none data-closed:overflow-hidden', className), ...props }) }) }));
|
|
21
|
+
}
|
|
22
|
+
function DropdownMenuGroup({ ...props }) {
|
|
23
|
+
return _jsx(MenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
|
|
24
|
+
}
|
|
25
|
+
function DropdownMenuLabel({ className, inset, ...props }) {
|
|
26
|
+
return (_jsx(MenuPrimitive.GroupLabel, { "data-slot": "dropdown-menu-label", "data-inset": inset, className: cn('px-1.5 py-1 text-xs in-data-[platform=mobile]:text-sm font-medium text-muted-foreground data-inset:pl-7', className), ...props }));
|
|
27
|
+
}
|
|
28
|
+
function DropdownMenuItem({ className, inset, variant = 'default', disabled, disabledReason, ...props }) {
|
|
29
|
+
const item = (_jsx(MenuPrimitive.Item, { "data-slot": "dropdown-menu-item", "data-inset": inset, "data-variant": variant, disabled: disabled || Boolean(disabledReason), className: cn("group/dropdown-menu-item relative flex cursor-pointer items-center gap-1.5 rounded-md px-1.5 py-1 text-sm in-data-[platform=mobile]:text-base outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 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-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive", className), ...props }));
|
|
30
|
+
return disabledReason ? (_jsx(DisabledReason, { reason: disabledReason, side: "inline-end", focusable: false, className: "flex rounded-md", children: item })) : (item);
|
|
31
|
+
}
|
|
32
|
+
function DropdownMenuSub({ actionsRef, onOpenChange, ...props }) {
|
|
33
|
+
const exit = usePopupExit(actionsRef, onOpenChange);
|
|
34
|
+
return (_jsx(PopupExitContext, { value: exit.unmount, children: _jsx(MenuPrimitive.SubmenuRoot, { "data-slot": "dropdown-menu-sub", ...props, actionsRef: exit.actionsRef, onOpenChange: exit.onOpenChange }) }));
|
|
35
|
+
}
|
|
36
|
+
function DropdownMenuSubTrigger({ className, inset, children, ...props }) {
|
|
37
|
+
return (_jsxs(MenuPrimitive.SubmenuTrigger, { "data-slot": "dropdown-menu-sub-trigger", "data-inset": inset, className: cn("flex cursor-pointer items-center gap-1.5 rounded-md px-1.5 py-1 text-sm in-data-[platform=mobile]:text-base outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: [children, _jsx(ChevronRightIcon, { className: "ml-auto" })] }));
|
|
38
|
+
}
|
|
39
|
+
function DropdownMenuSubContent({ align = 'start', alignOffset = -3, side = 'right', sideOffset = 0, className, ...props }) {
|
|
40
|
+
return (_jsx(DropdownMenuContent, { "data-slot": "dropdown-menu-sub-content", className: cn('w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground in-data-[platform=mobile]:flex in-data-[platform=mobile]:flex-col in-data-[platform=mobile]:gap-0.5 shadow-lg ring-1 ring-foreground/10', className), align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, ...props }));
|
|
41
|
+
}
|
|
42
|
+
function DropdownMenuCheckboxItem({ className, children, checked, inset, ...props }) {
|
|
43
|
+
return (_jsxs(MenuPrimitive.CheckboxItem, { "data-slot": "dropdown-menu-checkbox-item", "data-inset": inset, className: cn("relative flex cursor-pointer items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm in-data-[platform=mobile]:text-base outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), checked: checked, ...props, children: [_jsx("span", { className: "pointer-events-none absolute right-2 flex items-center justify-center", "data-slot": "dropdown-menu-checkbox-item-indicator", children: _jsx(MenuPrimitive.CheckboxItemIndicator, { children: _jsx(CheckIcon, {}) }) }), children] }));
|
|
44
|
+
}
|
|
45
|
+
function DropdownMenuRadioGroup({ ...props }) {
|
|
46
|
+
return _jsx(MenuPrimitive.RadioGroup, { "data-slot": "dropdown-menu-radio-group", ...props });
|
|
47
|
+
}
|
|
48
|
+
function DropdownMenuRadioItem({ className, children, inset, disabled, disabledReason, ...props }) {
|
|
49
|
+
const item = (_jsxs(MenuPrimitive.RadioItem, { "data-slot": "dropdown-menu-radio-item", "data-inset": inset, disabled: disabled || Boolean(disabledReason), className: cn("relative flex cursor-pointer items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm in-data-[platform=mobile]:text-base outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: [_jsx("span", { className: "pointer-events-none absolute right-2 flex items-center justify-center", "data-slot": "dropdown-menu-radio-item-indicator", children: _jsx(MenuPrimitive.RadioItemIndicator, { children: _jsx(CheckIcon, {}) }) }), children] }));
|
|
50
|
+
return disabledReason ? (_jsx(DisabledReason, { reason: disabledReason, side: "inline-end", focusable: false, className: "flex rounded-md", children: item })) : (item);
|
|
51
|
+
}
|
|
52
|
+
function DropdownMenuSeparator({ className, ...props }) {
|
|
53
|
+
return (_jsx(MenuPrimitive.Separator, { "data-slot": "dropdown-menu-separator", className: cn('-mx-1 my-1 h-px bg-border', className), ...props }));
|
|
54
|
+
}
|
|
55
|
+
function DropdownMenuShortcut({ className, ...props }) {
|
|
56
|
+
return (_jsx("span", { "data-slot": "dropdown-menu-shortcut", className: cn('ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground', className), ...props }));
|
|
57
|
+
}
|
|
58
|
+
export { DropdownMenu, DropdownMenuPortal, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type ComponentProps } from 'react';
|
|
2
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
+
/**
|
|
4
|
+
* Typography applied to both the trigger button and the editing input so the
|
|
5
|
+
* layout does not shift when entering or leaving edit mode.
|
|
6
|
+
*/
|
|
7
|
+
declare const editableTextVariants: (props?: ({
|
|
8
|
+
presentation?: "h3" | "base" | "h1" | "h2" | "h4" | "h5" | "h6" | "sm" | "pageTitle" | null | undefined;
|
|
9
|
+
align?: "center" | "left" | "right" | null | undefined;
|
|
10
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
11
|
+
type HeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
12
|
+
interface EditableTextProps extends Omit<ComponentProps<'span'>, 'children'>, VariantProps<typeof editableTextVariants> {
|
|
13
|
+
/** Current committed value. The component is fully controlled. */
|
|
14
|
+
value: string;
|
|
15
|
+
/**
|
|
16
|
+
* Called when the user commits an edit via Enter or blur. Receives the
|
|
17
|
+
* trimmed new value. Not called when the value is unchanged or when the
|
|
18
|
+
* input is empty (empty is silently rejected and the prior value is
|
|
19
|
+
* restored).
|
|
20
|
+
*/
|
|
21
|
+
onCommit?: (value: string) => void;
|
|
22
|
+
/** Placeholder text shown when `value` is empty. */
|
|
23
|
+
placeholder?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Start in edit mode on mount (the input is focused with the value selected). Used when an
|
|
26
|
+
* external action such as a "Rename" menu item mounts the control to edit right away.
|
|
27
|
+
*/
|
|
28
|
+
defaultEditing?: boolean;
|
|
29
|
+
/** Fires when edit mode is entered (`true`) or left by commit or cancel (`false`). */
|
|
30
|
+
onEditingChange?: (editing: boolean) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Prevents entering edit mode by mouse or keyboard. The trigger button is
|
|
33
|
+
* not focusable when disabled.
|
|
34
|
+
*/
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Wraps the control in a semantic heading element so screen readers can
|
|
38
|
+
* navigate to it by heading level. The `presentation` prop controls the
|
|
39
|
+
* visual size independently.
|
|
40
|
+
*
|
|
41
|
+
* Covers the `EditableHeading` use-case (chat header title, 1 call site).
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // Semantically h1 but visually h3-sized — compact chat header
|
|
45
|
+
* <EditableText as="h1" presentation="h3" value={title} onCommit={setTitle} />
|
|
46
|
+
*/
|
|
47
|
+
as?: HeadingTag;
|
|
48
|
+
/**
|
|
49
|
+
* Accessible name for both the trigger button and the edit input. Defaults
|
|
50
|
+
* to the current `value` (or `placeholder` when empty). Supply this when
|
|
51
|
+
* the rendered text alone does not make the field's purpose clear.
|
|
52
|
+
*/
|
|
53
|
+
'aria-label'?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* `EditableText` — inline-rename primitive.
|
|
57
|
+
*
|
|
58
|
+
* Replaces Vibe's `EditableText` (sidebar rename, 2 call sites) **and**
|
|
59
|
+
* `EditableHeading` (chat header title, 1 call site). One component covers
|
|
60
|
+
* both: use `as` for heading semantics and `presentation` for visual size.
|
|
61
|
+
*
|
|
62
|
+
* ### Accessibility contract
|
|
63
|
+
*
|
|
64
|
+
* **Read mode:** a native `<button>` — keyboard-focusable, announces as
|
|
65
|
+
* interactive, activatable via Enter or Space.
|
|
66
|
+
*
|
|
67
|
+
* **Edit mode:** a `<input type="text">` — on entry, focus moves to the
|
|
68
|
+
* input and the existing text is pre-selected so typing immediately replaces.
|
|
69
|
+
*
|
|
70
|
+
* **Commit:** Enter or blur. Blur is the right default here because it
|
|
71
|
+
* mirrors every OS file-rename pattern — clicking away is "done".
|
|
72
|
+
*
|
|
73
|
+
* **Cancel:** Escape. The _original_ value is restored (not just edit mode
|
|
74
|
+
* exited). Focus returns to the trigger button.
|
|
75
|
+
*
|
|
76
|
+
* **Empty:** blank input is rejected on commit; `onCommit` is not called and
|
|
77
|
+
* the prior value is silently restored.
|
|
78
|
+
*
|
|
79
|
+
* **Focus return:** after commit or cancel, focus returns to the trigger
|
|
80
|
+
* button — not to `document.body`.
|
|
81
|
+
*
|
|
82
|
+
* **Mode-change perception:** the native `<button>` announces as interactive.
|
|
83
|
+
* On activation focus shifts to the input, which is the screen-reader cue for
|
|
84
|
+
* the mode change. No `aria-live` region is used — it would fire twice (once
|
|
85
|
+
* on enter, once on exit) and is noisier than the natural focus-based cue.
|
|
86
|
+
* A visually-hidden `aria-describedby` hint tells SR users how to activate
|
|
87
|
+
* without lengthening the button's primary label.
|
|
88
|
+
*
|
|
89
|
+
* **Layout stability:** the trigger button and the input share identical
|
|
90
|
+
* padding and a 1 px border (transparent on the button, `border-input` on
|
|
91
|
+
* the input) so the surrounding layout does not shift on mode change.
|
|
92
|
+
*/
|
|
93
|
+
declare function EditableText({ value, onCommit, placeholder, disabled, defaultEditing, onEditingChange, as: Tag, presentation, align, className, 'aria-label': ariaLabel, ...rest }: EditableTextProps): import("react").JSX.Element;
|
|
94
|
+
export { EditableText, editableTextVariants };
|
|
95
|
+
export type { EditableTextProps };
|