@vendure/dashboard 3.5.0-minor-202510071456 → 3.5.0-minor-202510161257

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.
Files changed (201) hide show
  1. package/dist/plugin/dashboard.plugin.js +1 -1
  2. package/dist/vite/utils/ast-utils.spec.js +3 -3
  3. package/dist/vite/vite-plugin-hmr.d.ts +8 -0
  4. package/dist/vite/vite-plugin-hmr.js +34 -0
  5. package/dist/vite/vite-plugin-theme.js +6 -6
  6. package/dist/vite/vite-plugin-transform-index.js +6 -1
  7. package/dist/vite/vite-plugin-vendure-dashboard.d.ts +31 -4
  8. package/dist/vite/vite-plugin-vendure-dashboard.js +89 -34
  9. package/package.json +17 -5
  10. package/src/app/app-providers.tsx +4 -1
  11. package/src/app/common/map-faceted-filter-fields.ts +21 -0
  12. package/src/app/main.tsx +3 -1
  13. package/src/app/routes/_authenticated/_administrators/administrators.graphql.ts +2 -2
  14. package/src/app/routes/_authenticated/_administrators/administrators.tsx +13 -3
  15. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +6 -13
  16. package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +1 -1
  17. package/src/app/routes/_authenticated/_assets/assets.tsx +17 -1
  18. package/src/app/routes/_authenticated/_collections/collections.graphql.ts +1 -0
  19. package/src/app/routes/_authenticated/_collections/collections.tsx +5 -0
  20. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +0 -1
  21. package/src/app/routes/_authenticated/_customers/customers.tsx +9 -5
  22. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +0 -6
  23. package/src/app/routes/_authenticated/_facets/components/facet-value-bulk-actions.tsx +16 -0
  24. package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +43 -12
  25. package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +14 -5
  26. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +117 -92
  27. package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +1 -1
  28. package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +2 -1
  29. package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +26 -27
  30. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +5 -3
  31. package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +6 -9
  32. package/src/app/routes/_authenticated/_orders/orders.graphql.ts +17 -1
  33. package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +48 -281
  34. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +59 -40
  35. package/src/app/routes/_authenticated/_orders/utils/order-utils.ts +73 -0
  36. package/src/app/routes/_authenticated/_orders/utils/use-modify-order.ts +312 -0
  37. package/src/app/routes/_authenticated/_payment-methods/payment-methods.graphql.ts +2 -2
  38. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +4 -0
  39. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +0 -6
  40. package/src/app/routes/_authenticated/_products/products.tsx +6 -2
  41. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +4 -8
  42. package/src/app/routes/_authenticated/_promotions/components/promotion-bulk-actions.tsx +0 -10
  43. package/src/app/routes/_authenticated/_promotions/promotions.graphql.ts +2 -2
  44. package/src/app/routes/_authenticated/_promotions/promotions.tsx +12 -0
  45. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +6 -2
  46. package/src/app/routes/_authenticated/_sellers/sellers.graphql.ts +2 -2
  47. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.graphql.ts +2 -2
  48. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +4 -0
  49. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +4 -10
  50. package/src/app/routes/_authenticated/_stock-locations/stock-locations.graphql.ts +2 -2
  51. package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +2 -2
  52. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +9 -0
  53. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +1 -0
  54. package/src/app/routes/_authenticated/_zones/zones.graphql.ts +2 -2
  55. package/src/app/routes/login.tsx +2 -2
  56. package/src/i18n/locales/ar.po +420 -289
  57. package/src/i18n/locales/cs.po +420 -289
  58. package/src/i18n/locales/de.po +420 -289
  59. package/src/i18n/locales/en.po +420 -289
  60. package/src/i18n/locales/es.po +420 -289
  61. package/src/i18n/locales/fa.po +420 -289
  62. package/src/i18n/locales/fr.po +468 -337
  63. package/src/i18n/locales/he.po +420 -289
  64. package/src/i18n/locales/hr.po +420 -289
  65. package/src/i18n/locales/it.po +420 -289
  66. package/src/i18n/locales/ja.po +420 -289
  67. package/src/i18n/locales/nb.po +420 -289
  68. package/src/i18n/locales/ne.po +420 -289
  69. package/src/i18n/locales/pl.po +420 -289
  70. package/src/i18n/locales/pt_BR.po +420 -289
  71. package/src/i18n/locales/pt_PT.po +420 -289
  72. package/src/i18n/locales/ru.po +420 -289
  73. package/src/i18n/locales/sv.po +420 -289
  74. package/src/i18n/locales/tr.po +420 -289
  75. package/src/i18n/locales/uk.po +420 -289
  76. package/src/i18n/locales/zh_Hans.po +420 -289
  77. package/src/i18n/locales/zh_Hant.po +420 -289
  78. package/src/lib/components/data-input/affixed-input.stories.tsx +93 -0
  79. package/src/lib/components/data-input/affixed-input.tsx +5 -2
  80. package/src/lib/components/data-input/boolean-input.stories.tsx +102 -0
  81. package/src/lib/components/data-input/checkbox-input.stories.tsx +61 -0
  82. package/src/lib/components/data-input/datetime-input.stories.tsx +62 -0
  83. package/src/lib/components/data-input/datetime-input.tsx +27 -13
  84. package/src/lib/components/data-input/default-relation-input.tsx +18 -12
  85. package/src/lib/components/data-input/money-input.stories.tsx +88 -0
  86. package/src/lib/components/data-input/number-input.stories.tsx +103 -0
  87. package/src/lib/components/data-input/number-input.tsx +10 -4
  88. package/src/lib/components/data-input/password-input.stories.tsx +65 -0
  89. package/src/lib/components/data-input/rich-text-input.stories.tsx +92 -0
  90. package/src/lib/components/data-input/slug-input.stories.tsx +232 -0
  91. package/src/lib/components/data-input/slug-input.tsx +9 -10
  92. package/src/lib/components/data-input/text-input.stories.tsx +52 -0
  93. package/src/lib/components/data-input/textarea-input.stories.tsx +55 -0
  94. package/src/lib/components/data-table/add-filter-menu.tsx +6 -1
  95. package/src/lib/components/data-table/column-header-wrapper.tsx +106 -0
  96. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +11 -9
  97. package/src/lib/components/data-table/data-table-bulk-actions.tsx +4 -4
  98. package/src/lib/components/data-table/data-table-column-header.tsx +17 -14
  99. package/src/lib/components/data-table/data-table-faceted-filter.tsx +33 -11
  100. package/src/lib/components/data-table/data-table-filter-badge-editable.tsx +35 -0
  101. package/src/lib/components/data-table/data-table-filter-badge.tsx +23 -16
  102. package/src/lib/components/data-table/data-table-filter-dialog.tsx +28 -8
  103. package/src/lib/components/data-table/data-table-pagination.tsx +23 -7
  104. package/src/lib/components/data-table/data-table.stories.tsx +249 -0
  105. package/src/lib/components/data-table/data-table.tsx +37 -9
  106. package/src/lib/components/data-table/filters/data-table-datetime-filter.tsx +79 -34
  107. package/src/lib/components/data-table/use-generated-columns.tsx +55 -27
  108. package/src/lib/components/layout/nav-user.tsx +19 -13
  109. package/src/lib/components/login/login-form.tsx +39 -123
  110. package/src/lib/components/shared/alerts.tsx +29 -17
  111. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +3 -3
  112. package/src/lib/components/shared/asset/asset-gallery.stories.tsx +76 -0
  113. package/src/lib/components/shared/asset/asset-gallery.tsx +147 -113
  114. package/src/lib/components/shared/asset/asset-picker-dialog.stories.tsx +58 -0
  115. package/src/lib/components/shared/customer-group-selector.tsx +5 -2
  116. package/src/lib/components/shared/detail-page-button.stories.tsx +52 -0
  117. package/src/lib/components/shared/facet-value-selector.stories.tsx +48 -0
  118. package/src/lib/components/shared/facet-value-selector.tsx +130 -34
  119. package/src/lib/components/shared/paginated-list-data-table.stories.tsx +212 -0
  120. package/src/lib/components/shared/paginated-list-data-table.tsx +12 -12
  121. package/src/lib/components/shared/permission-guard.stories.tsx +46 -0
  122. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +2 -0
  123. package/src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx +8 -4
  124. package/src/lib/components/shared/rich-text-editor/rich-text-editor.tsx +1 -0
  125. package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +40 -0
  126. package/src/lib/components/shared/vendure-image.stories.tsx +167 -0
  127. package/src/lib/components/shared/vendure-image.tsx +6 -7
  128. package/src/lib/components/ui/accordion.stories.tsx +33 -0
  129. package/src/lib/components/ui/alert-dialog.stories.tsx +48 -0
  130. package/src/lib/components/ui/alert.stories.tsx +35 -0
  131. package/src/lib/components/ui/aspect-ratio.stories.tsx +28 -0
  132. package/src/lib/components/ui/badge.stories.tsx +28 -0
  133. package/src/lib/components/ui/breadcrumb.stories.tsx +41 -0
  134. package/src/lib/components/ui/button.stories.tsx +38 -0
  135. package/src/lib/components/ui/calendar.stories.tsx +22 -0
  136. package/src/lib/components/ui/card.stories.tsx +28 -0
  137. package/src/lib/components/ui/carousel.stories.tsx +34 -0
  138. package/src/lib/components/ui/checkbox.stories.tsx +31 -0
  139. package/src/lib/components/ui/collapsible.stories.tsx +39 -0
  140. package/src/lib/components/ui/command.stories.tsx +44 -0
  141. package/src/lib/components/ui/context-menu.stories.tsx +38 -0
  142. package/src/lib/components/ui/dialog.stories.tsx +52 -0
  143. package/src/lib/components/ui/drawer.stories.tsx +50 -0
  144. package/src/lib/components/ui/dropdown-menu.stories.tsx +41 -0
  145. package/src/lib/components/ui/hover-card.stories.tsx +38 -0
  146. package/src/lib/components/ui/input-group.tsx +148 -0
  147. package/src/lib/components/ui/input-otp.stories.tsx +30 -0
  148. package/src/lib/components/ui/input.stories.tsx +38 -0
  149. package/src/lib/components/ui/label.stories.tsx +24 -0
  150. package/src/lib/components/ui/menubar.stories.tsx +53 -0
  151. package/src/lib/components/ui/navigation-menu.stories.tsx +54 -0
  152. package/src/lib/components/ui/pagination.stories.tsx +51 -0
  153. package/src/lib/components/ui/password-input.stories.tsx +32 -0
  154. package/src/lib/components/ui/password-input.tsx +33 -0
  155. package/src/lib/components/ui/popover.stories.tsx +33 -0
  156. package/src/lib/components/ui/progress.stories.tsx +27 -0
  157. package/src/lib/components/ui/radio-group.stories.tsx +34 -0
  158. package/src/lib/components/ui/resizable.stories.tsx +32 -0
  159. package/src/lib/components/ui/scroll-area.stories.tsx +31 -0
  160. package/src/lib/components/ui/select.stories.tsx +36 -0
  161. package/src/lib/components/ui/separator.stories.tsx +35 -0
  162. package/src/lib/components/ui/sheet.stories.tsx +50 -0
  163. package/src/lib/components/ui/sidebar-context.ts +16 -0
  164. package/src/lib/components/ui/sidebar.tsx +2 -13
  165. package/src/lib/components/ui/skeleton.stories.tsx +26 -0
  166. package/src/lib/components/ui/slider.stories.tsx +37 -0
  167. package/src/lib/components/ui/switch.stories.tsx +31 -0
  168. package/src/lib/components/ui/table.stories.tsx +52 -0
  169. package/src/lib/components/ui/tabs.stories.tsx +29 -0
  170. package/src/lib/components/ui/textarea.stories.tsx +32 -0
  171. package/src/lib/components/ui/toggle-group.stories.tsx +31 -0
  172. package/src/lib/components/ui/toggle.stories.tsx +39 -0
  173. package/src/lib/components/ui/tooltip.stories.tsx +30 -0
  174. package/src/lib/components/ui/tooltip.tsx +2 -2
  175. package/src/lib/framework/alert/alert-extensions.tsx +0 -11
  176. package/src/lib/framework/alert/alert-item.tsx +14 -19
  177. package/src/lib/framework/alert/alerts-indicator.tsx +14 -15
  178. package/src/lib/framework/alert/search-index-buffer-alert/search-index-buffer-alert.ts +41 -0
  179. package/src/lib/framework/component-registry/component-registry.tsx +3 -14
  180. package/src/lib/framework/dashboard-widget/base-widget.tsx +18 -9
  181. package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +12 -11
  182. package/src/lib/framework/defaults.ts +9 -13
  183. package/src/lib/framework/extension-api/input-component-extensions.tsx +6 -1
  184. package/src/lib/framework/extension-api/logic/alerts.ts +3 -2
  185. package/src/lib/framework/extension-api/types/alerts.ts +12 -6
  186. package/src/lib/framework/extension-api/types/data-table.ts +5 -2
  187. package/src/lib/framework/extension-api/types/login.ts +0 -21
  188. package/src/lib/framework/layout-engine/custom-form-page.stories.tsx +344 -0
  189. package/src/lib/framework/layout-engine/page-layout.tsx +11 -9
  190. package/src/lib/framework/layout-engine/page.stories.tsx +275 -0
  191. package/src/lib/framework/nav-menu/nav-menu-extensions.ts +32 -19
  192. package/src/lib/framework/page/detail-page.stories.tsx +151 -0
  193. package/src/lib/framework/page/list-page.stories.tsx +217 -0
  194. package/src/lib/framework/page/list-page.tsx +8 -1
  195. package/src/lib/graphql/api.ts +18 -1
  196. package/src/lib/graphql/graphql-env.d.ts +1 -1
  197. package/src/lib/hooks/use-alerts.ts +84 -0
  198. package/src/lib/hooks/use-floating-bulk-actions.ts +2 -3
  199. package/src/lib/index.ts +12 -5
  200. package/src/lib/providers/alerts-provider.tsx +60 -0
  201. package/src/lib/providers/theme-provider.tsx +6 -3
