@postxl/generators 1.1.0 → 1.2.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.
Files changed (169) hide show
  1. package/dist/backend-core/template/apps/api/src/e2e.ts +13 -4
  2. package/dist/e2e/e2e.generator.js +2 -14
  3. package/dist/e2e/e2e.generator.js.map +1 -1
  4. package/dist/e2e/generators/docker-sh.generator.d.ts +2 -0
  5. package/dist/e2e/generators/docker-sh.generator.js +25 -0
  6. package/dist/e2e/generators/docker-sh.generator.js.map +1 -0
  7. package/dist/frontend-core/frontend.generator.d.ts +0 -58
  8. package/dist/frontend-core/frontend.generator.js +6 -172
  9. package/dist/frontend-core/frontend.generator.js.map +1 -1
  10. package/dist/frontend-core/template/README.md +1 -1
  11. package/dist/frontend-core/template/src/components/admin/table-filter.tsx +1 -5
  12. package/dist/frontend-core/template/src/components/ui/color-mode-toggle/color-mode-toggle.tsx +10 -4
  13. package/dist/frontend-core/template/src/context-providers/auth-context-provider.tsx +2 -5
  14. package/dist/frontend-core/template/src/pages/dashboard/dashboard.page.tsx +2 -3
  15. package/dist/frontend-core/template/src/pages/error/default-error.page.tsx +1 -1
  16. package/dist/frontend-core/template/src/pages/error/not-found-error.page.tsx +1 -1
  17. package/dist/frontend-core/template/src/styles/styles.css +13 -1
  18. package/dist/frontend-core/template/tsconfig.json +2 -0
  19. package/dist/frontend-core/types/component.d.ts +1 -1
  20. package/dist/frontend-forms/generators/discriminated-union/fields.generator.js +4 -6
  21. package/dist/frontend-forms/generators/discriminated-union/fields.generator.js.map +1 -1
  22. package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js +1 -1
  23. package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js.map +1 -1
  24. package/dist/frontend-forms/generators/enum/inputs.generator.js +1 -1
  25. package/dist/frontend-forms/generators/enum/inputs.generator.js.map +1 -1
  26. package/dist/frontend-forms/generators/model/forms.generator.js +8 -12
  27. package/dist/frontend-forms/generators/model/forms.generator.js.map +1 -1
  28. package/dist/frontend-forms/generators/model/inputs.generator.js +2 -6
  29. package/dist/frontend-forms/generators/model/inputs.generator.js.map +1 -1
  30. package/dist/frontend-forms/template/src/components/ui/field/field.tsx +1 -4
  31. package/dist/frontend-tables/generators/model-table.generator.js +1 -5
  32. package/dist/frontend-tables/generators/model-table.generator.js.map +1 -1
  33. package/package.json +3 -2
  34. package/dist/e2e/template/scripts/docker.sh +0 -17
  35. package/dist/frontend-core/template/src/components/ui/accordion/accordion.stories.tsx +0 -47
  36. package/dist/frontend-core/template/src/components/ui/accordion/accordion.tsx +0 -52
  37. package/dist/frontend-core/template/src/components/ui/admin-sidebar/admin-sidebar.tsx +0 -195
  38. package/dist/frontend-core/template/src/components/ui/alert/alert.stories.tsx +0 -61
  39. package/dist/frontend-core/template/src/components/ui/alert/alert.tsx +0 -45
  40. package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.stories.tsx +0 -52
  41. package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.tsx +0 -105
  42. package/dist/frontend-core/template/src/components/ui/avatar/avatar.stories.tsx +0 -30
  43. package/dist/frontend-core/template/src/components/ui/avatar/avatar.tsx +0 -39
  44. package/dist/frontend-core/template/src/components/ui/badge/badge.stories.tsx +0 -78
  45. package/dist/frontend-core/template/src/components/ui/badge/badge.tsx +0 -48
  46. package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.stories.tsx +0 -67
  47. package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.tsx +0 -85
  48. package/dist/frontend-core/template/src/components/ui/button/button.stories.tsx +0 -150
  49. package/dist/frontend-core/template/src/components/ui/button/button.tsx +0 -68
  50. package/dist/frontend-core/template/src/components/ui/calendar/calendar.stories.tsx +0 -160
  51. package/dist/frontend-core/template/src/components/ui/calendar/calendar.tsx +0 -293
  52. package/dist/frontend-core/template/src/components/ui/card/card.stories.tsx +0 -77
  53. package/dist/frontend-core/template/src/components/ui/card/card.tsx +0 -45
  54. package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.stories.tsx +0 -29
  55. package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.tsx +0 -28
  56. package/dist/frontend-core/template/src/components/ui/carousel/carousel.stories.tsx +0 -154
  57. package/dist/frontend-core/template/src/components/ui/carousel/carousel.tsx +0 -227
  58. package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.stories.tsx +0 -106
  59. package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.tsx +0 -88
  60. package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.stories.tsx +0 -90
  61. package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.tsx +0 -54
  62. package/dist/frontend-core/template/src/components/ui/collapse/collapse.stories.tsx +0 -52
  63. package/dist/frontend-core/template/src/components/ui/collapse/collapse.tsx +0 -9
  64. package/dist/frontend-core/template/src/components/ui/combobox/combobox.stories.tsx +0 -207
  65. package/dist/frontend-core/template/src/components/ui/combobox/combobox.tsx +0 -79
  66. package/dist/frontend-core/template/src/components/ui/command/command.stories.tsx +0 -186
  67. package/dist/frontend-core/template/src/components/ui/command/command.tsx +0 -165
  68. package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.stories.tsx +0 -160
  69. package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.tsx +0 -134
  70. package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.stories.tsx +0 -198
  71. package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.tsx +0 -100
  72. package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.stories.tsx +0 -78
  73. package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.tsx +0 -179
  74. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/cell-variant-types.ts +0 -11
  75. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/checkbox-cell.tsx +0 -116
  76. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/date-cell.tsx +0 -157
  77. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/gantt-cell.tsx +0 -82
  78. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/long-text-cell.tsx +0 -180
  79. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/multi-select-cell.tsx +0 -280
  80. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/number-cell.tsx +0 -169
  81. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/react-node-cell.tsx +0 -33
  82. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/select-cell.tsx +0 -175
  83. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/short-text-cell.tsx +0 -138
  84. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timeline.tsx +0 -92
  85. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timerange-picker.tsx +0 -330
  86. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell-wrapper.tsx +0 -212
  87. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell.tsx +0 -157
  88. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-column-header.tsx +0 -340
  89. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-context-menu.tsx +0 -271
  90. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-row.tsx +0 -123
  91. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-search.tsx +0 -211
  92. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-types.ts +0 -159
  93. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-utils.ts +0 -67
  94. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-view-menu.tsx +0 -360
  95. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.stories.tsx +0 -780
  96. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.tsx +0 -217
  97. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-callback-ref.ts +0 -22
  98. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-data-grid.tsx +0 -1892
  99. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-debounced-callback.ts +0 -19
  100. package/dist/frontend-core/template/src/components/ui/data-grid/styles.css +0 -3
  101. package/dist/frontend-core/template/src/components/ui/data-table/context-menu-simple.tsx +0 -141
  102. package/dist/frontend-core/template/src/components/ui/data-table/data-table.stories.tsx +0 -146
  103. package/dist/frontend-core/template/src/components/ui/data-table/data-table.tsx +0 -447
  104. package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-array-cell-renderer.tsx +0 -77
  105. package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-cell-renderer.tsx +0 -56
  106. package/dist/frontend-core/template/src/components/ui/data-table/renderers/favorite-cell-renderer.tsx +0 -68
  107. package/dist/frontend-core/template/src/components/ui/data-table/renderers/links-cell-renderer.tsx +0 -205
  108. package/dist/frontend-core/template/src/components/ui/data-table/utils/columns.ts +0 -351
  109. package/dist/frontend-core/template/src/components/ui/data-table/utils/data-table.utils.ts +0 -49
  110. package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.stories.tsx +0 -149
  111. package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.tsx +0 -30
  112. package/dist/frontend-core/template/src/components/ui/dialog/dialog.stories.tsx +0 -80
  113. package/dist/frontend-core/template/src/components/ui/dialog/dialog.tsx +0 -134
  114. package/dist/frontend-core/template/src/components/ui/drawer/drawer.stories.tsx +0 -104
  115. package/dist/frontend-core/template/src/components/ui/drawer/drawer.tsx +0 -87
  116. package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.stories.tsx +0 -168
  117. package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.tsx +0 -225
  118. package/dist/frontend-core/template/src/components/ui/input/input.stories.tsx +0 -141
  119. package/dist/frontend-core/template/src/components/ui/input/input.tsx +0 -47
  120. package/dist/frontend-core/template/src/components/ui/label/label.stories.tsx +0 -41
  121. package/dist/frontend-core/template/src/components/ui/label/label.tsx +0 -20
  122. package/dist/frontend-core/template/src/components/ui/loader/loader.stories.tsx +0 -45
  123. package/dist/frontend-core/template/src/components/ui/loader/loader.tsx +0 -17
  124. package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.stories.tsx +0 -114
  125. package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.tsx +0 -48
  126. package/dist/frontend-core/template/src/components/ui/menubar/menu.stories.tsx +0 -134
  127. package/dist/frontend-core/template/src/components/ui/menubar/menubar.tsx +0 -208
  128. package/dist/frontend-core/template/src/components/ui/modal/modal.stories.tsx +0 -297
  129. package/dist/frontend-core/template/src/components/ui/modal/modal.tsx +0 -80
  130. package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.stories.tsx +0 -213
  131. package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.tsx +0 -142
  132. package/dist/frontend-core/template/src/components/ui/pagination/pagination.stories.tsx +0 -49
  133. package/dist/frontend-core/template/src/components/ui/pagination/pagination.tsx +0 -84
  134. package/dist/frontend-core/template/src/components/ui/popover/popover.stories.tsx +0 -82
  135. package/dist/frontend-core/template/src/components/ui/popover/popover.tsx +0 -55
  136. package/dist/frontend-core/template/src/components/ui/progress/progress.stories.tsx +0 -80
  137. package/dist/frontend-core/template/src/components/ui/progress/progress.tsx +0 -17
  138. package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.stories.tsx +0 -154
  139. package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.tsx +0 -68
  140. package/dist/frontend-core/template/src/components/ui/resizable/resizable.stories.tsx +0 -73
  141. package/dist/frontend-core/template/src/components/ui/resizable/resizeable.tsx +0 -38
  142. package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.stories.tsx +0 -55
  143. package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.tsx +0 -39
  144. package/dist/frontend-core/template/src/components/ui/select/select.stories.tsx +0 -297
  145. package/dist/frontend-core/template/src/components/ui/select/select.tsx +0 -227
  146. package/dist/frontend-core/template/src/components/ui/separator/separator.tsx +0 -21
  147. package/dist/frontend-core/template/src/components/ui/separator/seperator.stories.tsx +0 -25
  148. package/dist/frontend-core/template/src/components/ui/sheet/sheet.stories.tsx +0 -45
  149. package/dist/frontend-core/template/src/components/ui/sheet/sheet.tsx +0 -107
  150. package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.stories.tsx +0 -26
  151. package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.tsx +0 -7
  152. package/dist/frontend-core/template/src/components/ui/slider/slider.stories.tsx +0 -101
  153. package/dist/frontend-core/template/src/components/ui/slider/slider.tsx +0 -98
  154. package/dist/frontend-core/template/src/components/ui/spinner/spinner.stories.tsx +0 -19
  155. package/dist/frontend-core/template/src/components/ui/spinner/spinner.tsx +0 -21
  156. package/dist/frontend-core/template/src/components/ui/switch/switch.stories.tsx +0 -33
  157. package/dist/frontend-core/template/src/components/ui/switch/switch.tsx +0 -28
  158. package/dist/frontend-core/template/src/components/ui/tabs/tabs.stories.tsx +0 -215
  159. package/dist/frontend-core/template/src/components/ui/tabs/tabs.tsx +0 -70
  160. package/dist/frontend-core/template/src/components/ui/textarea/textarea.stories.tsx +0 -138
  161. package/dist/frontend-core/template/src/components/ui/textarea/textarea.tsx +0 -40
  162. package/dist/frontend-core/template/src/components/ui/toast/toast.mdx +0 -31
  163. package/dist/frontend-core/template/src/components/ui/toast/toast.stories.tsx +0 -89
  164. package/dist/frontend-core/template/src/components/ui/toggle/toggle.stories.tsx +0 -65
  165. package/dist/frontend-core/template/src/components/ui/toggle/toggle.tsx +0 -38
  166. package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.stories.tsx +0 -85
  167. package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.tsx +0 -54
  168. package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.stories.tsx +0 -29
  169. package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.tsx +0 -29
