@adea-ai/ui 0.61.0 → 0.62.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 +44 -6
- package/dist/LICENSE +201 -0
- package/dist/NOTICE +50 -0
- package/dist/components/composites/account-menu/index.js +2 -0
- package/dist/components/composites/list-row/index.js +2 -0
- package/dist/components/composites/settings/index.js +2 -0
- package/dist/components/composites/stat/index.js +2 -0
- package/dist/components/composites/update-dialog/index.js +2 -0
- package/dist/components/composites/workspace-mark/index.js +2 -0
- package/dist/components/conversation/index.js +6 -0
- package/dist/components/layout/app-shell/index.js +2 -0
- package/dist/components/layout/page/index.js +2 -0
- package/dist/components/layout/panel/index.js +2 -0
- package/dist/components/layout/side-rail/index.js +3 -0
- package/dist/components/layout/sidebar-nav/index.js +2 -0
- package/dist/components/layout/status-bar/index.js +2 -0
- package/dist/components/layout/top-bar/index.js +2 -0
- package/dist/components/motion/index.js +2 -2
- package/dist/components/theme/index.js +5 -0
- package/dist/components/ui/accordion/index.js +2 -0
- package/dist/components/ui/alert/index.js +2 -0
- package/dist/components/ui/alert-dialog/index.js +2 -0
- package/dist/components/ui/aspect-ratio/index.js +2 -0
- package/dist/components/ui/avatar/index.js +2 -0
- package/dist/components/ui/badge/index.js +2 -0
- package/dist/components/ui/board/index.js +2 -0
- package/dist/components/ui/breadcrumb/index.js +2 -0
- package/dist/components/ui/button/index.js +2 -0
- package/dist/components/ui/button-group/index.js +2 -0
- package/dist/components/ui/calendar/index.js +2 -0
- package/dist/components/ui/card/index.js +2 -0
- package/dist/components/ui/carousel/index.js +2 -0
- package/dist/components/ui/chart/index.js +2 -0
- package/dist/components/ui/checkbox/index.js +2 -0
- package/dist/components/ui/code-block/index.js +2 -0
- package/dist/components/ui/collapsible/index.js +2 -0
- package/dist/components/ui/combobox/index.js +2 -0
- package/dist/components/ui/command/index.js +2 -0
- package/dist/components/ui/context-menu/index.js +2 -0
- package/dist/components/ui/detail-panel/index.js +2 -0
- package/dist/components/ui/dialog/index.js +2 -0
- package/dist/components/ui/diff-block/index.js +2 -0
- package/dist/components/ui/drawer/index.js +2 -0
- package/dist/components/ui/dropdown-menu/index.js +2 -0
- package/dist/components/ui/empty/index.js +2 -0
- package/dist/components/ui/entity-icon/index.js +2 -0
- package/dist/components/ui/field/index.js +2 -0
- package/dist/components/ui/hover-card/index.js +2 -0
- package/dist/components/ui/input/index.js +2 -0
- package/dist/components/ui/input-group/index.js +2 -0
- package/dist/components/ui/input-otp/index.js +2 -0
- package/dist/components/ui/item/index.js +2 -0
- package/dist/components/ui/kbd/index.js +2 -0
- package/dist/components/ui/label/index.js +2 -0
- package/dist/components/ui/menubar/index.js +2 -0
- package/dist/components/ui/modal-dialog/index.js +2 -0
- package/dist/components/ui/navigation-menu/index.js +2 -0
- package/dist/components/ui/pagination/index.js +2 -0
- package/dist/components/ui/popover/index.js +2 -0
- package/dist/components/ui/progress/index.js +2 -0
- package/dist/components/ui/radio-group/index.js +2 -0
- package/dist/components/ui/resizable/index.js +2 -0
- package/dist/components/ui/scroll-area/index.js +2 -0
- package/dist/components/ui/select/index.js +2 -0
- package/dist/components/ui/separator/index.js +2 -0
- package/dist/components/ui/sheet/index.js +2 -0
- package/dist/components/ui/skeleton/index.js +2 -0
- package/dist/components/ui/slider/index.js +2 -0
- package/dist/components/ui/spinner/index.js +2 -0
- package/dist/components/ui/status-chip/index.js +2 -0
- package/dist/components/ui/switch/index.js +2 -0
- package/dist/components/ui/table/index.js +2 -0
- package/dist/components/ui/tabs/index.js +2 -0
- package/dist/components/ui/textarea/index.js +2 -0
- package/dist/components/ui/toast/index.js +2 -0
- package/dist/components/ui/toggle/index.js +2 -0
- package/dist/components/ui/toggle-group/index.js +2 -0
- package/dist/components/ui/tooltip/index.js +2 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/r/accordion.json +3 -1
- package/dist/r/account-menu.json +2 -1
- package/dist/r/alert-dialog.json +3 -1
- package/dist/r/alert.json +3 -1
- package/dist/r/app-shell.json +3 -1
- package/dist/r/aspect-ratio.json +3 -1
- package/dist/r/avatar.json +3 -1
- package/dist/r/badge.json +3 -1
- package/dist/r/board.json +3 -1
- package/dist/r/breadcrumb.json +3 -1
- package/dist/r/button-group.json +2 -1
- package/dist/r/button.json +3 -1
- package/dist/r/calendar.json +2 -1
- package/dist/r/card.json +3 -1
- package/dist/r/carousel.json +2 -1
- package/dist/r/chart.json +3 -1
- package/dist/r/checkbox.json +3 -1
- package/dist/r/code-block.json +2 -1
- package/dist/r/collapsible.json +3 -1
- package/dist/r/combobox.json +3 -1
- package/dist/r/command.json +3 -1
- package/dist/r/context-menu.json +3 -1
- package/dist/r/conversation.json +2 -1
- package/dist/r/detail-panel.json +2 -1
- package/dist/r/dialog.json +3 -1
- package/dist/r/diff-block.json +3 -1
- package/dist/r/drawer.json +3 -1
- package/dist/r/dropdown-menu.json +3 -1
- package/dist/r/empty.json +3 -1
- package/dist/r/entity-icon.json +3 -1
- package/dist/r/field.json +3 -1
- package/dist/r/hover-card.json +3 -1
- package/dist/r/input-group.json +3 -1
- package/dist/r/input-otp.json +3 -1
- package/dist/r/input.json +3 -1
- package/dist/r/item.json +3 -1
- package/dist/r/kbd.json +3 -1
- package/dist/r/label.json +3 -1
- package/dist/r/lib.json +50 -0
- package/dist/r/list-row.json +3 -1
- package/dist/r/menubar.json +3 -1
- package/dist/r/modal-dialog.json +2 -1
- package/dist/r/motion.json +22 -0
- package/dist/r/navigation-menu.json +3 -1
- package/dist/r/page.json +3 -1
- package/dist/r/pagination.json +3 -1
- package/dist/r/panel.json +3 -1
- package/dist/r/popover.json +3 -1
- package/dist/r/progress.json +3 -1
- package/dist/r/radio-group.json +3 -1
- package/dist/r/registry.json +320 -73
- package/dist/r/resizable.json +3 -1
- package/dist/r/scroll-area.json +3 -1
- package/dist/r/select.json +3 -1
- package/dist/r/separator.json +3 -1
- package/dist/r/settings.json +3 -1
- package/dist/r/sheet.json +2 -1
- package/dist/r/side-rail.json +3 -1
- package/dist/r/sidebar-nav.json +3 -1
- package/dist/r/skeleton.json +3 -1
- package/dist/r/slider.json +3 -1
- package/dist/r/spinner.json +3 -1
- package/dist/r/src/components/composites/account-menu/account-menu.tsx +150 -0
- package/dist/r/src/components/composites/account-menu/index.ts +1 -0
- package/dist/r/src/components/composites/list-row/index.ts +1 -0
- package/dist/r/src/components/composites/list-row/list-row.tsx +116 -0
- package/dist/r/src/components/composites/settings/index.ts +1 -0
- package/dist/r/src/components/composites/settings/settings.tsx +142 -0
- package/dist/r/src/components/composites/stat/index.ts +9 -0
- package/dist/r/src/components/composites/stat/stat.tsx +155 -0
- package/dist/r/src/components/composites/update-dialog/index.ts +7 -0
- package/dist/r/src/components/composites/update-dialog/update-dialog.tsx +529 -0
- package/dist/r/src/components/composites/workspace-mark/index.ts +1 -0
- package/dist/r/src/components/composites/workspace-mark/workspace-mark.tsx +72 -0
- package/dist/r/src/components/conversation/conversation-avatar.tsx +60 -0
- package/dist/r/src/components/conversation/conversation-surface.tsx +107 -0
- package/dist/r/src/components/conversation/index.ts +25 -0
- package/dist/r/src/components/conversation/message-composer.tsx +239 -0
- package/dist/r/src/components/conversation/message-row.tsx +387 -0
- package/dist/r/src/components/conversation/thread-panel.tsx +141 -0
- package/dist/r/src/components/layout/app-shell/app-shell.tsx +92 -0
- package/dist/r/src/components/layout/app-shell/index.ts +1 -0
- package/dist/r/src/components/layout/page/index.ts +9 -0
- package/dist/r/src/components/layout/page/page.tsx +122 -0
- package/dist/r/src/components/layout/panel/index.ts +12 -0
- package/dist/r/src/components/layout/panel/panel.tsx +166 -0
- package/dist/r/src/components/layout/side-rail/index.ts +12 -0
- package/dist/r/src/components/layout/side-rail/side-rail-context.ts +42 -0
- package/dist/r/src/components/layout/side-rail/side-rail.tsx +405 -0
- package/dist/r/src/components/layout/sidebar-nav/index.ts +14 -0
- package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +244 -0
- package/dist/r/src/components/layout/status-bar/index.ts +1 -0
- package/dist/r/src/components/layout/status-bar/status-bar.tsx +73 -0
- package/dist/r/src/components/layout/top-bar/index.ts +10 -0
- package/dist/r/src/components/layout/top-bar/top-bar.tsx +166 -0
- package/dist/r/src/components/motion/index.ts +2 -0
- package/dist/r/src/components/motion/presence.tsx +32 -0
- package/dist/r/src/components/theme/appearance-panel.tsx +179 -0
- package/dist/r/src/components/theme/index.ts +22 -0
- package/dist/r/src/components/theme/theme-picker.tsx +174 -0
- package/dist/r/src/components/theme/theme-provider.tsx +309 -0
- package/dist/r/src/components/theme/theme-toggle.tsx +64 -0
- package/dist/r/src/components/ui/accordion/accordion.tsx +66 -0
- package/dist/r/src/components/ui/accordion/index.ts +1 -0
- package/dist/r/src/components/ui/alert/alert.tsx +95 -0
- package/dist/r/src/components/ui/alert/index.ts +1 -0
- package/dist/r/src/components/ui/alert-dialog/alert-dialog.tsx +176 -0
- package/dist/r/src/components/ui/alert-dialog/index.ts +13 -0
- package/dist/r/src/components/ui/aspect-ratio/aspect-ratio.tsx +38 -0
- package/dist/r/src/components/ui/aspect-ratio/index.ts +1 -0
- package/dist/r/src/components/ui/avatar/avatar.tsx +114 -0
- package/dist/r/src/components/ui/avatar/index.ts +9 -0
- package/dist/r/src/components/ui/badge/badge.tsx +59 -0
- package/dist/r/src/components/ui/badge/index.ts +1 -0
- package/dist/r/src/components/ui/board/board.tsx +254 -0
- package/dist/r/src/components/ui/board/index.ts +10 -0
- package/dist/r/src/components/ui/breadcrumb/breadcrumb.tsx +117 -0
- package/dist/r/src/components/ui/breadcrumb/index.ts +9 -0
- package/dist/r/src/components/ui/button/button.tsx +89 -0
- package/dist/r/src/components/ui/button/index.ts +1 -0
- package/dist/r/src/components/ui/button-group/button-group.tsx +92 -0
- package/dist/r/src/components/ui/button-group/index.ts +6 -0
- package/dist/r/src/components/ui/calendar/calendar.tsx +277 -0
- package/dist/r/src/components/ui/calendar/index.ts +1 -0
- package/dist/r/src/components/ui/card/card.tsx +82 -0
- package/dist/r/src/components/ui/card/index.ts +10 -0
- package/dist/r/src/components/ui/carousel/carousel.tsx +209 -0
- package/dist/r/src/components/ui/carousel/index.ts +1 -0
- package/dist/r/src/components/ui/chart/chart.tsx +413 -0
- package/dist/r/src/components/ui/chart/index.ts +17 -0
- package/dist/r/src/components/ui/checkbox/checkbox.tsx +99 -0
- package/dist/r/src/components/ui/checkbox/index.ts +1 -0
- package/dist/r/src/components/ui/code-block/code-block.tsx +238 -0
- package/dist/r/src/components/ui/code-block/index.ts +1 -0
- package/dist/r/src/components/ui/collapsible/collapsible.tsx +54 -0
- package/dist/r/src/components/ui/collapsible/index.ts +1 -0
- package/dist/r/src/components/ui/combobox/combobox.tsx +142 -0
- package/dist/r/src/components/ui/combobox/index.ts +10 -0
- package/dist/r/src/components/ui/command/command.tsx +214 -0
- package/dist/r/src/components/ui/command/index.ts +12 -0
- package/dist/r/src/components/ui/context-menu/context-menu.tsx +163 -0
- package/dist/r/src/components/ui/context-menu/index.ts +15 -0
- package/dist/r/src/components/ui/detail-panel/detail-panel.tsx +161 -0
- package/dist/r/src/components/ui/detail-panel/index.ts +9 -0
- package/dist/r/src/components/ui/dialog/dialog.tsx +138 -0
- package/dist/r/src/components/ui/dialog/index.ts +14 -0
- package/dist/r/src/components/ui/diff-block/diff-block.tsx +286 -0
- package/dist/r/src/components/ui/diff-block/index.ts +11 -0
- package/dist/r/src/components/ui/drawer/drawer.tsx +144 -0
- package/dist/r/src/components/ui/drawer/index.ts +13 -0
- package/dist/r/src/components/ui/dropdown-menu/dropdown-menu.tsx +203 -0
- package/dist/r/src/components/ui/dropdown-menu/index.ts +18 -0
- package/dist/r/src/components/ui/empty/empty.tsx +104 -0
- package/dist/r/src/components/ui/empty/index.ts +10 -0
- package/dist/r/src/components/ui/entity-icon/entity-icon.tsx +154 -0
- package/dist/r/src/components/ui/entity-icon/index.ts +1 -0
- package/dist/r/src/components/ui/field/field.tsx +131 -0
- package/dist/r/src/components/ui/field/index.ts +11 -0
- package/dist/r/src/components/ui/hover-card/hover-card.tsx +48 -0
- package/dist/r/src/components/ui/hover-card/index.ts +1 -0
- package/dist/r/src/components/ui/input/index.ts +1 -0
- package/dist/r/src/components/ui/input/input.tsx +41 -0
- package/dist/r/src/components/ui/input-group/index.ts +8 -0
- package/dist/r/src/components/ui/input-group/input-group.tsx +111 -0
- package/dist/r/src/components/ui/input-otp/index.ts +1 -0
- package/dist/r/src/components/ui/input-otp/input-otp.tsx +108 -0
- package/dist/r/src/components/ui/item/index.ts +10 -0
- package/dist/r/src/components/ui/item/item.tsx +146 -0
- package/dist/r/src/components/ui/kbd/index.ts +1 -0
- package/dist/r/src/components/ui/kbd/kbd.tsx +42 -0
- package/dist/r/src/components/ui/label/index.ts +1 -0
- package/dist/r/src/components/ui/label/label.tsx +36 -0
- package/dist/r/src/components/ui/menubar/index.ts +16 -0
- package/dist/r/src/components/ui/menubar/menubar.tsx +190 -0
- package/dist/r/src/components/ui/modal-dialog/index.ts +1 -0
- package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +95 -0
- package/dist/r/src/components/ui/navigation-menu/index.ts +13 -0
- package/dist/r/src/components/ui/navigation-menu/navigation-menu.tsx +229 -0
- package/dist/r/src/components/ui/pagination/index.ts +8 -0
- package/dist/r/src/components/ui/pagination/pagination.tsx +144 -0
- package/dist/r/src/components/ui/popover/index.ts +10 -0
- package/dist/r/src/components/ui/popover/popover.tsx +81 -0
- package/dist/r/src/components/ui/progress/index.ts +1 -0
- package/dist/r/src/components/ui/progress/progress.tsx +67 -0
- package/dist/r/src/components/ui/radio-group/index.ts +1 -0
- package/dist/r/src/components/ui/radio-group/radio-group.tsx +78 -0
- package/dist/r/src/components/ui/resizable/index.ts +6 -0
- package/dist/r/src/components/ui/resizable/resizable.tsx +74 -0
- package/dist/r/src/components/ui/scroll-area/index.ts +1 -0
- package/dist/r/src/components/ui/scroll-area/scroll-area.tsx +66 -0
- package/dist/r/src/components/ui/select/index.ts +11 -0
- package/dist/r/src/components/ui/select/select.tsx +188 -0
- package/dist/r/src/components/ui/separator/index.ts +1 -0
- package/dist/r/src/components/ui/separator/separator.tsx +40 -0
- package/dist/r/src/components/ui/sheet/index.ts +13 -0
- package/dist/r/src/components/ui/sheet/sheet.tsx +132 -0
- package/dist/r/src/components/ui/skeleton/index.ts +1 -0
- package/dist/r/src/components/ui/skeleton/skeleton.tsx +28 -0
- package/dist/r/src/components/ui/slider/index.ts +1 -0
- package/dist/r/src/components/ui/slider/slider.tsx +81 -0
- package/dist/r/src/components/ui/spinner/index.ts +1 -0
- package/dist/r/src/components/ui/spinner/spinner.tsx +58 -0
- package/dist/r/src/components/ui/status-chip/index.ts +8 -0
- package/dist/r/src/components/ui/status-chip/status-chip.tsx +142 -0
- package/dist/r/src/components/ui/switch/index.ts +1 -0
- package/dist/r/src/components/ui/switch/switch.tsx +100 -0
- package/dist/r/src/components/ui/table/index.ts +11 -0
- package/dist/r/src/components/ui/table/table.tsx +125 -0
- package/dist/r/src/components/ui/tabs/index.ts +8 -0
- package/dist/r/src/components/ui/tabs/tabs.tsx +77 -0
- package/dist/r/src/components/ui/textarea/index.ts +1 -0
- package/dist/r/src/components/ui/textarea/textarea.tsx +36 -0
- package/dist/r/src/components/ui/toast/index.ts +1 -0
- package/dist/r/src/components/ui/toast/toast.tsx +220 -0
- package/dist/r/src/components/ui/toggle/index.ts +1 -0
- package/dist/r/src/components/ui/toggle/toggle.tsx +60 -0
- package/dist/r/src/components/ui/toggle-group/index.ts +6 -0
- package/dist/r/src/components/ui/toggle-group/toggle-group.tsx +66 -0
- package/dist/r/src/components/ui/tooltip/index.ts +9 -0
- package/dist/r/src/components/ui/tooltip/tooltip.tsx +102 -0
- package/dist/r/src/lib/keyed-rows.ts +68 -0
- package/dist/r/src/lib/overlay.ts +70 -0
- package/dist/r/src/lib/themes.ts +490 -0
- package/dist/r/src/lib/tokens.ts +688 -0
- package/dist/r/src/lib/utils.ts +76 -0
- package/dist/r/src/lib/variants.ts +62 -0
- package/dist/r/src/lib/version-notes.ts +65 -0
- package/dist/r/src/styles/base.css +644 -0
- package/dist/r/src/styles/fonts.css +26 -0
- package/dist/r/src/styles/globals.css +18 -0
- package/dist/r/src/styles/theme.css +864 -0
- package/dist/r/stat.json +3 -1
- package/dist/r/status-bar.json +3 -1
- package/dist/r/status-chip.json +2 -1
- package/dist/r/switch.json +3 -1
- package/dist/r/table.json +3 -1
- package/dist/r/tabs.json +3 -1
- package/dist/r/textarea.json +3 -1
- package/dist/r/theming.json +42 -0
- package/dist/r/toast.json +3 -1
- package/dist/r/toggle-group.json +2 -1
- package/dist/r/toggle.json +3 -1
- package/dist/r/tooltip.json +3 -1
- package/dist/r/top-bar.json +3 -1
- package/dist/r/update-dialog.json +2 -1
- package/dist/r/workspace-mark.json +2 -1
- package/package.json +10 -9
- package/registry.json +320 -73
- package/src/index.ts +2 -4
- package/dist/components/ui/diff-block/diff-block.test.d.ts +0 -2
- package/dist/components/ui/diff-block/diff-block.test.d.ts.map +0 -1
- package/dist/lib/keyed-rows.test.d.ts +0 -2
- package/dist/lib/keyed-rows.test.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Input } from './input'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ComponentProps } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Input.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately a plain `<input>` rather than a Kobalte TextField part. The
|
|
9
|
+
* styling contract is what a consumer needs from an input; validation,
|
|
10
|
+
* description and error wiring come from `Field`, which composes this. Keeping
|
|
11
|
+
* them separate is what lets an input sit inside a custom control without
|
|
12
|
+
* inheriting a form's ARIA graph.
|
|
13
|
+
*
|
|
14
|
+
* Height comes from `h-control-md`; an input cannot be given a new height
|
|
15
|
+
* without a new token, which is what keeps it aligned with Button and Select.
|
|
16
|
+
*/
|
|
17
|
+
export function Input(props: ComponentProps<'input'>) {
|
|
18
|
+
const [local, rest] = splitProps(props, ['class', 'type'])
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<input
|
|
22
|
+
data-slot="input"
|
|
23
|
+
type={local.type ?? 'text'}
|
|
24
|
+
class={cn(
|
|
25
|
+
'h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm',
|
|
26
|
+
'transition-[color,box-shadow,border-color] ease-out outline-none',
|
|
27
|
+
'placeholder:text-muted-foreground',
|
|
28
|
+
'selection:bg-primary selection:text-primary-foreground',
|
|
29
|
+
'file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground',
|
|
30
|
+
/* A pointer click on a text field is a typing affordance, so the ring
|
|
31
|
+
appears where the user agent already matches :focus-visible. */
|
|
32
|
+
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
33
|
+
'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',
|
|
34
|
+
'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
35
|
+
'read-only:bg-surface-hover',
|
|
36
|
+
local.class
|
|
37
|
+
)}
|
|
38
|
+
{...rest}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* InputGroup.
|
|
7
|
+
*
|
|
8
|
+
* A field with attached chrome: a leading icon, a unit, a trailing button, a
|
|
9
|
+
* clear affordance. The point of the component is that the adornments and the
|
|
10
|
+
* input share *one* border and *one* focus ring, so the group reads as a single
|
|
11
|
+
* control. Two separate elements side by side always drift — the ring appears
|
|
12
|
+
* on the wrong box, or the border doubles where they meet.
|
|
13
|
+
*
|
|
14
|
+
* The focus ring therefore lives on the group and follows `focus-within`. A
|
|
15
|
+
* group containing several focusable things still reads as focused once, which
|
|
16
|
+
* is the correct affordance: the user is somewhere inside it.
|
|
17
|
+
*/
|
|
18
|
+
export function InputGroup(props: ComponentProps<'div'>) {
|
|
19
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div
|
|
23
|
+
data-slot="input-group"
|
|
24
|
+
class={cn(
|
|
25
|
+
'border-input flex h-control-md w-full min-w-0 items-center gap-1.5 rounded-md border bg-transparent px-control-sm',
|
|
26
|
+
'transition-[color,box-shadow,border-color] ease-out',
|
|
27
|
+
'focus-within:border-ring focus-within:ring-3 focus-within:ring-primary-subtle',
|
|
28
|
+
'has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:ring-3 has-[[aria-invalid=true]]:ring-destructive-subtle',
|
|
29
|
+
'has-[input:disabled]:pointer-events-none has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50',
|
|
30
|
+
local.class
|
|
31
|
+
)}
|
|
32
|
+
{...rest}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function InputGroupInput(props: ComponentProps<'input'>) {
|
|
38
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<input
|
|
42
|
+
data-slot="input-group-input"
|
|
43
|
+
class={cn(
|
|
44
|
+
'h-full min-w-0 flex-1 bg-transparent text-sm outline-none',
|
|
45
|
+
'placeholder:text-muted-foreground',
|
|
46
|
+
'disabled:cursor-not-allowed',
|
|
47
|
+
local.class
|
|
48
|
+
)}
|
|
49
|
+
{...rest}
|
|
50
|
+
/>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type InputGroupAddonProps = ComponentProps<'span'> & {
|
|
55
|
+
/** Which edge the adornment sits on; also sets the pointer-events rule. */
|
|
56
|
+
align?: 'start' | 'end'
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A non-interactive adornment. `pointer-events-none` by default, because an
|
|
61
|
+
* adornment that swallows a click makes the whole control feel dead just to
|
|
62
|
+
* the left of the caret — the most annoying possible bug. Pass `align="end"`
|
|
63
|
+
* and a real element when the adornment must be clickable.
|
|
64
|
+
*/
|
|
65
|
+
export function InputGroupAddon(props: InputGroupAddonProps) {
|
|
66
|
+
const [local, rest] = splitProps(props, ['class', 'align', 'children'])
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<span
|
|
70
|
+
data-slot="input-group-addon"
|
|
71
|
+
class={cn(
|
|
72
|
+
'text-muted-foreground flex shrink-0 items-center gap-1.5 text-sm select-none',
|
|
73
|
+
'[&_svg]:pointer-events-none [&_svg]:size-4',
|
|
74
|
+
{ 'order-first': local.align !== 'end', 'order-last': local.align === 'end' },
|
|
75
|
+
local.class
|
|
76
|
+
)}
|
|
77
|
+
{...rest}
|
|
78
|
+
>
|
|
79
|
+
{local.children}
|
|
80
|
+
</span>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** A clickable trailing button, sized to the group's height. */
|
|
85
|
+
export function InputGroupButton(props: ComponentProps<'button'>) {
|
|
86
|
+
const [local, rest] = splitProps(props, ['class', 'children'])
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<button
|
|
90
|
+
type="button"
|
|
91
|
+
data-slot="input-group-button"
|
|
92
|
+
class={cn(
|
|
93
|
+
'text-muted-foreground -me-1 flex size-6 shrink-0 items-center justify-center rounded-sm',
|
|
94
|
+
'transition-colors ease-out outline-none hover:bg-surface-hover hover:text-foreground',
|
|
95
|
+
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
96
|
+
'disabled:pointer-events-none disabled:opacity-50',
|
|
97
|
+
'[&_svg]:size-3.5',
|
|
98
|
+
local.class
|
|
99
|
+
)}
|
|
100
|
+
{...rest}
|
|
101
|
+
>
|
|
102
|
+
{local.children}
|
|
103
|
+
</button>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Text that reads as a value but is not an input, e.g. a unit or a suffix. */
|
|
108
|
+
export function InputGroupText(props: ComponentProps<'span'> & { children?: JSX.Element }) {
|
|
109
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
110
|
+
return <span class={cn('text-muted-foreground text-sm', local.class)} {...rest} />
|
|
111
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InputOtp, InputOtpCaret, type InputOtpProps } from './input-otp'
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import OtpField from '@corvu/otp-field'
|
|
2
|
+
import type { ComponentProps } from 'solid-js'
|
|
3
|
+
import { For, Show, splitProps } from 'solid-js'
|
|
4
|
+
import { cn } from '../../../lib/utils'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* InputOtp.
|
|
8
|
+
*
|
|
9
|
+
* A one-time code, entered into separate boxes. The boxes are the *paint*: the
|
|
10
|
+
* value lives in a single real input, so paste works, autofill works, and a
|
|
11
|
+
* password manager sees one field rather than six.
|
|
12
|
+
*
|
|
13
|
+
* That split is the whole reason to use a component rather than six inputs. Six
|
|
14
|
+
* inputs cannot be pasted into, cannot be autofilled, and announce as six unrelated
|
|
15
|
+
* fields — every one of which is a defect a user hits on the first try.
|
|
16
|
+
*
|
|
17
|
+
* corvu supplies the value handling, the caret movement, the paste split and the
|
|
18
|
+
* keyboard behaviour.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* `maxLength` is omitted rather than exposed: corvu requires it, and a caller who
|
|
22
|
+
* has to set both it and `length` will eventually set them to different numbers.
|
|
23
|
+
* `length` is the one input and it drives the other.
|
|
24
|
+
*/
|
|
25
|
+
export type InputOtpProps = Omit<ComponentProps<typeof OtpField>, 'maxLength'> & {
|
|
26
|
+
/** How many characters. */
|
|
27
|
+
length?: number
|
|
28
|
+
/** Group the boxes into runs, e.g. `[3, 3]` for a six-character code. */
|
|
29
|
+
groups?: readonly number[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function InputOtp(props: InputOtpProps) {
|
|
33
|
+
const [local, rest] = splitProps(props, ['class', 'length', 'groups', 'children'])
|
|
34
|
+
|
|
35
|
+
const length = () => local.length ?? 6
|
|
36
|
+
const groups = () => local.groups ?? [length()]
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<OtpField
|
|
40
|
+
maxLength={length()}
|
|
41
|
+
class={cn('flex items-center gap-2', local.class)}
|
|
42
|
+
{...rest}
|
|
43
|
+
children={(field) => (
|
|
44
|
+
<>
|
|
45
|
+
<OtpField.Input
|
|
46
|
+
aria-label={props['aria-label'] ?? 'One-time code'}
|
|
47
|
+
class="absolute inset-0 opacity-0"
|
|
48
|
+
/>
|
|
49
|
+
<For each={groups()}>
|
|
50
|
+
{(size, groupIndex) => (
|
|
51
|
+
<>
|
|
52
|
+
<Show when={groupIndex() > 0}>
|
|
53
|
+
<span aria-hidden="true" class="text-muted-foreground px-1">
|
|
54
|
+
–
|
|
55
|
+
</span>
|
|
56
|
+
</Show>
|
|
57
|
+
<span class="flex items-center gap-1.5">
|
|
58
|
+
<For each={Array.from({ length: size })}>
|
|
59
|
+
{(_, index) => {
|
|
60
|
+
// The slot's index across the whole field, so the boxes after a
|
|
61
|
+
// group boundary continue counting rather than restarting.
|
|
62
|
+
const offset = groups()
|
|
63
|
+
.slice(0, groupIndex())
|
|
64
|
+
.reduce((total, run) => total + run, 0)
|
|
65
|
+
const slot = offset + index()
|
|
66
|
+
return (
|
|
67
|
+
<span
|
|
68
|
+
class={cn(
|
|
69
|
+
'border-input bg-transparent flex size-10 items-center justify-center rounded-md border text-sm font-medium',
|
|
70
|
+
'transition-[color,box-shadow,border-color] ease-out',
|
|
71
|
+
'data-[active=true]:border-ring data-[active=true]:ring-3 data-[active=true]:ring-primary-subtle',
|
|
72
|
+
'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50'
|
|
73
|
+
)}
|
|
74
|
+
data-active={field.activeSlots.includes(slot)}
|
|
75
|
+
data-disabled={props.disabled}
|
|
76
|
+
>
|
|
77
|
+
{field.value[slot] ?? ''}
|
|
78
|
+
</span>
|
|
79
|
+
)
|
|
80
|
+
}}
|
|
81
|
+
</For>
|
|
82
|
+
</span>
|
|
83
|
+
</>
|
|
84
|
+
)}
|
|
85
|
+
</For>
|
|
86
|
+
</>
|
|
87
|
+
)}
|
|
88
|
+
/>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A caret drawn inside the active box.
|
|
94
|
+
*
|
|
95
|
+
* Exported for a caller building its own slot: the box above renders the character
|
|
96
|
+
* directly, and a blinking caret is the alternative when the field should look
|
|
97
|
+
* empty until something is typed.
|
|
98
|
+
*/
|
|
99
|
+
export function InputOtpCaret(props: ComponentProps<'span'>) {
|
|
100
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
101
|
+
return (
|
|
102
|
+
<span
|
|
103
|
+
aria-hidden="true"
|
|
104
|
+
class={cn('animate-caret bg-foreground inline-block h-4 w-px', local.class)}
|
|
105
|
+
{...rest}
|
|
106
|
+
/>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
2
|
+
import { Show, splitProps } from 'solid-js'
|
|
3
|
+
import { cva, type VariantProps } from '../../../lib/variants'
|
|
4
|
+
import { cn } from '../../../lib/utils'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Item.
|
|
8
|
+
*
|
|
9
|
+
* The general row: a leading slot, a body, and a trailing slot. It is the shape
|
|
10
|
+
* almost every list in an application takes — a file, a member, a setting, a
|
|
11
|
+
* search result — and it exists as a component because a row is where inconsistency
|
|
12
|
+
* is most visible: twenty of them make any drift in height, padding or alignment
|
|
13
|
+
* obvious at a glance.
|
|
14
|
+
*
|
|
15
|
+
* The difference from `ListRow` is what it is *for*. `ListRow` is one row in a list
|
|
16
|
+
* of like things, sized by the row ladder and meant to be scanned down a column.
|
|
17
|
+
* `Item` is a self-contained block — it has a border, its own surface, an optional
|
|
18
|
+
* title and description — and is meant to stand alone or sit in a grid. A list uses
|
|
19
|
+
* `ListRow`; a search result or a settings card uses `Item`.
|
|
20
|
+
*
|
|
21
|
+
* `variant="outline"` and `"muted"` exist because the two questions a caller
|
|
22
|
+
* actually has are "does this need an edge" and "is it on the canvas or inset".
|
|
23
|
+
*/
|
|
24
|
+
export const itemVariants = cva('flex w-full items-center gap-3 rounded-lg text-sm', {
|
|
25
|
+
variants: {
|
|
26
|
+
variant: {
|
|
27
|
+
default: 'bg-transparent',
|
|
28
|
+
/** On the canvas, with an edge — the search-result shape. */
|
|
29
|
+
outline: 'border border-border bg-card',
|
|
30
|
+
/** Inset: a code well, a disabled row, a quoted message. */
|
|
31
|
+
muted: 'bg-muted',
|
|
32
|
+
},
|
|
33
|
+
size: {
|
|
34
|
+
sm: 'min-h-row-sm px-3 py-1.5',
|
|
35
|
+
md: 'min-h-row-md px-3 py-2',
|
|
36
|
+
lg: 'min-h-row-lg px-4 py-2.5',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
defaultVariants: { variant: 'default', size: 'md' },
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
type ItemVariantProps = VariantProps<typeof itemVariants>
|
|
43
|
+
|
|
44
|
+
export type ItemProps = ComponentProps<'div'> &
|
|
45
|
+
ItemVariantProps & {
|
|
46
|
+
/** A media slot: an icon, an avatar, a thumbnail. */
|
|
47
|
+
media?: JSX.Element
|
|
48
|
+
/** A trailing slot: a badge, a timestamp, a menu trigger. */
|
|
49
|
+
trailing?: JSX.Element
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function Item(props: ItemProps) {
|
|
53
|
+
const [local, rest] = splitProps(props, [
|
|
54
|
+
'class',
|
|
55
|
+
'variant',
|
|
56
|
+
'size',
|
|
57
|
+
'media',
|
|
58
|
+
'trailing',
|
|
59
|
+
'children',
|
|
60
|
+
])
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div
|
|
64
|
+
data-slot="item"
|
|
65
|
+
class={cn(itemVariants({ variant: local.variant, size: local.size }), local.class)}
|
|
66
|
+
{...rest}
|
|
67
|
+
>
|
|
68
|
+
<Show when={local.media}>
|
|
69
|
+
<span
|
|
70
|
+
data-slot="item-media"
|
|
71
|
+
class="flex size-8 shrink-0 items-center justify-center [&_svg]:size-4"
|
|
72
|
+
>
|
|
73
|
+
{local.media}
|
|
74
|
+
</span>
|
|
75
|
+
</Show>
|
|
76
|
+
<div data-slot="item-body" class="flex min-w-0 flex-1 flex-col gap-0.5">
|
|
77
|
+
{local.children}
|
|
78
|
+
</div>
|
|
79
|
+
<Show when={local.trailing}>
|
|
80
|
+
<span data-slot="item-trailing" class="flex shrink-0 items-center gap-2">
|
|
81
|
+
{local.trailing}
|
|
82
|
+
</span>
|
|
83
|
+
</Show>
|
|
84
|
+
</div>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function ItemTitle(props: ComponentProps<'div'>) {
|
|
89
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
90
|
+
return <div data-slot="item-title" class={cn('truncate font-medium', local.class)} {...rest} />
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function ItemDescription(props: ComponentProps<'div'>) {
|
|
94
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
95
|
+
return (
|
|
96
|
+
<div
|
|
97
|
+
data-slot="item-description"
|
|
98
|
+
class={cn('text-muted-foreground line-clamp-2 text-xs text-pretty', local.class)}
|
|
99
|
+
{...rest}
|
|
100
|
+
/>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* A group of items with an optional heading. It is a real `role="list"` with
|
|
106
|
+
* `role="listitem"` children, so a screen reader reports the count — which is how a
|
|
107
|
+
* user knows how many results there are without counting them.
|
|
108
|
+
*/
|
|
109
|
+
export function ItemGroup(
|
|
110
|
+
props: ComponentProps<'div'> & {
|
|
111
|
+
label?: string
|
|
112
|
+
/** The list's accessible name. */ listLabel?: string
|
|
113
|
+
}
|
|
114
|
+
) {
|
|
115
|
+
const [local, rest] = splitProps(props, ['class', 'label', 'listLabel', 'children'])
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<div data-slot="item-group" class={cn('flex flex-col gap-2', local.class)} {...rest}>
|
|
119
|
+
<Show when={local.label}>
|
|
120
|
+
<div class="text-muted-foreground text-2xs font-medium tracking-wide uppercase">
|
|
121
|
+
{local.label}
|
|
122
|
+
</div>
|
|
123
|
+
</Show>
|
|
124
|
+
<div role="list" aria-label={local.listLabel ?? local.label} class="flex flex-col gap-2">
|
|
125
|
+
{local.children}
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** An item inside an `ItemGroup`, which is what makes it a list item. */
|
|
132
|
+
export function ItemGroupEntry(props: ItemProps) {
|
|
133
|
+
return <Item role="listitem" {...props} />
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** A centred message for a group with nothing in it. */
|
|
137
|
+
export function ItemEmpty(props: ComponentProps<'div'>) {
|
|
138
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
139
|
+
return (
|
|
140
|
+
<div
|
|
141
|
+
data-slot="item-empty"
|
|
142
|
+
class={cn('text-muted-foreground py-6 text-center text-sm', local.class)}
|
|
143
|
+
{...rest}
|
|
144
|
+
/>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Kbd, KbdGroup } from './kbd'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ComponentProps } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Kbd.
|
|
7
|
+
*
|
|
8
|
+
* A keyboard key, in the order the user presses them. The element is a real
|
|
9
|
+
* `<kbd>` so the semantics survive copy-paste, and the mono face is what makes
|
|
10
|
+
* a shortcut visually distinct from the sentence around it.
|
|
11
|
+
*
|
|
12
|
+
* `KbdGroup` exists because a shortcut is a sequence: typing `⌘` then `K`
|
|
13
|
+
* needs a gap between them that is a layout concern, not punctuation.
|
|
14
|
+
*/
|
|
15
|
+
export function Kbd(props: ComponentProps<'kbd'>) {
|
|
16
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<kbd
|
|
20
|
+
data-slot="kbd"
|
|
21
|
+
class={cn(
|
|
22
|
+
'bg-muted text-muted-foreground pointer-events-none inline-flex h-5 min-w-5 items-center justify-center gap-1 rounded-sm border border-border px-1 font-mono text-2xs font-medium select-none',
|
|
23
|
+
/* Inside a hover/selected row the key needs to recede with the row. */
|
|
24
|
+
'in-data-[slot=br-tooltip-content]:bg-background/20 in-data-[slot=br-tooltip-content]:text-scrim-foreground in-data-[slot=br-tooltip-content]:border-transparent',
|
|
25
|
+
local.class
|
|
26
|
+
)}
|
|
27
|
+
{...rest}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function KbdGroup(props: ComponentProps<'span'>) {
|
|
33
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<span
|
|
37
|
+
data-slot="kbd-group"
|
|
38
|
+
class={cn('inline-flex items-center gap-1', local.class)}
|
|
39
|
+
{...rest}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Label } from './label'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ComponentProps } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Label.
|
|
7
|
+
*
|
|
8
|
+
* A plain `<label>` rather than a Kobalte control. Kobalte has no standalone
|
|
9
|
+
* label primitive — its labels are parts of `TextField`, `Checkbox` and
|
|
10
|
+
* friends, and those parts carry the association wiring for *their* control.
|
|
11
|
+
* A free-standing label has to be the real element so the browser's native
|
|
12
|
+
* `for` → control association, click-to-focus, and `aria-labelledby` all keep
|
|
13
|
+
* working.
|
|
14
|
+
*
|
|
15
|
+
* Use the compound controls' own labels (`Switch.Label`, `Checkbox.Label`) when
|
|
16
|
+
* the label belongs to one of them; use this one for an `Input` or `Textarea`,
|
|
17
|
+
* which are plain elements with no wrapper.
|
|
18
|
+
*/
|
|
19
|
+
export function Label(props: ComponentProps<'label'>) {
|
|
20
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<label
|
|
24
|
+
data-slot="label"
|
|
25
|
+
class={cn(
|
|
26
|
+
'flex items-center gap-2 text-sm leading-none font-medium select-none',
|
|
27
|
+
/* A label inside a disabled group is part of a dead control and must
|
|
28
|
+
not offer a pointer that does nothing. */
|
|
29
|
+
'group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50',
|
|
30
|
+
'peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
|
|
31
|
+
local.class
|
|
32
|
+
)}
|
|
33
|
+
{...rest}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export {
|
|
2
|
+
Menubar,
|
|
3
|
+
MenubarCheckboxItem,
|
|
4
|
+
MenubarContent,
|
|
5
|
+
MenubarGroup,
|
|
6
|
+
MenubarItem,
|
|
7
|
+
MenubarLabel,
|
|
8
|
+
MenubarMenu,
|
|
9
|
+
MenubarRadioGroup,
|
|
10
|
+
MenubarRadioItem,
|
|
11
|
+
MenubarSeparator,
|
|
12
|
+
MenubarSub,
|
|
13
|
+
MenubarSubContent,
|
|
14
|
+
MenubarSubTrigger,
|
|
15
|
+
MenubarTrigger,
|
|
16
|
+
} from './menubar'
|