@polymarbot/nuxt-layer-shadcn-ui 0.1.9 → 0.2.0-w
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/app/assets/styles/colors.css +10 -10
- package/app/assets/styles/globals.css +1 -0
- package/app/assets/styles/z-index.css +27 -0
- package/app/components/ui/Accordion/index.stories.ts +60 -56
- package/app/components/ui/Accordion/index.vue +1 -1
- package/app/components/ui/AdminLayout/SidebarMenus.vue +0 -2
- package/app/components/ui/AdminLayout/index.stories.ts +9 -8
- package/app/components/ui/Alert/index.stories.ts +28 -26
- package/app/components/ui/Alert/index.vue +6 -6
- package/app/components/ui/Alert/types.ts +2 -1
- package/app/components/ui/AlertDialog/index.stories.ts +85 -50
- package/app/components/ui/AsyncDataTable/index.stories.ts +53 -36
- package/app/components/ui/Avatar/index.stories.ts +56 -51
- package/app/components/ui/Avatar/index.vue +1 -1
- package/app/components/ui/Avatar/types.ts +5 -2
- package/app/components/ui/Badge/index.stories.ts +41 -41
- package/app/components/ui/Badge/index.vue +1 -1
- package/app/components/ui/Badge/types.ts +3 -1
- package/app/components/ui/Breadcrumb/index.stories.ts +48 -37
- package/app/components/ui/Breadcrumb/index.vue +1 -1
- package/app/components/ui/Button/index.stories.ts +94 -90
- package/app/components/ui/Button/index.vue +1 -1
- package/app/components/ui/Button/types.ts +4 -1
- package/app/components/ui/ButtonGroup/index.stories.ts +61 -49
- package/app/components/ui/Card/index.stories.ts +55 -47
- package/app/components/ui/Card/index.vue +1 -1
- package/app/components/ui/Checkbox/index.stories.ts +69 -46
- package/app/components/ui/Checkbox/index.vue +1 -1
- package/app/components/ui/CopyButton/index.stories.ts +89 -31
- package/app/components/ui/DataTable/index.stories.ts +218 -168
- package/app/components/ui/DataTable/index.vue +1 -1
- package/app/components/ui/DatePicker/index.stories.ts +131 -37
- package/app/components/ui/DateRangePicker/index.stories.ts +107 -33
- package/app/components/ui/Divider/index.stories.ts +46 -24
- package/app/components/ui/Divider/index.vue +1 -1
- package/app/components/ui/Drawer/index.stories.ts +131 -81
- package/app/components/ui/Drawer/index.vue +1 -7
- package/app/components/ui/Drawer/types.ts +1 -1
- package/app/components/ui/Dropdown/index.stories.ts +134 -89
- package/app/components/ui/Dropdown/index.vue +5 -1
- package/app/components/ui/Dropdown/types.ts +1 -1
- package/app/components/ui/FormItem/index.stories.ts +87 -43
- package/app/components/ui/FormItem/index.vue +1 -1
- package/app/components/ui/Help/index.stories.ts +46 -35
- package/app/components/ui/Icon/index.stories.ts +41 -43
- package/app/components/ui/Input/index.stories.ts +95 -41
- package/app/components/ui/Input/index.vue +1 -1
- package/app/components/ui/InputCurrency/index.stories.ts +89 -49
- package/app/components/ui/InputNumber/index.stories.ts +93 -29
- package/app/components/ui/InputNumber/index.vue +1 -1
- package/app/components/ui/InputOtp/index.stories.ts +6 -7
- package/app/components/ui/InputOtp/index.vue +1 -1
- package/app/components/ui/InputPercent/index.stories.ts +6 -7
- package/app/components/ui/InputRange/index.stories.ts +6 -7
- package/app/components/ui/Loading/index.stories.ts +19 -19
- package/app/components/ui/Markdown/index.stories.ts +7 -10
- package/app/components/ui/Modal/index.stories.ts +135 -80
- package/app/components/ui/Modal/index.vue +1 -6
- package/app/components/ui/Modal/types.ts +1 -1
- package/app/components/ui/ModalContent/index.stories.ts +54 -26
- package/app/components/ui/ModalContent/index.vue +2 -2
- package/app/components/ui/PageCard/index.stories.ts +177 -67
- package/app/components/ui/Pagination/index.stories.ts +68 -51
- package/app/components/ui/Pagination/index.vue +2 -2
- package/app/components/ui/Popover/index.stories.ts +47 -45
- package/app/components/ui/Popover/index.vue +1 -1
- package/app/components/ui/Qrcode/index.stories.ts +42 -34
- package/app/components/ui/RadioCardGroup/index.stories.ts +23 -32
- package/app/components/ui/RadioCardGroup/index.vue +1 -1
- package/app/components/ui/RadioGroup/index.stories.ts +123 -0
- package/app/components/ui/RadioGroup/index.vue +73 -0
- package/app/components/ui/RadioGroup/types.ts +13 -0
- package/app/components/ui/ScrollArea/index.stories.ts +69 -37
- package/app/components/ui/ScrollArea/index.vue +1 -1
- package/app/components/ui/SearchSelect/index.stories.ts +104 -66
- package/app/components/ui/Select/index.stories.ts +152 -98
- package/app/components/ui/Select/index.vue +3 -3
- package/app/components/ui/Skeleton/index.stories.ts +27 -30
- package/app/components/ui/Skeleton/index.vue +1 -1
- package/app/components/ui/Slider/index.stories.ts +73 -31
- package/app/components/ui/Slider/index.vue +1 -1
- package/app/components/ui/Surface/index.stories.ts +47 -21
- package/app/components/ui/Surface/index.vue +39 -28
- package/app/components/ui/Surface/types.ts +2 -2
- package/app/components/ui/Switch/index.stories.ts +6 -7
- package/app/components/ui/Switch/index.vue +1 -1
- package/app/components/ui/Tabs/index.stories.ts +103 -61
- package/app/components/ui/Tabs/index.vue +1 -1
- package/app/components/ui/Tag/index.stories.ts +42 -25
- package/app/components/ui/Tag/index.vue +39 -28
- package/app/components/ui/Tag/types.ts +2 -2
- package/app/components/ui/Textarea/index.stories.ts +73 -9
- package/app/components/ui/Textarea/index.vue +1 -1
- package/app/components/ui/Toast/index.stories.ts +71 -18
- package/app/components/ui/Toast/index.vue +1 -1
- package/app/components/ui/Tooltip/index.stories.ts +45 -38
- package/app/components/ui/Tooltip/index.vue +1 -1
- package/app/components/ui/WebLink/index.stories.ts +76 -41
- package/app/components/ui/WebLink/index.vue +1 -1
- package/package.json +2 -2
- package/app/components/ui/Radio/index.stories.ts +0 -71
- package/app/components/ui/Radio/index.vue +0 -10
- package/app/components/ui/Radio/types.ts +0 -3
|
@@ -1,55 +1,113 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import CopyButton from './index.vue'
|
|
3
3
|
|
|
4
|
+
const variants = [ 'default', 'destructive', 'outline', 'secondary', 'ghost', 'link' ] as const
|
|
5
|
+
const sizes = [ 'sm', 'default', 'lg', 'icon-sm', 'icon', 'icon-lg' ] as const
|
|
6
|
+
|
|
4
7
|
const meta = {
|
|
5
8
|
title: 'UI/CopyButton',
|
|
6
9
|
component: CopyButton,
|
|
7
10
|
argTypes: {
|
|
8
11
|
copy: { control: 'text' },
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
beforeCopyText: { control: 'text' },
|
|
13
|
+
afterCopyText: { control: 'text' },
|
|
14
|
+
variant: { control: 'select', options: variants },
|
|
15
|
+
size: { control: 'select', options: sizes },
|
|
16
|
+
rounded: { control: 'boolean' },
|
|
17
|
+
disabled: { control: 'boolean' },
|
|
18
|
+
loading: { control: 'boolean' },
|
|
11
19
|
},
|
|
12
20
|
args: {
|
|
13
21
|
copy: 'Hello, World!',
|
|
22
|
+
beforeCopyText: '',
|
|
23
|
+
afterCopyText: '',
|
|
14
24
|
variant: 'outline',
|
|
25
|
+
size: 'default',
|
|
26
|
+
rounded: false,
|
|
27
|
+
disabled: false,
|
|
28
|
+
loading: false,
|
|
15
29
|
},
|
|
30
|
+
render: args => ({
|
|
31
|
+
components: { CopyButton },
|
|
32
|
+
setup: () => ({ args }),
|
|
33
|
+
template: '<CopyButton v-bind="args">Copy Text</CopyButton>',
|
|
34
|
+
}),
|
|
16
35
|
} satisfies Meta<typeof CopyButton>
|
|
17
36
|
|
|
18
37
|
export default meta
|
|
19
38
|
type Story = StoryObj<typeof meta>
|
|
20
39
|
|
|
21
|
-
export const Default: Story = {
|
|
22
|
-
|
|
40
|
+
export const Default: Story = {}
|
|
41
|
+
|
|
42
|
+
export const IconOnly: Story = {
|
|
43
|
+
render: () => ({
|
|
44
|
+
components: { CopyButton },
|
|
45
|
+
template: `
|
|
46
|
+
<div class="flex items-center gap-4">
|
|
47
|
+
<CopyButton copy="Hello, World!" variant="outline" />
|
|
48
|
+
<CopyButton copy="Hello, World!" variant="ghost" />
|
|
49
|
+
<CopyButton copy="Hello, World!" variant="secondary" />
|
|
50
|
+
</div>
|
|
51
|
+
`,
|
|
52
|
+
}),
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const WithLabel: Story = {
|
|
56
|
+
render: () => ({
|
|
23
57
|
components: { CopyButton },
|
|
24
|
-
setup: () => ({ args }),
|
|
25
58
|
template: `
|
|
26
|
-
<div class="
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
<div class="flex items-center gap-4">
|
|
30
|
-
<CopyButton v-bind="args" />
|
|
31
|
-
<CopyButton v-bind="args" variant="ghost" />
|
|
32
|
-
<CopyButton v-bind="args" variant="secondary" />
|
|
33
|
-
</div>
|
|
34
|
-
</section>
|
|
35
|
-
|
|
36
|
-
<section>
|
|
37
|
-
<h3 class="mb-4 text-lg font-medium">With Label</h3>
|
|
38
|
-
<div class="flex items-center gap-4">
|
|
39
|
-
<CopyButton v-bind="args">Copy Text</CopyButton>
|
|
40
|
-
<CopyButton v-bind="args" variant="secondary">Copy Address</CopyButton>
|
|
41
|
-
</div>
|
|
42
|
-
</section>
|
|
43
|
-
|
|
44
|
-
<section>
|
|
45
|
-
<h3 class="mb-4 text-lg font-medium">Sizes</h3>
|
|
46
|
-
<div class="flex items-center gap-4">
|
|
47
|
-
<CopyButton v-bind="args" size="sm">Small</CopyButton>
|
|
48
|
-
<CopyButton v-bind="args" size="default">Default</CopyButton>
|
|
49
|
-
<CopyButton v-bind="args" size="lg">Large</CopyButton>
|
|
50
|
-
</div>
|
|
51
|
-
</section>
|
|
59
|
+
<div class="flex items-center gap-4">
|
|
60
|
+
<CopyButton copy="Hello, World!" variant="outline">Copy Text</CopyButton>
|
|
61
|
+
<CopyButton copy="123 Main St" variant="secondary">Copy Address</CopyButton>
|
|
52
62
|
</div>
|
|
53
63
|
`,
|
|
54
64
|
}),
|
|
55
65
|
}
|
|
66
|
+
|
|
67
|
+
export const Variants: Story = {
|
|
68
|
+
render: () => ({
|
|
69
|
+
components: { CopyButton },
|
|
70
|
+
setup: () => ({ variants }),
|
|
71
|
+
template: `
|
|
72
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
73
|
+
<CopyButton
|
|
74
|
+
v-for="v in variants"
|
|
75
|
+
:key="v"
|
|
76
|
+
:variant="v"
|
|
77
|
+
copy="Hello, World!"
|
|
78
|
+
>
|
|
79
|
+
{{ v }}
|
|
80
|
+
</CopyButton>
|
|
81
|
+
</div>
|
|
82
|
+
`,
|
|
83
|
+
}),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const Sizes: Story = {
|
|
87
|
+
render: () => ({
|
|
88
|
+
components: { CopyButton },
|
|
89
|
+
template: `
|
|
90
|
+
<div class="flex items-center gap-4">
|
|
91
|
+
<CopyButton copy="Hello, World!" variant="outline" size="sm">Small</CopyButton>
|
|
92
|
+
<CopyButton copy="Hello, World!" variant="outline" size="default">Default</CopyButton>
|
|
93
|
+
<CopyButton copy="Hello, World!" variant="outline" size="lg">Large</CopyButton>
|
|
94
|
+
</div>
|
|
95
|
+
`,
|
|
96
|
+
}),
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const CustomTooltipText: Story = {
|
|
100
|
+
render: () => ({
|
|
101
|
+
components: { CopyButton },
|
|
102
|
+
template: `
|
|
103
|
+
<CopyButton
|
|
104
|
+
copy="secret-token-123"
|
|
105
|
+
before-copy-text="Click to copy token"
|
|
106
|
+
after-copy-text="Token copied!"
|
|
107
|
+
variant="outline"
|
|
108
|
+
>
|
|
109
|
+
Copy Token
|
|
110
|
+
</CopyButton>
|
|
111
|
+
`,
|
|
112
|
+
}),
|
|
113
|
+
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import type { DataTableColumn } from './types'
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
// Cast generic component for Storybook compatibility
|
|
6
|
-
const DataTable = DataTableRaw as any
|
|
3
|
+
import DataTable from './index.vue'
|
|
7
4
|
|
|
8
5
|
interface User {
|
|
9
6
|
id: number
|
|
@@ -30,37 +27,122 @@ const basicColumns: DataTableColumn[] = [
|
|
|
30
27
|
{ field: 'status', title: 'Status', width: '100px' },
|
|
31
28
|
]
|
|
32
29
|
|
|
30
|
+
const sortableColumns: DataTableColumn[] = [
|
|
31
|
+
{ field: 'name', title: 'Name', width: '120px', sortable: true },
|
|
32
|
+
{ field: 'email', title: 'Email', minWidth: '200px' },
|
|
33
|
+
{ field: 'role', title: 'Role', width: '100px', sortable: true },
|
|
34
|
+
{ field: 'amount', title: 'Amount', width: '120px', type: 'currency', sortable: true },
|
|
35
|
+
{ field: 'createdAt', title: 'Created', width: '140px', type: 'date', sortable: true },
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
const typeColumns: DataTableColumn[] = [
|
|
39
|
+
{ field: 'name', title: 'Name', width: '120px' },
|
|
40
|
+
{ field: 'amount', title: 'Amount', width: '120px', type: 'currency' },
|
|
41
|
+
{ field: 'createdAt', title: 'Date', width: '140px', type: 'date' },
|
|
42
|
+
{ field: 'status', title: 'Empty', width: '100px', type: 'empty' },
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
const slotColumns: DataTableColumn[] = [
|
|
46
|
+
{ field: 'name', title: 'Name', width: '120px' },
|
|
47
|
+
{ field: 'email', title: 'Email', minWidth: '200px' },
|
|
48
|
+
{ field: 'status', title: 'Status', width: '120px' },
|
|
49
|
+
{ field: 'amount', title: 'Amount', width: '120px' },
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
const frozenColumns: DataTableColumn[] = [
|
|
53
|
+
{ field: 'name', title: 'Name', width: '120px', fixed: 'left' },
|
|
54
|
+
{ field: 'email', title: 'Email', width: '250px', fixed: 'left' },
|
|
55
|
+
{ field: 'role', title: 'Role', width: '150px' },
|
|
56
|
+
{ field: 'status', title: 'Status', width: '150px' },
|
|
57
|
+
{ field: 'amount', title: 'Amount', width: '150px' },
|
|
58
|
+
{ field: 'createdAt', title: 'Created', width: '180px', type: 'date' },
|
|
59
|
+
{ field: 'id', title: 'Actions', width: '100px', fixed: 'right' },
|
|
60
|
+
]
|
|
61
|
+
|
|
33
62
|
const meta = {
|
|
34
63
|
title: 'UI/DataTable',
|
|
35
|
-
component: DataTable,
|
|
64
|
+
component: DataTable as any,
|
|
36
65
|
argTypes: {
|
|
66
|
+
selectionMode: { control: 'select', options: [ undefined, 'single', 'multiple' ]},
|
|
37
67
|
loading: { control: 'boolean' },
|
|
68
|
+
sortBy: { control: 'text' },
|
|
69
|
+
sortOrder: { control: 'select', options: [ null, 1, -1 ]},
|
|
38
70
|
},
|
|
39
71
|
args: {
|
|
72
|
+
selectionMode: undefined,
|
|
40
73
|
loading: false,
|
|
74
|
+
sortBy: null,
|
|
75
|
+
sortOrder: null,
|
|
41
76
|
},
|
|
77
|
+
render: args => ({
|
|
78
|
+
components: { DataTable: DataTable as any },
|
|
79
|
+
setup: () => ({ args, data: sampleData, basicColumns }),
|
|
80
|
+
template: `
|
|
81
|
+
<div class="w-full">
|
|
82
|
+
<DataTable :data="data" :columns="basicColumns" v-bind="args" />
|
|
83
|
+
</div>
|
|
84
|
+
`,
|
|
85
|
+
}),
|
|
42
86
|
} satisfies Meta
|
|
43
87
|
|
|
44
88
|
export default meta
|
|
45
89
|
type Story = StoryObj<typeof meta>
|
|
46
90
|
|
|
47
|
-
export const Default: Story = {
|
|
48
|
-
|
|
49
|
-
|
|
91
|
+
export const Default: Story = {}
|
|
92
|
+
|
|
93
|
+
export const SingleSelection: Story = {
|
|
94
|
+
render: () => ({
|
|
95
|
+
components: { DataTable: DataTable as any },
|
|
96
|
+
setup () {
|
|
97
|
+
const selection = ref<User | null>(null)
|
|
98
|
+
return { data: sampleData, basicColumns, selection }
|
|
99
|
+
},
|
|
100
|
+
template: `
|
|
101
|
+
<div class="w-full">
|
|
102
|
+
<DataTable
|
|
103
|
+
:data="data"
|
|
104
|
+
:columns="basicColumns"
|
|
105
|
+
selectionMode="single"
|
|
106
|
+
v-model:selection="selection"
|
|
107
|
+
/>
|
|
108
|
+
<div class="mt-2 text-sm text-muted-foreground">
|
|
109
|
+
Selected: {{ selection?.name ?? 'none' }}
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
`,
|
|
113
|
+
}),
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const MultipleSelection: Story = {
|
|
117
|
+
render: () => ({
|
|
118
|
+
components: { DataTable: DataTable as any },
|
|
119
|
+
setup () {
|
|
120
|
+
const selection = ref<User[]>([])
|
|
121
|
+
return { data: sampleData, basicColumns, selection }
|
|
122
|
+
},
|
|
123
|
+
template: `
|
|
124
|
+
<div class="w-full">
|
|
125
|
+
<DataTable
|
|
126
|
+
:data="data"
|
|
127
|
+
:columns="basicColumns"
|
|
128
|
+
selectionMode="multiple"
|
|
129
|
+
v-model:selection="selection"
|
|
130
|
+
/>
|
|
131
|
+
<div class="mt-2 text-sm text-muted-foreground">
|
|
132
|
+
Selected: {{ selection.length > 0 ? selection.map(r => r.name).join(', ') : 'none' }}
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
`,
|
|
136
|
+
}),
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const Sortable: Story = {
|
|
140
|
+
render: () => ({
|
|
141
|
+
components: { DataTable: DataTable as any },
|
|
50
142
|
setup () {
|
|
51
|
-
const singleSelection = ref(null)
|
|
52
|
-
const multipleSelection = ref([])
|
|
53
143
|
const sortBy = ref<string | null>(null)
|
|
54
144
|
const sortOrder = ref<number | null>(null)
|
|
55
145
|
|
|
56
|
-
const sortableColumns: DataTableColumn[] = [
|
|
57
|
-
{ field: 'name', title: 'Name', width: '120px', sortable: true },
|
|
58
|
-
{ field: 'email', title: 'Email', minWidth: '200px' },
|
|
59
|
-
{ field: 'role', title: 'Role', width: '100px', sortable: true },
|
|
60
|
-
{ field: 'amount', title: 'Amount', width: '120px', type: 'currency', sortable: true },
|
|
61
|
-
{ field: 'createdAt', title: 'Created', width: '140px', type: 'date', sortable: true },
|
|
62
|
-
]
|
|
63
|
-
|
|
64
146
|
const sortedData = computed(() => {
|
|
65
147
|
if (!sortBy.value || !sortOrder.value) return sampleData
|
|
66
148
|
return [ ...sampleData ].sort((a, b) => {
|
|
@@ -72,159 +154,127 @@ export const Default: Story = {
|
|
|
72
154
|
})
|
|
73
155
|
})
|
|
74
156
|
|
|
75
|
-
|
|
76
|
-
{ field: 'name', title: 'Name', width: '120px' },
|
|
77
|
-
{ field: 'amount', title: 'Amount', width: '120px', type: 'currency' },
|
|
78
|
-
{ field: 'createdAt', title: 'Date', width: '140px', type: 'date' },
|
|
79
|
-
{ field: 'status', title: 'Empty', width: '100px', type: 'empty' },
|
|
80
|
-
]
|
|
81
|
-
|
|
82
|
-
const slotColumns: DataTableColumn[] = [
|
|
83
|
-
{ field: 'name', title: 'Name', width: '120px' },
|
|
84
|
-
{ field: 'email', title: 'Email', minWidth: '200px' },
|
|
85
|
-
{ field: 'status', title: 'Status', width: '120px' },
|
|
86
|
-
{ field: 'amount', title: 'Amount', width: '120px' },
|
|
87
|
-
]
|
|
88
|
-
|
|
89
|
-
const frozenColumns: DataTableColumn[] = [
|
|
90
|
-
{ field: 'name', title: 'Name', width: '120px', fixed: 'left' },
|
|
91
|
-
{ field: 'email', title: 'Email', width: '250px', fixed: 'left' },
|
|
92
|
-
{ field: 'role', title: 'Role', width: '150px' },
|
|
93
|
-
{ field: 'status', title: 'Status', width: '150px' },
|
|
94
|
-
{ field: 'amount', title: 'Amount', width: '150px', type: 'currency' },
|
|
95
|
-
{ field: 'createdAt', title: 'Created', width: '180px', type: 'date' },
|
|
96
|
-
{ field: 'id', title: 'Actions', width: '100px', fixed: 'right' },
|
|
97
|
-
]
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
args,
|
|
101
|
-
data: sampleData,
|
|
102
|
-
basicColumns,
|
|
103
|
-
sortableColumns,
|
|
104
|
-
typeColumns,
|
|
105
|
-
slotColumns,
|
|
106
|
-
frozenColumns,
|
|
107
|
-
singleSelection,
|
|
108
|
-
multipleSelection,
|
|
109
|
-
sortBy,
|
|
110
|
-
sortOrder,
|
|
111
|
-
sortedData,
|
|
112
|
-
}
|
|
157
|
+
return { sortableColumns, sortBy, sortOrder, sortedData }
|
|
113
158
|
},
|
|
114
159
|
template: `
|
|
115
|
-
<div class="w-full
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
v-model:sortOrder="sortOrder"
|
|
158
|
-
/>
|
|
159
|
-
<div class="mt-2 text-sm text-muted-foreground">
|
|
160
|
-
Sort: {{ sortBy ?? 'none' }} / {{ sortOrder ?? 'none' }}
|
|
161
|
-
</div>
|
|
162
|
-
</section>
|
|
163
|
-
|
|
164
|
-
<!-- Column Types -->
|
|
165
|
-
<section>
|
|
166
|
-
<h3 class="mb-4 text-lg font-medium">Column Types (text, currency, date, empty)</h3>
|
|
167
|
-
<DataTable :data="data" :columns="typeColumns" />
|
|
168
|
-
</section>
|
|
169
|
-
|
|
170
|
-
<!-- Custom Slots -->
|
|
171
|
-
<section>
|
|
172
|
-
<h3 class="mb-4 text-lg font-medium">Custom Cell Slots</h3>
|
|
173
|
-
<DataTable :data="data" :columns="slotColumns">
|
|
174
|
-
<template #status="{ value }">
|
|
175
|
-
<span
|
|
176
|
-
:class="[
|
|
177
|
-
'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',
|
|
178
|
-
value === 'active'
|
|
179
|
-
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
|
|
180
|
-
: 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200',
|
|
181
|
-
]"
|
|
182
|
-
>
|
|
183
|
-
{{ value }}
|
|
184
|
-
</span>
|
|
185
|
-
</template>
|
|
186
|
-
<template #amount="{ value }">
|
|
187
|
-
<span class="font-mono font-medium">\${{ Number(value).toFixed(2) }}</span>
|
|
188
|
-
</template>
|
|
189
|
-
</DataTable>
|
|
190
|
-
</section>
|
|
191
|
-
|
|
192
|
-
<!-- Empty State -->
|
|
193
|
-
<section>
|
|
194
|
-
<h3 class="mb-4 text-lg font-medium">Empty State</h3>
|
|
195
|
-
<DataTable :data="[]" :columns="basicColumns" />
|
|
196
|
-
</section>
|
|
197
|
-
|
|
198
|
-
<!-- Footer Slot -->
|
|
199
|
-
<section>
|
|
200
|
-
<h3 class="mb-4 text-lg font-medium">Footer Slot</h3>
|
|
201
|
-
<DataTable :data="data" :columns="slotColumns">
|
|
202
|
-
<template #footer>
|
|
203
|
-
<tr class="h-12 border-t text-sm font-medium">
|
|
204
|
-
<td class="px-4">Total</td>
|
|
205
|
-
<td class="px-4" colspan="2"></td>
|
|
206
|
-
<td class="px-4 font-mono">\${{ data.reduce((sum, r) => sum + r.amount, 0).toFixed(2) }}</td>
|
|
207
|
-
</tr>
|
|
208
|
-
</template>
|
|
209
|
-
</DataTable>
|
|
210
|
-
</section>
|
|
211
|
-
|
|
212
|
-
<!-- Frozen Columns -->
|
|
213
|
-
<section>
|
|
214
|
-
<h3 class="mb-4 text-lg font-medium">Frozen Columns (scroll horizontally)</h3>
|
|
215
|
-
<div class="max-w-[600px]">
|
|
216
|
-
<DataTable
|
|
217
|
-
:data="data"
|
|
218
|
-
:columns="frozenColumns"
|
|
219
|
-
selectionMode="multiple"
|
|
220
|
-
v-model:selection="multipleSelection"
|
|
160
|
+
<div class="w-full">
|
|
161
|
+
<DataTable
|
|
162
|
+
:data="sortedData"
|
|
163
|
+
:columns="sortableColumns"
|
|
164
|
+
v-model:sortBy="sortBy"
|
|
165
|
+
v-model:sortOrder="sortOrder"
|
|
166
|
+
/>
|
|
167
|
+
<div class="mt-2 text-sm text-muted-foreground">
|
|
168
|
+
Sort: {{ sortBy ?? 'none' }} / {{ sortOrder ?? 'none' }}
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
`,
|
|
172
|
+
}),
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const ColumnTypes: Story = {
|
|
176
|
+
render: () => ({
|
|
177
|
+
components: { DataTable: DataTable as any },
|
|
178
|
+
setup: () => ({ data: sampleData, typeColumns }),
|
|
179
|
+
template: `
|
|
180
|
+
<div class="w-full">
|
|
181
|
+
<DataTable :data="data" :columns="typeColumns" />
|
|
182
|
+
</div>
|
|
183
|
+
`,
|
|
184
|
+
}),
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export const CustomSlots: Story = {
|
|
188
|
+
render: () => ({
|
|
189
|
+
components: { DataTable: DataTable as any },
|
|
190
|
+
setup: () => ({ data: sampleData, slotColumns }),
|
|
191
|
+
template: `
|
|
192
|
+
<div class="w-full">
|
|
193
|
+
<DataTable :data="data" :columns="slotColumns">
|
|
194
|
+
<template #status="{ value }">
|
|
195
|
+
<span
|
|
196
|
+
:class="[
|
|
197
|
+
'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',
|
|
198
|
+
value === 'active'
|
|
199
|
+
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
|
|
200
|
+
: 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200',
|
|
201
|
+
]"
|
|
221
202
|
>
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
203
|
+
{{ value }}
|
|
204
|
+
</span>
|
|
205
|
+
</template>
|
|
206
|
+
<template #amount="{ value }">
|
|
207
|
+
<span class="font-mono font-medium">\${{ Number(value).toFixed(2) }}</span>
|
|
208
|
+
</template>
|
|
209
|
+
</DataTable>
|
|
210
|
+
</div>
|
|
211
|
+
`,
|
|
212
|
+
}),
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export const EmptyState: Story = {
|
|
216
|
+
render: () => ({
|
|
217
|
+
components: { DataTable: DataTable as any },
|
|
218
|
+
setup: () => ({ basicColumns }),
|
|
219
|
+
template: `
|
|
220
|
+
<div class="w-full">
|
|
221
|
+
<DataTable :data="[]" :columns="basicColumns" />
|
|
222
|
+
</div>
|
|
223
|
+
`,
|
|
224
|
+
}),
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export const FooterSlot: Story = {
|
|
228
|
+
render: () => ({
|
|
229
|
+
components: { DataTable: DataTable as any },
|
|
230
|
+
setup: () => ({ data: sampleData, slotColumns }),
|
|
231
|
+
template: `
|
|
232
|
+
<div class="w-full">
|
|
233
|
+
<DataTable :data="data" :columns="slotColumns">
|
|
234
|
+
<template #footer>
|
|
235
|
+
<tr class="h-12 border-t text-sm font-medium">
|
|
236
|
+
<td class="px-4">Total</td>
|
|
237
|
+
<td class="px-4" colspan="2"></td>
|
|
238
|
+
<td class="px-4 font-mono">\${{ data.reduce((sum, r) => sum + r.amount, 0).toFixed(2) }}</td>
|
|
239
|
+
</tr>
|
|
240
|
+
</template>
|
|
241
|
+
</DataTable>
|
|
242
|
+
</div>
|
|
243
|
+
`,
|
|
244
|
+
}),
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export const FrozenColumns: Story = {
|
|
248
|
+
render: () => ({
|
|
249
|
+
components: { DataTable: DataTable as any },
|
|
250
|
+
setup () {
|
|
251
|
+
const selection = ref<User[]>([])
|
|
252
|
+
return { data: sampleData, frozenColumns, selection }
|
|
253
|
+
},
|
|
254
|
+
template: `
|
|
255
|
+
<div class="max-w-[600px]">
|
|
256
|
+
<DataTable
|
|
257
|
+
:data="data"
|
|
258
|
+
:columns="frozenColumns"
|
|
259
|
+
selectionMode="multiple"
|
|
260
|
+
v-model:selection="selection"
|
|
261
|
+
>
|
|
262
|
+
<template #id>
|
|
263
|
+
<button class="text-sm text-primary underline">Edit</button>
|
|
264
|
+
</template>
|
|
265
|
+
</DataTable>
|
|
266
|
+
</div>
|
|
267
|
+
`,
|
|
268
|
+
}),
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export const Loading: Story = {
|
|
272
|
+
render: () => ({
|
|
273
|
+
components: { DataTable: DataTable as any },
|
|
274
|
+
setup: () => ({ data: sampleData, basicColumns }),
|
|
275
|
+
template: `
|
|
276
|
+
<div class="w-full">
|
|
277
|
+
<DataTable :data="data" :columns="basicColumns" loading />
|
|
228
278
|
</div>
|
|
229
279
|
`,
|
|
230
280
|
}),
|