@@ -1,207 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite'
2
-
3
- import { ComboboxDemo } from './combobox'
4
- import { useState } from 'react'
5
- import { Button } from '@components/ui/button/button'
6
- import {
7
- CommandPalette,
8
- CommandPaletteEmpty,
9
- CommandPaletteGroup,
10
- CommandPaletteInput,
11
- CommandPaletteItem,
12
- CommandPaletteList,
13
- } from '@components/ui/command-palette/command-palette'
14
- import { Popover, PopoverContent, PopoverTrigger } from '@components/ui/popover/popover'
15
- import {
16
- DropdownMenu,
17
- DropdownMenuContent,
18
- DropdownMenuGroup,
19
- DropdownMenuItem,
20
- DropdownMenuLabel,
21
- DropdownMenuSeparator,
22
- DropdownMenuShortcut,
23
- DropdownMenuSub,
24
- DropdownMenuSubContent,
25
- DropdownMenuSubTrigger,
26
- DropdownMenuTrigger,
27
- } from 'components/ui/dropdown-menu/dropdown-menu'
28
- import { DotsHorizontalIcon } from '@radix-ui/react-icons'
29
-
30
- // DATA ------------------------------------------------------------------------
31
-
32
- const labels = ['feature', 'bug', 'enhancement', 'documentation', 'design', 'question', 'maintenance']
33
-
34
- type Status = {
35
- value: string
36
- label: string
37
- }
38
-
39
- const statuses: Status[] = [
40
- {
41
- value: 'backlog',
42
- label: 'Backlog',
43
- },
44
- {
45
- value: 'todo',
46
- label: 'Todo',
47
- },
48
- {
49
- value: 'in progress',
50
- label: 'In Progress',
51
- },
52
- {
53
- value: 'done',
54
- label: 'Done',
55
- },
56
- {
57
- value: 'canceled',
58
- label: 'Canceled',
59
- },
60
- ]
61
-
62
- const meta = {
63
- title: 'Combobox',
64
- component: ComboboxDemo,
65
- tags: ['autodocs'],
66
- } satisfies Meta<typeof ComboboxDemo>
67
-
68
- export default meta
69
- type Story = StoryObj<typeof meta>
70
-
71
- export const Default: Story = {
72
- parameters: {
73
- docs: {
74
- description: {
75
- story: 'A basic combobox component with search and selection functionality.',
76
- },
77
- },
78
- },
79
- render: () => (
80
- <div className="flex items-center justify-center">
81
- <ComboboxDemo />
82
- </div>
83
- ),
84
- }
85
-
86
- const PopoverComboboxExample = () => {
87
- const [openPopover, setOpenPopover] = useState(false)
88
- const [selectedStatus, setSelectedStatus] = useState<Status | null>(null)
89
-
90
- return (
91
- <div className="flex items-center space-x-4">
92
- <p className="text-sm text-muted-foreground">Status</p>
93
- <Popover open={openPopover} onOpenChange={setOpenPopover}>
94
- <PopoverTrigger asChild>
95
- <Button variant="outline" className="w-[150px] justify-start">
96
- {selectedStatus ? <>{selectedStatus.label}</> : <>+ Set status</>}
97
- </Button>
98
- </PopoverTrigger>
99
- <PopoverContent className="p-0" side="right" align="start">
100
- <CommandPalette>
101
- <CommandPaletteInput placeholder="Change status..." />
102
- <CommandPaletteList>
103
- <CommandPaletteEmpty>No results found.</CommandPaletteEmpty>
104
- <CommandPaletteGroup>
105
- {statuses.map((status) => (
106
- <CommandPaletteItem
107
- key={status.value}
108
- value={status.value}
109
- onSelect={(value) => {
110
- setSelectedStatus(statuses.find((priority) => priority.value === value) || null)
111
- setOpenPopover(false)
112
- }}
113
- >
114
- {status.label}
115
- </CommandPaletteItem>
116
- ))}
117
- </CommandPaletteGroup>
118
- </CommandPaletteList>
119
- </CommandPalette>
120
- </PopoverContent>
121
- </Popover>
122
- </div>
123
- )
124
- }
125
-
126
- export const WithPopover: Story = {
127
- parameters: {
128
- docs: {
129
- description: {
130
- story: 'A combobox implemented using a popover with status selection functionality.',
131
- },
132
- },
133
- },
134
- render: () => <PopoverComboboxExample />,
135
- }
136
-
137
- const DropdownMenuComboboxExample = () => {
138
- const [label, setLabel] = useState('feature')
139
- const [openDropdown, setOpenDropdown] = useState(false)
140
-
141
- return (
142
- <div className="flex items-center justify-center">
143
- <div className="flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center">
144
- <p className="text-sm font-medium leading-none">
145
- <span className="mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">{label}</span>
146
- <span className="text-muted-foreground">Create a new project</span>
147
- </p>
148
- <DropdownMenu open={openDropdown} onOpenChange={setOpenDropdown}>
149
- <DropdownMenuTrigger asChild>
150
- <Button variant="ghost" size="sm">
151
- <DotsHorizontalIcon />
152
- </Button>
153
- </DropdownMenuTrigger>
154
- <DropdownMenuContent align="end" className="w-[200px]">
155
- <DropdownMenuLabel>Actions</DropdownMenuLabel>
156
- <DropdownMenuGroup>
157
- <DropdownMenuItem>Assign to...</DropdownMenuItem>
158
- <DropdownMenuItem>Set due date...</DropdownMenuItem>
159
- <DropdownMenuSeparator />
160
- <DropdownMenuSub>
161
- <DropdownMenuSubTrigger>Apply label</DropdownMenuSubTrigger>
162
- <DropdownMenuSubContent className="p-0">
163
- <CommandPalette>
164
- <CommandPaletteInput placeholder="Filter label..." autoFocus={true} className="h-9" />
165
- <CommandPaletteList>
166
- <CommandPaletteEmpty>No label found.</CommandPaletteEmpty>
167
- <DropdownMenuGroup>
168
- {labels.map((label) => (
169
- <CommandPaletteItem
170
- key={label}
171
- value={label}
172
- onSelect={(value) => {
173
- setLabel(value)
174
- setOpenDropdown(false)
175
- }}
176
- >
177
- {label}
178
- </CommandPaletteItem>
179
- ))}
180
- </DropdownMenuGroup>
181
- </CommandPaletteList>
182
- </CommandPalette>
183
- </DropdownMenuSubContent>
184
- </DropdownMenuSub>
185
- <DropdownMenuSeparator />
186
- <DropdownMenuItem className="text-red-600">
187
- Delete
188
- <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
189
- </DropdownMenuItem>
190
- </DropdownMenuGroup>
191
- </DropdownMenuContent>
192
- </DropdownMenu>
193
- </div>
194
- </div>
195
- )
196
- }
197
-
198
- export const WithDropdownMenu: Story = {
199
- parameters: {
200
- docs: {
201
- description: {
202
- story: 'A combobox integrated within a dropdown menu for label selection with project management actions.',
203
- },
204
- },
205
- },
206
- render: () => <DropdownMenuComboboxExample />,
207
- }
@@ -1,79 +0,0 @@
1
- import { CaretSortIcon, CheckIcon } from '@radix-ui/react-icons'
2
-
3
- import * as React from 'react'
4
-
5
- import { Button } from '@components/ui/button/button'
6
- import {
7
- CommandPalette,
8
- CommandPaletteEmpty,
9
- CommandPaletteGroup,
10
- CommandPaletteInput,
11
- CommandPaletteItem,
12
- CommandPaletteList,
13
- } from '@components/ui/command-palette/command-palette'
14
- import { Popover, PopoverContent, PopoverTrigger } from '@components/ui/popover/popover'
15
- import { cn } from '@lib/utils'
16
-
17
- const frameworks = [
18
- {
19
- value: 'next.js',
20
- label: 'Next.js',
21
- },
22
- {
23
- value: 'sveltekit',
24
- label: 'SvelteKit',
25
- },
26
- {
27
- value: 'nuxt.js',
28
- label: 'Nuxt.js',
29
- },
30
- {
31
- value: 'remix',
32
- label: 'Remix',
33
- },
34
- {
35
- value: 'astro',
36
- label: 'Astro',
37
- },
38
- ]
39
-
40
- export function ComboboxDemo() {
41
- const [open, setOpen] = React.useState(false)
42
- const [value, setValue] = React.useState('')
43
-
44
- return (
45
- <Popover open={open} onOpenChange={setOpen}>
46
- <PopoverTrigger asChild>
47
- <Button variant="outline" aria-expanded={open} className="w-[200px] justify-between">
48
- {value ? frameworks.find((framework) => framework.value === value)?.label : 'Select framework...'}
49
- <CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
50
- </Button>
51
- </PopoverTrigger>
52
- <PopoverContent className="w-[200px] p-0">
53
- <CommandPalette>
54
- <CommandPaletteInput placeholder="Search framework..." className="h-9" />
55
- <CommandPaletteList>
56
- <CommandPaletteEmpty>No framework found.</CommandPaletteEmpty>
57
- <CommandPaletteGroup>
58
- {frameworks.map((framework) => (
59
- <CommandPaletteItem
60
- key={framework.value}
61
- value={framework.value}
62
- onSelect={(currentValue) => {
63
- setValue(currentValue === value ? '' : currentValue)
64
- setOpen(false)
65
- }}
66
- >
67
- {framework.label}
68
- <CheckIcon
69
- className={cn('ml-auto h-4 w-4', value === framework.value ? 'opacity-100' : 'opacity-0')}
70
- />
71
- </CommandPaletteItem>
72
- ))}
73
- </CommandPaletteGroup>
74
- </CommandPaletteList>
75
- </CommandPalette>
76
- </PopoverContent>
77
- </Popover>
78
- )
79
- }
@@ -1,186 +0,0 @@
1
- import type { StoryObj } from '@storybook/react-vite'
2
-
3
- import {
4
- Command,
5
- CommandEmpty,
6
- CommandInput,
7
- CommandItem,
8
- CommandList,
9
- CommandGroup,
10
- CommandSeparator,
11
- CommandShortcut,
12
- CommandInputProps,
13
- } from './command'
14
- import { expect, userEvent, waitFor, screen } from 'storybook/test'
15
- import { useState } from 'storybook/preview-api'
16
-
17
- const CommandWithInput = ({
18
- variant: inputVariant,
19
- inputSize,
20
- showContent = true,
21
- searchValue,
22
- setSearchValue,
23
- placeholder,
24
- ...rest
25
- }: CommandProps & { showContent?: boolean } & { searchValue?: string } & {
26
- setSearchValue?: (val: string) => void
27
- }) => (
28
- <Command {...rest} className="w-[250px] border">
29
- <CommandInput
30
- placeholder={placeholder}
31
- variant={inputVariant}
32
- inputSize={inputSize}
33
- value={searchValue}
34
- onValueChange={(val) => {
35
- setSearchValue?.(val)
36
- }}
37
- />
38
- {showContent && (
39
- <CommandList>
40
- <CommandEmpty>No results found.</CommandEmpty>
41
- <CommandGroup heading="Category 1">
42
- <CommandItem>
43
- <span>Item</span>
44
- </CommandItem>
45
- <CommandItem disabled>
46
- <span>Disabled item</span>
47
- </CommandItem>
48
- </CommandGroup>
49
- <CommandSeparator />
50
- <CommandGroup heading="Category 2">
51
- <CommandItem>
52
- <span>With shortcut</span>
53
- <CommandShortcut>⌘P (only visually)</CommandShortcut>
54
- </CommandItem>
55
- </CommandGroup>
56
- </CommandList>
57
- )}
58
- </Command>
59
- )
60
-
61
- const meta = {
62
- title: 'Command',
63
- component: CommandWithInput,
64
- tags: ['autodocs'],
65
- parameters: {
66
- layout: 'centered',
67
- },
68
- argTypes: {
69
- inputVariant: {
70
- control: 'select',
71
- options: ['default', 'borderless'],
72
- },
73
- inputSize: {
74
- control: 'select',
75
- options: ['md', 'sm', 'lg'],
76
- },
77
- },
78
- }
79
- export default meta
80
-
81
- interface CommandStoryArgs {
82
- inputVariant?: 'default' | 'borderless'
83
- inputSize?: 'md' | 'sm' | 'lg'
84
- }
85
-
86
- type Story = StoryObj<CommandStoryArgs>
87
-
88
- type CommandProps = CommandInputProps &
89
- React.ComponentProps<typeof Command> & {
90
- inputVariant?: 'default' | 'borderless'
91
- }
92
-
93
- export const Default: Story = {
94
- render: (args) => (
95
- <CommandWithInput
96
- variant={args.inputVariant}
97
- inputSize={args.inputSize}
98
- placeholder="Command with border and w-[250px]"
99
- />
100
- ),
101
- }
102
-
103
- export const InputVariants: Story = {
104
- render: () => (
105
- <div className="flex flex-wrap gap-4">
106
- <CommandWithInput variant="default" inputSize="md" placeholder="Command with border and w-[250px]" />
107
- <CommandWithInput variant="borderless" inputSize="md" placeholder="Command with border and w-[250px]" />
108
- </div>
109
- ),
110
- }
111
-
112
- export const InputSizes: Story = {
113
- render: () => (
114
- <div className="flex flex-wrap gap-4 items-center">
115
- <CommandWithInput
116
- variant="borderless"
117
- inputSize="sm"
118
- showContent={false}
119
- placeholder="Command with border and w-[250px]"
120
- />
121
- <CommandWithInput
122
- variant="borderless"
123
- inputSize="md"
124
- showContent={false}
125
- placeholder="Command with border and w-[250px]"
126
- />
127
- <CommandWithInput
128
- variant="borderless"
129
- inputSize="lg"
130
- showContent={false}
131
- placeholder="Command with border and w-[250px]"
132
- />
133
- </div>
134
- ),
135
- }
136
-
137
- export const InteractiveExample: Story = {
138
- render: () => {
139
- const [open, setOpen] = useState(false)
140
- const [searchValue, setSearchValue] = useState('')
141
- return (
142
- <CommandWithInput
143
- variant={open ? 'default' : 'borderless'}
144
- inputSize="md"
145
- placeholder="Type a command or search..."
146
- searchValue={searchValue}
147
- setSearchValue={(val) => {
148
- setSearchValue(val)
149
- }}
150
- showContent={open}
151
- onBlur={() => {
152
- setOpen(false)
153
- setSearchValue('')
154
- }}
155
- onFocus={() => setOpen(true)}
156
- />
157
- )
158
- },
159
- play: async () => {
160
- const input = screen.getByPlaceholderText('Type a command or search...')
161
-
162
- // 1. Dropdown should be closed initially
163
- await expect(screen.queryByText('Category 1')).toBeNull()
164
- // 2. Focus input, dropdown opens
165
- await userEvent.click(input)
166
- // await expect(await screen.findByText('Category 1')).toBeVisible()
167
- // 3. Type to filter items
168
- await userEvent.type(input, 'Item')
169
- // await expect(await screen.findByText('Item')).toBeVisible()
170
- await expect(screen.queryByText('With shortcut')).toBeNull()
171
- // 4. Clear input, all items visible again
172
- await userEvent.clear(input)
173
- // await expect(await screen.findByText('Category 1')).toBeVisible()
174
- // await expect(await screen.findByText('With shortcut')).toBeVisible()
175
- // 5. Blur input, dropdown closes
176
- await userEvent.tab()
177
- await waitFor(() => {
178
- const el = screen.queryByText('Category 1')
179
- expect(!el || el.getAttribute('aria-hidden') === 'true').toBe(true)
180
- })
181
- // 6. check that value is reset correctly
182
- const inputField = screen.getByPlaceholderText('Type a command or search...')
183
- await expect(inputField).toHaveValue('')
184
- await expect(inputField).not.toHaveFocus()
185
- },
186
- }
@@ -1,165 +0,0 @@
1
- import { MagnifyingGlassIcon } from '@radix-ui/react-icons'
2
-
3
- import { cva, type VariantProps } from 'class-variance-authority'
4
- import { Command as CommandPrimitive } from 'cmdk'
5
- import React from 'react'
6
-
7
- import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@components/ui/dialog/dialog'
8
- import { cn } from '@lib/utils'
9
-
10
- function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>) {
11
- return (
12
- <CommandPrimitive
13
- data-slot="command"
14
- className={cn(
15
- 'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md',
16
- className,
17
- )}
18
- {...props}
19
- />
20
- )
21
- }
22
-
23
- function CommandDialog({
24
- title = 'Command Palette',
25
- description = 'Search for a command to run...',
26
- children,
27
- className,
28
- showCloseButton = true,
29
- ...props
30
- }: React.ComponentProps<typeof Dialog> & {
31
- title?: string
32
- description?: string
33
- className?: string
34
- showCloseButton?: boolean
35
- }) {
36
- return (
37
- <Dialog {...props}>
38
- <DialogHeader className="sr-only">
39
- <DialogTitle>{title}</DialogTitle>
40
- <DialogDescription>{description}</DialogDescription>
41
- </DialogHeader>
42
- <DialogContent className={cn('overflow-hidden p-0', className)} showCloseButton={showCloseButton}>
43
- <Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
44
- {children}
45
- </Command>
46
- </DialogContent>
47
- </Dialog>
48
- )
49
- }
50
-
51
- const commandInputVariants = cva('', {
52
- variants: {
53
- variant: { default: '', borderless: 'border-none' },
54
- inputSize: {
55
- sm: 'h-7.5 py-2',
56
- md: 'h-9 py-3',
57
- lg: 'h-12 py-4',
58
- },
59
- },
60
- defaultVariants: { variant: 'default', inputSize: 'md' },
61
- })
62
-
63
- export type CommandInputProps = Omit<React.ComponentProps<typeof CommandPrimitive.Input>, 'size'> &
64
- VariantProps<typeof commandInputVariants> & {
65
- wrapperClassName?: string
66
- }
67
-
68
- export const CommandInput = React.forwardRef<HTMLInputElement, CommandInputProps>(
69
- ({ className, wrapperClassName, variant, inputSize, ...props }, ref) => {
70
- return (
71
- <div
72
- data-slot="command-input-wrapper"
73
- className={cn(
74
- 'flex items-center gap-2 border-b px-3',
75
- commandInputVariants({ variant, inputSize }),
76
- wrapperClassName,
77
- )}
78
- >
79
- <MagnifyingGlassIcon className="size-4 shrink-0 opacity-50" />
80
- <CommandPrimitive.Input
81
- ref={ref}
82
- data-slot="command-input"
83
- className={cn(
84
- 'placeholder:text-muted-foreground flex w-full rounded bg-transparent text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
85
- className,
86
- )}
87
- {...props}
88
- />
89
- </div>
90
- )
91
- },
92
- )
93
- CommandInput.displayName = 'CommandInput'
94
-
95
- function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>) {
96
- return (
97
- <CommandPrimitive.List
98
- data-slot="command-list"
99
- className={cn('max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto', className)}
100
- {...props}
101
- />
102
- )
103
- }
104
-
105
- function CommandEmpty({ ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
106
- return <CommandPrimitive.Empty data-slot="command-empty" className="py-6 text-center text-sm" {...props} />
107
- }
108
-
109
- function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>) {
110
- return (
111
- <CommandPrimitive.Group
112
- data-slot="command-group"
113
- className={cn(
114
- 'text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium',
115
- className,
116
- )}
117
- {...props}
118
- />
119
- )
120
- }
121
-
122
- function CommandSeparator({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
123
- return (
124
- <CommandPrimitive.Separator
125
- data-slot="command-separator"
126
- className={cn('bg-border -mx-1 h-px', className)}
127
- {...props}
128
- />
129
- )
130
- }
131
-
132
- function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {
133
- return (
134
- <CommandPrimitive.Item
135
- data-slot="command-item"
136
- className={cn(
137
- "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
138
- className,
139
- )}
140
- {...props}
141
- />
142
- )
143
- }
144
-
145
- function CommandShortcut({ className, ...props }: React.ComponentProps<'span'>) {
146
- return (
147
- <span
148
- data-slot="command-shortcut"
149
- className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
150
- {...props}
151
- />
152
- )
153
- }
154
-
155
- export {
156
- Command,
157
- CommandDialog,
158
- commandInputVariants,
159
- CommandList,
160
- CommandEmpty,
161
- CommandGroup,
162
- CommandItem,
163
- CommandShortcut,
164
- CommandSeparator,
165
- }