@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.
- package/dist/frontend-core/frontend.generator.d.ts +0 -58
- package/dist/frontend-core/frontend.generator.js +6 -172
- package/dist/frontend-core/frontend.generator.js.map +1 -1
- package/dist/frontend-core/template/README.md +1 -1
- package/dist/frontend-core/template/src/components/admin/table-filter.tsx +1 -5
- package/dist/frontend-core/template/src/components/ui/color-mode-toggle/color-mode-toggle.tsx +10 -4
- package/dist/frontend-core/template/src/pages/dashboard/dashboard.page.tsx +2 -3
- package/dist/frontend-core/template/src/pages/error/default-error.page.tsx +1 -1
- package/dist/frontend-core/template/src/pages/error/not-found-error.page.tsx +1 -1
- package/dist/frontend-core/template/src/styles/styles.css +13 -1
- package/dist/frontend-core/template/tsconfig.json +2 -0
- package/dist/frontend-core/types/component.d.ts +1 -1
- package/dist/frontend-forms/generators/discriminated-union/fields.generator.js +4 -6
- package/dist/frontend-forms/generators/discriminated-union/fields.generator.js.map +1 -1
- package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js +1 -1
- package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js.map +1 -1
- package/dist/frontend-forms/generators/enum/inputs.generator.js +1 -1
- package/dist/frontend-forms/generators/enum/inputs.generator.js.map +1 -1
- package/dist/frontend-forms/generators/model/forms.generator.js +8 -12
- package/dist/frontend-forms/generators/model/forms.generator.js.map +1 -1
- package/dist/frontend-forms/generators/model/inputs.generator.js +2 -6
- package/dist/frontend-forms/generators/model/inputs.generator.js.map +1 -1
- package/dist/frontend-forms/template/src/components/ui/field/field.tsx +1 -4
- package/dist/frontend-tables/generators/model-table.generator.js +1 -5
- package/dist/frontend-tables/generators/model-table.generator.js.map +1 -1
- package/package.json +3 -2
- package/dist/frontend-core/template/src/components/ui/accordion/accordion.stories.tsx +0 -47
- package/dist/frontend-core/template/src/components/ui/accordion/accordion.tsx +0 -52
- package/dist/frontend-core/template/src/components/ui/admin-sidebar/admin-sidebar.tsx +0 -195
- package/dist/frontend-core/template/src/components/ui/alert/alert.stories.tsx +0 -61
- package/dist/frontend-core/template/src/components/ui/alert/alert.tsx +0 -45
- package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.stories.tsx +0 -52
- package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.tsx +0 -105
- package/dist/frontend-core/template/src/components/ui/avatar/avatar.stories.tsx +0 -30
- package/dist/frontend-core/template/src/components/ui/avatar/avatar.tsx +0 -39
- package/dist/frontend-core/template/src/components/ui/badge/badge.stories.tsx +0 -78
- package/dist/frontend-core/template/src/components/ui/badge/badge.tsx +0 -48
- package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.stories.tsx +0 -67
- package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.tsx +0 -85
- package/dist/frontend-core/template/src/components/ui/button/button.stories.tsx +0 -150
- package/dist/frontend-core/template/src/components/ui/button/button.tsx +0 -68
- package/dist/frontend-core/template/src/components/ui/calendar/calendar.stories.tsx +0 -160
- package/dist/frontend-core/template/src/components/ui/calendar/calendar.tsx +0 -293
- package/dist/frontend-core/template/src/components/ui/card/card.stories.tsx +0 -77
- package/dist/frontend-core/template/src/components/ui/card/card.tsx +0 -45
- package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.stories.tsx +0 -29
- package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.tsx +0 -28
- package/dist/frontend-core/template/src/components/ui/carousel/carousel.stories.tsx +0 -154
- package/dist/frontend-core/template/src/components/ui/carousel/carousel.tsx +0 -227
- package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.stories.tsx +0 -106
- package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.tsx +0 -88
- package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.stories.tsx +0 -90
- package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.tsx +0 -54
- package/dist/frontend-core/template/src/components/ui/collapse/collapse.stories.tsx +0 -52
- package/dist/frontend-core/template/src/components/ui/collapse/collapse.tsx +0 -9
- package/dist/frontend-core/template/src/components/ui/combobox/combobox.stories.tsx +0 -207
- package/dist/frontend-core/template/src/components/ui/combobox/combobox.tsx +0 -79
- package/dist/frontend-core/template/src/components/ui/command/command.stories.tsx +0 -186
- package/dist/frontend-core/template/src/components/ui/command/command.tsx +0 -165
- package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.stories.tsx +0 -160
- package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.tsx +0 -134
- package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.stories.tsx +0 -198
- package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.tsx +0 -100
- package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.stories.tsx +0 -78
- package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.tsx +0 -179
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/cell-variant-types.ts +0 -11
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/checkbox-cell.tsx +0 -116
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/date-cell.tsx +0 -157
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/gantt-cell.tsx +0 -82
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/long-text-cell.tsx +0 -180
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/multi-select-cell.tsx +0 -280
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/number-cell.tsx +0 -169
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/react-node-cell.tsx +0 -33
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/select-cell.tsx +0 -175
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/short-text-cell.tsx +0 -138
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timeline.tsx +0 -92
- package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timerange-picker.tsx +0 -330
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell-wrapper.tsx +0 -212
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell.tsx +0 -157
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-column-header.tsx +0 -340
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-context-menu.tsx +0 -271
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-row.tsx +0 -123
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-search.tsx +0 -211
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-types.ts +0 -159
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-utils.ts +0 -67
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-view-menu.tsx +0 -360
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.stories.tsx +0 -780
- package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.tsx +0 -217
- package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-callback-ref.ts +0 -22
- package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-data-grid.tsx +0 -1892
- package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-debounced-callback.ts +0 -19
- package/dist/frontend-core/template/src/components/ui/data-grid/styles.css +0 -3
- package/dist/frontend-core/template/src/components/ui/data-table/context-menu-simple.tsx +0 -141
- package/dist/frontend-core/template/src/components/ui/data-table/data-table.stories.tsx +0 -146
- package/dist/frontend-core/template/src/components/ui/data-table/data-table.tsx +0 -447
- package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-array-cell-renderer.tsx +0 -77
- package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-cell-renderer.tsx +0 -56
- package/dist/frontend-core/template/src/components/ui/data-table/renderers/favorite-cell-renderer.tsx +0 -68
- package/dist/frontend-core/template/src/components/ui/data-table/renderers/links-cell-renderer.tsx +0 -205
- package/dist/frontend-core/template/src/components/ui/data-table/utils/columns.ts +0 -351
- package/dist/frontend-core/template/src/components/ui/data-table/utils/data-table.utils.ts +0 -49
- package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.stories.tsx +0 -149
- package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.tsx +0 -30
- package/dist/frontend-core/template/src/components/ui/dialog/dialog.stories.tsx +0 -80
- package/dist/frontend-core/template/src/components/ui/dialog/dialog.tsx +0 -134
- package/dist/frontend-core/template/src/components/ui/drawer/drawer.stories.tsx +0 -104
- package/dist/frontend-core/template/src/components/ui/drawer/drawer.tsx +0 -87
- package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.stories.tsx +0 -168
- package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.tsx +0 -225
- package/dist/frontend-core/template/src/components/ui/input/input.stories.tsx +0 -141
- package/dist/frontend-core/template/src/components/ui/input/input.tsx +0 -47
- package/dist/frontend-core/template/src/components/ui/label/label.stories.tsx +0 -41
- package/dist/frontend-core/template/src/components/ui/label/label.tsx +0 -20
- package/dist/frontend-core/template/src/components/ui/loader/loader.stories.tsx +0 -45
- package/dist/frontend-core/template/src/components/ui/loader/loader.tsx +0 -17
- package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.stories.tsx +0 -114
- package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.tsx +0 -48
- package/dist/frontend-core/template/src/components/ui/menubar/menu.stories.tsx +0 -134
- package/dist/frontend-core/template/src/components/ui/menubar/menubar.tsx +0 -208
- package/dist/frontend-core/template/src/components/ui/modal/modal.stories.tsx +0 -297
- package/dist/frontend-core/template/src/components/ui/modal/modal.tsx +0 -80
- package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.stories.tsx +0 -213
- package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.tsx +0 -142
- package/dist/frontend-core/template/src/components/ui/pagination/pagination.stories.tsx +0 -49
- package/dist/frontend-core/template/src/components/ui/pagination/pagination.tsx +0 -84
- package/dist/frontend-core/template/src/components/ui/popover/popover.stories.tsx +0 -82
- package/dist/frontend-core/template/src/components/ui/popover/popover.tsx +0 -55
- package/dist/frontend-core/template/src/components/ui/progress/progress.stories.tsx +0 -80
- package/dist/frontend-core/template/src/components/ui/progress/progress.tsx +0 -17
- package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.stories.tsx +0 -154
- package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.tsx +0 -68
- package/dist/frontend-core/template/src/components/ui/resizable/resizable.stories.tsx +0 -73
- package/dist/frontend-core/template/src/components/ui/resizable/resizeable.tsx +0 -38
- package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.stories.tsx +0 -55
- package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.tsx +0 -39
- package/dist/frontend-core/template/src/components/ui/select/select.stories.tsx +0 -297
- package/dist/frontend-core/template/src/components/ui/select/select.tsx +0 -227
- package/dist/frontend-core/template/src/components/ui/separator/separator.tsx +0 -21
- package/dist/frontend-core/template/src/components/ui/separator/seperator.stories.tsx +0 -25
- package/dist/frontend-core/template/src/components/ui/sheet/sheet.stories.tsx +0 -45
- package/dist/frontend-core/template/src/components/ui/sheet/sheet.tsx +0 -107
- package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.stories.tsx +0 -26
- package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.tsx +0 -7
- package/dist/frontend-core/template/src/components/ui/slider/slider.stories.tsx +0 -101
- package/dist/frontend-core/template/src/components/ui/slider/slider.tsx +0 -98
- package/dist/frontend-core/template/src/components/ui/spinner/spinner.stories.tsx +0 -19
- package/dist/frontend-core/template/src/components/ui/spinner/spinner.tsx +0 -21
- package/dist/frontend-core/template/src/components/ui/switch/switch.stories.tsx +0 -33
- package/dist/frontend-core/template/src/components/ui/switch/switch.tsx +0 -28
- package/dist/frontend-core/template/src/components/ui/tabs/tabs.stories.tsx +0 -215
- package/dist/frontend-core/template/src/components/ui/tabs/tabs.tsx +0 -70
- package/dist/frontend-core/template/src/components/ui/textarea/textarea.stories.tsx +0 -138
- package/dist/frontend-core/template/src/components/ui/textarea/textarea.tsx +0 -40
- package/dist/frontend-core/template/src/components/ui/toast/toast.mdx +0 -31
- package/dist/frontend-core/template/src/components/ui/toast/toast.stories.tsx +0 -89
- package/dist/frontend-core/template/src/components/ui/toggle/toggle.stories.tsx +0 -65
- package/dist/frontend-core/template/src/components/ui/toggle/toggle.tsx +0 -38
- package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.stories.tsx +0 -85
- package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.tsx +0 -54
- package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.stories.tsx +0 -29
- package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.tsx +0 -29
package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.stories.tsx
DELETED
|
@@ -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
|
-
}
|