@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,203 @@
|
|
|
1
|
+
import { DropdownMenu as KobalteDropdownMenu } from '@kobalte/core/dropdown-menu'
|
|
2
|
+
import { Check, ChevronRight, Circle } from 'lucide-solid'
|
|
3
|
+
import type { ComponentProps } from 'solid-js'
|
|
4
|
+
import { splitProps } from 'solid-js'
|
|
5
|
+
import {
|
|
6
|
+
menuContentPadding,
|
|
7
|
+
menuItem,
|
|
8
|
+
menuLabel,
|
|
9
|
+
menuSeparator,
|
|
10
|
+
overlayMotion,
|
|
11
|
+
overlaySurface,
|
|
12
|
+
popoverArrow,
|
|
13
|
+
} from '../../../lib/overlay'
|
|
14
|
+
import { cn } from '../../../lib/utils'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* DropdownMenu.
|
|
18
|
+
*
|
|
19
|
+
* A list of actions on a trigger. This is the right home for "what can I do
|
|
20
|
+
* with this thing": rename, duplicate, export, delete. It is not a Select
|
|
21
|
+
* (which holds a *value* the user is choosing) and not a Popover (which holds
|
|
22
|
+
* arbitrary content).
|
|
23
|
+
*
|
|
24
|
+
* Kobalte supplies the full menu contract — arrow keys, typeahead, the roving
|
|
25
|
+
* highlight, Escape to close and return focus — which is exactly what a
|
|
26
|
+
* hand-rolled `div` with click handlers gets wrong.
|
|
27
|
+
*
|
|
28
|
+
* The `destructive` variant on an item is a *colour*, not a confirmation.
|
|
29
|
+
* Pairing it with an AlertDialog is the caller's job.
|
|
30
|
+
*/
|
|
31
|
+
export function DropdownMenu(props: ComponentProps<typeof KobalteDropdownMenu>) {
|
|
32
|
+
return <KobalteDropdownMenu {...props} />
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function DropdownMenuTrigger(props: ComponentProps<typeof KobalteDropdownMenu.Trigger>) {
|
|
36
|
+
return <KobalteDropdownMenu.Trigger {...props} />
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function DropdownMenuPortal(props: ComponentProps<typeof KobalteDropdownMenu.Portal>) {
|
|
40
|
+
return <KobalteDropdownMenu.Portal {...props} />
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type DropdownMenuContentProps = ComponentProps<typeof KobalteDropdownMenu.Content> & {
|
|
44
|
+
hideArrow?: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function DropdownMenuContent(props: DropdownMenuContentProps) {
|
|
48
|
+
const [local, rest] = splitProps(props, ['class', 'hideArrow', 'children'])
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<KobalteDropdownMenu.Portal>
|
|
52
|
+
<KobalteDropdownMenu.Content
|
|
53
|
+
class={cn(
|
|
54
|
+
overlaySurface,
|
|
55
|
+
overlayMotion,
|
|
56
|
+
'z-(--z-menu) min-w-[10rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',
|
|
57
|
+
menuContentPadding,
|
|
58
|
+
local.class
|
|
59
|
+
)}
|
|
60
|
+
{...rest}
|
|
61
|
+
>
|
|
62
|
+
{!local.hideArrow && <KobalteDropdownMenu.Arrow aria-hidden="true" class={popoverArrow} />}
|
|
63
|
+
{local.children}
|
|
64
|
+
</KobalteDropdownMenu.Content>
|
|
65
|
+
</KobalteDropdownMenu.Portal>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function DropdownMenuItem(
|
|
70
|
+
props: ComponentProps<typeof KobalteDropdownMenu.Item> & {
|
|
71
|
+
/** Colour the row as a destructive action. Confirm it separately. */
|
|
72
|
+
variant?: 'default' | 'destructive'
|
|
73
|
+
/** Draw a shortcut hint at the trailing edge of the row. */
|
|
74
|
+
shortcut?: string
|
|
75
|
+
}
|
|
76
|
+
) {
|
|
77
|
+
const [local, rest] = splitProps(props, ['class', 'variant', 'shortcut', 'children'])
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<KobalteDropdownMenu.Item
|
|
81
|
+
class={cn(
|
|
82
|
+
menuItem,
|
|
83
|
+
{
|
|
84
|
+
'text-destructive data-[highlighted]:bg-destructive-subtle data-[highlighted]:text-destructive':
|
|
85
|
+
local.variant === 'destructive',
|
|
86
|
+
},
|
|
87
|
+
local.class
|
|
88
|
+
)}
|
|
89
|
+
{...rest}
|
|
90
|
+
>
|
|
91
|
+
{local.children}
|
|
92
|
+
{local.shortcut ? (
|
|
93
|
+
<span class="text-muted-foreground ms-auto font-mono text-2xs tracking-widest">
|
|
94
|
+
{local.shortcut}
|
|
95
|
+
</span>
|
|
96
|
+
) : null}
|
|
97
|
+
</KobalteDropdownMenu.Item>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The chord drawn at a row's trailing edge.
|
|
103
|
+
*
|
|
104
|
+
* A component as well as the `shortcut` prop on an item, because a caller composing
|
|
105
|
+
* a row by hand needs the same treatment — and because the alternative is every
|
|
106
|
+
* caller inventing the same mono-and-dimmed span.
|
|
107
|
+
*/
|
|
108
|
+
export function DropdownMenuShortcut(props: ComponentProps<'span'>) {
|
|
109
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
110
|
+
return (
|
|
111
|
+
<span
|
|
112
|
+
data-slot="dropdown-menu-shortcut"
|
|
113
|
+
class={cn('text-muted-foreground ms-auto font-mono text-2xs tracking-widest', local.class)}
|
|
114
|
+
{...rest}
|
|
115
|
+
/>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function DropdownMenuCheckboxItem(
|
|
120
|
+
props: ComponentProps<typeof KobalteDropdownMenu.CheckboxItem>
|
|
121
|
+
) {
|
|
122
|
+
const [local, rest] = splitProps(props, ['class', 'children'])
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<KobalteDropdownMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>
|
|
126
|
+
{local.children}
|
|
127
|
+
<KobalteDropdownMenu.ItemIndicator class="absolute end-2 flex size-4 items-center justify-center">
|
|
128
|
+
<Check class="size-4" />
|
|
129
|
+
</KobalteDropdownMenu.ItemIndicator>
|
|
130
|
+
</KobalteDropdownMenu.CheckboxItem>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function DropdownMenuRadioGroup(
|
|
135
|
+
props: ComponentProps<typeof KobalteDropdownMenu.RadioGroup>
|
|
136
|
+
) {
|
|
137
|
+
return <KobalteDropdownMenu.RadioGroup {...props} />
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function DropdownMenuRadioItem(props: ComponentProps<typeof KobalteDropdownMenu.RadioItem>) {
|
|
141
|
+
const [local, rest] = splitProps(props, ['class', 'children'])
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<KobalteDropdownMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>
|
|
145
|
+
{local.children}
|
|
146
|
+
<KobalteDropdownMenu.ItemIndicator class="absolute end-2 flex size-4 items-center justify-center">
|
|
147
|
+
<Circle class="size-2 fill-current" />
|
|
148
|
+
</KobalteDropdownMenu.ItemIndicator>
|
|
149
|
+
</KobalteDropdownMenu.RadioItem>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function DropdownMenuLabel(props: ComponentProps<typeof KobalteDropdownMenu.GroupLabel>) {
|
|
154
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
155
|
+
return <KobalteDropdownMenu.GroupLabel class={cn(menuLabel, local.class)} {...rest} />
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function DropdownMenuGroup(props: ComponentProps<typeof KobalteDropdownMenu.Group>) {
|
|
159
|
+
return <KobalteDropdownMenu.Group {...props} />
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function DropdownMenuSeparator(props: ComponentProps<typeof KobalteDropdownMenu.Separator>) {
|
|
163
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
164
|
+
return <KobalteDropdownMenu.Separator class={cn(menuSeparator, local.class)} {...rest} />
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function DropdownMenuSub(props: ComponentProps<typeof KobalteDropdownMenu.Sub>) {
|
|
168
|
+
return <KobalteDropdownMenu.Sub {...props} />
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function DropdownMenuSubTrigger(
|
|
172
|
+
props: ComponentProps<typeof KobalteDropdownMenu.SubTrigger>
|
|
173
|
+
) {
|
|
174
|
+
const [local, rest] = splitProps(props, ['class', 'children'])
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<KobalteDropdownMenu.SubTrigger class={cn(menuItem, local.class)} {...rest}>
|
|
178
|
+
{local.children}
|
|
179
|
+
<ChevronRight class="ms-auto size-4" />
|
|
180
|
+
</KobalteDropdownMenu.SubTrigger>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function DropdownMenuSubContent(
|
|
185
|
+
props: ComponentProps<typeof KobalteDropdownMenu.SubContent>
|
|
186
|
+
) {
|
|
187
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<KobalteDropdownMenu.Portal>
|
|
191
|
+
<KobalteDropdownMenu.SubContent
|
|
192
|
+
class={cn(
|
|
193
|
+
overlaySurface,
|
|
194
|
+
overlayMotion,
|
|
195
|
+
'z-(--z-menu) min-w-[8rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',
|
|
196
|
+
menuContentPadding,
|
|
197
|
+
local.class
|
|
198
|
+
)}
|
|
199
|
+
{...rest}
|
|
200
|
+
/>
|
|
201
|
+
</KobalteDropdownMenu.Portal>
|
|
202
|
+
)
|
|
203
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export {
|
|
2
|
+
DropdownMenu,
|
|
3
|
+
DropdownMenuCheckboxItem,
|
|
4
|
+
DropdownMenuContent,
|
|
5
|
+
DropdownMenuGroup,
|
|
6
|
+
DropdownMenuItem,
|
|
7
|
+
DropdownMenuLabel,
|
|
8
|
+
DropdownMenuPortal,
|
|
9
|
+
DropdownMenuRadioGroup,
|
|
10
|
+
DropdownMenuRadioItem,
|
|
11
|
+
DropdownMenuSeparator,
|
|
12
|
+
DropdownMenuShortcut,
|
|
13
|
+
DropdownMenuSub,
|
|
14
|
+
DropdownMenuSubContent,
|
|
15
|
+
DropdownMenuSubTrigger,
|
|
16
|
+
DropdownMenuTrigger,
|
|
17
|
+
type DropdownMenuContentProps,
|
|
18
|
+
} from './dropdown-menu'
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Empty.
|
|
7
|
+
*
|
|
8
|
+
* The state of a region that has nothing to show yet, or after a filter
|
|
9
|
+
* removed everything. It exists as a component because an empty state is where
|
|
10
|
+
* apps most often improvise: a bare grey sentence in one view and a centred
|
|
11
|
+
* illustration with two buttons in another.
|
|
12
|
+
*
|
|
13
|
+
* The shape is fixed — media, title, description, actions — so the only
|
|
14
|
+
* decisions a caller makes are which parts to include. A region with an
|
|
15
|
+
* action to offer must give `EmptyContent` something focusable, otherwise the
|
|
16
|
+
* state is a dead end.
|
|
17
|
+
*/
|
|
18
|
+
export function Empty(props: ComponentProps<'div'>) {
|
|
19
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div
|
|
23
|
+
data-slot="empty"
|
|
24
|
+
class={cn(
|
|
25
|
+
'flex min-h-40 w-full flex-col items-center justify-center gap-4 rounded-lg px-6 py-10 text-center text-balance',
|
|
26
|
+
local.class
|
|
27
|
+
)}
|
|
28
|
+
{...rest}
|
|
29
|
+
/>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function EmptyHeader(props: ComponentProps<'div'>) {
|
|
34
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
35
|
+
return (
|
|
36
|
+
<div
|
|
37
|
+
data-slot="empty-header"
|
|
38
|
+
class={cn('flex max-w-sm flex-col items-center gap-1.5', local.class)}
|
|
39
|
+
{...rest}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type EmptyMediaProps = ComponentProps<'div'> & {
|
|
45
|
+
variant?: 'icon' | 'image'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function EmptyMedia(props: EmptyMediaProps) {
|
|
49
|
+
const [local, rest] = splitProps(props, ['class', 'variant'])
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
data-slot="empty-media"
|
|
54
|
+
class={cn(
|
|
55
|
+
'flex shrink-0 items-center justify-center',
|
|
56
|
+
{
|
|
57
|
+
'bg-muted text-muted-foreground size-9 rounded-lg [&_svg]:size-4':
|
|
58
|
+
local.variant !== 'image',
|
|
59
|
+
'size-24 rounded-xl [&_img]:size-full [&_img]:object-contain': local.variant === 'image',
|
|
60
|
+
},
|
|
61
|
+
local.class
|
|
62
|
+
)}
|
|
63
|
+
{...rest}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function EmptyTitle(props: ComponentProps<'div'>) {
|
|
69
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
70
|
+
return (
|
|
71
|
+
<div
|
|
72
|
+
data-slot="empty-title"
|
|
73
|
+
class={cn('text-sm font-medium tracking-tight', local.class)}
|
|
74
|
+
{...rest}
|
|
75
|
+
/>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function EmptyDescription(props: ComponentProps<'div'>) {
|
|
80
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
81
|
+
return (
|
|
82
|
+
<div
|
|
83
|
+
data-slot="empty-description"
|
|
84
|
+
class={cn(
|
|
85
|
+
'text-muted-foreground text-sm [&_a]:text-primary [&_a]:underline [&_a]:underline-offset-4',
|
|
86
|
+
local.class
|
|
87
|
+
)}
|
|
88
|
+
{...rest}
|
|
89
|
+
/>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function EmptyContent(props: ComponentProps<'div'>) {
|
|
94
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
95
|
+
return (
|
|
96
|
+
<div
|
|
97
|
+
data-slot="empty-content"
|
|
98
|
+
class={cn('flex max-w-sm flex-col items-center gap-2', local.class)}
|
|
99
|
+
{...rest}
|
|
100
|
+
/>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type EmptyProps = ComponentProps<'div'> & { children?: JSX.Element }
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Show, splitProps, type Component, type ComponentProps, type JSX } from 'solid-js'
|
|
2
|
+
import { Dynamic } from 'solid-js/web'
|
|
3
|
+
import { cva, type VariantProps } from '../../../lib/variants'
|
|
4
|
+
import { cn } from '../../../lib/utils'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* EntityIcon.
|
|
8
|
+
*
|
|
9
|
+
* A tile that stands for a thing: a room, a project, an agent, an installed
|
|
10
|
+
* plugin, a workspace. Its job is to be identifiable in a column of its
|
|
11
|
+
* siblings, which is a different job from `Avatar`'s (identifying a *person*) and
|
|
12
|
+
* the reason the two are separate components rather than one with a `round` prop.
|
|
13
|
+
*
|
|
14
|
+
* Three decisions are baked in because getting them wrong is what makes icon
|
|
15
|
+
* grids look messy:
|
|
16
|
+
*
|
|
17
|
+
* 1. **A glyph is always present.** A brand with no logo gets a monogram, not an
|
|
18
|
+
* empty box. `fallback` takes the name and returns the glyph, so a caller can
|
|
19
|
+
* choose initials, a domain letter, or a kind icon.
|
|
20
|
+
* 2. **The tile owns its own contrast.** `tone` tints the background and the
|
|
21
|
+
* glyph together, so a caller never picks a colour pair and never ships an
|
|
22
|
+
* icon that disappears against its tile.
|
|
23
|
+
* 3. **Size is on the control ladder**, not arbitrary. A tile in a rail and a
|
|
24
|
+
* tile in a detail header are the same two or three sizes every other
|
|
25
|
+
* interactive element uses.
|
|
26
|
+
*
|
|
27
|
+
* `shape="rounded"` is the default because a rounded square reads as an object
|
|
28
|
+
* and a circle reads as a person; use `circle` only when the tile really does
|
|
29
|
+
* hold a face.
|
|
30
|
+
*/
|
|
31
|
+
export const entityIconVariants = cva(
|
|
32
|
+
'relative inline-flex shrink-0 items-center justify-center overflow-hidden border font-semibold select-none [&_svg]:pointer-events-none [&_svg]:shrink-0',
|
|
33
|
+
{
|
|
34
|
+
variants: {
|
|
35
|
+
shape: {
|
|
36
|
+
rounded: 'rounded-lg',
|
|
37
|
+
circle: 'rounded-full',
|
|
38
|
+
square: 'rounded-none',
|
|
39
|
+
},
|
|
40
|
+
size: {
|
|
41
|
+
xs: 'size-5 text-2xs [&_svg]:size-3',
|
|
42
|
+
sm: 'size-6 text-2xs [&_svg]:size-3.5',
|
|
43
|
+
md: 'size-8 text-xs [&_svg]:size-4',
|
|
44
|
+
lg: 'size-10 text-sm [&_svg]:size-5',
|
|
45
|
+
xl: 'size-12 text-base [&_svg]:size-6',
|
|
46
|
+
},
|
|
47
|
+
tone: {
|
|
48
|
+
/** Neutral: an inset tile with a hairline edge — the default. */
|
|
49
|
+
neutral: 'border-border bg-muted text-muted-foreground',
|
|
50
|
+
/** On the brand: for a thing the application itself owns. */
|
|
51
|
+
primary: 'border-transparent bg-primary-subtle text-primary',
|
|
52
|
+
/** Bare: no fill and no edge, for a tile that already sits on a surface. */
|
|
53
|
+
bare: 'border-transparent bg-transparent text-foreground',
|
|
54
|
+
success: 'border-transparent bg-success-subtle text-success',
|
|
55
|
+
warning: 'border-transparent bg-warning-subtle text-warning',
|
|
56
|
+
danger: 'border-transparent bg-destructive-subtle text-destructive',
|
|
57
|
+
info: 'border-transparent bg-info-subtle text-info',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
defaultVariants: { shape: 'rounded', size: 'md', tone: 'neutral' },
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
type EntityIconVariantProps = VariantProps<typeof entityIconVariants>
|
|
65
|
+
|
|
66
|
+
export type EntityIconProps = Omit<ComponentProps<'span'>, 'children'> &
|
|
67
|
+
EntityIconVariantProps & {
|
|
68
|
+
/** The entity's name. Used for the accessible label and, via `fallback`, the monogram. */
|
|
69
|
+
name: string
|
|
70
|
+
/**
|
|
71
|
+
* A logo or icon — a Lucide icon reference (`icon={Wrench}`) or an element
|
|
72
|
+
* (`icon={<Wrench />}`). Both are accepted because both are what a caller
|
|
73
|
+
* naturally writes, and the difference is an implementation detail they should
|
|
74
|
+
* not have to know.
|
|
75
|
+
*/
|
|
76
|
+
icon?: Component | JSX.Element
|
|
77
|
+
/** Glyph for an entity with no icon. Defaults to the name's first two letters. */
|
|
78
|
+
fallback?: (name: string) => JSX.Element
|
|
79
|
+
/** A corner badge: a status dot, an unread count, an installed tick. */
|
|
80
|
+
badge?: JSX.Element
|
|
81
|
+
/** A second edge, drawn outside the tile — an active or selected ring. */
|
|
82
|
+
ring?: boolean
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Two letters from a name, chosen so the result is stable and readable: the
|
|
87
|
+
* first letter of the first two words when there are two ("Agent HQ" → "AH"),
|
|
88
|
+
* otherwise the first two characters ("Kitchen" → "Ki").
|
|
89
|
+
*/
|
|
90
|
+
export function monogram(name: string): string {
|
|
91
|
+
const words = name.trim().split(/\s+/).filter(Boolean)
|
|
92
|
+
if (words.length >= 2) return (words[0]![0]! + words[1]![0]!).toUpperCase()
|
|
93
|
+
return name.trim().slice(0, 2)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* A glyph is either a component reference or an element, and the two render
|
|
98
|
+
* differently — `Dynamic` for the first, the element itself for the second. The
|
|
99
|
+
* union is discriminated so the branch is checked rather than cast.
|
|
100
|
+
*/
|
|
101
|
+
type Glyph = { kind: 'component'; value: Component } | { kind: 'element'; value: JSX.Element }
|
|
102
|
+
|
|
103
|
+
function Glyph(props: { glyph: Glyph }) {
|
|
104
|
+
return props.glyph.kind === 'component' ? (
|
|
105
|
+
<Dynamic component={props.glyph.value} />
|
|
106
|
+
) : (
|
|
107
|
+
props.glyph.value
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function EntityIcon(props: EntityIconProps) {
|
|
112
|
+
const [local, rest] = splitProps(props, [
|
|
113
|
+
'name',
|
|
114
|
+
'icon',
|
|
115
|
+
'fallback',
|
|
116
|
+
'badge',
|
|
117
|
+
'ring',
|
|
118
|
+
'shape',
|
|
119
|
+
'size',
|
|
120
|
+
'tone',
|
|
121
|
+
'class',
|
|
122
|
+
])
|
|
123
|
+
|
|
124
|
+
const glyph = (): Glyph | undefined => {
|
|
125
|
+
const icon = local.icon
|
|
126
|
+
if (!icon) return undefined
|
|
127
|
+
return typeof icon === 'function'
|
|
128
|
+
? { kind: 'component', value: icon as Component }
|
|
129
|
+
: { kind: 'element', value: icon as JSX.Element }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<span
|
|
134
|
+
class={cn(
|
|
135
|
+
entityIconVariants({ shape: local.shape, size: local.size, tone: local.tone }),
|
|
136
|
+
local.ring && 'ring-2 ring-ring ring-offset-2 ring-offset-background',
|
|
137
|
+
local.class
|
|
138
|
+
)}
|
|
139
|
+
role="img"
|
|
140
|
+
aria-label={local.name}
|
|
141
|
+
{...rest}
|
|
142
|
+
>
|
|
143
|
+
<Show
|
|
144
|
+
when={glyph()}
|
|
145
|
+
fallback={local.fallback ? local.fallback(local.name) : monogram(local.name)}
|
|
146
|
+
>
|
|
147
|
+
{(value) => <Glyph glyph={value()} />}
|
|
148
|
+
</Show>
|
|
149
|
+
<Show when={local.badge}>
|
|
150
|
+
<span class="absolute right-0 bottom-0 translate-x-1/4 translate-y-1/4">{local.badge}</span>
|
|
151
|
+
</Show>
|
|
152
|
+
</span>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EntityIcon, entityIconVariants, monogram, type EntityIconProps } from './entity-icon'
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { TextField as KobalteTextField } from '@kobalte/core/text-field'
|
|
2
|
+
import type { ComponentProps } from 'solid-js'
|
|
3
|
+
import { Show, splitProps } from 'solid-js'
|
|
4
|
+
import { cn } from '../../../lib/utils'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Field.
|
|
8
|
+
*
|
|
9
|
+
* The wrapper that makes a form control describable and validatable: a label,
|
|
10
|
+
* a description, an error message, and the ARIA relationships between them.
|
|
11
|
+
*
|
|
12
|
+
* It is built on Kobalte's TextField specifically so `aria-describedby`,
|
|
13
|
+
* `aria-invalid` and `aria-errormessage` are wired by construction. Those three
|
|
14
|
+
* attributes are the difference between "this field is required and empty" and
|
|
15
|
+
* a red border that only a sighted user can perceive — and they are also the
|
|
16
|
+
* first thing a hand-rolled form drops.
|
|
17
|
+
*
|
|
18
|
+
* `Field` owns the description and the error slot, so a form's controls line up
|
|
19
|
+
* and its messages land in the same place regardless of which control is used.
|
|
20
|
+
* Compose it with any control: `Field` wraps, `Label`/`Input`/`Select` fill it.
|
|
21
|
+
*/
|
|
22
|
+
export function Field(props: ComponentProps<typeof KobalteTextField>) {
|
|
23
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
24
|
+
return <KobalteTextField class={cn('flex flex-col gap-1.5', local.class)} {...rest} />
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function FieldLabel(props: ComponentProps<typeof KobalteTextField.Label>) {
|
|
28
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
29
|
+
return (
|
|
30
|
+
<KobalteTextField.Label class={cn('text-sm leading-none font-medium', local.class)} {...rest} />
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function FieldDescription(props: ComponentProps<typeof KobalteTextField.Description>) {
|
|
35
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
36
|
+
return (
|
|
37
|
+
<KobalteTextField.Description
|
|
38
|
+
class={cn('text-muted-foreground text-sm', local.class)}
|
|
39
|
+
{...rest}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function FieldError(props: ComponentProps<typeof KobalteTextField.ErrorMessage>) {
|
|
45
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
46
|
+
return (
|
|
47
|
+
<KobalteTextField.ErrorMessage class={cn('text-destructive text-sm', local.class)} {...rest} />
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function FieldInput(props: ComponentProps<typeof KobalteTextField.Input>) {
|
|
52
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<KobalteTextField.Input
|
|
56
|
+
class={cn(
|
|
57
|
+
'h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm',
|
|
58
|
+
'transition-[color,box-shadow,border-color] ease-out outline-none',
|
|
59
|
+
'placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground',
|
|
60
|
+
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
61
|
+
'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',
|
|
62
|
+
'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
63
|
+
local.class
|
|
64
|
+
)}
|
|
65
|
+
{...rest}
|
|
66
|
+
/>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function FieldTextArea(props: ComponentProps<typeof KobalteTextField.TextArea>) {
|
|
71
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<KobalteTextField.TextArea
|
|
75
|
+
class={cn(
|
|
76
|
+
'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-control-md py-2 text-sm',
|
|
77
|
+
'transition-[color,box-shadow,border-color] ease-out outline-none resize-y',
|
|
78
|
+
'placeholder:text-muted-foreground',
|
|
79
|
+
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
80
|
+
'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',
|
|
81
|
+
'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
82
|
+
local.class
|
|
83
|
+
)}
|
|
84
|
+
{...rest}
|
|
85
|
+
/>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A labelled group of fields with a single legend, for a real `<fieldset>`.
|
|
91
|
+
* Grouping is what lets a screen reader announce "Shipping address, group"
|
|
92
|
+
* before reading the four fields inside it.
|
|
93
|
+
*/
|
|
94
|
+
export function FieldSet(props: ComponentProps<'fieldset'>) {
|
|
95
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
96
|
+
return <fieldset class={cn('flex flex-col gap-4', local.class)} {...rest} />
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function FieldLegend(props: ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {
|
|
100
|
+
const [local, rest] = splitProps(props, ['class', 'variant'])
|
|
101
|
+
return (
|
|
102
|
+
<legend
|
|
103
|
+
class={cn(
|
|
104
|
+
'mb-1',
|
|
105
|
+
local.variant === 'label'
|
|
106
|
+
? 'text-sm font-medium'
|
|
107
|
+
: 'text-base font-semibold tracking-tight',
|
|
108
|
+
local.class
|
|
109
|
+
)}
|
|
110
|
+
{...rest}
|
|
111
|
+
/>
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** A horizontal rule with a word in it, for "or continue with" separators. */
|
|
116
|
+
export function FieldSeparator(props: {
|
|
117
|
+
class?: string
|
|
118
|
+
children?: ComponentProps<'span'>['children']
|
|
119
|
+
}) {
|
|
120
|
+
const [local, rest] = splitProps(props, ['class', 'children'])
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<div class={cn('relative flex items-center gap-3 py-1', local.class)} {...rest}>
|
|
124
|
+
<span class="bg-border h-px flex-1" />
|
|
125
|
+
<Show when={local.children}>
|
|
126
|
+
<span class="text-muted-foreground text-2xs tracking-wide uppercase">{local.children}</span>
|
|
127
|
+
</Show>
|
|
128
|
+
<span class="bg-border h-px flex-1" />
|
|
129
|
+
</div>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { HoverCard as KobalteHoverCard } from '@kobalte/core/hover-card'
|
|
2
|
+
import type { ComponentProps } from 'solid-js'
|
|
3
|
+
import { splitProps } from 'solid-js'
|
|
4
|
+
import { overlaySurface, popoverArrow } from '../../../lib/overlay'
|
|
5
|
+
import { cn } from '../../../lib/utils'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* HoverCard.
|
|
9
|
+
*
|
|
10
|
+
* A rich preview shown on hover: a user's profile, a file's summary, a link's
|
|
11
|
+
* destination. The difference from Tooltip is that this may be hovered *into*
|
|
12
|
+
* — the pointer can leave the trigger, cross the gap, and read the card.
|
|
13
|
+
*
|
|
14
|
+
* Because it only opens on hover, its content must also be reachable another
|
|
15
|
+
* way (clicking the trigger, for instance). A hover card that holds the only
|
|
16
|
+
* route to something is unreachable by keyboard and by touch.
|
|
17
|
+
*/
|
|
18
|
+
export function HoverCard(props: ComponentProps<typeof KobalteHoverCard>) {
|
|
19
|
+
return <KobalteHoverCard {...props} />
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function HoverCardTrigger(props: ComponentProps<typeof KobalteHoverCard.Trigger>) {
|
|
23
|
+
return <KobalteHoverCard.Trigger {...props} />
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function HoverCardContent(props: ComponentProps<typeof KobalteHoverCard.Content>) {
|
|
27
|
+
const [local, rest] = splitProps(props, ['class', 'children'])
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<KobalteHoverCard.Portal>
|
|
31
|
+
<KobalteHoverCard.Content
|
|
32
|
+
class={cn(
|
|
33
|
+
overlaySurface,
|
|
34
|
+
'z-(--z-menu) w-64 p-3',
|
|
35
|
+
'origin-(--kb-hover-card-content-transform-origin)',
|
|
36
|
+
'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95',
|
|
37
|
+
'data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',
|
|
38
|
+
'data-expanded:duration-150 data-closed:duration-100',
|
|
39
|
+
local.class
|
|
40
|
+
)}
|
|
41
|
+
{...rest}
|
|
42
|
+
>
|
|
43
|
+
{local.children}
|
|
44
|
+
<KobalteHoverCard.Arrow aria-hidden="true" class={popoverArrow} />
|
|
45
|
+
</KobalteHoverCard.Content>
|
|
46
|
+
</KobalteHoverCard.Portal>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HoverCard, HoverCardContent, HoverCardTrigger } from './hover-card'
|