@polymarbot/nuxt-layer-shadcn-ui 0.1.10 → 0.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/app/assets/styles/colors.css +10 -10
- 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 -1
- 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 -1
- 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
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
|
|
25
25
|
/* Status */
|
|
26
26
|
--status-foreground: oklch(0.985 0 0);
|
|
27
|
-
--success: oklch(0.58 0.
|
|
28
|
-
--info: oklch(0.58 0.
|
|
29
|
-
--help: oklch(0.
|
|
30
|
-
--warn: oklch(0.
|
|
31
|
-
--danger: oklch(0.
|
|
27
|
+
--success: oklch(0.58 0.19 150.81);
|
|
28
|
+
--info: oklch(0.58 0.195 253.83);
|
|
29
|
+
--help: oklch(0.58 0.21 293.541);
|
|
30
|
+
--warn: oklch(0.58 0.158 72.33);
|
|
31
|
+
--danger: oklch(0.58 0.233 25.74);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
.dark {
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
|
|
56
56
|
/* Status */
|
|
57
57
|
--status-foreground: oklch(0.145 0 0);
|
|
58
|
-
--success: oklch(0.
|
|
59
|
-
--info: oklch(0.
|
|
60
|
-
--help: oklch(0.
|
|
61
|
-
--warn: oklch(0.
|
|
62
|
-
--danger: oklch(0.
|
|
58
|
+
--success: oklch(0.73 0.19 150.81);
|
|
59
|
+
--info: oklch(0.72 0.19 253.83);
|
|
60
|
+
--help: oklch(0.72 0.22 293.541);
|
|
61
|
+
--warn: oklch(0.78 0.14 72.33);
|
|
62
|
+
--danger: oklch(0.70 0.22 25.74);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/* Register colors in Tailwind v4 theme (supports opacity modifier) */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import type { AccordionItem } from './types'
|
|
2
3
|
import Icon from '../Icon/index.vue'
|
|
3
4
|
import Surface from '../Surface/index.vue'
|
|
4
|
-
import type { AccordionItem } from './types'
|
|
5
5
|
import Accordion from './index.vue'
|
|
6
6
|
|
|
7
7
|
const items: AccordionItem[] = [
|
|
@@ -38,71 +38,75 @@ const meta = {
|
|
|
38
38
|
collapsible: true,
|
|
39
39
|
disabled: false,
|
|
40
40
|
},
|
|
41
|
+
render: args => ({
|
|
42
|
+
components: { Accordion, Surface },
|
|
43
|
+
setup: () => ({ args, items }),
|
|
44
|
+
template: `
|
|
45
|
+
<Surface variant="bordered" class="max-w-md px-4">
|
|
46
|
+
<Accordion v-bind="args" :items="items" default-value="shipping" />
|
|
47
|
+
</Surface>
|
|
48
|
+
`,
|
|
49
|
+
}),
|
|
41
50
|
} satisfies Meta
|
|
42
51
|
|
|
43
52
|
export default meta
|
|
44
53
|
type Story = StoryObj<typeof meta>
|
|
45
54
|
|
|
46
|
-
export const Default: Story = {
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
export const Default: Story = {}
|
|
56
|
+
|
|
57
|
+
export const Multiple: Story = {
|
|
58
|
+
render: () => ({
|
|
59
|
+
components: { Accordion, Surface },
|
|
49
60
|
setup () {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
const slotValue = ref<string>('shipping')
|
|
53
|
-
return { args, items, singleValue, multipleValue, slotValue }
|
|
61
|
+
const value = ref<string[]>([ 'shipping', 'returns' ])
|
|
62
|
+
return { items, value }
|
|
54
63
|
},
|
|
55
64
|
template: `
|
|
56
|
-
<div class="max-w-md
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
/>
|
|
66
|
-
</Surface>
|
|
67
|
-
<div class="mt-3 text-sm text-muted-foreground">Open: {{ singleValue || '(none)' }}</div>
|
|
68
|
-
</section>
|
|
65
|
+
<div class="max-w-md">
|
|
66
|
+
<Surface variant="bordered" class="px-4">
|
|
67
|
+
<Accordion v-model="value" type="multiple" :items="items" />
|
|
68
|
+
</Surface>
|
|
69
|
+
<div class="mt-3 text-sm text-muted-foreground">Open: {{ value.join(', ') || '(none)' }}</div>
|
|
70
|
+
</div>
|
|
71
|
+
`,
|
|
72
|
+
}),
|
|
73
|
+
}
|
|
69
74
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
</section>
|
|
75
|
+
export const Disabled: Story = {
|
|
76
|
+
render: () => ({
|
|
77
|
+
components: { Accordion, Surface },
|
|
78
|
+
setup: () => ({ items }),
|
|
79
|
+
template: `
|
|
80
|
+
<Surface variant="bordered" class="max-w-md px-4">
|
|
81
|
+
<Accordion disabled :items="items" default-value="shipping" />
|
|
82
|
+
</Surface>
|
|
83
|
+
`,
|
|
84
|
+
}),
|
|
85
|
+
}
|
|
82
86
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
</
|
|
103
|
-
</
|
|
104
|
-
</
|
|
105
|
-
</
|
|
87
|
+
export const CustomSlots: Story = {
|
|
88
|
+
render: () => ({
|
|
89
|
+
components: { Accordion, Surface, Icon },
|
|
90
|
+
setup () {
|
|
91
|
+
const value = ref<string>('shipping')
|
|
92
|
+
return { items, value }
|
|
93
|
+
},
|
|
94
|
+
template: `
|
|
95
|
+
<Surface variant="bordered" class="max-w-md px-4">
|
|
96
|
+
<Accordion v-model="value" :items="items">
|
|
97
|
+
<template #title="{ item, open }">
|
|
98
|
+
<span class="flex items-center gap-2">
|
|
99
|
+
<span class="inline-flex size-5 items-center justify-center rounded-full bg-primary/15 text-primary">
|
|
100
|
+
<Icon :name="open ? 'minus' : 'plus'" class="size-3" />
|
|
101
|
+
</span>
|
|
102
|
+
{{ item.title }}
|
|
103
|
+
</span>
|
|
104
|
+
</template>
|
|
105
|
+
<template #content="{ item }">
|
|
106
|
+
<p class="text-muted-foreground">{{ item.content }}</p>
|
|
107
|
+
</template>
|
|
108
|
+
</Accordion>
|
|
109
|
+
</Surface>
|
|
106
110
|
`,
|
|
107
111
|
}),
|
|
108
112
|
}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
AccordionContent,
|
|
5
5
|
AccordionItem as ShadcnAccordionItem,
|
|
6
6
|
AccordionTrigger,
|
|
7
|
-
} from '
|
|
7
|
+
} from '../../shadcn/accordion'
|
|
8
8
|
import type { AccordionRootProps } from 'reka-ui'
|
|
9
9
|
import type { AccordionItem, AccordionProps } from './types'
|
|
10
10
|
|
|
@@ -140,7 +140,6 @@ function hasActiveChild (item: AdminLayoutSidebarMenuItem): boolean {
|
|
|
140
140
|
<WebLink
|
|
141
141
|
v-if="isLink(item)"
|
|
142
142
|
:href="item.href"
|
|
143
|
-
:externalIcon="false"
|
|
144
143
|
unstyled
|
|
145
144
|
>
|
|
146
145
|
<Icon
|
|
@@ -215,7 +214,6 @@ function hasActiveChild (item: AdminLayoutSidebarMenuItem): boolean {
|
|
|
215
214
|
<WebLink
|
|
216
215
|
v-if="isLink(item)"
|
|
217
216
|
:href="item.href"
|
|
218
|
-
:externalIcon="false"
|
|
219
217
|
unstyled
|
|
220
218
|
>
|
|
221
219
|
<Icon
|
|
@@ -6,6 +6,9 @@ import Breadcrumb from '../Breadcrumb/index.vue'
|
|
|
6
6
|
import Button from '../Button/index.vue'
|
|
7
7
|
import Card from '../Card/index.vue'
|
|
8
8
|
|
|
9
|
+
const variants = [ 'sidebar', 'floating', 'inset' ] as const
|
|
10
|
+
const collapsibles = [ 'icon', 'offcanvas', 'none' ] as const
|
|
11
|
+
|
|
9
12
|
const menus: AdminLayoutSidebarMenuItem[] = [
|
|
10
13
|
{
|
|
11
14
|
label: 'Dashboard',
|
|
@@ -91,17 +94,15 @@ const meta = {
|
|
|
91
94
|
title: 'UI/AdminLayout',
|
|
92
95
|
component: AdminLayout,
|
|
93
96
|
argTypes: {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
},
|
|
98
|
-
collapsible: {
|
|
99
|
-
control: 'select',
|
|
100
|
-
options: [ 'icon', 'offcanvas', 'none' ],
|
|
101
|
-
},
|
|
97
|
+
menus: { control: 'object' },
|
|
98
|
+
headerDropdown: { control: 'object' },
|
|
99
|
+
footerDropdown: { control: 'object' },
|
|
100
|
+
variant: { control: 'select', options: variants },
|
|
101
|
+
collapsible: { control: 'select', options: collapsibles },
|
|
102
102
|
},
|
|
103
103
|
args: {
|
|
104
104
|
menus,
|
|
105
|
+
headerDropdown: undefined,
|
|
105
106
|
footerDropdown: { profile, menuItems },
|
|
106
107
|
variant: 'sidebar',
|
|
107
108
|
collapsible: 'icon',
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import type { AlertType } from './types'
|
|
2
3
|
import Alert from './index.vue'
|
|
3
4
|
|
|
4
|
-
type AlertType = 'default' | 'success' | 'info' | 'help' | 'warn' | 'danger'
|
|
5
|
-
|
|
6
5
|
const types: AlertType[] = [ 'default', 'success', 'info', 'help', 'warn', 'danger' ]
|
|
7
6
|
|
|
8
7
|
const meta = {
|
|
@@ -14,39 +13,42 @@ const meta = {
|
|
|
14
13
|
},
|
|
15
14
|
args: {
|
|
16
15
|
type: 'default',
|
|
16
|
+
icon: '',
|
|
17
17
|
},
|
|
18
|
+
render: args => ({
|
|
19
|
+
components: { Alert },
|
|
20
|
+
setup: () => ({ args }),
|
|
21
|
+
template: '<Alert v-bind="args">This is an alert message.</Alert>',
|
|
22
|
+
}),
|
|
18
23
|
} satisfies Meta<typeof Alert>
|
|
19
24
|
|
|
20
25
|
export default meta
|
|
21
26
|
type Story = StoryObj<typeof meta>
|
|
22
27
|
|
|
23
|
-
export const Default: Story = {
|
|
24
|
-
|
|
28
|
+
export const Default: Story = {}
|
|
29
|
+
|
|
30
|
+
export const Types: Story = {
|
|
31
|
+
render: () => ({
|
|
25
32
|
components: { Alert },
|
|
26
|
-
setup: () => ({
|
|
33
|
+
setup: () => ({ types }),
|
|
27
34
|
template: `
|
|
28
|
-
<div class="space-y-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<section>
|
|
37
|
-
<h3 class="mb-4 text-lg font-medium">All Types</h3>
|
|
38
|
-
<div class="space-y-3">
|
|
39
|
-
<Alert v-for="t in types" :key="t" :type="t">
|
|
40
|
-
This is a <strong>{{ t }}</strong> alert message.
|
|
41
|
-
</Alert>
|
|
42
|
-
</div>
|
|
43
|
-
</section>
|
|
35
|
+
<div class="space-y-3">
|
|
36
|
+
<Alert v-for="t in types" :key="t" :type="t">
|
|
37
|
+
This is a <strong>{{ t }}</strong> alert message.
|
|
38
|
+
</Alert>
|
|
39
|
+
</div>
|
|
40
|
+
`,
|
|
41
|
+
}),
|
|
42
|
+
}
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
export const WithIcons: Story = {
|
|
45
|
+
render: () => ({
|
|
46
|
+
components: { Alert },
|
|
47
|
+
template: `
|
|
48
|
+
<div class="space-y-3">
|
|
49
|
+
<Alert type="info" icon="bell">Alert with a custom bell icon.</Alert>
|
|
50
|
+
<Alert type="success" icon="sparkles">Alert with a custom sparkles icon.</Alert>
|
|
51
|
+
<Alert type="warn" icon="flag">Alert with a custom flag icon.</Alert>
|
|
50
52
|
</div>
|
|
51
53
|
`,
|
|
52
54
|
}),
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { Alert as ShadcnAlert } from '
|
|
2
|
+
import { Alert as ShadcnAlert } from '../../shadcn/alert'
|
|
3
3
|
import type { AlertProps, AlertType } from './types'
|
|
4
4
|
|
|
5
|
-
const typeIconNameMap: Record<AlertType, string
|
|
6
|
-
default: 'info',
|
|
5
|
+
const typeIconNameMap: Partial<Record<AlertType, string>> = {
|
|
7
6
|
success: 'circle-check',
|
|
8
7
|
info: 'info',
|
|
9
8
|
help: 'circle-question-mark',
|
|
@@ -27,7 +26,8 @@ const props = withDefaults(defineProps<AlertProps>(), {
|
|
|
27
26
|
})
|
|
28
27
|
|
|
29
28
|
const defaultIconName = computed(() => {
|
|
30
|
-
|
|
29
|
+
// null explicitly hides the icon; any truthy value is an explicit icon.
|
|
30
|
+
if (props.icon || props.icon === null) return undefined
|
|
31
31
|
return typeIconNameMap[props.type]
|
|
32
32
|
})
|
|
33
33
|
|
|
@@ -42,7 +42,7 @@ const mergedClass = computed(() =>
|
|
|
42
42
|
<template>
|
|
43
43
|
<ShadcnAlert :class="mergedClass">
|
|
44
44
|
<Icon
|
|
45
|
-
v-if="typeof icon === 'string'"
|
|
45
|
+
v-if="typeof icon === 'string' && icon"
|
|
46
46
|
:name="icon"
|
|
47
47
|
/>
|
|
48
48
|
<component
|
|
@@ -54,7 +54,7 @@ const mergedClass = computed(() =>
|
|
|
54
54
|
v-else-if="defaultIconName"
|
|
55
55
|
:name="defaultIconName"
|
|
56
56
|
/>
|
|
57
|
-
<div>
|
|
57
|
+
<div class="col-start-2">
|
|
58
58
|
<slot />
|
|
59
59
|
</div>
|
|
60
60
|
</ShadcnAlert>
|
|
@@ -4,6 +4,7 @@ export type AlertType = 'default' | 'success' | 'info' | 'help' | 'warn' | 'dang
|
|
|
4
4
|
|
|
5
5
|
export interface AlertProps {
|
|
6
6
|
type?: AlertType
|
|
7
|
-
icon
|
|
7
|
+
/** Pass `null` to explicitly hide the icon; leave undefined to use the type's default. */
|
|
8
|
+
icon?: string | Component | null
|
|
8
9
|
class?: ClassValue
|
|
9
10
|
}
|
|
@@ -12,30 +12,79 @@ const meta = {
|
|
|
12
12
|
template: '<div><story /><AlertDialog /></div>',
|
|
13
13
|
}),
|
|
14
14
|
],
|
|
15
|
+
render: () => ({
|
|
16
|
+
components: { Button },
|
|
17
|
+
setup () {
|
|
18
|
+
const { confirm } = useDialog()
|
|
19
|
+
const result = ref('')
|
|
20
|
+
async function handleConfirm () {
|
|
21
|
+
const ok = await confirm({ title: 'Confirm', message: 'Do you want to proceed?' })
|
|
22
|
+
result.value = `confirm → ${ok}`
|
|
23
|
+
}
|
|
24
|
+
return { handleConfirm, result }
|
|
25
|
+
},
|
|
26
|
+
template: `
|
|
27
|
+
<div class="space-y-4">
|
|
28
|
+
<Button @click="handleConfirm">Confirm</Button>
|
|
29
|
+
<div v-if="result" class="rounded-md bg-muted p-4 text-sm">Result: {{ result }}</div>
|
|
30
|
+
</div>
|
|
31
|
+
`,
|
|
32
|
+
}),
|
|
15
33
|
} satisfies Meta<typeof AlertDialog>
|
|
16
34
|
|
|
17
35
|
export default meta
|
|
18
36
|
type Story = StoryObj<typeof meta>
|
|
19
37
|
|
|
20
|
-
export const Default: Story = {
|
|
38
|
+
export const Default: Story = {}
|
|
39
|
+
|
|
40
|
+
export const Alert: Story = {
|
|
21
41
|
render: () => ({
|
|
22
42
|
components: { Button },
|
|
23
43
|
setup () {
|
|
24
|
-
const {
|
|
44
|
+
const { alert } = useDialog()
|
|
25
45
|
const result = ref('')
|
|
26
|
-
|
|
27
|
-
async function handleConfirm () {
|
|
28
|
-
const ok = await confirm({ title: 'Confirm', message: 'Do you want to proceed?' })
|
|
29
|
-
result.value = `confirm → ${ok}`
|
|
30
|
-
}
|
|
31
46
|
async function handleAlert () {
|
|
32
47
|
await alert({ title: 'Error', type: 'error', message: 'Something went wrong.' })
|
|
33
48
|
result.value = 'alert → closed'
|
|
34
49
|
}
|
|
50
|
+
return { handleAlert, result }
|
|
51
|
+
},
|
|
52
|
+
template: `
|
|
53
|
+
<div class="space-y-4">
|
|
54
|
+
<Button variant="outline" @click="handleAlert">Alert</Button>
|
|
55
|
+
<div v-if="result" class="rounded-md bg-muted p-4 text-sm">Result: {{ result }}</div>
|
|
56
|
+
</div>
|
|
57
|
+
`,
|
|
58
|
+
}),
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const Destroy: Story = {
|
|
62
|
+
render: () => ({
|
|
63
|
+
components: { Button },
|
|
64
|
+
setup () {
|
|
65
|
+
const { destroy } = useDialog()
|
|
66
|
+
const result = ref('')
|
|
35
67
|
async function handleDestroy () {
|
|
36
68
|
const ok = await destroy({ title: 'Delete Item', message: 'This action cannot be undone.' })
|
|
37
69
|
result.value = `destroy → ${ok}`
|
|
38
70
|
}
|
|
71
|
+
return { handleDestroy, result }
|
|
72
|
+
},
|
|
73
|
+
template: `
|
|
74
|
+
<div class="space-y-4">
|
|
75
|
+
<Button variant="destructive" @click="handleDestroy">Destroy</Button>
|
|
76
|
+
<div v-if="result" class="rounded-md bg-muted p-4 text-sm">Result: {{ result }}</div>
|
|
77
|
+
</div>
|
|
78
|
+
`,
|
|
79
|
+
}),
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const MultiDialog: Story = {
|
|
83
|
+
render: () => ({
|
|
84
|
+
components: { Button },
|
|
85
|
+
setup () {
|
|
86
|
+
const { confirm, alert, destroy } = useDialog()
|
|
87
|
+
const result = ref('')
|
|
39
88
|
async function handleMulti () {
|
|
40
89
|
result.value = 'waiting...'
|
|
41
90
|
const r1 = confirm({ title: 'Dialog 1', message: 'First confirm dialog' })
|
|
@@ -44,6 +93,23 @@ export const Default: Story = {
|
|
|
44
93
|
const [ v1, , v3 ] = await Promise.all([ r1, r2, r3 ])
|
|
45
94
|
result.value = `multi → confirm: ${v1}, alert: done, destroy: ${v3}`
|
|
46
95
|
}
|
|
96
|
+
return { handleMulti, result }
|
|
97
|
+
},
|
|
98
|
+
template: `
|
|
99
|
+
<div class="space-y-4">
|
|
100
|
+
<Button variant="secondary" @click="handleMulti">Multi Dialog</Button>
|
|
101
|
+
<div v-if="result" class="rounded-md bg-muted p-4 text-sm">Result: {{ result }}</div>
|
|
102
|
+
</div>
|
|
103
|
+
`,
|
|
104
|
+
}),
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const WithTypes: Story = {
|
|
108
|
+
render: () => ({
|
|
109
|
+
components: { Button },
|
|
110
|
+
setup () {
|
|
111
|
+
const { confirm, alert, destroy } = useDialog()
|
|
112
|
+
const result = ref('')
|
|
47
113
|
async function handleWithType () {
|
|
48
114
|
const ok = await confirm({ title: 'Warning', type: 'warn', message: 'This operation may affect your data. Do you want to continue?' })
|
|
49
115
|
result.value = `typed confirm → ${ok}`
|
|
@@ -52,55 +118,24 @@ export const Default: Story = {
|
|
|
52
118
|
await alert({ title: 'Information', type: 'info', message: 'Your changes have been saved successfully.' })
|
|
53
119
|
result.value = 'typed alert → closed'
|
|
54
120
|
}
|
|
55
|
-
async function handleDestroyDanger () {
|
|
56
|
-
const ok = await destroy({ title: 'Delete Account', message: 'All data will be permanently removed. This action cannot be undone.' })
|
|
57
|
-
result.value = `typed destroy → ${ok}`
|
|
58
|
-
}
|
|
59
121
|
async function handleSuccess () {
|
|
60
122
|
await alert({ title: 'Success', type: 'success', message: 'Payment completed successfully.' })
|
|
61
123
|
result.value = 'success alert → closed'
|
|
62
124
|
}
|
|
63
|
-
|
|
64
|
-
|
|
125
|
+
async function handleDestroyDanger () {
|
|
126
|
+
const ok = await destroy({ title: 'Delete Account', message: 'All data will be permanently removed. This action cannot be undone.' })
|
|
127
|
+
result.value = `typed destroy → ${ok}`
|
|
128
|
+
}
|
|
129
|
+
return { handleWithType, handleAlertInfo, handleSuccess, handleDestroyDanger, result }
|
|
65
130
|
},
|
|
66
131
|
template: `
|
|
67
|
-
<div class="space-y-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<
|
|
71
|
-
<Button @click="
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<!-- Alert -->
|
|
75
|
-
<section>
|
|
76
|
-
<h3 class="mb-4 text-lg font-medium">Alert</h3>
|
|
77
|
-
<Button variant="outline" @click="handleAlert">Alert</Button>
|
|
78
|
-
</section>
|
|
79
|
-
|
|
80
|
-
<!-- Destroy -->
|
|
81
|
-
<section>
|
|
82
|
-
<h3 class="mb-4 text-lg font-medium">Destroy</h3>
|
|
83
|
-
<Button variant="destructive" @click="handleDestroy">Destroy</Button>
|
|
84
|
-
</section>
|
|
85
|
-
|
|
86
|
-
<!-- Multi Dialog -->
|
|
87
|
-
<section>
|
|
88
|
-
<h3 class="mb-4 text-lg font-medium">Multi Dialog</h3>
|
|
89
|
-
<Button variant="secondary" @click="handleMulti">Multi Dialog</Button>
|
|
90
|
-
</section>
|
|
91
|
-
|
|
92
|
-
<!-- With Type (ModalContent) -->
|
|
93
|
-
<section>
|
|
94
|
-
<h3 class="mb-4 text-lg font-medium">With Type (ModalContent)</h3>
|
|
95
|
-
<div class="flex gap-2">
|
|
96
|
-
<Button variant="outline" @click="handleWithType">Warn Confirm</Button>
|
|
97
|
-
<Button variant="outline" @click="handleAlertInfo">Info Alert</Button>
|
|
98
|
-
<Button variant="outline" @click="handleSuccess">Success Alert</Button>
|
|
99
|
-
<Button variant="destructive" @click="handleDestroyDanger">Danger Destroy</Button>
|
|
100
|
-
</div>
|
|
101
|
-
</section>
|
|
102
|
-
|
|
103
|
-
<!-- Result -->
|
|
132
|
+
<div class="space-y-4">
|
|
133
|
+
<div class="flex gap-2">
|
|
134
|
+
<Button variant="outline" @click="handleWithType">Warn Confirm</Button>
|
|
135
|
+
<Button variant="outline" @click="handleAlertInfo">Info Alert</Button>
|
|
136
|
+
<Button variant="outline" @click="handleSuccess">Success Alert</Button>
|
|
137
|
+
<Button variant="destructive" @click="handleDestroyDanger">Danger Destroy</Button>
|
|
138
|
+
</div>
|
|
104
139
|
<div v-if="result" class="rounded-md bg-muted p-4 text-sm">Result: {{ result }}</div>
|
|
105
140
|
</div>
|
|
106
141
|
`,
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import type { AsyncDataTableBatchAction, AsyncDataTableFetchParams, AsyncDataTableFetchResult } from './types'
|
|
3
3
|
import type { DataTableColumn } from '../DataTable/types'
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
// Cast generic component for Storybook compatibility
|
|
7
|
-
const AsyncDataTable = AsyncDataTableRaw as any
|
|
4
|
+
import AsyncDataTable from './index.vue'
|
|
8
5
|
|
|
9
6
|
interface User {
|
|
10
7
|
id: number
|
|
@@ -59,50 +56,70 @@ function mockFetch (params: AsyncDataTableFetchParams): Promise<AsyncDataTableFe
|
|
|
59
56
|
})
|
|
60
57
|
}
|
|
61
58
|
|
|
59
|
+
const batchActions: AsyncDataTableBatchAction<User>[] = [
|
|
60
|
+
{
|
|
61
|
+
label: 'Delete',
|
|
62
|
+
icon: 'trash-2',
|
|
63
|
+
color: 'danger',
|
|
64
|
+
action: items => console.debug(`Delete ${items.length} items`),
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
label: 'Export',
|
|
68
|
+
icon: 'download',
|
|
69
|
+
action: items => console.debug(`Export ${items.length} items`),
|
|
70
|
+
},
|
|
71
|
+
]
|
|
72
|
+
|
|
62
73
|
const meta = {
|
|
63
74
|
title: 'UI/AsyncDataTable',
|
|
64
|
-
component: AsyncDataTable,
|
|
65
|
-
|
|
75
|
+
component: AsyncDataTable as any,
|
|
76
|
+
argTypes: {
|
|
77
|
+
columns: { control: 'object' },
|
|
78
|
+
fetchMethod: { control: false },
|
|
79
|
+
autoFetch: { control: 'boolean' },
|
|
80
|
+
data: { control: 'object' },
|
|
81
|
+
filters: { control: 'object' },
|
|
82
|
+
showTopToolbar: { control: 'boolean' },
|
|
83
|
+
showBottomToolbar: { control: 'boolean' },
|
|
84
|
+
pageSizeOptions: { control: 'object' },
|
|
85
|
+
showPagination: { control: 'boolean' },
|
|
86
|
+
selectable: { control: 'boolean' },
|
|
87
|
+
batchActions: { control: 'object' },
|
|
88
|
+
selection: { control: 'object' },
|
|
89
|
+
},
|
|
90
|
+
args: {
|
|
91
|
+
columns,
|
|
92
|
+
fetchMethod: mockFetch,
|
|
93
|
+
autoFetch: true,
|
|
94
|
+
data: [],
|
|
95
|
+
filters: undefined,
|
|
96
|
+
showTopToolbar: undefined,
|
|
97
|
+
showBottomToolbar: true,
|
|
98
|
+
pageSizeOptions: [ 10, 20, 50 ],
|
|
99
|
+
showPagination: true,
|
|
100
|
+
selectable: false,
|
|
101
|
+
batchActions: [],
|
|
102
|
+
selection: [],
|
|
103
|
+
},
|
|
104
|
+
render: args => ({
|
|
105
|
+
components: { AsyncDataTable },
|
|
106
|
+
setup: () => ({ args }),
|
|
107
|
+
template: '<AsyncDataTable v-bind="args" />',
|
|
108
|
+
}),
|
|
109
|
+
} satisfies Meta<typeof AsyncDataTable>
|
|
66
110
|
|
|
67
111
|
export default meta
|
|
68
112
|
type Story = StoryObj<typeof meta>
|
|
69
113
|
|
|
70
114
|
/** Async fetch with pagination, sorting, page size selector */
|
|
71
|
-
export const Default: Story = {
|
|
72
|
-
render: () => ({
|
|
73
|
-
components: { AsyncDataTable },
|
|
74
|
-
setup: () => ({ columns, mockFetch }),
|
|
75
|
-
template: `
|
|
76
|
-
<AsyncDataTable
|
|
77
|
-
:columns="columns"
|
|
78
|
-
:fetchMethod="mockFetch"
|
|
79
|
-
:pageSizeOptions="[10, 20, 50]"
|
|
80
|
-
/>
|
|
81
|
-
`,
|
|
82
|
-
}),
|
|
83
|
-
}
|
|
115
|
+
export const Default: Story = {}
|
|
84
116
|
|
|
85
117
|
/** Batch actions with row selection and dual toolbars */
|
|
86
|
-
export const
|
|
118
|
+
export const WithBatchActions: Story = {
|
|
87
119
|
render: () => ({
|
|
88
120
|
components: { AsyncDataTable },
|
|
89
121
|
setup () {
|
|
90
122
|
const selection = ref<User[]>([])
|
|
91
|
-
|
|
92
|
-
const batchActions: AsyncDataTableBatchAction<User>[] = [
|
|
93
|
-
{
|
|
94
|
-
label: 'Delete',
|
|
95
|
-
icon: 'trash-2',
|
|
96
|
-
color: 'danger',
|
|
97
|
-
action: items => console.debug(`Delete ${items.length} items`),
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
label: 'Export',
|
|
101
|
-
icon: 'download',
|
|
102
|
-
action: items => console.debug(`Export ${items.length} items`),
|
|
103
|
-
},
|
|
104
|
-
]
|
|
105
|
-
|
|
106
123
|
return { columns, mockFetch, selection, batchActions }
|
|
107
124
|
},
|
|
108
125
|
template: `
|
|
@@ -121,7 +138,7 @@ export const BatchActions: Story = {
|
|
|
121
138
|
}
|
|
122
139
|
|
|
123
140
|
/** Custom toolbar slot with action button */
|
|
124
|
-
export const
|
|
141
|
+
export const WithCustomToolbar: Story = {
|
|
125
142
|
render: () => ({
|
|
126
143
|
components: { AsyncDataTable },
|
|
127
144
|
setup: () => ({ columns, mockFetch }),
|