@postxl/generators 1.1.1 → 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 (161) hide show
  1. package/dist/frontend-core/frontend.generator.d.ts +0 -58
  2. package/dist/frontend-core/frontend.generator.js +6 -172
  3. package/dist/frontend-core/frontend.generator.js.map +1 -1
  4. package/dist/frontend-core/template/README.md +1 -1
  5. package/dist/frontend-core/template/src/components/admin/table-filter.tsx +1 -5
  6. package/dist/frontend-core/template/src/components/ui/color-mode-toggle/color-mode-toggle.tsx +10 -4
  7. package/dist/frontend-core/template/src/pages/dashboard/dashboard.page.tsx +2 -3
  8. package/dist/frontend-core/template/src/pages/error/default-error.page.tsx +1 -1
  9. package/dist/frontend-core/template/src/pages/error/not-found-error.page.tsx +1 -1
  10. package/dist/frontend-core/template/src/styles/styles.css +13 -1
  11. package/dist/frontend-core/template/tsconfig.json +2 -0
  12. package/dist/frontend-core/types/component.d.ts +1 -1
  13. package/dist/frontend-forms/generators/discriminated-union/fields.generator.js +4 -6
  14. package/dist/frontend-forms/generators/discriminated-union/fields.generator.js.map +1 -1
  15. package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js +1 -1
  16. package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js.map +1 -1
  17. package/dist/frontend-forms/generators/enum/inputs.generator.js +1 -1
  18. package/dist/frontend-forms/generators/enum/inputs.generator.js.map +1 -1
  19. package/dist/frontend-forms/generators/model/forms.generator.js +8 -12
  20. package/dist/frontend-forms/generators/model/forms.generator.js.map +1 -1
  21. package/dist/frontend-forms/generators/model/inputs.generator.js +2 -6
  22. package/dist/frontend-forms/generators/model/inputs.generator.js.map +1 -1
  23. package/dist/frontend-forms/template/src/components/ui/field/field.tsx +1 -4
  24. package/dist/frontend-tables/generators/model-table.generator.js +1 -5
  25. package/dist/frontend-tables/generators/model-table.generator.js.map +1 -1
  26. package/package.json +3 -2
  27. package/dist/frontend-core/template/src/components/ui/accordion/accordion.stories.tsx +0 -47
  28. package/dist/frontend-core/template/src/components/ui/accordion/accordion.tsx +0 -52
  29. package/dist/frontend-core/template/src/components/ui/admin-sidebar/admin-sidebar.tsx +0 -195
  30. package/dist/frontend-core/template/src/components/ui/alert/alert.stories.tsx +0 -61
  31. package/dist/frontend-core/template/src/components/ui/alert/alert.tsx +0 -45
  32. package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.stories.tsx +0 -52
  33. package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.tsx +0 -105
  34. package/dist/frontend-core/template/src/components/ui/avatar/avatar.stories.tsx +0 -30
  35. package/dist/frontend-core/template/src/components/ui/avatar/avatar.tsx +0 -39
  36. package/dist/frontend-core/template/src/components/ui/badge/badge.stories.tsx +0 -78
  37. package/dist/frontend-core/template/src/components/ui/badge/badge.tsx +0 -48
  38. package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.stories.tsx +0 -67
  39. package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.tsx +0 -85
  40. package/dist/frontend-core/template/src/components/ui/button/button.stories.tsx +0 -150
  41. package/dist/frontend-core/template/src/components/ui/button/button.tsx +0 -68
  42. package/dist/frontend-core/template/src/components/ui/calendar/calendar.stories.tsx +0 -160
  43. package/dist/frontend-core/template/src/components/ui/calendar/calendar.tsx +0 -293
  44. package/dist/frontend-core/template/src/components/ui/card/card.stories.tsx +0 -77
  45. package/dist/frontend-core/template/src/components/ui/card/card.tsx +0 -45
  46. package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.stories.tsx +0 -29
  47. package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.tsx +0 -28
  48. package/dist/frontend-core/template/src/components/ui/carousel/carousel.stories.tsx +0 -154
  49. package/dist/frontend-core/template/src/components/ui/carousel/carousel.tsx +0 -227
  50. package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.stories.tsx +0 -106
  51. package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.tsx +0 -88
  52. package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.stories.tsx +0 -90
  53. package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.tsx +0 -54
  54. package/dist/frontend-core/template/src/components/ui/collapse/collapse.stories.tsx +0 -52
  55. package/dist/frontend-core/template/src/components/ui/collapse/collapse.tsx +0 -9
  56. package/dist/frontend-core/template/src/components/ui/combobox/combobox.stories.tsx +0 -207
  57. package/dist/frontend-core/template/src/components/ui/combobox/combobox.tsx +0 -79
  58. package/dist/frontend-core/template/src/components/ui/command/command.stories.tsx +0 -186
  59. package/dist/frontend-core/template/src/components/ui/command/command.tsx +0 -165
  60. package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.stories.tsx +0 -160
  61. package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.tsx +0 -134
  62. package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.stories.tsx +0 -198
  63. package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.tsx +0 -100
  64. package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.stories.tsx +0 -78
  65. package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.tsx +0 -179
  66. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/cell-variant-types.ts +0 -11
  67. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/checkbox-cell.tsx +0 -116
  68. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/date-cell.tsx +0 -157
  69. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/gantt-cell.tsx +0 -82
  70. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/long-text-cell.tsx +0 -180
  71. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/multi-select-cell.tsx +0 -280
  72. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/number-cell.tsx +0 -169
  73. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/react-node-cell.tsx +0 -33
  74. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/select-cell.tsx +0 -175
  75. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/short-text-cell.tsx +0 -138
  76. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timeline.tsx +0 -92
  77. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timerange-picker.tsx +0 -330
  78. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell-wrapper.tsx +0 -212
  79. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell.tsx +0 -157
  80. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-column-header.tsx +0 -340
  81. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-context-menu.tsx +0 -271
  82. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-row.tsx +0 -123
  83. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-search.tsx +0 -211
  84. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-types.ts +0 -159
  85. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-utils.ts +0 -67
  86. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-view-menu.tsx +0 -360
  87. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.stories.tsx +0 -780
  88. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.tsx +0 -217
  89. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-callback-ref.ts +0 -22
  90. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-data-grid.tsx +0 -1892
  91. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-debounced-callback.ts +0 -19
  92. package/dist/frontend-core/template/src/components/ui/data-grid/styles.css +0 -3
  93. package/dist/frontend-core/template/src/components/ui/data-table/context-menu-simple.tsx +0 -141
  94. package/dist/frontend-core/template/src/components/ui/data-table/data-table.stories.tsx +0 -146
  95. package/dist/frontend-core/template/src/components/ui/data-table/data-table.tsx +0 -447
  96. package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-array-cell-renderer.tsx +0 -77
  97. package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-cell-renderer.tsx +0 -56
  98. package/dist/frontend-core/template/src/components/ui/data-table/renderers/favorite-cell-renderer.tsx +0 -68
  99. package/dist/frontend-core/template/src/components/ui/data-table/renderers/links-cell-renderer.tsx +0 -205
  100. package/dist/frontend-core/template/src/components/ui/data-table/utils/columns.ts +0 -351
  101. package/dist/frontend-core/template/src/components/ui/data-table/utils/data-table.utils.ts +0 -49
  102. package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.stories.tsx +0 -149
  103. package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.tsx +0 -30
  104. package/dist/frontend-core/template/src/components/ui/dialog/dialog.stories.tsx +0 -80
  105. package/dist/frontend-core/template/src/components/ui/dialog/dialog.tsx +0 -134
  106. package/dist/frontend-core/template/src/components/ui/drawer/drawer.stories.tsx +0 -104
  107. package/dist/frontend-core/template/src/components/ui/drawer/drawer.tsx +0 -87
  108. package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.stories.tsx +0 -168
  109. package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.tsx +0 -225
  110. package/dist/frontend-core/template/src/components/ui/input/input.stories.tsx +0 -141
  111. package/dist/frontend-core/template/src/components/ui/input/input.tsx +0 -47
  112. package/dist/frontend-core/template/src/components/ui/label/label.stories.tsx +0 -41
  113. package/dist/frontend-core/template/src/components/ui/label/label.tsx +0 -20
  114. package/dist/frontend-core/template/src/components/ui/loader/loader.stories.tsx +0 -45
  115. package/dist/frontend-core/template/src/components/ui/loader/loader.tsx +0 -17
  116. package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.stories.tsx +0 -114
  117. package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.tsx +0 -48
  118. package/dist/frontend-core/template/src/components/ui/menubar/menu.stories.tsx +0 -134
  119. package/dist/frontend-core/template/src/components/ui/menubar/menubar.tsx +0 -208
  120. package/dist/frontend-core/template/src/components/ui/modal/modal.stories.tsx +0 -297
  121. package/dist/frontend-core/template/src/components/ui/modal/modal.tsx +0 -80
  122. package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.stories.tsx +0 -213
  123. package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.tsx +0 -142
  124. package/dist/frontend-core/template/src/components/ui/pagination/pagination.stories.tsx +0 -49
  125. package/dist/frontend-core/template/src/components/ui/pagination/pagination.tsx +0 -84
  126. package/dist/frontend-core/template/src/components/ui/popover/popover.stories.tsx +0 -82
  127. package/dist/frontend-core/template/src/components/ui/popover/popover.tsx +0 -55
  128. package/dist/frontend-core/template/src/components/ui/progress/progress.stories.tsx +0 -80
  129. package/dist/frontend-core/template/src/components/ui/progress/progress.tsx +0 -17
  130. package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.stories.tsx +0 -154
  131. package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.tsx +0 -68
  132. package/dist/frontend-core/template/src/components/ui/resizable/resizable.stories.tsx +0 -73
  133. package/dist/frontend-core/template/src/components/ui/resizable/resizeable.tsx +0 -38
  134. package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.stories.tsx +0 -55
  135. package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.tsx +0 -39
  136. package/dist/frontend-core/template/src/components/ui/select/select.stories.tsx +0 -297
  137. package/dist/frontend-core/template/src/components/ui/select/select.tsx +0 -227
  138. package/dist/frontend-core/template/src/components/ui/separator/separator.tsx +0 -21
  139. package/dist/frontend-core/template/src/components/ui/separator/seperator.stories.tsx +0 -25
  140. package/dist/frontend-core/template/src/components/ui/sheet/sheet.stories.tsx +0 -45
  141. package/dist/frontend-core/template/src/components/ui/sheet/sheet.tsx +0 -107
  142. package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.stories.tsx +0 -26
  143. package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.tsx +0 -7
  144. package/dist/frontend-core/template/src/components/ui/slider/slider.stories.tsx +0 -101
  145. package/dist/frontend-core/template/src/components/ui/slider/slider.tsx +0 -98
  146. package/dist/frontend-core/template/src/components/ui/spinner/spinner.stories.tsx +0 -19
  147. package/dist/frontend-core/template/src/components/ui/spinner/spinner.tsx +0 -21
  148. package/dist/frontend-core/template/src/components/ui/switch/switch.stories.tsx +0 -33
  149. package/dist/frontend-core/template/src/components/ui/switch/switch.tsx +0 -28
  150. package/dist/frontend-core/template/src/components/ui/tabs/tabs.stories.tsx +0 -215
  151. package/dist/frontend-core/template/src/components/ui/tabs/tabs.tsx +0 -70
  152. package/dist/frontend-core/template/src/components/ui/textarea/textarea.stories.tsx +0 -138
  153. package/dist/frontend-core/template/src/components/ui/textarea/textarea.tsx +0 -40
  154. package/dist/frontend-core/template/src/components/ui/toast/toast.mdx +0 -31
  155. package/dist/frontend-core/template/src/components/ui/toast/toast.stories.tsx +0 -89
  156. package/dist/frontend-core/template/src/components/ui/toggle/toggle.stories.tsx +0 -65
  157. package/dist/frontend-core/template/src/components/ui/toggle/toggle.tsx +0 -38
  158. package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.stories.tsx +0 -85
  159. package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.tsx +0 -54
  160. package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.stories.tsx +0 -29
  161. package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.tsx +0 -29
