@polymarbot/nuxt-layer-shadcn-ui 0.8.0 → 0.8.2
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/z-index.css +12 -0
- package/app/components/ui/Accordion/index.stories.ts +15 -9
- package/app/components/ui/AlertDialog/index.vue +3 -1
- package/app/components/ui/Checkbox/index.stories.ts +14 -10
- package/app/components/ui/DatePicker/index.stories.ts +14 -12
- package/app/components/ui/DateRangePicker/index.stories.ts +21 -18
- package/app/components/ui/Drawer/index.stories.ts +19 -16
- package/app/components/ui/Drawer/index.vue +4 -0
- package/app/components/ui/Input/index.stories.ts +9 -7
- package/app/components/ui/InputCurrency/index.stories.ts +18 -15
- package/app/components/ui/InputNumber/index.stories.ts +16 -13
- package/app/components/ui/InputOtp/index.stories.ts +14 -12
- package/app/components/ui/InputPercent/index.stories.ts +22 -17
- package/app/components/ui/InputRange/index.stories.ts +19 -16
- package/app/components/ui/Modal/index.stories.ts +19 -16
- package/app/components/ui/Modal/index.vue +4 -0
- package/app/components/ui/Pagination/index.stories.ts +10 -5
- package/app/components/ui/RadioCardGroup/index.stories.ts +14 -12
- package/app/components/ui/RadioCardGroup/index.vue +9 -9
- package/app/components/ui/RadioGroup/index.stories.ts +9 -5
- package/app/components/ui/RadioGroup/index.vue +8 -8
- package/app/components/ui/SearchSelect/index.stories.ts +20 -17
- package/app/components/ui/Select/index.stories.ts +16 -13
- package/app/components/ui/Slider/index.stories.ts +16 -13
- package/app/components/ui/Switch/index.stories.ts +16 -13
- package/app/components/ui/Tabs/index.stories.ts +9 -5
- package/app/components/ui/Textarea/index.stories.ts +13 -9
- package/app/composables/useDialog.ts +16 -1
- package/package.json +2 -2
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* Stacking order (low → high):
|
|
9
9
|
* layout header z-100 (project convention)
|
|
10
10
|
* dialog / sheet (Modal / Drawer) z-200 (cover the header)
|
|
11
|
+
* alert dialog (system interrupts) z-250 (always above other modals)
|
|
11
12
|
* tooltip / popover / dropdown / select z-300 (above modal when nested)
|
|
12
13
|
* ========================================================================= */
|
|
13
14
|
|
|
@@ -19,6 +20,17 @@
|
|
|
19
20
|
z-index: 200;
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
/* AlertDialog must always sit above regular Modals, regardless of teleport
|
|
24
|
+
* order. Vue's <Teleport> places content at a stable anchor based on the
|
|
25
|
+
* host component's mount time — so an AlertDialog declared in app.vue (early
|
|
26
|
+
* mount) ends up *behind* a page-level Modal opened later. The overlay is
|
|
27
|
+
* matched via :has() because reka-ui's DialogPortal renders it as the
|
|
28
|
+
* adjacent previous sibling of the content. */
|
|
29
|
+
[data-slot='dialog-content'][data-alert-dialog],
|
|
30
|
+
[data-slot='dialog-overlay']:has(+ [data-slot='dialog-content'][data-alert-dialog]) {
|
|
31
|
+
z-index: 250;
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
[data-slot='tooltip-content'],
|
|
23
35
|
[data-slot='popover-content'],
|
|
24
36
|
[data-slot='dropdown-menu-content'],
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
2
3
|
import type { AccordionItem } from './types'
|
|
3
4
|
import Icon from '../Icon/index.vue'
|
|
4
5
|
import Surface from '../Surface/index.vue'
|
|
@@ -29,24 +30,29 @@ const meta = {
|
|
|
29
30
|
title: 'UI/Accordion',
|
|
30
31
|
component: Accordion as any,
|
|
31
32
|
argTypes: {
|
|
33
|
+
modelValue: { control: 'text' },
|
|
32
34
|
type: { control: 'select', options: [ 'single', 'multiple' ]},
|
|
33
35
|
collapsible: { control: 'boolean' },
|
|
34
36
|
disabled: { control: 'boolean' },
|
|
35
37
|
},
|
|
36
38
|
args: {
|
|
39
|
+
modelValue: 'shipping',
|
|
37
40
|
type: 'single',
|
|
38
41
|
collapsible: true,
|
|
39
42
|
disabled: false,
|
|
40
43
|
},
|
|
41
|
-
render: args =>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
render: args => {
|
|
45
|
+
const onUpdate = useArgsModel()
|
|
46
|
+
return {
|
|
47
|
+
components: { Accordion, Surface },
|
|
48
|
+
setup: () => ({ args, onUpdate, items }),
|
|
49
|
+
template: `
|
|
50
|
+
<Surface variant="bordered" class="max-w-md px-4">
|
|
51
|
+
<Accordion v-bind="args" :items="items" @update:modelValue="onUpdate" />
|
|
52
|
+
</Surface>
|
|
53
|
+
`,
|
|
54
|
+
}
|
|
55
|
+
},
|
|
50
56
|
} satisfies Meta
|
|
51
57
|
|
|
52
58
|
export default meta
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
const { current, isOpen, close, onClosed } = useDialogState()
|
|
2
|
+
const { current, isOpen, isActive, close, onClosed } = useDialogState()
|
|
3
3
|
|
|
4
4
|
const isAlert = computed(() => current.value?.options.rejectLabel === '')
|
|
5
5
|
const isDestructive = computed(() => {
|
|
@@ -10,6 +10,8 @@ const isDestructive = computed(() => {
|
|
|
10
10
|
|
|
11
11
|
<template>
|
|
12
12
|
<Modal
|
|
13
|
+
v-if="isActive"
|
|
14
|
+
data-alert-dialog
|
|
13
15
|
:visible="isOpen"
|
|
14
16
|
:title="current?.options.title"
|
|
15
17
|
:type="current?.options.type"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
2
3
|
import Checkbox from './index.vue'
|
|
3
4
|
|
|
4
5
|
const meta = {
|
|
@@ -20,16 +21,19 @@ const meta = {
|
|
|
20
21
|
name: '',
|
|
21
22
|
value: '',
|
|
22
23
|
},
|
|
23
|
-
render: args =>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
render: args => {
|
|
25
|
+
const onUpdate = useArgsModel()
|
|
26
|
+
return {
|
|
27
|
+
components: { Checkbox },
|
|
28
|
+
setup: () => ({ args, onUpdate }),
|
|
29
|
+
template: `
|
|
30
|
+
<label class="flex items-center gap-2 cursor-pointer">
|
|
31
|
+
<Checkbox v-bind="args" @update:modelValue="onUpdate" />
|
|
32
|
+
<span class="text-sm">Accept terms and conditions</span>
|
|
33
|
+
</label>
|
|
34
|
+
`,
|
|
35
|
+
}
|
|
36
|
+
},
|
|
33
37
|
} satisfies Meta<typeof Checkbox>
|
|
34
38
|
|
|
35
39
|
export default meta
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
2
3
|
import type { DatePickerType } from './types'
|
|
3
4
|
import Button from '../Button/index.vue'
|
|
4
5
|
import Modal from '../Modal/index.vue'
|
|
@@ -35,18 +36,19 @@ const meta = {
|
|
|
35
36
|
autoApply: true,
|
|
36
37
|
class: '',
|
|
37
38
|
},
|
|
38
|
-
render: args =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
render: args => {
|
|
40
|
+
const onUpdate = useArgsModel()
|
|
41
|
+
return {
|
|
42
|
+
components: { DatePicker },
|
|
43
|
+
setup: () => ({ args, onUpdate }),
|
|
44
|
+
template: `
|
|
45
|
+
<div class="max-w-xs">
|
|
46
|
+
<DatePicker v-bind="args" @update:modelValue="onUpdate" />
|
|
47
|
+
<div class="mt-2 text-sm text-muted-foreground">Value: {{ args.modelValue }}</div>
|
|
48
|
+
</div>
|
|
49
|
+
`,
|
|
50
|
+
}
|
|
51
|
+
},
|
|
50
52
|
} satisfies Meta<typeof DatePicker>
|
|
51
53
|
|
|
52
54
|
export default meta
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
2
3
|
import DateRangePicker from './index.vue'
|
|
3
4
|
|
|
4
5
|
const meta = {
|
|
@@ -34,25 +35,27 @@ const meta = {
|
|
|
34
35
|
autoApply: true,
|
|
35
36
|
class: '',
|
|
36
37
|
},
|
|
37
|
-
render: args =>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<div
|
|
51
|
-
|
|
38
|
+
render: args => {
|
|
39
|
+
const onUpdateStart = useArgsModel('start')
|
|
40
|
+
const onUpdateEnd = useArgsModel('end')
|
|
41
|
+
return {
|
|
42
|
+
components: { DateRangePicker },
|
|
43
|
+
setup: () => ({ args, onUpdateStart, onUpdateEnd }),
|
|
44
|
+
template: `
|
|
45
|
+
<div class="max-w-lg">
|
|
46
|
+
<DateRangePicker
|
|
47
|
+
v-bind="args"
|
|
48
|
+
@update:start="onUpdateStart"
|
|
49
|
+
@update:end="onUpdateEnd"
|
|
50
|
+
/>
|
|
51
|
+
<div class="mt-2 text-sm text-muted-foreground">
|
|
52
|
+
<div>Start: {{ args.start }}</div>
|
|
53
|
+
<div>End: {{ args.end }}</div>
|
|
54
|
+
</div>
|
|
52
55
|
</div>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
+
`,
|
|
57
|
+
}
|
|
58
|
+
},
|
|
56
59
|
} satisfies Meta<typeof DateRangePicker>
|
|
57
60
|
|
|
58
61
|
export default meta
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import Button from '../Button/index.vue'
|
|
4
5
|
import Input from '../Input/index.vue'
|
|
5
6
|
import type { ButtonVariant } from '../Button/types'
|
|
@@ -13,6 +14,7 @@ const meta = {
|
|
|
13
14
|
title: 'UI/Drawer',
|
|
14
15
|
component: Drawer,
|
|
15
16
|
argTypes: {
|
|
17
|
+
visible: { control: 'boolean' },
|
|
16
18
|
loading: { control: 'boolean' },
|
|
17
19
|
disabled: { control: 'boolean' },
|
|
18
20
|
confirmDisabled: { control: 'boolean' },
|
|
@@ -31,6 +33,7 @@ const meta = {
|
|
|
31
33
|
class: { control: 'text' },
|
|
32
34
|
},
|
|
33
35
|
args: {
|
|
36
|
+
visible: false,
|
|
34
37
|
loading: false,
|
|
35
38
|
disabled: false,
|
|
36
39
|
confirmDisabled: false,
|
|
@@ -48,22 +51,22 @@ const meta = {
|
|
|
48
51
|
cancelVariant: 'outline',
|
|
49
52
|
class: '',
|
|
50
53
|
},
|
|
51
|
-
render: args =>
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
</
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
54
|
+
render: args => {
|
|
55
|
+
const onUpdateVisible = useArgsModel('visible')
|
|
56
|
+
return {
|
|
57
|
+
components: { Drawer, Button, Input },
|
|
58
|
+
setup: () => ({ args, onUpdateVisible }),
|
|
59
|
+
template: `
|
|
60
|
+
<div>
|
|
61
|
+
<Button @click="onUpdateVisible(true)">Open Drawer</Button>
|
|
62
|
+
<Drawer v-bind="args" @update:visible="onUpdateVisible">
|
|
63
|
+
<p>This is the drawer content.</p>
|
|
64
|
+
<Input class="mt-4" placeholder="Try interacting with this input" />
|
|
65
|
+
</Drawer>
|
|
66
|
+
</div>
|
|
67
|
+
`,
|
|
68
|
+
}
|
|
69
|
+
},
|
|
67
70
|
} satisfies Meta<typeof Drawer>
|
|
68
71
|
|
|
69
72
|
export default meta
|
|
@@ -11,7 +11,10 @@ import {
|
|
|
11
11
|
} from '../../shadcn/sheet'
|
|
12
12
|
import type { DrawerProps } from './types'
|
|
13
13
|
|
|
14
|
+
defineOptions({ inheritAttrs: false })
|
|
15
|
+
|
|
14
16
|
const props = withDefaults(defineProps<DrawerProps>(), {
|
|
17
|
+
showCancel: true,
|
|
15
18
|
showClose: true,
|
|
16
19
|
closeOnClickOutside: false,
|
|
17
20
|
side: 'right',
|
|
@@ -92,6 +95,7 @@ const contentClass = computed(() =>
|
|
|
92
95
|
</SheetTrigger>
|
|
93
96
|
|
|
94
97
|
<SheetContent
|
|
98
|
+
v-bind="$attrs"
|
|
95
99
|
:side="side"
|
|
96
100
|
:class="contentClass"
|
|
97
101
|
@pointerDownOutside="onPointerDownOutside"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import Icon from '../Icon/index.vue'
|
|
4
5
|
import Input from './index.vue'
|
|
5
6
|
|
|
@@ -22,13 +23,14 @@ const meta = {
|
|
|
22
23
|
invalid: false,
|
|
23
24
|
class: 'max-w-sm',
|
|
24
25
|
},
|
|
25
|
-
render: args =>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
render: args => {
|
|
27
|
+
const onUpdate = useArgsModel()
|
|
28
|
+
return {
|
|
29
|
+
components: { Input },
|
|
30
|
+
setup: () => ({ args, onUpdate }),
|
|
31
|
+
template: '<Input v-bind="args" placeholder="Type something..." @update:modelValue="onUpdate" />',
|
|
32
|
+
}
|
|
33
|
+
},
|
|
32
34
|
} satisfies Meta<typeof Input>
|
|
33
35
|
|
|
34
36
|
export default meta
|
|
@@ -1,33 +1,36 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
2
3
|
import InputCurrency from './index.vue'
|
|
3
4
|
|
|
4
5
|
const currencyDisplays = [ 'symbol', 'narrowSymbol', 'code', 'name' ] as const
|
|
5
6
|
|
|
6
7
|
const meta = {
|
|
7
8
|
title: 'UI/InputCurrency',
|
|
8
|
-
component: InputCurrency,
|
|
9
|
+
component: InputCurrency as any,
|
|
9
10
|
argTypes: {
|
|
11
|
+
modelValue: { control: 'number' },
|
|
10
12
|
currency: { control: 'text' },
|
|
11
13
|
currencyDisplay: { control: 'select', options: currencyDisplays },
|
|
12
14
|
},
|
|
13
15
|
args: {
|
|
16
|
+
modelValue: 1000,
|
|
14
17
|
currency: 'JPY',
|
|
15
18
|
currencyDisplay: 'symbol',
|
|
16
19
|
},
|
|
17
|
-
render: args =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
} satisfies Meta
|
|
20
|
+
render: args => {
|
|
21
|
+
const onUpdate = useArgsModel()
|
|
22
|
+
return {
|
|
23
|
+
components: { InputCurrency },
|
|
24
|
+
setup: () => ({ args, onUpdate }),
|
|
25
|
+
template: `
|
|
26
|
+
<div class="max-w-xs">
|
|
27
|
+
<InputCurrency v-bind="args" @update:modelValue="onUpdate" />
|
|
28
|
+
<div class="mt-2 text-sm text-muted-foreground">Value: {{ args.modelValue }}</div>
|
|
29
|
+
</div>
|
|
30
|
+
`,
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
} satisfies Meta
|
|
31
34
|
|
|
32
35
|
export default meta
|
|
33
36
|
type Story = StoryObj<typeof meta>
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import InputNumber from './index.vue'
|
|
4
5
|
|
|
5
6
|
const meta = {
|
|
6
7
|
title: 'UI/InputNumber',
|
|
7
8
|
component: InputNumber,
|
|
8
9
|
argTypes: {
|
|
10
|
+
modelValue: { control: 'number' },
|
|
9
11
|
min: { control: 'number' },
|
|
10
12
|
max: { control: 'number' },
|
|
11
13
|
step: { control: 'number' },
|
|
@@ -15,6 +17,7 @@ const meta = {
|
|
|
15
17
|
invalid: { control: 'boolean' },
|
|
16
18
|
},
|
|
17
19
|
args: {
|
|
20
|
+
modelValue: 0,
|
|
18
21
|
min: undefined,
|
|
19
22
|
max: undefined,
|
|
20
23
|
step: 1,
|
|
@@ -23,19 +26,19 @@ const meta = {
|
|
|
23
26
|
disabled: false,
|
|
24
27
|
invalid: false,
|
|
25
28
|
},
|
|
26
|
-
render: args =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
29
|
+
render: args => {
|
|
30
|
+
const onUpdate = useArgsModel()
|
|
31
|
+
return {
|
|
32
|
+
components: { InputNumber },
|
|
33
|
+
setup: () => ({ args, onUpdate }),
|
|
34
|
+
template: `
|
|
35
|
+
<div class="max-w-xs">
|
|
36
|
+
<InputNumber v-bind="args" @update:modelValue="onUpdate" />
|
|
37
|
+
<div class="mt-2 text-sm text-muted-foreground">Value: {{ args.modelValue }}</div>
|
|
38
|
+
</div>
|
|
39
|
+
`,
|
|
40
|
+
}
|
|
41
|
+
},
|
|
39
42
|
} satisfies Meta<typeof InputNumber>
|
|
40
43
|
|
|
41
44
|
export default meta
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import InputOtp from './index.vue'
|
|
4
5
|
|
|
5
6
|
const meta = {
|
|
@@ -15,18 +16,19 @@ const meta = {
|
|
|
15
16
|
length: 6,
|
|
16
17
|
disabled: false,
|
|
17
18
|
},
|
|
18
|
-
render: args =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
render: args => {
|
|
20
|
+
const onUpdate = useArgsModel()
|
|
21
|
+
return {
|
|
22
|
+
components: { InputOtp },
|
|
23
|
+
setup: () => ({ args, onUpdate }),
|
|
24
|
+
template: `
|
|
25
|
+
<div class="space-y-4">
|
|
26
|
+
<InputOtp v-bind="args" @update:modelValue="onUpdate" />
|
|
27
|
+
<div class="text-sm text-muted-foreground">Value: {{ args.modelValue }}</div>
|
|
28
|
+
</div>
|
|
29
|
+
`,
|
|
30
|
+
}
|
|
31
|
+
},
|
|
30
32
|
} satisfies Meta<typeof InputOtp>
|
|
31
33
|
|
|
32
34
|
export default meta
|
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
2
3
|
import InputPercent from './index.vue'
|
|
3
4
|
|
|
4
5
|
const meta = {
|
|
5
6
|
title: 'UI/InputPercent',
|
|
6
|
-
component: InputPercent,
|
|
7
|
-
argTypes: {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
7
|
+
component: InputPercent as any,
|
|
8
|
+
argTypes: {
|
|
9
|
+
modelValue: { control: 'number' },
|
|
10
|
+
},
|
|
11
|
+
args: {
|
|
12
|
+
modelValue: 0.5,
|
|
13
|
+
},
|
|
14
|
+
render: args => {
|
|
15
|
+
const onUpdate = useArgsModel()
|
|
16
|
+
return {
|
|
17
|
+
components: { InputPercent },
|
|
18
|
+
setup: () => ({ args, onUpdate }),
|
|
19
|
+
template: `
|
|
20
|
+
<div class="max-w-xs space-y-4">
|
|
21
|
+
<InputPercent v-bind="args" @update:modelValue="onUpdate" />
|
|
22
|
+
<div class="text-sm text-muted-foreground">Value: {{ args.modelValue }}</div>
|
|
23
|
+
</div>
|
|
24
|
+
`,
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
} satisfies Meta
|
|
23
28
|
|
|
24
29
|
export default meta
|
|
25
30
|
type Story = StoryObj<typeof meta>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import InputRange from './index.vue'
|
|
4
5
|
|
|
5
6
|
const meta = {
|
|
@@ -23,22 +24,24 @@ const meta = {
|
|
|
23
24
|
endPlaceholder: '',
|
|
24
25
|
disabled: false,
|
|
25
26
|
},
|
|
26
|
-
render: args =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
render: args => {
|
|
28
|
+
const onUpdateStart = useArgsModel('start')
|
|
29
|
+
const onUpdateEnd = useArgsModel('end')
|
|
30
|
+
return {
|
|
31
|
+
components: { InputRange },
|
|
32
|
+
setup: () => ({ args, onUpdateStart, onUpdateEnd }),
|
|
33
|
+
template: `
|
|
34
|
+
<div class="max-w-md">
|
|
35
|
+
<InputRange
|
|
36
|
+
v-bind="args"
|
|
37
|
+
@update:start="onUpdateStart"
|
|
38
|
+
@update:end="onUpdateEnd"
|
|
39
|
+
/>
|
|
40
|
+
<div class="mt-2 text-sm text-muted-foreground">Start: {{ args.start }}, End: {{ args.end }}</div>
|
|
41
|
+
</div>
|
|
42
|
+
`,
|
|
43
|
+
}
|
|
44
|
+
},
|
|
42
45
|
} satisfies Meta<typeof InputRange>
|
|
43
46
|
|
|
44
47
|
export default meta
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import type { ModalContentType } from '../ModalContent/types'
|
|
3
3
|
import EventLog from '#storybook/EventLog.vue'
|
|
4
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
4
5
|
import Button from '../Button/index.vue'
|
|
5
6
|
import Input from '../Input/index.vue'
|
|
6
7
|
import Modal from './index.vue'
|
|
@@ -11,6 +12,7 @@ const meta = {
|
|
|
11
12
|
title: 'UI/Modal',
|
|
12
13
|
component: Modal,
|
|
13
14
|
argTypes: {
|
|
15
|
+
visible: { control: 'boolean' },
|
|
14
16
|
loading: { control: 'boolean' },
|
|
15
17
|
disabled: { control: 'boolean' },
|
|
16
18
|
confirmDisabled: { control: 'boolean' },
|
|
@@ -27,6 +29,7 @@ const meta = {
|
|
|
27
29
|
cancelText: { control: 'text' },
|
|
28
30
|
},
|
|
29
31
|
args: {
|
|
32
|
+
visible: false,
|
|
30
33
|
loading: false,
|
|
31
34
|
disabled: false,
|
|
32
35
|
confirmDisabled: false,
|
|
@@ -42,22 +45,22 @@ const meta = {
|
|
|
42
45
|
confirmText: 'OK',
|
|
43
46
|
cancelText: 'Cancel',
|
|
44
47
|
},
|
|
45
|
-
render: args =>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
</
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
48
|
+
render: args => {
|
|
49
|
+
const onUpdateVisible = useArgsModel('visible')
|
|
50
|
+
return {
|
|
51
|
+
components: { Modal, Button, Input },
|
|
52
|
+
setup: () => ({ args, onUpdateVisible }),
|
|
53
|
+
template: `
|
|
54
|
+
<div>
|
|
55
|
+
<Button @click="onUpdateVisible(true)">Open Modal</Button>
|
|
56
|
+
<Modal v-bind="args" @update:visible="onUpdateVisible">
|
|
57
|
+
<p>This is the modal content.</p>
|
|
58
|
+
<Input class="mt-4" placeholder="Try interacting with this input" />
|
|
59
|
+
</Modal>
|
|
60
|
+
</div>
|
|
61
|
+
`,
|
|
62
|
+
}
|
|
63
|
+
},
|
|
61
64
|
} satisfies Meta<typeof Modal>
|
|
62
65
|
|
|
63
66
|
export default meta
|
|
@@ -11,7 +11,10 @@ import {
|
|
|
11
11
|
} from '../../shadcn/dialog'
|
|
12
12
|
import type { ModalProps } from './types'
|
|
13
13
|
|
|
14
|
+
defineOptions({ inheritAttrs: false })
|
|
15
|
+
|
|
14
16
|
const props = withDefaults(defineProps<ModalProps>(), {
|
|
17
|
+
showCancel: true,
|
|
15
18
|
showClose: true,
|
|
16
19
|
closeOnClickOutside: false,
|
|
17
20
|
title: undefined,
|
|
@@ -97,6 +100,7 @@ const contentClass = computed(() =>
|
|
|
97
100
|
</DialogTrigger>
|
|
98
101
|
|
|
99
102
|
<DialogContent
|
|
103
|
+
v-bind="$attrs"
|
|
100
104
|
:class="contentClass"
|
|
101
105
|
:showCloseButton="false"
|
|
102
106
|
@pointerDownOutside="onPointerDownOutside"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import Pagination from './index.vue'
|
|
4
5
|
|
|
5
6
|
const sizes = [ 'default', 'sm' ] as const
|
|
@@ -25,11 +26,15 @@ const meta = {
|
|
|
25
26
|
siblingCount: 1,
|
|
26
27
|
size: 'default',
|
|
27
28
|
},
|
|
28
|
-
render: args =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
render: args => {
|
|
30
|
+
const onUpdatePage = useArgsModel('page')
|
|
31
|
+
const onUpdatePageSize = useArgsModel('pageSize')
|
|
32
|
+
return {
|
|
33
|
+
components: { Pagination },
|
|
34
|
+
setup: () => ({ args, onUpdatePage, onUpdatePageSize }),
|
|
35
|
+
template: '<Pagination v-bind="args" @update:page="onUpdatePage" @update:pageSize="onUpdatePageSize" />',
|
|
36
|
+
}
|
|
37
|
+
},
|
|
33
38
|
} satisfies Meta<typeof Pagination>
|
|
34
39
|
|
|
35
40
|
export default meta
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import type { RadioCardGroupOption } from './types'
|
|
4
5
|
import RadioCardGroup from './index.vue'
|
|
5
6
|
|
|
@@ -48,18 +49,19 @@ const meta = {
|
|
|
48
49
|
options,
|
|
49
50
|
disabled: false,
|
|
50
51
|
},
|
|
51
|
-
render: args =>
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
52
|
+
render: args => {
|
|
53
|
+
const onUpdate = useArgsModel()
|
|
54
|
+
return {
|
|
55
|
+
components: { RadioCardGroup },
|
|
56
|
+
setup: () => ({ args, onUpdate }),
|
|
57
|
+
template: `
|
|
58
|
+
<div class="max-w-md space-y-4">
|
|
59
|
+
<RadioCardGroup v-bind="args" @update:modelValue="onUpdate" />
|
|
60
|
+
<div class="text-sm text-muted-foreground">Selected: {{ args.modelValue }}</div>
|
|
61
|
+
</div>
|
|
62
|
+
`,
|
|
63
|
+
}
|
|
64
|
+
},
|
|
63
65
|
} satisfies Meta<typeof RadioCardGroup>
|
|
64
66
|
|
|
65
67
|
export default meta
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {
|
|
3
|
-
RadioGroup,
|
|
4
|
-
RadioGroupItem,
|
|
3
|
+
RadioGroup as ShadcnRadioGroup,
|
|
4
|
+
RadioGroupItem as ShadcnRadioGroupItem,
|
|
5
5
|
} from '../../shadcn/radio-group'
|
|
6
6
|
import type { RadioCardGroupProps } from './types'
|
|
7
7
|
|
|
@@ -26,7 +26,7 @@ const mergedClass = computed(() => cn('gap-3', props.class))
|
|
|
26
26
|
</script>
|
|
27
27
|
|
|
28
28
|
<template>
|
|
29
|
-
<
|
|
29
|
+
<ShadcnRadioGroup
|
|
30
30
|
v-model="model"
|
|
31
31
|
:disabled="disabled"
|
|
32
32
|
:class="mergedClass"
|
|
@@ -35,20 +35,20 @@ const mergedClass = computed(() => cn('gap-3', props.class))
|
|
|
35
35
|
v-for="option in options"
|
|
36
36
|
:key="option.value"
|
|
37
37
|
class="
|
|
38
|
-
|
|
39
|
-
px-4 py-3 transition-colors
|
|
40
|
-
has-data-disabled:cursor-not-allowed has-data-disabled:opacity-50
|
|
38
|
+
gap-3 rounded-lg border-border px-4 py-3
|
|
41
39
|
has-data-[state=checked]:border-primary
|
|
40
|
+
flex cursor-pointer items-center border transition-colors
|
|
41
|
+
has-data-disabled:cursor-not-allowed has-data-disabled:opacity-50
|
|
42
42
|
"
|
|
43
43
|
:class="[
|
|
44
44
|
option.disabled ? 'cursor-not-allowed opacity-50' : 'hover:bg-accent/50',
|
|
45
45
|
]"
|
|
46
46
|
>
|
|
47
|
-
<
|
|
47
|
+
<ShadcnRadioGroupItem
|
|
48
48
|
:value="option.value"
|
|
49
49
|
:disabled="option.disabled"
|
|
50
50
|
/>
|
|
51
|
-
<div class="grid flex-1
|
|
51
|
+
<div class="gap-0.5 grid flex-1">
|
|
52
52
|
<span class="text-sm font-medium">
|
|
53
53
|
{{ option.title }}
|
|
54
54
|
</span>
|
|
@@ -60,5 +60,5 @@ const mergedClass = computed(() => cn('gap-3', props.class))
|
|
|
60
60
|
</span>
|
|
61
61
|
</div>
|
|
62
62
|
</label>
|
|
63
|
-
</
|
|
63
|
+
</ShadcnRadioGroup>
|
|
64
64
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import type { RadioGroupItem } from './types'
|
|
4
5
|
import RadioGroup from './index.vue'
|
|
5
6
|
|
|
@@ -30,11 +31,14 @@ const meta = {
|
|
|
30
31
|
disabled: false,
|
|
31
32
|
orientation: 'vertical',
|
|
32
33
|
},
|
|
33
|
-
render: args =>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
render: args => {
|
|
35
|
+
const onUpdate = useArgsModel()
|
|
36
|
+
return {
|
|
37
|
+
components: { RadioGroup },
|
|
38
|
+
setup: () => ({ args, onUpdate }),
|
|
39
|
+
template: '<RadioGroup v-bind="args" @update:modelValue="onUpdate" />',
|
|
40
|
+
}
|
|
41
|
+
},
|
|
38
42
|
} satisfies Meta<typeof RadioGroup>
|
|
39
43
|
|
|
40
44
|
export default meta
|
|
@@ -59,15 +59,15 @@ const mergedClass = computed(() => cn(
|
|
|
59
59
|
:value="item.value"
|
|
60
60
|
:disabled="item.disabled"
|
|
61
61
|
/>
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
>
|
|
62
|
+
<slot
|
|
63
|
+
name="label"
|
|
64
|
+
:item="item"
|
|
65
|
+
:checked="model === item.value"
|
|
66
|
+
>
|
|
67
|
+
<span class="text-sm">
|
|
68
68
|
{{ item.label || item.value }}
|
|
69
|
-
</
|
|
70
|
-
</
|
|
69
|
+
</span>
|
|
70
|
+
</slot>
|
|
71
71
|
</label>
|
|
72
72
|
</ShadcnRadioGroup>
|
|
73
73
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import type { SearchSelectLoadMethodParams, SearchSelectLoadMethodResult } from './types'
|
|
4
5
|
import SearchSelect from './index.vue'
|
|
5
6
|
|
|
@@ -41,6 +42,7 @@ const meta = {
|
|
|
41
42
|
title: 'UI/SearchSelect',
|
|
42
43
|
component: SearchSelect as any,
|
|
43
44
|
argTypes: {
|
|
45
|
+
modelValue: { control: 'text' },
|
|
44
46
|
placeholder: { control: 'text' },
|
|
45
47
|
searchPlaceholder: { control: 'text' },
|
|
46
48
|
emptyText: { control: 'text' },
|
|
@@ -52,6 +54,7 @@ const meta = {
|
|
|
52
54
|
disabled: { control: 'boolean' },
|
|
53
55
|
},
|
|
54
56
|
args: {
|
|
57
|
+
modelValue: undefined,
|
|
55
58
|
placeholder: '',
|
|
56
59
|
searchPlaceholder: '',
|
|
57
60
|
emptyText: '',
|
|
@@ -62,23 +65,23 @@ const meta = {
|
|
|
62
65
|
autoLoad: false,
|
|
63
66
|
disabled: false,
|
|
64
67
|
},
|
|
65
|
-
render: args =>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
68
|
+
render: args => {
|
|
69
|
+
const onUpdate = useArgsModel()
|
|
70
|
+
return {
|
|
71
|
+
components: { SearchSelect },
|
|
72
|
+
setup: () => ({ args, onUpdate, mockLoadMethod }),
|
|
73
|
+
template: `
|
|
74
|
+
<div class="max-w-sm">
|
|
75
|
+
<SearchSelect
|
|
76
|
+
v-bind="args"
|
|
77
|
+
:loadMethod="mockLoadMethod"
|
|
78
|
+
@update:modelValue="onUpdate"
|
|
79
|
+
/>
|
|
80
|
+
<div class="mt-2 text-sm text-muted-foreground">Selected: {{ args.modelValue ?? 'none' }}</div>
|
|
81
|
+
</div>
|
|
82
|
+
`,
|
|
83
|
+
}
|
|
84
|
+
},
|
|
82
85
|
} satisfies Meta
|
|
83
86
|
|
|
84
87
|
export default meta
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import Select from './index.vue'
|
|
4
5
|
|
|
5
6
|
const frameworks = [
|
|
@@ -34,6 +35,7 @@ const meta = {
|
|
|
34
35
|
title: 'UI/Select',
|
|
35
36
|
component: Select as any,
|
|
36
37
|
argTypes: {
|
|
38
|
+
modelValue: { control: 'text' },
|
|
37
39
|
placeholder: { control: 'text' },
|
|
38
40
|
disabled: { control: 'boolean' },
|
|
39
41
|
loading: { control: 'boolean' },
|
|
@@ -43,6 +45,7 @@ const meta = {
|
|
|
43
45
|
emptyText: { control: 'text' },
|
|
44
46
|
},
|
|
45
47
|
args: {
|
|
48
|
+
modelValue: undefined,
|
|
46
49
|
placeholder: 'Select an option',
|
|
47
50
|
disabled: false,
|
|
48
51
|
loading: false,
|
|
@@ -51,19 +54,19 @@ const meta = {
|
|
|
51
54
|
searchPlaceholder: '',
|
|
52
55
|
emptyText: '',
|
|
53
56
|
},
|
|
54
|
-
render: args =>
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
57
|
+
render: args => {
|
|
58
|
+
const onUpdate = useArgsModel()
|
|
59
|
+
return {
|
|
60
|
+
components: { Select },
|
|
61
|
+
setup: () => ({ args, onUpdate, frameworks }),
|
|
62
|
+
template: `
|
|
63
|
+
<div class="max-w-sm">
|
|
64
|
+
<Select v-bind="args" :options="frameworks" @update:modelValue="onUpdate" />
|
|
65
|
+
<div class="mt-2 text-sm text-muted-foreground">Selected: {{ args.modelValue ?? 'none' }}</div>
|
|
66
|
+
</div>
|
|
67
|
+
`,
|
|
68
|
+
}
|
|
69
|
+
},
|
|
67
70
|
} satisfies Meta
|
|
68
71
|
|
|
69
72
|
export default meta
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import Slider from './index.vue'
|
|
4
5
|
|
|
5
6
|
const meta = {
|
|
6
7
|
title: 'UI/Slider',
|
|
7
8
|
component: Slider,
|
|
8
9
|
argTypes: {
|
|
10
|
+
modelValue: { control: 'number' },
|
|
9
11
|
min: { control: 'number' },
|
|
10
12
|
max: { control: 'number' },
|
|
11
13
|
step: { control: 'number' },
|
|
@@ -13,25 +15,26 @@ const meta = {
|
|
|
13
15
|
orientation: { control: 'select', options: [ 'horizontal', 'vertical' ]},
|
|
14
16
|
},
|
|
15
17
|
args: {
|
|
18
|
+
modelValue: 50,
|
|
16
19
|
min: 0,
|
|
17
20
|
max: 100,
|
|
18
21
|
step: 1,
|
|
19
22
|
disabled: false,
|
|
20
23
|
orientation: 'horizontal',
|
|
21
24
|
},
|
|
22
|
-
render: args =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
25
|
+
render: args => {
|
|
26
|
+
const onUpdate = useArgsModel()
|
|
27
|
+
return {
|
|
28
|
+
components: { Slider },
|
|
29
|
+
setup: () => ({ args, onUpdate }),
|
|
30
|
+
template: `
|
|
31
|
+
<div class="max-w-sm">
|
|
32
|
+
<Slider v-bind="args" @update:modelValue="onUpdate" />
|
|
33
|
+
<div class="mt-2 text-sm text-muted-foreground">Value: {{ args.modelValue }}</div>
|
|
34
|
+
</div>
|
|
35
|
+
`,
|
|
36
|
+
}
|
|
37
|
+
},
|
|
35
38
|
} satisfies Meta<typeof Slider>
|
|
36
39
|
|
|
37
40
|
export default meta
|
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import Switch from './index.vue'
|
|
4
5
|
|
|
5
6
|
const meta = {
|
|
6
7
|
title: 'UI/Switch',
|
|
7
8
|
component: Switch,
|
|
8
9
|
argTypes: {
|
|
10
|
+
modelValue: { control: 'boolean' },
|
|
9
11
|
disabled: { control: 'boolean' },
|
|
10
12
|
},
|
|
11
13
|
args: {
|
|
14
|
+
modelValue: true,
|
|
12
15
|
disabled: false,
|
|
13
16
|
},
|
|
14
|
-
render: args =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
17
|
+
render: args => {
|
|
18
|
+
const onUpdate = useArgsModel()
|
|
19
|
+
return {
|
|
20
|
+
components: { Switch },
|
|
21
|
+
setup: () => ({ args, onUpdate }),
|
|
22
|
+
template: `
|
|
23
|
+
<div class="flex items-center gap-4">
|
|
24
|
+
<Switch v-bind="args" @update:modelValue="onUpdate" />
|
|
25
|
+
<div class="text-sm text-muted-foreground">Value: {{ args.modelValue }}</div>
|
|
26
|
+
</div>
|
|
27
|
+
`,
|
|
28
|
+
}
|
|
29
|
+
},
|
|
27
30
|
} satisfies Meta<typeof Switch>
|
|
28
31
|
|
|
29
32
|
export default meta
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import Card from '../Card/index.vue'
|
|
4
5
|
import type { TabsItem } from './types'
|
|
5
6
|
import Tabs from './index.vue'
|
|
@@ -52,11 +53,14 @@ const meta = {
|
|
|
52
53
|
listClass: '',
|
|
53
54
|
triggerClass: '',
|
|
54
55
|
},
|
|
55
|
-
render: args =>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
render: args => {
|
|
57
|
+
const onUpdate = useArgsModel()
|
|
58
|
+
return {
|
|
59
|
+
components: { Tabs },
|
|
60
|
+
setup: () => ({ args, onUpdate }),
|
|
61
|
+
template: '<Tabs v-bind="args" class="max-w-md" @update:modelValue="onUpdate" />',
|
|
62
|
+
}
|
|
63
|
+
},
|
|
60
64
|
} satisfies Meta<typeof Tabs>
|
|
61
65
|
|
|
62
66
|
export default meta
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import EventLog from '#storybook/EventLog.vue'
|
|
3
|
+
import { useArgsModel } from '#storybook/argsModel'
|
|
3
4
|
import Textarea from './index.vue'
|
|
4
5
|
|
|
5
6
|
const meta = {
|
|
@@ -19,15 +20,18 @@ const meta = {
|
|
|
19
20
|
invalid: false,
|
|
20
21
|
class: '',
|
|
21
22
|
},
|
|
22
|
-
render: args =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
render: args => {
|
|
24
|
+
const onUpdate = useArgsModel()
|
|
25
|
+
return {
|
|
26
|
+
components: { Textarea },
|
|
27
|
+
setup: () => ({ args, onUpdate }),
|
|
28
|
+
template: `
|
|
29
|
+
<div class="max-w-sm">
|
|
30
|
+
<Textarea v-bind="args" placeholder="Type your message here..." @update:modelValue="onUpdate" />
|
|
31
|
+
</div>
|
|
32
|
+
`,
|
|
33
|
+
}
|
|
34
|
+
},
|
|
31
35
|
} satisfies Meta<typeof Textarea>
|
|
32
36
|
|
|
33
37
|
export default meta
|
|
@@ -18,6 +18,7 @@ interface DialogQueueItem {
|
|
|
18
18
|
|
|
19
19
|
const dialogQueue = reactive<DialogQueueItem[]>([])
|
|
20
20
|
const isOpen = ref(false)
|
|
21
|
+
const mountedInstances = ref<symbol[]>([])
|
|
21
22
|
|
|
22
23
|
function showDialog (options: DialogOptions): Promise<boolean> {
|
|
23
24
|
return new Promise<boolean>(resolve => {
|
|
@@ -52,8 +53,22 @@ export function useDialog () {
|
|
|
52
53
|
|
|
53
54
|
/**
|
|
54
55
|
* Internal composable for the AlertDialog component to access dialog queue.
|
|
56
|
+
*
|
|
57
|
+
* Multiple `<AlertDialog />` instances can be mounted simultaneously (e.g. in
|
|
58
|
+
* Storybook docs view), but only the first one renders the modal — the rest
|
|
59
|
+
* stay inert via `isActive`. This prevents stacked overlays and duplicate
|
|
60
|
+
* `onClosed` events from over-shifting the shared queue.
|
|
55
61
|
*/
|
|
56
62
|
export function useDialogState () {
|
|
63
|
+
const id = Symbol('AlertDialog')
|
|
64
|
+
mountedInstances.value.push(id)
|
|
65
|
+
|
|
66
|
+
onScopeDispose(() => {
|
|
67
|
+
const idx = mountedInstances.value.indexOf(id)
|
|
68
|
+
if (idx >= 0) mountedInstances.value.splice(idx, 1)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const isActive = computed(() => mountedInstances.value[0] === id)
|
|
57
72
|
const current = computed(() => dialogQueue[0] ?? null)
|
|
58
73
|
|
|
59
74
|
/** Resolve current dialog and trigger close animation */
|
|
@@ -72,5 +87,5 @@ export function useDialogState () {
|
|
|
72
87
|
}
|
|
73
88
|
}
|
|
74
89
|
|
|
75
|
-
return { current, isOpen, close, onClosed }
|
|
90
|
+
return { current, isOpen, isActive, close, onClosed }
|
|
76
91
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polymarbot/nuxt-layer-shadcn-ui",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Nuxt layer providing shadcn-vue based UI components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./nuxt.config.ts",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"vue-i18n": "^11",
|
|
43
43
|
"vue-router": "^4 || ^5"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "f3a22e25c23b87c559dba70c2227bc02c6167baf"
|
|
46
46
|
}
|