@polymarbot/nuxt-layer-shadcn-ui 0.1.10 → 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/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
|
@@ -15,7 +15,7 @@ const options: RadioCardGroupOption[] = [
|
|
|
15
15
|
},
|
|
16
16
|
]
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const planOptions: RadioCardGroupOption[] = [
|
|
19
19
|
{
|
|
20
20
|
value: 'free',
|
|
21
21
|
title: 'Free',
|
|
@@ -38,53 +38,44 @@ const meta = {
|
|
|
38
38
|
title: 'UI/RadioCardGroup',
|
|
39
39
|
component: RadioCardGroup,
|
|
40
40
|
argTypes: {
|
|
41
|
+
modelValue: { control: 'text' },
|
|
42
|
+
options: { control: 'object' },
|
|
41
43
|
disabled: { control: 'boolean' },
|
|
42
44
|
},
|
|
43
45
|
args: {
|
|
46
|
+
modelValue: 'current',
|
|
44
47
|
options,
|
|
45
48
|
disabled: false,
|
|
46
49
|
},
|
|
47
|
-
} satisfies Meta<typeof RadioCardGroup>
|
|
48
|
-
|
|
49
|
-
export default meta
|
|
50
|
-
type Story = StoryObj<typeof meta>
|
|
51
|
-
|
|
52
|
-
export const Default: Story = {
|
|
53
50
|
render: args => ({
|
|
54
51
|
components: { RadioCardGroup },
|
|
55
52
|
setup () {
|
|
56
|
-
const selected = ref('
|
|
57
|
-
return { args, selected
|
|
53
|
+
const selected = ref(args.modelValue ?? '')
|
|
54
|
+
return { args, selected }
|
|
58
55
|
},
|
|
59
56
|
template: `
|
|
60
57
|
<div class="max-w-md space-y-4">
|
|
61
|
-
<RadioCardGroup
|
|
62
|
-
v-model="selected"
|
|
63
|
-
:options="options"
|
|
64
|
-
:disabled="args.disabled"
|
|
65
|
-
/>
|
|
58
|
+
<RadioCardGroup v-bind="args" v-model="selected" />
|
|
66
59
|
<div class="text-sm text-muted-foreground">Selected: {{ selected }}</div>
|
|
67
60
|
</div>
|
|
68
61
|
`,
|
|
69
62
|
}),
|
|
70
|
-
}
|
|
63
|
+
} satisfies Meta<typeof RadioCardGroup>
|
|
64
|
+
|
|
65
|
+
export default meta
|
|
66
|
+
type Story = StoryObj<typeof meta>
|
|
67
|
+
|
|
68
|
+
export const Default: Story = {}
|
|
71
69
|
|
|
72
70
|
export const WithDisabledOption: Story = {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
:options="manyOptions"
|
|
84
|
-
:disabled="args.disabled"
|
|
85
|
-
/>
|
|
86
|
-
<div class="text-sm text-muted-foreground">Selected: {{ selected }}</div>
|
|
87
|
-
</div>
|
|
88
|
-
`,
|
|
89
|
-
}),
|
|
71
|
+
args: {
|
|
72
|
+
modelValue: 'pro',
|
|
73
|
+
options: planOptions,
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const Disabled: Story = {
|
|
78
|
+
args: {
|
|
79
|
+
disabled: true,
|
|
80
|
+
},
|
|
90
81
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
RadioGroup,
|
|
4
4
|
RadioGroupItem,
|
|
5
|
-
} from '
|
|
5
|
+
} from '../../shadcn/radio-group'
|
|
6
6
|
import type { RadioCardGroupProps } from './types'
|
|
7
7
|
|
|
8
8
|
const props = withDefaults(defineProps<RadioCardGroupProps>(), {
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import type { RadioGroupItem } from './types'
|
|
3
|
+
import RadioGroup from './index.vue'
|
|
4
|
+
|
|
5
|
+
const options: RadioGroupItem[] = [
|
|
6
|
+
{ value: 'option1', label: 'Option 1' },
|
|
7
|
+
{ value: 'option2', label: 'Option 2' },
|
|
8
|
+
{ value: 'option3', label: 'Option 3' },
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
const plans: RadioGroupItem[] = [
|
|
12
|
+
{ value: 'free', label: 'Free - $0/month' },
|
|
13
|
+
{ value: 'pro', label: 'Pro - $9/month' },
|
|
14
|
+
{ value: 'enterprise', label: 'Enterprise - $29/month', disabled: true },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
const meta = {
|
|
18
|
+
title: 'UI/RadioGroup',
|
|
19
|
+
component: RadioGroup,
|
|
20
|
+
argTypes: {
|
|
21
|
+
items: { control: 'object' },
|
|
22
|
+
modelValue: { control: 'text' },
|
|
23
|
+
disabled: { control: 'boolean' },
|
|
24
|
+
orientation: { control: 'inline-radio', options: [ 'vertical', 'horizontal' ]},
|
|
25
|
+
},
|
|
26
|
+
args: {
|
|
27
|
+
items: options,
|
|
28
|
+
modelValue: 'option1',
|
|
29
|
+
disabled: false,
|
|
30
|
+
orientation: 'vertical',
|
|
31
|
+
},
|
|
32
|
+
render: args => ({
|
|
33
|
+
components: { RadioGroup },
|
|
34
|
+
setup: () => ({ args }),
|
|
35
|
+
template: '<RadioGroup v-bind="args" />',
|
|
36
|
+
}),
|
|
37
|
+
} satisfies Meta<typeof RadioGroup>
|
|
38
|
+
|
|
39
|
+
export default meta
|
|
40
|
+
type Story = StoryObj<typeof meta>
|
|
41
|
+
|
|
42
|
+
export const Default: Story = {}
|
|
43
|
+
|
|
44
|
+
export const Controlled: Story = {
|
|
45
|
+
render: () => ({
|
|
46
|
+
components: { RadioGroup },
|
|
47
|
+
setup () {
|
|
48
|
+
const selected = ref('option1')
|
|
49
|
+
return { options, selected }
|
|
50
|
+
},
|
|
51
|
+
template: `
|
|
52
|
+
<div class="space-y-2">
|
|
53
|
+
<RadioGroup v-model="selected" :items="options" />
|
|
54
|
+
<div class="text-sm text-muted-foreground">Selected: {{ selected }}</div>
|
|
55
|
+
</div>
|
|
56
|
+
`,
|
|
57
|
+
}),
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const Horizontal: Story = {
|
|
61
|
+
render: () => ({
|
|
62
|
+
components: { RadioGroup },
|
|
63
|
+
setup () {
|
|
64
|
+
const selected = ref('option1')
|
|
65
|
+
return { options, selected }
|
|
66
|
+
},
|
|
67
|
+
template: `
|
|
68
|
+
<div class="space-y-2">
|
|
69
|
+
<RadioGroup v-model="selected" :items="options" orientation="horizontal" />
|
|
70
|
+
<div class="text-sm text-muted-foreground">Selected: {{ selected }}</div>
|
|
71
|
+
</div>
|
|
72
|
+
`,
|
|
73
|
+
}),
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const WithDisabledItem: Story = {
|
|
77
|
+
render: () => ({
|
|
78
|
+
components: { RadioGroup },
|
|
79
|
+
setup () {
|
|
80
|
+
const plan = ref('pro')
|
|
81
|
+
return { plans, plan }
|
|
82
|
+
},
|
|
83
|
+
template: `
|
|
84
|
+
<div class="space-y-2">
|
|
85
|
+
<RadioGroup v-model="plan" :items="plans" />
|
|
86
|
+
<div class="text-sm text-muted-foreground">Plan: {{ plan }}</div>
|
|
87
|
+
</div>
|
|
88
|
+
`,
|
|
89
|
+
}),
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const Disabled: Story = {
|
|
93
|
+
render: () => ({
|
|
94
|
+
components: { RadioGroup },
|
|
95
|
+
setup () {
|
|
96
|
+
const selected = ref('option1')
|
|
97
|
+
return { options, selected }
|
|
98
|
+
},
|
|
99
|
+
template: '<RadioGroup v-model="selected" :items="options" disabled />',
|
|
100
|
+
}),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const CustomSlots: Story = {
|
|
104
|
+
render: () => ({
|
|
105
|
+
components: { RadioGroup },
|
|
106
|
+
setup () {
|
|
107
|
+
const plan = ref('pro')
|
|
108
|
+
return { plans, plan }
|
|
109
|
+
},
|
|
110
|
+
template: `
|
|
111
|
+
<div class="space-y-2">
|
|
112
|
+
<RadioGroup v-model="plan" :items="plans">
|
|
113
|
+
<template #label="{ item, checked }">
|
|
114
|
+
<span :class="checked ? 'font-semibold text-primary' : 'text-foreground'">
|
|
115
|
+
{{ item.label }}
|
|
116
|
+
</span>
|
|
117
|
+
</template>
|
|
118
|
+
</RadioGroup>
|
|
119
|
+
<div class="text-sm text-muted-foreground">Plan: {{ plan }}</div>
|
|
120
|
+
</div>
|
|
121
|
+
`,
|
|
122
|
+
}),
|
|
123
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
RadioGroup as ShadcnRadioGroup,
|
|
4
|
+
RadioGroupItem as ShadcnRadioGroupItem,
|
|
5
|
+
} from '../../shadcn/radio-group'
|
|
6
|
+
import type { RadioGroupItem, RadioGroupProps } from './types'
|
|
7
|
+
|
|
8
|
+
const props = withDefaults(defineProps<RadioGroupProps>(), {
|
|
9
|
+
items: () => [],
|
|
10
|
+
modelValue: undefined,
|
|
11
|
+
disabled: false,
|
|
12
|
+
orientation: 'vertical',
|
|
13
|
+
class: undefined,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const emit = defineEmits<{
|
|
17
|
+
'update:modelValue': [value: string]
|
|
18
|
+
}>()
|
|
19
|
+
|
|
20
|
+
defineSlots<{
|
|
21
|
+
label?: (props: { item: RadioGroupItem, checked: boolean }) => unknown
|
|
22
|
+
}>()
|
|
23
|
+
|
|
24
|
+
const model = computed({
|
|
25
|
+
get: () => props.modelValue,
|
|
26
|
+
set: value => {
|
|
27
|
+
if (value !== undefined) emit('update:modelValue', value)
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const orientationClass = {
|
|
32
|
+
horizontal: 'flex-row flex-wrap items-center',
|
|
33
|
+
vertical: 'flex-col',
|
|
34
|
+
} as const
|
|
35
|
+
|
|
36
|
+
const mergedClass = computed(() => cn(
|
|
37
|
+
'flex gap-3',
|
|
38
|
+
orientationClass[props.orientation],
|
|
39
|
+
props.class,
|
|
40
|
+
))
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<ShadcnRadioGroup
|
|
45
|
+
v-model="model"
|
|
46
|
+
:disabled="disabled"
|
|
47
|
+
:orientation="orientation"
|
|
48
|
+
:class="mergedClass"
|
|
49
|
+
>
|
|
50
|
+
<label
|
|
51
|
+
v-for="item in items"
|
|
52
|
+
:key="item.value"
|
|
53
|
+
class="
|
|
54
|
+
flex cursor-pointer items-center gap-2
|
|
55
|
+
has-data-disabled:cursor-not-allowed has-data-disabled:opacity-50
|
|
56
|
+
"
|
|
57
|
+
>
|
|
58
|
+
<ShadcnRadioGroupItem
|
|
59
|
+
:value="item.value"
|
|
60
|
+
:disabled="item.disabled"
|
|
61
|
+
/>
|
|
62
|
+
<span class="text-sm">
|
|
63
|
+
<slot
|
|
64
|
+
name="label"
|
|
65
|
+
:item="item"
|
|
66
|
+
:checked="model === item.value"
|
|
67
|
+
>
|
|
68
|
+
{{ item.label ?? item.value }}
|
|
69
|
+
</slot>
|
|
70
|
+
</span>
|
|
71
|
+
</label>
|
|
72
|
+
</ShadcnRadioGroup>
|
|
73
|
+
</template>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface RadioGroupItem {
|
|
2
|
+
value: string
|
|
3
|
+
label?: string
|
|
4
|
+
disabled?: boolean
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface RadioGroupProps {
|
|
8
|
+
modelValue?: string
|
|
9
|
+
items?: RadioGroupItem[]
|
|
10
|
+
disabled?: boolean
|
|
11
|
+
orientation?: 'vertical' | 'horizontal'
|
|
12
|
+
class?: ClassValue
|
|
13
|
+
}
|
|
@@ -1,65 +1,97 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import ScrollArea from './index.vue'
|
|
3
3
|
|
|
4
|
+
const types = [ 'auto', 'always', 'scroll', 'hover' ] as const
|
|
5
|
+
|
|
4
6
|
const meta = {
|
|
5
7
|
title: 'UI/ScrollArea',
|
|
6
8
|
component: ScrollArea,
|
|
7
9
|
argTypes: {
|
|
8
10
|
fadeMask: { control: 'boolean' },
|
|
11
|
+
type: { control: 'select', options: types },
|
|
12
|
+
dir: { control: 'select', options: [ 'ltr', 'rtl' ]},
|
|
13
|
+
scrollHideDelay: { control: 'number' },
|
|
9
14
|
},
|
|
10
15
|
args: {
|
|
11
16
|
fadeMask: false,
|
|
17
|
+
type: 'hover',
|
|
18
|
+
dir: 'ltr',
|
|
19
|
+
scrollHideDelay: 600,
|
|
12
20
|
},
|
|
21
|
+
render: args => ({
|
|
22
|
+
components: { ScrollArea },
|
|
23
|
+
setup () {
|
|
24
|
+
const items = Array.from({ length: 30 }, (_, i) => `Item ${i + 1}`)
|
|
25
|
+
return { args, items }
|
|
26
|
+
},
|
|
27
|
+
template: `
|
|
28
|
+
<div class="h-[250px] w-[250px] rounded-md border bg-card">
|
|
29
|
+
<ScrollArea class="h-full" v-bind="args">
|
|
30
|
+
<div class="p-4 space-y-2">
|
|
31
|
+
<div
|
|
32
|
+
v-for="item in items"
|
|
33
|
+
:key="item"
|
|
34
|
+
class="rounded-md border bg-muted px-3 py-2 text-sm"
|
|
35
|
+
>
|
|
36
|
+
{{ item }}
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</ScrollArea>
|
|
40
|
+
</div>
|
|
41
|
+
`,
|
|
42
|
+
}),
|
|
13
43
|
} satisfies Meta<typeof ScrollArea>
|
|
14
44
|
|
|
15
45
|
export default meta
|
|
16
46
|
type Story = StoryObj<typeof meta>
|
|
17
47
|
|
|
18
|
-
export const Default: Story = {
|
|
19
|
-
|
|
48
|
+
export const Default: Story = {}
|
|
49
|
+
|
|
50
|
+
export const FadeMask: Story = {
|
|
51
|
+
render: () => ({
|
|
20
52
|
components: { ScrollArea },
|
|
21
53
|
setup () {
|
|
22
54
|
const items = Array.from({ length: 30 }, (_, i) => `Item ${i + 1}`)
|
|
23
|
-
|
|
24
|
-
return { args, items, fewItems }
|
|
55
|
+
return { items }
|
|
25
56
|
},
|
|
26
57
|
template: `
|
|
27
|
-
<div class="
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class="rounded-md border bg-muted px-3 py-2 text-sm"
|
|
38
|
-
>
|
|
39
|
-
{{ item }}
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
</ScrollArea>
|
|
58
|
+
<div class="h-[250px] w-[250px] rounded-md border bg-card">
|
|
59
|
+
<ScrollArea class="h-full" fadeMask>
|
|
60
|
+
<div class="p-4 space-y-2">
|
|
61
|
+
<div
|
|
62
|
+
v-for="item in items"
|
|
63
|
+
:key="item"
|
|
64
|
+
class="rounded-md border bg-muted px-3 py-2 text-sm"
|
|
65
|
+
>
|
|
66
|
+
{{ item }}
|
|
67
|
+
</div>
|
|
43
68
|
</div>
|
|
44
|
-
</
|
|
69
|
+
</ScrollArea>
|
|
70
|
+
</div>
|
|
71
|
+
`,
|
|
72
|
+
}),
|
|
73
|
+
}
|
|
45
74
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
75
|
+
export const NoOverflow: Story = {
|
|
76
|
+
render: () => ({
|
|
77
|
+
components: { ScrollArea },
|
|
78
|
+
setup () {
|
|
79
|
+
const fewItems = Array.from({ length: 3 }, (_, i) => `Item ${i + 1}`)
|
|
80
|
+
return { fewItems }
|
|
81
|
+
},
|
|
82
|
+
template: `
|
|
83
|
+
<div class="h-[250px] w-[250px] rounded-md border bg-card">
|
|
84
|
+
<ScrollArea class="h-full" fadeMask>
|
|
85
|
+
<div class="p-4 space-y-2">
|
|
86
|
+
<div
|
|
87
|
+
v-for="item in fewItems"
|
|
88
|
+
:key="item"
|
|
89
|
+
class="rounded-md border bg-muted px-3 py-2 text-sm"
|
|
90
|
+
>
|
|
91
|
+
{{ item }}
|
|
92
|
+
</div>
|
|
61
93
|
</div>
|
|
62
|
-
</
|
|
94
|
+
</ScrollArea>
|
|
63
95
|
</div>
|
|
64
96
|
`,
|
|
65
97
|
}),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {
|
|
3
3
|
ScrollArea as ShadcnScrollArea,
|
|
4
|
-
} from '
|
|
4
|
+
} from '../../shadcn/scroll-area'
|
|
5
5
|
import { useResizeObserver } from '@vueuse/core'
|
|
6
6
|
import type { ScrollAreaProps } from './types'
|
|
7
7
|
|
|
@@ -31,95 +31,133 @@ function mockLoadValueOptionMethod (value: string) {
|
|
|
31
31
|
})
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
const defaultOptions = [
|
|
35
|
+
{ label: 'All Items', value: 'all' },
|
|
36
|
+
{ label: 'Featured', value: 'featured' },
|
|
37
|
+
]
|
|
38
|
+
|
|
34
39
|
const meta = {
|
|
35
40
|
title: 'UI/SearchSelect',
|
|
36
41
|
component: SearchSelect as any,
|
|
37
42
|
argTypes: {
|
|
43
|
+
placeholder: { control: 'text' },
|
|
44
|
+
searchPlaceholder: { control: 'text' },
|
|
45
|
+
emptyText: { control: 'text' },
|
|
46
|
+
searchEmptyText: { control: 'text' },
|
|
47
|
+
createNewTo: { control: 'text' },
|
|
48
|
+
createNewText: { control: 'text' },
|
|
49
|
+
loadLimit: { control: 'number' },
|
|
38
50
|
autoLoad: { control: 'boolean' },
|
|
39
51
|
disabled: { control: 'boolean' },
|
|
40
52
|
},
|
|
41
53
|
args: {
|
|
54
|
+
placeholder: '',
|
|
55
|
+
searchPlaceholder: '',
|
|
56
|
+
emptyText: '',
|
|
57
|
+
searchEmptyText: '',
|
|
58
|
+
createNewTo: '',
|
|
59
|
+
createNewText: '',
|
|
60
|
+
loadLimit: 20,
|
|
42
61
|
autoLoad: false,
|
|
43
62
|
disabled: false,
|
|
44
63
|
},
|
|
64
|
+
render: args => ({
|
|
65
|
+
components: { SearchSelect },
|
|
66
|
+
setup () {
|
|
67
|
+
const value = ref<string>()
|
|
68
|
+
return { args, value, mockLoadMethod }
|
|
69
|
+
},
|
|
70
|
+
template: `
|
|
71
|
+
<div class="max-w-sm">
|
|
72
|
+
<SearchSelect
|
|
73
|
+
v-model="value"
|
|
74
|
+
:loadMethod="mockLoadMethod"
|
|
75
|
+
v-bind="args"
|
|
76
|
+
/>
|
|
77
|
+
<div class="mt-2 text-sm text-muted-foreground">Selected: {{ value ?? 'none' }}</div>
|
|
78
|
+
</div>
|
|
79
|
+
`,
|
|
80
|
+
}),
|
|
45
81
|
} satisfies Meta
|
|
46
82
|
|
|
47
83
|
export default meta
|
|
48
84
|
type Story = StoryObj<typeof meta>
|
|
49
85
|
|
|
50
|
-
export const Default: Story = {
|
|
51
|
-
|
|
86
|
+
export const Default: Story = {}
|
|
87
|
+
|
|
88
|
+
export const Preselected: Story = {
|
|
89
|
+
render: () => ({
|
|
52
90
|
components: { SearchSelect },
|
|
53
91
|
setup () {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const withDefaults = ref<string>()
|
|
57
|
-
const withCreateNew = ref<string>()
|
|
58
|
-
|
|
59
|
-
const defaultOptions = [
|
|
60
|
-
{ label: 'All Items', value: 'all' },
|
|
61
|
-
{ label: 'Featured', value: 'featured' },
|
|
62
|
-
]
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
args,
|
|
66
|
-
selected,
|
|
67
|
-
withPreselect,
|
|
68
|
-
withDefaults,
|
|
69
|
-
withCreateNew,
|
|
70
|
-
defaultOptions,
|
|
71
|
-
mockLoadMethod,
|
|
72
|
-
mockLoadValueOptionMethod,
|
|
73
|
-
}
|
|
92
|
+
const value = ref<string>('item-42')
|
|
93
|
+
return { value, mockLoadMethod, mockLoadValueOptionMethod }
|
|
74
94
|
},
|
|
75
95
|
template: `
|
|
76
|
-
<div class="
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
96
|
+
<div class="max-w-sm">
|
|
97
|
+
<SearchSelect
|
|
98
|
+
v-model="value"
|
|
99
|
+
:loadMethod="mockLoadMethod"
|
|
100
|
+
:loadValueOptionMethod="mockLoadValueOptionMethod"
|
|
101
|
+
autoLoad
|
|
102
|
+
/>
|
|
103
|
+
<div class="mt-2 text-sm text-muted-foreground">Selected: {{ value ?? 'none' }}</div>
|
|
104
|
+
</div>
|
|
105
|
+
`,
|
|
106
|
+
}),
|
|
107
|
+
}
|
|
87
108
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
109
|
+
export const WithDefaultOptions: Story = {
|
|
110
|
+
render: () => ({
|
|
111
|
+
components: { SearchSelect },
|
|
112
|
+
setup () {
|
|
113
|
+
const value = ref<string>()
|
|
114
|
+
return { value, mockLoadMethod, defaultOptions }
|
|
115
|
+
},
|
|
116
|
+
template: `
|
|
117
|
+
<div class="max-w-sm">
|
|
118
|
+
<SearchSelect
|
|
119
|
+
v-model="value"
|
|
120
|
+
:loadMethod="mockLoadMethod"
|
|
121
|
+
:defaultOptions="defaultOptions"
|
|
122
|
+
autoLoad
|
|
123
|
+
/>
|
|
124
|
+
<div class="mt-2 text-sm text-muted-foreground">Selected: {{ value ?? 'none' }}</div>
|
|
125
|
+
</div>
|
|
126
|
+
`,
|
|
127
|
+
}),
|
|
128
|
+
}
|
|
99
129
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
130
|
+
export const WithCreateNew: Story = {
|
|
131
|
+
render: () => ({
|
|
132
|
+
components: { SearchSelect },
|
|
133
|
+
setup () {
|
|
134
|
+
const value = ref<string>()
|
|
135
|
+
return { value, mockLoadMethod }
|
|
136
|
+
},
|
|
137
|
+
template: `
|
|
138
|
+
<div class="max-w-sm">
|
|
139
|
+
<SearchSelect
|
|
140
|
+
v-model="value"
|
|
141
|
+
:loadMethod="mockLoadMethod"
|
|
142
|
+
createNewTo="/create"
|
|
143
|
+
autoLoad
|
|
144
|
+
/>
|
|
145
|
+
<div class="mt-2 text-sm text-muted-foreground">Selected: {{ value ?? 'none' }}</div>
|
|
146
|
+
</div>
|
|
147
|
+
`,
|
|
148
|
+
}),
|
|
149
|
+
}
|
|
111
150
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
</section>
|
|
151
|
+
export const Disabled: Story = {
|
|
152
|
+
render: () => ({
|
|
153
|
+
components: { SearchSelect },
|
|
154
|
+
setup () {
|
|
155
|
+
const value = ref<string>()
|
|
156
|
+
return { value, mockLoadMethod }
|
|
157
|
+
},
|
|
158
|
+
template: `
|
|
159
|
+
<div class="max-w-sm">
|
|
160
|
+
<SearchSelect v-model="value" :loadMethod="mockLoadMethod" disabled />
|
|
123
161
|
</div>
|
|
124
162
|
`,
|
|
125
163
|
}),
|