@@ -0,0 +1,39 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { useState } from 'react';
3
+ import { Button } from './button.js';
4
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './collapsible.js';
5
+
6
+ const meta = {
7
+ title: 'UI/Collapsible',
8
+ component: Collapsible,
9
+ parameters: {
10
+ layout: 'centered',
11
+ },
12
+ tags: ['autodocs'],
13
+ } satisfies Meta<typeof Collapsible>;
14
+
15
+ export default meta;
16
+ type Story = StoryObj<typeof meta>;
17
+
18
+ export const Playground: Story = {
19
+ render: () => {
20
+ const [isOpen, setIsOpen] = useState(false);
21
+ return (
22
+ <Collapsible open={isOpen} onOpenChange={setIsOpen} className="w-[350px] space-y-2">
23
+ <div className="flex items-center justify-between space-x-4 px-4">
24
+ <h4 className="text-sm font-semibold">@peduarte starred 3 repositories</h4>
25
+ <CollapsibleTrigger asChild>
26
+ <Button variant="ghost" size="sm">
27
+ {isOpen ? 'Hide' : 'Show'}
28
+ </Button>
29
+ </CollapsibleTrigger>
30
+ </div>
31
+ <div className="rounded-md border px-4 py-3 font-mono text-sm">@radix-ui/primitives</div>
32
+ <CollapsibleContent className="space-y-2">
33
+ <div className="rounded-md border px-4 py-3 font-mono text-sm">@radix-ui/colors</div>
34
+ <div className="rounded-md border px-4 py-3 font-mono text-sm">@stitches/react</div>
35
+ </CollapsibleContent>
36
+ </Collapsible>
37
+ );
38
+ },
39
+ };
@@ -0,0 +1,44 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import {
3
+ Command,
4
+ CommandEmpty,
5
+ CommandGroup,
6
+ CommandInput,
7
+ CommandItem,
8
+ CommandList,
9
+ CommandSeparator,
10
+ } from './command.js';
11
+
12
+ const meta = {
13
+ title: 'UI/Command',
14
+ component: Command,
15
+ parameters: {
16
+ layout: 'centered',
17
+ },
18
+ tags: ['autodocs'],
19
+ } satisfies Meta<typeof Command>;
20
+
21
+ export default meta;
22
+ type Story = StoryObj<typeof meta>;
23
+
24
+ export const Playground: Story = {
25
+ render: () => (
26
+ <Command className="rounded-lg border shadow-md w-[400px]">
27
+ <CommandInput placeholder="Type a command or search..." />
28
+ <CommandList>
29
+ <CommandEmpty>No results found.</CommandEmpty>
30
+ <CommandGroup heading="Suggestions">
31
+ <CommandItem>Calendar</CommandItem>
32
+ <CommandItem>Search Emoji</CommandItem>
33
+ <CommandItem>Calculator</CommandItem>
34
+ </CommandGroup>
35
+ <CommandSeparator />
36
+ <CommandGroup heading="Settings">
37
+ <CommandItem>Profile</CommandItem>
38
+ <CommandItem>Billing</CommandItem>
39
+ <CommandItem>Settings</CommandItem>
40
+ </CommandGroup>
41
+ </CommandList>
42
+ </Command>
43
+ ),
44
+ };
@@ -0,0 +1,38 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import {
3
+ ContextMenu,
4
+ ContextMenuContent,
5
+ ContextMenuItem,
6
+ ContextMenuSeparator,
7
+ ContextMenuTrigger,
8
+ } from './context-menu.js';
9
+
10
+ const meta = {
11
+ title: 'UI/Context Menu',
12
+ component: ContextMenu,
13
+ parameters: {
14
+ layout: 'centered',
15
+ },
16
+ tags: ['autodocs'],
17
+ } satisfies Meta<typeof ContextMenu>;
18
+
19
+ export default meta;
20
+ type Story = StoryObj<typeof meta>;
21
+
22
+ export const Playground: Story = {
23
+ render: () => (
24
+ <ContextMenu>
25
+ <ContextMenuTrigger className="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
26
+ Right click here
27
+ </ContextMenuTrigger>
28
+ <ContextMenuContent>
29
+ <ContextMenuItem>Back</ContextMenuItem>
30
+ <ContextMenuItem>Forward</ContextMenuItem>
31
+ <ContextMenuItem>Reload</ContextMenuItem>
32
+ <ContextMenuSeparator />
33
+ <ContextMenuItem>Save Page As...</ContextMenuItem>
34
+ <ContextMenuItem>Print...</ContextMenuItem>
35
+ </ContextMenuContent>
36
+ </ContextMenu>
37
+ ),
38
+ };
@@ -0,0 +1,52 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { useState } from 'react';
3
+ import { Button } from './button.js';
4
+ import {
5
+ Dialog,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogFooter,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ DialogTrigger,
12
+ } from './dialog.js';
13
+
14
+ const meta = {
15
+ title: 'UI/Dialog',
16
+ component: Dialog,
17
+ parameters: {
18
+ layout: 'centered',
19
+ },
20
+ tags: ['autodocs'],
21
+ } satisfies Meta<typeof Dialog>;
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ export const Playground: Story = {
27
+ render: () => {
28
+ const [open, setOpen] = useState(false);
29
+ return (
30
+ <Dialog open={open} onOpenChange={setOpen}>
31
+ <DialogTrigger asChild>
32
+ <Button>Open Dialog</Button>
33
+ </DialogTrigger>
34
+ <DialogContent>
35
+ <DialogHeader>
36
+ <DialogTitle>Dialog Title</DialogTitle>
37
+ <DialogDescription>
38
+ This is a dialog description. You can add any content here.
39
+ </DialogDescription>
40
+ </DialogHeader>
41
+ <div className="py-4">Dialog content goes here</div>
42
+ <DialogFooter>
43
+ <Button variant="outline" onClick={() => setOpen(false)}>
44
+ Cancel
45
+ </Button>
46
+ <Button onClick={() => setOpen(false)}>Confirm</Button>
47
+ </DialogFooter>
48
+ </DialogContent>
49
+ </Dialog>
50
+ );
51
+ },
52
+ };
@@ -0,0 +1,50 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { useState } from 'react';
3
+ import { Button } from './button.js';
4
+ import {
5
+ Drawer,
6
+ DrawerClose,
7
+ DrawerContent,
8
+ DrawerDescription,
9
+ DrawerFooter,
10
+ DrawerHeader,
11
+ DrawerTitle,
12
+ DrawerTrigger,
13
+ } from './drawer.js';
14
+
15
+ const meta = {
16
+ title: 'UI/Drawer',
17
+ component: Drawer,
18
+ parameters: {
19
+ layout: 'centered',
20
+ },
21
+ tags: ['autodocs'],
22
+ } satisfies Meta<typeof Drawer>;
23
+
24
+ export default meta;
25
+ type Story = StoryObj<typeof meta>;
26
+
27
+ export const Playground: Story = {
28
+ render: () => (
29
+ <Drawer>
30
+ <DrawerTrigger asChild>
31
+ <Button>Open Drawer</Button>
32
+ </DrawerTrigger>
33
+ <DrawerContent>
34
+ <DrawerHeader>
35
+ <DrawerTitle>Drawer Title</DrawerTitle>
36
+ <DrawerDescription>This is a drawer description</DrawerDescription>
37
+ </DrawerHeader>
38
+ <div className="p-4">
39
+ <p>Drawer content goes here</p>
40
+ </div>
41
+ <DrawerFooter>
42
+ <Button>Submit</Button>
43
+ <DrawerClose asChild>
44
+ <Button variant="outline">Cancel</Button>
45
+ </DrawerClose>
46
+ </DrawerFooter>
47
+ </DrawerContent>
48
+ </Drawer>
49
+ ),
50
+ };
@@ -0,0 +1,41 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Button } from './button.js';
3
+ import {
4
+ DropdownMenu,
5
+ DropdownMenuContent,
6
+ DropdownMenuItem,
7
+ DropdownMenuLabel,
8
+ DropdownMenuSeparator,
9
+ DropdownMenuTrigger,
10
+ } from './dropdown-menu.js';
11
+
12
+ const meta = {
13
+ title: 'UI/Dropdown Menu',
14
+ component: DropdownMenu,
15
+ parameters: {
16
+ layout: 'centered',
17
+ },
18
+ tags: ['autodocs'],
19
+ } satisfies Meta<typeof DropdownMenu>;
20
+
21
+ export default meta;
22
+ type Story = StoryObj<typeof meta>;
23
+
24
+ export const Playground: Story = {
25
+ render: () => (
26
+ <DropdownMenu>
27
+ <DropdownMenuTrigger asChild>
28
+ <Button>Open Menu</Button>
29
+ </DropdownMenuTrigger>
30
+ <DropdownMenuContent>
31
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
32
+ <DropdownMenuSeparator />
33
+ <DropdownMenuItem>Profile</DropdownMenuItem>
34
+ <DropdownMenuItem>Settings</DropdownMenuItem>
35
+ <DropdownMenuItem>Team</DropdownMenuItem>
36
+ <DropdownMenuSeparator />
37
+ <DropdownMenuItem>Log out</DropdownMenuItem>
38
+ </DropdownMenuContent>
39
+ </DropdownMenu>
40
+ ),
41
+ };
@@ -0,0 +1,38 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Button } from './button.js';
3
+ import { HoverCard, HoverCardContent, HoverCardTrigger } from './hover-card.js';
4
+
5
+ const meta = {
6
+ title: 'UI/Hover Card',
7
+ component: HoverCard,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ tags: ['autodocs'],
12
+ } satisfies Meta<typeof HoverCard>;
13
+
14
+ export default meta;
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Playground: Story = {
18
+ render: () => (
19
+ <HoverCard>
20
+ <HoverCardTrigger asChild>
21
+ <Button variant="link">@username</Button>
22
+ </HoverCardTrigger>
23
+ <HoverCardContent className="w-80">
24
+ <div className="flex justify-between space-x-4">
25
+ <div className="space-y-1">
26
+ <h4 className="text-sm font-semibold">@username</h4>
27
+ <p className="text-sm">
28
+ The React Framework – created and maintained by @vercel.
29
+ </p>
30
+ <div className="flex items-center pt-2">
31
+ <span className="text-xs text-muted-foreground">Joined December 2021</span>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ </HoverCardContent>
36
+ </HoverCard>
37
+ ),
38
+ };
@@ -0,0 +1,148 @@
1
+ import { cva, type VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
+
4
+ import { Button } from '@/vdb/components/ui/button.js';
5
+ import { Input } from '@/vdb/components/ui/input.js';
6
+ import { Textarea } from '@/vdb/components/ui/textarea.js';
7
+ import { cn } from '@/vdb/lib/utils.js';
8
+
9
+ function InputGroup({ className, ...props }: React.ComponentProps<'div'>) {
10
+ return (
11
+ <div
12
+ data-slot="input-group"
13
+ role="group"
14
+ className={cn(
15
+ 'group/input-group border-input dark:bg-input/30 relative flex w-full items-center rounded-md border shadow-xs transition-[color,box-shadow] outline-none',
16
+ 'h-9 has-[>textarea]:h-auto',
17
+
18
+ // Variants based on alignment.
19
+ 'has-[>[data-align=inline-start]]:[&>input]:pl-2',
20
+ 'has-[>[data-align=inline-end]]:[&>input]:pr-2',
21
+ 'has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3',
22
+ 'has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3',
23
+
24
+ // Focus state.
25
+ 'has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]',
26
+
27
+ // Error state.
28
+ 'has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40',
29
+
30
+ className,
31
+ )}
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ const inputGroupAddonVariants = cva(
38
+ "text-muted-foreground flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium select-none [&>svg:not([class*='size-'])]:size-4 [&>kbd]:rounded-[calc(var(--radius)-5px)] group-data-[disabled=true]/input-group:opacity-50",
39
+ {
40
+ variants: {
41
+ align: {
42
+ 'inline-start': 'order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]',
43
+ 'inline-end': 'order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]',
44
+ 'block-start':
45
+ 'order-first w-full justify-start px-3 pt-3 [.border-b]:pb-3 group-has-[>input]/input-group:pt-2.5',
46
+ 'block-end':
47
+ 'order-last w-full justify-start px-3 pb-3 [.border-t]:pt-3 group-has-[>input]/input-group:pb-2.5',
48
+ },
49
+ },
50
+ defaultVariants: {
51
+ align: 'inline-start',
52
+ },
53
+ },
54
+ );
55
+
56
+ function InputGroupAddon({
57
+ className,
58
+ align = 'inline-start',
59
+ ...props
60
+ }: React.ComponentProps<'div'> & VariantProps<typeof inputGroupAddonVariants>) {
61
+ return (
62
+ <div
63
+ role="group"
64
+ data-slot="input-group-addon"
65
+ data-align={align}
66
+ className={cn(inputGroupAddonVariants({ align }), className)}
67
+ onClick={e => {
68
+ if ((e.target as HTMLElement).closest('button')) {
69
+ return;
70
+ }
71
+ e.currentTarget.parentElement?.querySelector('input')?.focus();
72
+ }}
73
+ {...props}
74
+ />
75
+ );
76
+ }
77
+
78
+ const inputGroupButtonVariants = cva('text-sm shadow-none flex gap-2 items-center', {
79
+ variants: {
80
+ size: {
81
+ xs: "h-6 gap-1 px-2 rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-3.5 has-[>svg]:px-2",
82
+ sm: 'h-8 px-2.5 gap-1.5 rounded-md has-[>svg]:px-2.5',
83
+ 'icon-xs': 'size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0',
84
+ 'icon-sm': 'size-8 p-0 has-[>svg]:p-0',
85
+ },
86
+ },
87
+ defaultVariants: {
88
+ size: 'xs',
89
+ },
90
+ });
91
+
92
+ function InputGroupButton({
93
+ className,
94
+ type = 'button',
95
+ variant = 'ghost',
96
+ size = 'xs',
97
+ ...props
98
+ }: Omit<React.ComponentProps<typeof Button>, 'size'> & VariantProps<typeof inputGroupButtonVariants>) {
99
+ return (
100
+ <Button
101
+ type={type}
102
+ data-size={size}
103
+ variant={variant}
104
+ className={cn(inputGroupButtonVariants({ size }), className)}
105
+ {...props}
106
+ />
107
+ );
108
+ }
109
+
110
+ function InputGroupText({ className, ...props }: React.ComponentProps<'span'>) {
111
+ return (
112
+ <span
113
+ className={cn(
114
+ "text-muted-foreground flex items-center gap-2 text-sm [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
115
+ className,
116
+ )}
117
+ {...props}
118
+ />
119
+ );
120
+ }
121
+
122
+ function InputGroupInput({ className, ...props }: React.ComponentProps<'input'>) {
123
+ return (
124
+ <Input
125
+ data-slot="input-group-control"
126
+ className={cn(
127
+ 'flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent',
128
+ className,
129
+ )}
130
+ {...props}
131
+ />
132
+ );
133
+ }
134
+
135
+ function InputGroupTextarea({ className, ...props }: React.ComponentProps<'textarea'>) {
136
+ return (
137
+ <Textarea
138
+ data-slot="input-group-control"
139
+ className={cn(
140
+ 'flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent',
141
+ className,
142
+ )}
143
+ {...props}
144
+ />
145
+ );
146
+ }
147
+
148
+ export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea };
@@ -0,0 +1,30 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { REGEXP_ONLY_DIGITS_AND_CHARS } from 'input-otp';
3
+ import { InputOTP, InputOTPGroup, InputOTPSlot } from './input-otp.js';
4
+
5
+ const meta = {
6
+ title: 'UI/Input OTP',
7
+ component: InputOTP,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ tags: ['autodocs'],
12
+ } satisfies Meta<typeof InputOTP>;
13
+
14
+ export default meta;
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Playground: Story = {
18
+ render: () => (
19
+ <InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS_AND_CHARS}>
20
+ <InputOTPGroup>
21
+ <InputOTPSlot index={0} />
22
+ <InputOTPSlot index={1} />
23
+ <InputOTPSlot index={2} />
24
+ <InputOTPSlot index={3} />
25
+ <InputOTPSlot index={4} />
26
+ <InputOTPSlot index={5} />
27
+ </InputOTPGroup>
28
+ </InputOTP>
29
+ ),
30
+ };
@@ -0,0 +1,38 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Input } from './input.js';
3
+
4
+ const meta = {
5
+ title: 'UI/Input',
6
+ component: Input,
7
+ parameters: {
8
+ layout: 'centered',
9
+ },
10
+ tags: ['autodocs'],
11
+ argTypes: {
12
+ type: {
13
+ control: 'select',
14
+ options: ['text', 'email', 'password', 'number', 'tel', 'url'],
15
+ description: 'Input type',
16
+ },
17
+ placeholder: {
18
+ control: 'text',
19
+ description: 'Placeholder text',
20
+ },
21
+ disabled: {
22
+ control: 'boolean',
23
+ description: 'Whether the input is disabled',
24
+ },
25
+ },
26
+ } satisfies Meta<typeof Input>;
27
+
28
+ export default meta;
29
+ type Story = StoryObj<typeof meta>;
30
+
31
+ export const Playground: Story = {
32
+ args: {
33
+ type: 'text',
34
+ placeholder: 'Enter text...',
35
+ disabled: false,
36
+ },
37
+ render: args => <Input {...args} className="w-[300px]" />,
38
+ };
@@ -0,0 +1,24 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Checkbox } from './checkbox.js';
3
+ import { Label } from './label.js';
4
+
5
+ const meta = {
6
+ title: 'UI/Label',
7
+ component: Label,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ tags: ['autodocs'],
12
+ } satisfies Meta<typeof Label>;
13
+
14
+ export default meta;
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Playground: Story = {
18
+ render: () => (
19
+ <div className="flex items-center space-x-2">
20
+ <Checkbox id="terms" />
21
+ <Label htmlFor="terms">Accept terms and conditions</Label>
22
+ </div>
23
+ ),
24
+ };
@@ -0,0 +1,53 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import {
3
+ Menubar,
4
+ MenubarContent,
5
+ MenubarItem,
6
+ MenubarMenu,
7
+ MenubarSeparator,
8
+ MenubarTrigger,
9
+ } from './menubar.js';
10
+
11
+ const meta = {
12
+ title: 'UI/Menubar',
13
+ component: Menubar,
14
+ parameters: {
15
+ layout: 'centered',
16
+ },
17
+ tags: ['autodocs'],
18
+ } satisfies Meta<typeof Menubar>;
19
+
20
+ export default meta;
21
+ type Story = StoryObj<typeof meta>;
22
+
23
+ export const Playground: Story = {
24
+ render: () => (
25
+ <Menubar>
26
+ <MenubarMenu>
27
+ <MenubarTrigger>File</MenubarTrigger>
28
+ <MenubarContent>
29
+ <MenubarItem>New Tab</MenubarItem>
30
+ <MenubarItem>New Window</MenubarItem>
31
+ <MenubarSeparator />
32
+ <MenubarItem>Share</MenubarItem>
33
+ <MenubarSeparator />
34
+ <MenubarItem>Print</MenubarItem>
35
+ </MenubarContent>
36
+ </MenubarMenu>
37
+ <MenubarMenu>
38
+ <MenubarTrigger>Edit</MenubarTrigger>
39
+ <MenubarContent>
40
+ <MenubarItem>Undo</MenubarItem>
41
+ <MenubarItem>Redo</MenubarItem>
42
+ </MenubarContent>
43
+ </MenubarMenu>
44
+ <MenubarMenu>
45
+ <MenubarTrigger>View</MenubarTrigger>
46
+ <MenubarContent>
47
+ <MenubarItem>Zoom In</MenubarItem>
48
+ <MenubarItem>Zoom Out</MenubarItem>
49
+ </MenubarContent>
50
+ </MenubarMenu>
51
+ </Menubar>
52
+ ),
53
+ };
@@ -0,0 +1,54 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import {
3
+ NavigationMenu,
4
+ NavigationMenuContent,
5
+ NavigationMenuItem,
6
+ NavigationMenuLink,
7
+ NavigationMenuList,
8
+ NavigationMenuTrigger,
9
+ } from './navigation-menu.js';
10
+
11
+ const meta = {
12
+ title: 'UI/Navigation Menu',
13
+ component: NavigationMenu,
14
+ parameters: {
15
+ layout: 'centered',
16
+ },
17
+ tags: ['autodocs'],
18
+ } satisfies Meta<typeof NavigationMenu>;
19
+
20
+ export default meta;
21
+ type Story = StoryObj<typeof meta>;
22
+
23
+ export const Playground: Story = {
24
+ render: () => (
25
+ <NavigationMenu>
26
+ <NavigationMenuList>
27
+ <NavigationMenuItem>
28
+ <NavigationMenuTrigger>Getting started</NavigationMenuTrigger>
29
+ <NavigationMenuContent>
30
+ <div className="grid gap-3 p-6 w-[400px]">
31
+ <NavigationMenuLink className="block p-3 rounded-md hover:bg-accent">
32
+ <div className="font-medium">Introduction</div>
33
+ <div className="text-sm text-muted-foreground">
34
+ Re-usable components built using Radix UI and Tailwind CSS.
35
+ </div>
36
+ </NavigationMenuLink>
37
+ <NavigationMenuLink className="block p-3 rounded-md hover:bg-accent">
38
+ <div className="font-medium">Installation</div>
39
+ <div className="text-sm text-muted-foreground">
40
+ How to install dependencies and structure your app.
41
+ </div>
42
+ </NavigationMenuLink>
43
+ </div>
44
+ </NavigationMenuContent>
45
+ </NavigationMenuItem>
46
+ <NavigationMenuItem>
47
+ <NavigationMenuLink href="/docs" className="px-4 py-2">
48
+ Documentation
49
+ </NavigationMenuLink>
50
+ </NavigationMenuItem>
51
+ </NavigationMenuList>
52
+ </NavigationMenu>
53
+ ),
54
+ };