@@ -1,168 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite'
2
- import { SunIcon, ChevronUpIcon, ChevronDownIcon } from '@radix-ui/react-icons'
3
- import { expect, userEvent, screen, waitFor } from 'storybook/test'
4
- import { useState } from 'react'
5
- import {
6
- DropdownMenu,
7
- DropdownMenuPortal,
8
- DropdownMenuTrigger,
9
- DropdownMenuContent,
10
- DropdownMenuGroup,
11
- DropdownMenuLabel,
12
- DropdownMenuItem,
13
- DropdownMenuSeparator,
14
- DropdownMenuShortcut,
15
- DropdownMenuSub,
16
- DropdownMenuSubTrigger,
17
- DropdownMenuSubContent,
18
- } from './dropdown-menu'
19
- import { Button } from '@components/ui/button/button'
20
- import { Label } from '@components/ui/label/label'
21
- import { Checkbox } from '@components/ui/checkbox/checkbox'
22
- import { Input } from '@components/ui/input/input'
23
-
24
- const meta = {
25
- title: 'DropdownMenu',
26
- component: DropdownMenu,
27
- tags: ['autodocs'],
28
- parameters: {
29
- layout: 'centered',
30
- },
31
- argTypes: {},
32
- } satisfies Meta<typeof DropdownMenu>
33
- export default meta
34
-
35
- type Story = StoryObj<typeof meta>
36
-
37
- export const Default: Story = {
38
- render: () => (
39
- <div data-testid="outside-click-for-test" className="pointer-events-auto">
40
- <DropdownMenu>
41
- <DropdownMenuTrigger asChild>
42
- <Button variant="outline">Open dropdown</Button>
43
- </DropdownMenuTrigger>
44
- <DropdownMenuContent className="w-[250px]" align="start">
45
- <DropdownMenuLabel>Category 1</DropdownMenuLabel>
46
- <DropdownMenuGroup>
47
- <DropdownMenuItem>Item 1</DropdownMenuItem>
48
- <DropdownMenuItem>
49
- Item 2<DropdownMenuShortcut>⌘P (only visually)</DropdownMenuShortcut>
50
- </DropdownMenuItem>
51
- </DropdownMenuGroup>
52
- <DropdownMenuSeparator />
53
- <DropdownMenuGroup>
54
- <DropdownMenuSub>
55
- <DropdownMenuSubTrigger>Sub menu trigger</DropdownMenuSubTrigger>
56
- <DropdownMenuPortal>
57
- <DropdownMenuSubContent>
58
- <DropdownMenuItem>Sub Item 1</DropdownMenuItem>
59
- <DropdownMenuSeparator />
60
- <DropdownMenuItem>More... (just another item)</DropdownMenuItem>
61
- </DropdownMenuSubContent>
62
- </DropdownMenuPortal>
63
- </DropdownMenuSub>
64
- <DropdownMenuItem disabled>Disabled</DropdownMenuItem>
65
- <div className="flex items-center justify-center gap-3 mt-5">
66
- <span>or just use custom content instead of the DropdownMenuItems</span>
67
- <SunIcon className="size-15 text-yellow-500" />
68
- </div>
69
- </DropdownMenuGroup>
70
- </DropdownMenuContent>
71
- </DropdownMenu>
72
- </div>
73
- ),
74
- play: async () => {
75
- await userEvent.click(screen.getByText('Open dropdown'))
76
- const item1 = await screen.findByText('Item 1')
77
- await waitFor(() => {
78
- const style = window.getComputedStyle(item1)
79
- expect(style.visibility).toBe('visible')
80
- expect(Number(style.opacity)).toBeGreaterThan(0)
81
- })
82
- await userEvent.click(screen.getByTestId('outside-click-for-test'))
83
- await waitFor(() => {
84
- expect(screen.queryByText('Item 1')).toBeNull()
85
- })
86
- await userEvent.keyboard('{Escape}')
87
- await waitFor(() => {
88
- expect(screen.queryByText('Item 1')).toBeNull()
89
- })
90
- },
91
- }
92
-
93
- export const ExampleDropdownSearchableSelection: Story = {
94
- render: () => {
95
- const dummyUsers = [
96
- { id: '1', name: 'alice@wonderland.net' },
97
- { id: '2', name: 'bob.builder@kika.de' },
98
- { id: '3', name: 'charlie.bucket@chocolate-factory.com' },
99
- ]
100
- const [menuOpen, setMenuOpen] = useState(false)
101
- const [userFilterValue, setUserFilterValue] = useState('')
102
- const [selectedUserIds, setSelectedUserIds] = useState<string[]>([])
103
-
104
- const filteredUserData = dummyUsers.filter((user) =>
105
- user.name.toLowerCase().includes(userFilterValue.toLowerCase()),
106
- )
107
-
108
- const handleCheckboxChange = (userId: string) => {
109
- setSelectedUserIds((prev) => (prev.includes(userId) ? prev.filter((id) => id !== userId) : [...prev, userId]))
110
- }
111
-
112
- return (
113
- <div className="w-[180px]">
114
- <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>
115
- <DropdownMenuTrigger asChild>
116
- <Button
117
- variant="outline"
118
- size="sm"
119
- className="group w-full flex items-center justify-between disabled:text-muted-foreground border-input hover:bg-muted-foreground hover:text-background"
120
- >
121
- <span className="mx-auto">
122
- {selectedUserIds.length === 0
123
- ? 'Select specific users'
124
- : `${selectedUserIds.length} user${selectedUserIds.length > 1 ? 's' : ''} selected`}
125
- </span>
126
- {menuOpen ? (
127
- <ChevronUpIcon className="size-4 opacity-50 text-muted-foreground group-hover:text-background" />
128
- ) : (
129
- <ChevronDownIcon className="size-4 opacity-50 group-hover:opacity-100 text-muted-foreground group-hover:text-background" />
130
- )}
131
- </Button>
132
- </DropdownMenuTrigger>
133
- <DropdownMenuContent align="start" className="w-[280px] flex flex-col p-0 border-(--discreet-border)">
134
- <Input
135
- className=" rounded-none border-0 border-b-1"
136
- variant="simple"
137
- placeholder="Search users"
138
- value={userFilterValue}
139
- onChange={(e) => setUserFilterValue(e.target.value)}
140
- />
141
- <div className="p-1">
142
- {filteredUserData.length > 0 ? (
143
- filteredUserData.map((user) => (
144
- <div key={user.id} className="flex hover:bg-accent py-1 px-2 rounded items-center gap-2">
145
- <Checkbox
146
- checked={selectedUserIds.includes(user.id)}
147
- onChange={() => handleCheckboxChange(user.id)}
148
- id={`user-${user.id}`}
149
- variant="iconSolo"
150
- checkboxSize="lg"
151
- checkIcon="check"
152
- iconStyle="solo"
153
- />
154
- <Label htmlFor={`user-${user.id}`} className="cursor-pointer">
155
- {user.name}
156
- </Label>
157
- </div>
158
- ))
159
- ) : (
160
- <p className="text-center text-muted-foreground py-3">no results found</p>
161
- )}
162
- </div>
163
- </DropdownMenuContent>
164
- </DropdownMenu>
165
- </div>
166
- )
167
- },
168
- }
@@ -1,225 +0,0 @@
1
- import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
2
- import { CheckIcon, ChevronRightIcon, CircleIcon } from '@radix-ui/react-icons'
3
-
4
- import * as React from 'react'
5
-
6
- import { cn } from '@lib/utils'
7
-
8
- function DropdownMenu({ ...props }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.Root>>) {
9
- return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
10
- }
11
-
12
- function DropdownMenuPortal({ ...props }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.Portal>>) {
13
- return <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
14
- }
15
-
16
- function DropdownMenuTrigger({ ...props }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>>) {
17
- return <DropdownMenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />
18
- }
19
-
20
- function DropdownMenuContent({
21
- className,
22
- sideOffset = 4,
23
- ...props
24
- }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.Content>>) {
25
- return (
26
- <DropdownMenuPrimitive.Portal>
27
- <DropdownMenuPrimitive.Content
28
- data-slot="dropdown-menu-content"
29
- sideOffset={sideOffset}
30
- className={cn(
31
- 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md',
32
- className,
33
- )}
34
- {...props}
35
- />
36
- </DropdownMenuPrimitive.Portal>
37
- )
38
- }
39
-
40
- function DropdownMenuGroup({ ...props }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.Group>>) {
41
- return <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
42
- }
43
-
44
- function DropdownMenuItem({
45
- className,
46
- inset,
47
- variant = 'default',
48
- ...props
49
- }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
50
- inset?: boolean
51
- variant?: 'default' | 'destructive'
52
- }) {
53
- return (
54
- <DropdownMenuPrimitive.Item
55
- data-slot="dropdown-menu-item"
56
- data-inset={inset}
57
- data-variant={variant}
58
- className={cn(
59
- "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_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]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
60
- className,
61
- )}
62
- {...props}
63
- />
64
- )
65
- }
66
-
67
- function DropdownMenuCheckboxItem({
68
- className,
69
- children,
70
- checked,
71
- ...props
72
- }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>>) {
73
- return (
74
- <DropdownMenuPrimitive.CheckboxItem
75
- data-slot="dropdown-menu-checkbox-item"
76
- className={cn(
77
- "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
78
- className,
79
- )}
80
- checked={checked}
81
- {...props}
82
- >
83
- <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
84
- <DropdownMenuPrimitive.ItemIndicator>
85
- <CheckIcon className="size-4" />
86
- </DropdownMenuPrimitive.ItemIndicator>
87
- </span>
88
- {children}
89
- </DropdownMenuPrimitive.CheckboxItem>
90
- )
91
- }
92
-
93
- function DropdownMenuRadioGroup({ ...props }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>>) {
94
- return <DropdownMenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />
95
- }
96
-
97
- function DropdownMenuRadioItem({
98
- className,
99
- children,
100
- ...props
101
- }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>>) {
102
- return (
103
- <DropdownMenuPrimitive.RadioItem
104
- data-slot="dropdown-menu-radio-item"
105
- className={cn(
106
- "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
107
- className,
108
- )}
109
- {...props}
110
- >
111
- <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
112
- <DropdownMenuPrimitive.ItemIndicator>
113
- <CircleIcon className="size-2 fill-current" />
114
- </DropdownMenuPrimitive.ItemIndicator>
115
- </span>
116
- {children}
117
- </DropdownMenuPrimitive.RadioItem>
118
- )
119
- }
120
-
121
- function DropdownMenuLabel({
122
- className,
123
- inset,
124
- ...props
125
- }: Readonly<
126
- React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
127
- inset?: boolean
128
- }
129
- >) {
130
- return (
131
- <DropdownMenuPrimitive.Label
132
- data-slot="dropdown-menu-label"
133
- data-inset={inset}
134
- className={cn('px-2 py-1.5 text-sm font-medium data-[inset]:pl-8', className)}
135
- {...props}
136
- />
137
- )
138
- }
139
-
140
- function DropdownMenuSeparator({
141
- className,
142
- ...props
143
- }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.Separator>>) {
144
- return (
145
- <DropdownMenuPrimitive.Separator
146
- data-slot="dropdown-menu-separator"
147
- className={cn('bg-border -mx-1 my-1 h-px', className)}
148
- {...props}
149
- />
150
- )
151
- }
152
-
153
- function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
154
- return (
155
- <span
156
- data-slot="dropdown-menu-shortcut"
157
- className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
158
- {...props}
159
- />
160
- )
161
- }
162
-
163
- function DropdownMenuSub({ ...props }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.Sub>>) {
164
- return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
165
- }
166
-
167
- function DropdownMenuSubTrigger({
168
- className,
169
- inset,
170
- children,
171
- ...props
172
- }: Readonly<
173
- React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
174
- inset?: boolean
175
- }
176
- >) {
177
- return (
178
- <DropdownMenuPrimitive.SubTrigger
179
- data-slot="dropdown-menu-sub-trigger"
180
- data-inset={inset}
181
- className={cn(
182
- 'focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8',
183
- className,
184
- )}
185
- {...props}
186
- >
187
- {children}
188
- <ChevronRightIcon className="ml-auto size-4" />
189
- </DropdownMenuPrimitive.SubTrigger>
190
- )
191
- }
192
-
193
- function DropdownMenuSubContent({
194
- className,
195
- ...props
196
- }: Readonly<React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>>) {
197
- return (
198
- <DropdownMenuPrimitive.SubContent
199
- data-slot="dropdown-menu-sub-content"
200
- className={cn(
201
- 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg',
202
- className,
203
- )}
204
- {...props}
205
- />
206
- )
207
- }
208
-
209
- export {
210
- DropdownMenu,
211
- DropdownMenuPortal,
212
- DropdownMenuTrigger,
213
- DropdownMenuContent,
214
- DropdownMenuGroup,
215
- DropdownMenuLabel,
216
- DropdownMenuItem,
217
- DropdownMenuCheckboxItem,
218
- DropdownMenuRadioGroup,
219
- DropdownMenuRadioItem,
220
- DropdownMenuSeparator,
221
- DropdownMenuShortcut,
222
- DropdownMenuSub,
223
- DropdownMenuSubTrigger,
224
- DropdownMenuSubContent,
225
- }
@@ -1,141 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite'
2
- import { useState } from 'react'
3
-
4
- import { Input } from './input'
5
- import { expect, userEvent, screen } from 'storybook/test'
6
- import { Button } from '@components/ui/button/button'
7
-
8
- const meta = {
9
- title: 'Input',
10
- component: Input,
11
- tags: ['autodocs'],
12
- parameters: {
13
- layout: 'centered',
14
- },
15
- argTypes: {
16
- variant: {
17
- control: 'select',
18
- options: ['default', 'simple'],
19
- },
20
- },
21
- } satisfies Meta<typeof Input>
22
- export default meta
23
-
24
- type Story = StoryObj<typeof meta>
25
-
26
- export const Default: Story = {
27
- args: { variant: 'default' },
28
- render: (args) => {
29
- const [value, setValue] = useState('')
30
- return (
31
- <div className="flex items-center gap-2">
32
- <Input
33
- placeholder="Enter text..."
34
- {...args}
35
- value={value}
36
- onChange={(e) => setValue(e.target.value)}
37
- className="w-[200px]"
38
- />
39
- <span data-testid="input-value">
40
- {value ? 'value: ' : ''}
41
- {value}
42
- </span>
43
- </div>
44
- )
45
- },
46
- play: async () => {
47
- const input = screen.getByPlaceholderText('Enter text...')
48
- await userEvent.type(input, 'test')
49
- const valueSpan = screen.getByTestId('input-value')
50
- expect(valueSpan).toHaveTextContent('test')
51
- },
52
- }
53
-
54
- export const Variants: Story = {
55
- render: () => (
56
- <div className="flex flex-wrap gap-2 items-center">
57
- <Input placeholder="default" variant="default" className="w-48" />
58
- <Input placeholder="simple" variant="simple" className="w-48" />
59
- </div>
60
- ),
61
- }
62
-
63
- export const Disabled: Story = {
64
- render: (args) => (
65
- <div className="flex flex-wrap gap-4 items-center">
66
- <Input disabled {...args} className="w-[200px]" placeholder="Disabled" />
67
- </div>
68
- ),
69
- }
70
-
71
- export const EmailForm: Story = {
72
- render: () => {
73
- const [value, setValue] = useState('')
74
- const [error, setError] = useState<string | null>(null)
75
- const [submitted, setSubmitted] = useState(false)
76
- const [touched, setTouched] = useState(false)
77
-
78
- function validateEmail(email: string) {
79
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
80
- }
81
-
82
- function validate(value: string) {
83
- if (!value) return 'Field is required.'
84
- if (!validateEmail(value)) return 'Not a valid email.'
85
- return null
86
- }
87
-
88
- const handleSubmit = (e: React.FormEvent) => {
89
- e.preventDefault()
90
- setSubmitted(true)
91
- setError(validate(value))
92
- }
93
-
94
- const handleBlur = () => {
95
- setTouched(true)
96
- setError(validate(value))
97
- }
98
-
99
- return (
100
- <form className="flex flex-col gap-2 items-center w-[350px]" onSubmit={handleSubmit} noValidate>
101
- <Input
102
- className="w-full"
103
- placeholder="Enter an email..."
104
- value={value}
105
- onChange={(e) => {
106
- setValue(e.target.value)
107
- if (submitted || touched) setError(validate(e.target.value))
108
- }}
109
- onBlur={handleBlur}
110
- aria-invalid={!!error}
111
- />
112
- {error && (touched || submitted) && (
113
- <span className="text-destructive mt-1" role="alert">
114
- {error}
115
- </span>
116
- )}
117
- <Button type="submit" size="smLow">
118
- Submit
119
- </Button>
120
- </form>
121
- )
122
- },
123
- play: async () => {
124
- const input = screen.getByPlaceholderText('Enter an email...')
125
- const submitButton = screen.getByRole('button', { name: /submit/i })
126
-
127
- // Submit with empty input
128
- await userEvent.clear(input)
129
- await userEvent.click(submitButton)
130
- await expect(await screen.findByRole('alert')).toHaveTextContent('Field is required.')
131
- // Enter invalid email and submit
132
- await userEvent.type(input, 'not-an-email')
133
- await userEvent.click(submitButton)
134
- await expect(await screen.findByRole('alert')).toHaveTextContent('Not a valid email.')
135
- // Enter valid email and submit
136
- await userEvent.clear(input)
137
- await userEvent.type(input, 'test@example.com')
138
- await userEvent.click(submitButton)
139
- await expect(screen.queryByRole('alert')).toBeNull()
140
- },
141
- }
@@ -1,47 +0,0 @@
1
- import { cva, type VariantProps } from 'class-variance-authority'
2
- import * as React from 'react'
3
-
4
- import { cn } from '@lib/utils'
5
-
6
- const inputVariants = cva(
7
- 'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
8
- {
9
- variants: {
10
- variant: {
11
- default: 'h-9 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
12
- simple: 'h-8',
13
- },
14
- },
15
- defaultVariants: {
16
- variant: 'default',
17
- },
18
- },
19
- )
20
-
21
- type InputProps = React.ComponentProps<'input'> &
22
- VariantProps<typeof inputVariants> & {
23
- /**
24
- * E2E test_id to identify the input.
25
- */
26
- __e2e_test_id__?: string
27
- onEnter?: () => void
28
- }
29
- function Input({ className, type, variant, __e2e_test_id__, onEnter, ...props }: InputProps) {
30
- return (
31
- <input
32
- type={type}
33
- data-slot="input"
34
- className={cn(inputVariants({ variant, className }))}
35
- data-test-id={__e2e_test_id__}
36
- onKeyDown={(e) => {
37
- props.onKeyDown?.(e)
38
- if (e.key === 'Enter') {
39
- onEnter?.()
40
- }
41
- }}
42
- {...props}
43
- />
44
- )
45
- }
46
-
47
- export { Input }
@@ -1,41 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite'
2
- import { expect, userEvent, screen } from 'storybook/test'
3
-
4
- import { Label } from './label'
5
- import { Checkbox } from '@components/ui/checkbox/shadcn-checkbox'
6
-
7
- const meta = {
8
- title: 'Label',
9
- component: Label,
10
- tags: ['autodocs'],
11
- parameters: {
12
- layout: 'centered',
13
- },
14
- } satisfies Meta<typeof Label>
15
- export default meta
16
-
17
- type Story = StoryObj<typeof meta>
18
-
19
- export const Default: Story = {
20
- render: () => <Label>Label</Label>,
21
- }
22
-
23
- export const Usage: Story = {
24
- render: () => (
25
- <div className="flex flex-wrap gap-2 items-center">
26
- <Checkbox id="label-1" />
27
- <Label htmlFor="label-1" className="cursor-pointer">
28
- Label for usage demonstration (click label to toggle checkbox)
29
- </Label>
30
- </div>
31
- ),
32
- play: async () => {
33
- const label = screen.getByText(/Label for usage demonstration/)
34
- const checkbox = screen.getByRole('checkbox')
35
- await expect(checkbox).not.toBeChecked()
36
- await userEvent.click(label)
37
- await expect(checkbox).toBeChecked()
38
- await userEvent.click(label)
39
- await expect(checkbox).not.toBeChecked()
40
- },
41
- }
@@ -1,20 +0,0 @@
1
- import * as LabelPrimitive from '@radix-ui/react-label'
2
-
3
- import * as React from 'react'
4
-
5
- import { cn } from '@lib/utils'
6
-
7
- function Label({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {
8
- return (
9
- <LabelPrimitive.Root
10
- data-slot="label"
11
- className={cn(
12
- 'flex items-center gap-2 text-base leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
13
- className,
14
- )}
15
- {...props}
16
- />
17
- )
18
- }
19
-
20
- export { Label }
@@ -1,45 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite'
2
-
3
- import { Loader } from './loader'
4
-
5
- const meta = {
6
- title: 'Loader',
7
- component: Loader,
8
- tags: ['autodocs'],
9
- parameters: {
10
- layout: 'centered',
11
- },
12
- argTypes: {
13
- label: {
14
- control: 'text',
15
- },
16
- },
17
- } satisfies Meta<typeof Loader>
18
- export default meta
19
-
20
- type Story = StoryObj<typeof meta>
21
-
22
- export const Default: Story = {
23
- args: { label: 'Loading...' },
24
- render: (args) => (
25
- <div className="relative w-[350px] h-[150px] border">
26
- <span>Background, loader is applied on, which gets dimmed</span>
27
- <br />
28
- <span>needs position relative for correct loader placement</span>
29
- <Loader {...args} />
30
- </div>
31
- ),
32
- // play: async () => {
33
- // // Check that the loader label is visible
34
- // expect(screen.getByText('Loading...')).toBeVisible()
35
- // const loaderLabel = screen.getByText('Loading...')
36
- // // Find the SVG spinner within the loader
37
- // const svg = loaderLabel.closest('div')?.querySelector('svg')
38
- // expect(svg).toBeTruthy()
39
- // expect(svg).toBeVisible()
40
- // // Check that the SVG size is greater than 0
41
- // const rect = svg?.getBoundingClientRect()
42
- // expect(rect?.width).toBeGreaterThan(0)
43
- // expect(rect?.height).toBeGreaterThan(0)
44
- // },
45
- }