@byyuurin/ui 0.0.5 → 0.0.7
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/README.md +15 -11
- package/dist/module.cjs +5 -0
- package/dist/module.json +12 -0
- package/dist/{nuxt.mjs → module.mjs} +7 -6
- package/dist/module.mjs.map +1 -0
- package/dist/runtime/components/Accordion.vue +20 -31
- package/dist/runtime/components/Alert.vue +1 -1
- package/dist/runtime/components/App.vue +1 -1
- package/dist/runtime/components/Badge.vue +0 -1
- package/dist/runtime/components/Button.vue +14 -12
- package/dist/runtime/components/ButtonGroup.vue +47 -0
- package/dist/runtime/components/Card.vue +9 -6
- package/dist/runtime/components/Carousel.vue +310 -0
- package/dist/runtime/components/Checkbox.vue +3 -4
- package/dist/runtime/components/Chip.vue +9 -4
- package/dist/runtime/components/Collapsible.vue +56 -0
- package/dist/runtime/components/Drawer.vue +4 -2
- package/dist/runtime/components/Input.vue +12 -8
- package/dist/runtime/components/InputNumber.vue +167 -0
- package/dist/runtime/components/Link.vue +301 -72
- package/dist/runtime/components/LinkBase.vue +88 -0
- package/dist/runtime/components/Modal.vue +2 -4
- package/dist/runtime/components/Pagination.vue +167 -0
- package/dist/runtime/components/PinInput.vue +0 -1
- package/dist/runtime/components/RadioGroup.vue +0 -1
- package/dist/runtime/components/ScrollArea.vue +1 -1
- package/dist/runtime/components/Select.vue +9 -5
- package/dist/runtime/components/Separator.vue +63 -0
- package/dist/runtime/components/Slider.vue +0 -1
- package/dist/runtime/components/Switch.vue +4 -6
- package/dist/runtime/components/Table.vue +292 -0
- package/dist/runtime/components/Tabs.vue +17 -18
- package/dist/runtime/components/Textarea.vue +0 -1
- package/dist/runtime/components/Toast.vue +21 -10
- package/dist/runtime/components/Toaster.vue +4 -39
- package/dist/runtime/composables/useButtonGroup.d.ts +13 -0
- package/dist/runtime/composables/useButtonGroup.js +14 -0
- package/dist/runtime/composables/{useComponentIcons.mjs → useComponentIcons.js} +1 -1
- package/dist/runtime/composables/useModal.d.ts +1 -1
- package/dist/runtime/composables/{useModal.mjs → useModal.js} +1 -1
- package/dist/runtime/composables/useTheme.d.ts +4 -4
- package/dist/runtime/composables/{useTheme.mjs → useTheme.js} +4 -4
- package/dist/runtime/composables/useToast.d.ts +4 -4
- package/dist/runtime/composables/{useToast.mjs → useToast.js} +19 -6
- package/dist/runtime/index.d.ts +34 -0
- package/dist/runtime/index.js +34 -0
- package/dist/runtime/theme/accordion.d.ts +22 -5
- package/dist/runtime/theme/{accordion.mjs → accordion.js} +2 -2
- package/dist/runtime/theme/alert.d.ts +41 -1
- package/dist/runtime/theme/{alert.mjs → alert.js} +4 -4
- package/dist/runtime/theme/app.d.ts +8 -0
- package/dist/runtime/theme/app.js +18 -0
- package/dist/runtime/theme/badge.d.ts +48 -21
- package/dist/runtime/theme/{badge.mjs → badge.js} +5 -2
- package/dist/runtime/theme/button-group.d.ts +66 -0
- package/dist/runtime/theme/button-group.js +42 -0
- package/dist/runtime/theme/button.d.ts +68 -111
- package/dist/runtime/theme/button.js +164 -0
- package/dist/runtime/theme/card.d.ts +38 -19
- package/dist/runtime/theme/card.js +37 -0
- package/dist/runtime/theme/carousel.d.ts +113 -0
- package/dist/runtime/theme/carousel.js +43 -0
- package/dist/runtime/theme/checkbox.d.ts +4 -1
- package/dist/runtime/theme/{checkbox.mjs → checkbox.js} +7 -4
- package/dist/runtime/theme/chip.d.ts +56 -12
- package/dist/runtime/theme/{chip.mjs → chip.js} +10 -7
- package/dist/runtime/theme/collapsible.d.ts +38 -0
- package/dist/runtime/theme/collapsible.js +10 -0
- package/dist/runtime/theme/drawer.d.ts +71 -33
- package/dist/runtime/theme/{drawer.mjs → drawer.js} +33 -22
- package/dist/runtime/theme/index.d.ts +31 -24
- package/dist/runtime/theme/index.js +31 -0
- package/dist/runtime/theme/input-number.d.ts +135 -0
- package/dist/runtime/theme/input-number.js +92 -0
- package/dist/runtime/theme/input.d.ts +94 -111
- package/dist/runtime/theme/input.js +151 -0
- package/dist/runtime/theme/link.d.ts +14 -1
- package/dist/runtime/theme/{link.mjs → link.js} +1 -1
- package/dist/runtime/theme/modal.d.ts +33 -7
- package/dist/runtime/theme/{modal.mjs → modal.js} +8 -10
- package/dist/runtime/theme/pagination.d.ts +56 -0
- package/dist/runtime/theme/pagination.js +13 -0
- package/dist/runtime/theme/pinInput.d.ts +45 -42
- package/dist/runtime/theme/{pinInput.mjs → pinInput.js} +14 -11
- package/dist/runtime/theme/popover.d.ts +16 -5
- package/dist/runtime/theme/{radioGroup.d.ts → radio-group.d.ts} +4 -1
- package/dist/runtime/theme/{radioGroup.mjs → radio-group.js} +3 -0
- package/dist/runtime/theme/scroll-area.d.ts +73 -0
- package/dist/runtime/theme/{scrollArea.mjs → scroll-area.js} +2 -2
- package/dist/runtime/theme/select.d.ts +95 -99
- package/dist/runtime/theme/{select.mjs → select.js} +22 -17
- package/dist/runtime/theme/separator.d.ts +95 -0
- package/dist/runtime/theme/separator.js +53 -0
- package/dist/runtime/theme/slider.d.ts +4 -1
- package/dist/runtime/theme/{slider.mjs → slider.js} +6 -3
- package/dist/runtime/theme/switch.d.ts +4 -1
- package/dist/runtime/theme/{switch.mjs → switch.js} +5 -2
- package/dist/runtime/theme/table.d.ts +89 -0
- package/dist/runtime/theme/table.js +35 -0
- package/dist/runtime/theme/tabs.d.ts +72 -52
- package/dist/runtime/theme/{tabs.mjs → tabs.js} +15 -12
- package/dist/runtime/theme/textarea.d.ts +46 -37
- package/dist/runtime/theme/{textarea.mjs → textarea.js} +14 -11
- package/dist/runtime/theme/toast.d.ts +45 -7
- package/dist/runtime/theme/{toast.mjs → toast.js} +12 -7
- package/dist/runtime/theme/toaster.d.ts +89 -25
- package/dist/runtime/theme/{toaster.mjs → toaster.js} +5 -0
- package/dist/runtime/theme/tooltip.d.ts +20 -7
- package/dist/runtime/theme/{tooltip.mjs → tooltip.js} +2 -2
- package/dist/runtime/types/components.d.ts +7 -1
- package/dist/runtime/types/index.d.ts +4 -4
- package/dist/runtime/types/index.js +2 -0
- package/dist/runtime/types/utils.d.ts +1 -1
- package/dist/runtime/utils/index.d.ts +3 -3
- package/dist/runtime/utils/{index.mjs → index.js} +3 -3
- package/dist/runtime/utils/link.d.ts +22 -7
- package/dist/runtime/utils/link.js +30 -0
- package/dist/runtime/utils/styler.d.ts +2 -2
- package/dist/runtime/vue/stubs.d.ts +9 -0
- package/dist/runtime/vue/stubs.js +16 -0
- package/dist/shared/ui.d1728164.mjs +4 -0
- package/dist/shared/ui.d1728164.mjs.map +1 -0
- package/dist/types.d.mts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/{unocss-preset.d.ts → unocss.d.mts} +10 -15
- package/dist/{unocss-preset.d.mts → unocss.d.ts} +10 -15
- package/dist/{unocss-preset.mjs → unocss.mjs} +53 -21
- package/dist/unocss.mjs.map +1 -0
- package/dist/unplugin.d.mts +4 -3
- package/dist/unplugin.d.ts +4 -3
- package/dist/unplugin.mjs +49 -5
- package/dist/unplugin.mjs.map +1 -1
- package/dist/vite.d.mts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.mjs +7 -5
- package/dist/vite.mjs.map +1 -1
- package/package.json +59 -45
- package/dist/index.d.ts +0 -26
- package/dist/index.mjs +0 -26
- package/dist/nuxt.mjs.map +0 -1
- package/dist/runtime/theme/app.mjs +0 -10
- package/dist/runtime/theme/button.mjs +0 -143
- package/dist/runtime/theme/card.mjs +0 -14
- package/dist/runtime/theme/index.mjs +0 -24
- package/dist/runtime/theme/input.mjs +0 -146
- package/dist/runtime/theme/scrollArea.d.ts +0 -51
- package/dist/runtime/types/index.mjs +0 -2
- package/dist/runtime/utils/link.mjs +0 -4
- package/dist/shared/ui.CzDyI29e.mjs +0 -8
- package/dist/shared/ui.CzDyI29e.mjs.map +0 -1
- package/dist/unocss-preset.mjs.map +0 -1
- /package/{LICENSE.md → LICENSE} +0 -0
- /package/dist/{nuxt.d.mts → module.d.mts} +0 -0
- /package/dist/{nuxt.d.ts → module.d.ts} +0 -0
- /package/dist/runtime/composables/{defineInjection.mjs → defineInjection.js} +0 -0
- /package/dist/runtime/theme/{popover.mjs → popover.js} +0 -0
- /package/dist/runtime/types/{components.mjs → components.js} +0 -0
- /package/dist/runtime/types/{utils.mjs → utils.js} +0 -0
- /package/dist/runtime/utils/{extend-theme.mjs → extend-theme.js} +0 -0
- /package/dist/runtime/utils/{styler.mjs → styler.js} +0 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { VariantProps } from '@byyuurin/ui-kit'
|
|
3
|
+
import type { EmblaCarouselType, EmblaOptionsType, EmblaPluginType } from 'embla-carousel'
|
|
4
|
+
import type { AutoHeightOptionsType } from 'embla-carousel-auto-height'
|
|
5
|
+
import type { AutoScrollOptionsType } from 'embla-carousel-auto-scroll'
|
|
6
|
+
import type { AutoplayOptionsType } from 'embla-carousel-autoplay'
|
|
7
|
+
import type { ClassNamesOptionsType } from 'embla-carousel-class-names'
|
|
8
|
+
import type { FadeOptionsType } from 'embla-carousel-fade'
|
|
9
|
+
import type { WheelGesturesPluginOptions } from 'embla-carousel-wheel-gestures'
|
|
10
|
+
import type { AcceptableValue, PrimitiveProps } from 'reka-ui'
|
|
11
|
+
import type { carousel } from '../theme'
|
|
12
|
+
import type { ButtonProps, ComponentAttrs } from '../types'
|
|
13
|
+
|
|
14
|
+
type CarouselVariants = VariantProps<typeof carousel>
|
|
15
|
+
|
|
16
|
+
export interface CarouselProps<T> extends ComponentAttrs<typeof carousel>, Pick<PrimitiveProps, 'as'>, Omit<EmblaOptionsType, 'axis' | 'container' | 'slides' | 'direction'> {
|
|
17
|
+
/**
|
|
18
|
+
* Configure the prev button when arrows are enabled.
|
|
19
|
+
* @default { size: 'md', variant: 'link' }
|
|
20
|
+
*/
|
|
21
|
+
prev?: ButtonProps
|
|
22
|
+
/**
|
|
23
|
+
* The icon displayed in the prev button.
|
|
24
|
+
* @default `app.icons.arrowLeft`
|
|
25
|
+
*/
|
|
26
|
+
prevIcon?: string
|
|
27
|
+
/**
|
|
28
|
+
* Configure the next button when arrows are enabled.
|
|
29
|
+
* @default { size: 'md', variant: 'link' }
|
|
30
|
+
*/
|
|
31
|
+
next?: ButtonProps
|
|
32
|
+
/**
|
|
33
|
+
* The icon displayed in the next button.
|
|
34
|
+
* @default `app.icons.arrowRight`
|
|
35
|
+
*/
|
|
36
|
+
nextIcon?: string
|
|
37
|
+
/**
|
|
38
|
+
* Display prev and next buttons to scroll the carousel.
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
arrows?: boolean
|
|
42
|
+
/**
|
|
43
|
+
* Display dots to scroll to a specific slide.
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
dots?: boolean
|
|
47
|
+
orientation?: CarouselVariants['orientation']
|
|
48
|
+
items?: T[]
|
|
49
|
+
dir?: 'rtl' | 'ltr'
|
|
50
|
+
/**
|
|
51
|
+
* Enable Autoplay plugin
|
|
52
|
+
* @link https://www.embla-carousel.com/plugins/autoplay/
|
|
53
|
+
*/
|
|
54
|
+
autoplay?: boolean | AutoplayOptionsType
|
|
55
|
+
/**
|
|
56
|
+
* Enable Auto Scroll plugin
|
|
57
|
+
* @link https://www.embla-carousel.com/plugins/auto-scroll/
|
|
58
|
+
*/
|
|
59
|
+
autoScroll?: boolean | AutoScrollOptionsType
|
|
60
|
+
/**
|
|
61
|
+
* Enable Auto Height plugin
|
|
62
|
+
* @link https://www.embla-carousel.com/plugins/auto-height/
|
|
63
|
+
*/
|
|
64
|
+
autoHeight?: boolean | AutoHeightOptionsType
|
|
65
|
+
/**
|
|
66
|
+
* Enable Class Names plugin
|
|
67
|
+
* @link https://www.embla-carousel.com/plugins/class-names/
|
|
68
|
+
*/
|
|
69
|
+
classNames?: boolean | ClassNamesOptionsType
|
|
70
|
+
/**
|
|
71
|
+
* Enable Fade plugin
|
|
72
|
+
* @link https://www.embla-carousel.com/plugins/fade/
|
|
73
|
+
*/
|
|
74
|
+
fade?: boolean | FadeOptionsType
|
|
75
|
+
/**
|
|
76
|
+
* Enable Wheel Gestures plugin
|
|
77
|
+
* @link https://www.embla-carousel.com/plugins/wheel-gestures/
|
|
78
|
+
*/
|
|
79
|
+
wheelGestures?: boolean | WheelGesturesPluginOptions
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface CarouselSlots<T> {
|
|
83
|
+
default?: (props: { item: T, index: number }) => any
|
|
84
|
+
}
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<script setup lang="ts" generic="T extends AcceptableValue">
|
|
88
|
+
import { computedAsync, reactivePick } from '@vueuse/core'
|
|
89
|
+
import useEmblaCarousel from 'embla-carousel-vue'
|
|
90
|
+
import { Primitive, useForwardProps } from 'reka-ui'
|
|
91
|
+
import { computed, onMounted, ref, watch } from 'vue'
|
|
92
|
+
import { useTheme } from '../composables/useTheme'
|
|
93
|
+
import Button from './Button.vue'
|
|
94
|
+
|
|
95
|
+
const props = withDefaults(defineProps<CarouselProps<T>>(), {
|
|
96
|
+
orientation: 'horizontal',
|
|
97
|
+
arrows: false,
|
|
98
|
+
dots: false,
|
|
99
|
+
|
|
100
|
+
dir: 'ltr',
|
|
101
|
+
|
|
102
|
+
// Embla Options
|
|
103
|
+
active: true,
|
|
104
|
+
align: 'center',
|
|
105
|
+
breakpoints: () => ({}),
|
|
106
|
+
containScroll: 'trimSnaps',
|
|
107
|
+
dragFree: false,
|
|
108
|
+
dragThreshold: 10,
|
|
109
|
+
duration: 25,
|
|
110
|
+
inViewThreshold: 0,
|
|
111
|
+
loop: false,
|
|
112
|
+
skipSnaps: false,
|
|
113
|
+
slidesToScroll: 1,
|
|
114
|
+
startIndex: 0,
|
|
115
|
+
watchDrag: true,
|
|
116
|
+
watchResize: true,
|
|
117
|
+
watchSlides: true,
|
|
118
|
+
watchFocus: true,
|
|
119
|
+
|
|
120
|
+
// Embla Plugins
|
|
121
|
+
autoplay: false,
|
|
122
|
+
autoScroll: false,
|
|
123
|
+
autoHeight: false,
|
|
124
|
+
classNames: false,
|
|
125
|
+
fade: false,
|
|
126
|
+
wheelGestures: false,
|
|
127
|
+
})
|
|
128
|
+
defineSlots<CarouselSlots<T>>()
|
|
129
|
+
|
|
130
|
+
const rootProps = useForwardProps(reactivePick(props, 'active', 'align', 'breakpoints', 'containScroll', 'dragFree', 'dragThreshold', 'duration', 'inViewThreshold', 'loop', 'skipSnaps', 'slidesToScroll', 'startIndex', 'watchDrag', 'watchResize', 'watchSlides', 'watchFocus'))
|
|
131
|
+
|
|
132
|
+
const { theme, createStyler } = useTheme()
|
|
133
|
+
const style = computed(() => {
|
|
134
|
+
const styler = createStyler(theme.value.carousel)
|
|
135
|
+
return styler(props)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
const prevIcon = computed(() => props.prevIcon || (props.dir === 'rtl' ? theme.value.app.icons.arrowRight : theme.value.app.icons.arrowLeft))
|
|
139
|
+
const nextIcon = computed(() => props.nextIcon || (props.dir === 'rtl' ? theme.value.app.icons.arrowLeft : theme.value.app.icons.arrowRight))
|
|
140
|
+
|
|
141
|
+
const options = computed<EmblaOptionsType>(() => ({
|
|
142
|
+
...(props.fade ? { align: 'center', containScroll: false } : {}),
|
|
143
|
+
...rootProps.value,
|
|
144
|
+
axis: props.orientation === 'horizontal' ? 'x' : 'y',
|
|
145
|
+
direction: props.dir === 'rtl' ? 'rtl' : 'ltr',
|
|
146
|
+
}))
|
|
147
|
+
|
|
148
|
+
const plugins = computedAsync<EmblaPluginType[]>(async () => {
|
|
149
|
+
const plugins: EmblaPluginType[] = []
|
|
150
|
+
|
|
151
|
+
if (props.autoplay) {
|
|
152
|
+
const AutoplayPlugin = await import('embla-carousel-autoplay').then((r) => r.default)
|
|
153
|
+
plugins.push(AutoplayPlugin(typeof props.autoplay === 'boolean' ? {} : props.autoplay))
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (props.autoScroll) {
|
|
157
|
+
const AutoScrollPlugin = await import('embla-carousel-auto-scroll').then((r) => r.default)
|
|
158
|
+
plugins.push(AutoScrollPlugin(typeof props.autoScroll === 'boolean' ? {} : props.autoScroll))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (props.autoHeight) {
|
|
162
|
+
const AutoHeightPlugin = await import('embla-carousel-auto-height').then((r) => r.default)
|
|
163
|
+
plugins.push(AutoHeightPlugin(typeof props.autoHeight === 'boolean' ? {} : props.autoHeight))
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (props.classNames) {
|
|
167
|
+
const ClassNamesPlugin = await import('embla-carousel-class-names').then((r) => r.default)
|
|
168
|
+
plugins.push(ClassNamesPlugin(typeof props.classNames === 'boolean' ? {} : props.classNames))
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (props.fade) {
|
|
172
|
+
const FadePlugin = await import('embla-carousel-fade').then((r) => r.default)
|
|
173
|
+
plugins.push(FadePlugin(typeof props.fade === 'boolean' ? {} : props.fade))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (props.wheelGestures) {
|
|
177
|
+
const { WheelGesturesPlugin } = await import('embla-carousel-wheel-gestures')
|
|
178
|
+
plugins.push(WheelGesturesPlugin(typeof props.wheelGestures === 'boolean' ? {} : props.wheelGestures))
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return plugins
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
const [emblaRef, emblaApi] = useEmblaCarousel(options.value, plugins.value)
|
|
185
|
+
|
|
186
|
+
watch([options, plugins], () => {
|
|
187
|
+
emblaApi.value?.reInit(options.value, plugins.value)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
function scrollPrev() {
|
|
191
|
+
emblaApi.value?.scrollPrev()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function scrollNext() {
|
|
195
|
+
emblaApi.value?.scrollNext()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function scrollTo(index: number) {
|
|
199
|
+
emblaApi.value?.scrollTo(index)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function onKeyDown(event: KeyboardEvent) {
|
|
203
|
+
const prevKey = props.orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft'
|
|
204
|
+
const nextKey = props.orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight'
|
|
205
|
+
|
|
206
|
+
if (event.key === prevKey) {
|
|
207
|
+
event.preventDefault()
|
|
208
|
+
scrollPrev()
|
|
209
|
+
|
|
210
|
+
return
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (event.key === nextKey) {
|
|
214
|
+
event.preventDefault()
|
|
215
|
+
scrollNext()
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const canScrollNext = ref(false)
|
|
220
|
+
const canScrollPrev = ref(false)
|
|
221
|
+
const selectedIndex = ref<number>(0)
|
|
222
|
+
const scrollSnaps = ref<number[]>([])
|
|
223
|
+
|
|
224
|
+
function onInit(api: EmblaCarouselType) {
|
|
225
|
+
scrollSnaps.value = api?.scrollSnapList() || []
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function onSelect(api: EmblaCarouselType) {
|
|
229
|
+
canScrollNext.value = api?.canScrollNext() || false
|
|
230
|
+
canScrollPrev.value = api?.canScrollPrev() || false
|
|
231
|
+
selectedIndex.value = api?.selectedScrollSnap() || 0
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
onMounted(() => {
|
|
235
|
+
if (!emblaApi.value)
|
|
236
|
+
return
|
|
237
|
+
|
|
238
|
+
emblaApi.value?.on('init', onInit)
|
|
239
|
+
emblaApi.value?.on('init', onSelect)
|
|
240
|
+
emblaApi.value?.on('reInit', onInit)
|
|
241
|
+
emblaApi.value?.on('reInit', onSelect)
|
|
242
|
+
emblaApi.value?.on('select', onSelect)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
defineExpose({
|
|
246
|
+
emblaRef,
|
|
247
|
+
emblaApi,
|
|
248
|
+
})
|
|
249
|
+
</script>
|
|
250
|
+
|
|
251
|
+
<template>
|
|
252
|
+
<Primitive
|
|
253
|
+
:as="props.as"
|
|
254
|
+
role="region"
|
|
255
|
+
aria-roledescription="carousel"
|
|
256
|
+
tabindex="0"
|
|
257
|
+
:dir="props.dir"
|
|
258
|
+
:class="style.root({ class: [props.class, props.ui?.root] })"
|
|
259
|
+
@keydown="onKeyDown"
|
|
260
|
+
>
|
|
261
|
+
<div ref="emblaRef" :class="style.viewport({ class: props.ui?.viewport })">
|
|
262
|
+
<div :class="style.container({ class: props.ui?.container })">
|
|
263
|
+
<div
|
|
264
|
+
v-for="(item, index) in props.items"
|
|
265
|
+
:key="index"
|
|
266
|
+
role="group"
|
|
267
|
+
aria-roledescription="slide"
|
|
268
|
+
:class="style.item({ class: props.ui?.item })"
|
|
269
|
+
>
|
|
270
|
+
<slot :item="item" :index="index"></slot>
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
|
|
275
|
+
<div v-if="props.arrows || props.dots" :class="style.controls({ class: props.ui?.controls })">
|
|
276
|
+
<div v-if="props.arrows" :class="style.arrows({ class: props.ui?.arrows })">
|
|
277
|
+
<Button
|
|
278
|
+
:disabled="!canScrollPrev"
|
|
279
|
+
:icon="prevIcon"
|
|
280
|
+
size="md"
|
|
281
|
+
variant="outline"
|
|
282
|
+
aria-label="prev"
|
|
283
|
+
v-bind="typeof props.prev === 'object' ? props.prev : undefined"
|
|
284
|
+
:class="style.prev({ class: props.ui?.prev })"
|
|
285
|
+
@click="scrollPrev"
|
|
286
|
+
/>
|
|
287
|
+
<Button
|
|
288
|
+
:disabled="!canScrollNext"
|
|
289
|
+
:icon="nextIcon"
|
|
290
|
+
size="md"
|
|
291
|
+
variant="outline"
|
|
292
|
+
aria-label="next"
|
|
293
|
+
v-bind="typeof props.next === 'object' ? props.next : undefined"
|
|
294
|
+
:class="style.next({ class: props.ui?.next })"
|
|
295
|
+
@click="scrollNext"
|
|
296
|
+
/>
|
|
297
|
+
</div>
|
|
298
|
+
|
|
299
|
+
<div v-if="props.dots" :class="style.dots({ class: props.ui?.dots })">
|
|
300
|
+
<template v-for="(_, index) in scrollSnaps" :key="index">
|
|
301
|
+
<button
|
|
302
|
+
:aria-label="`Go to ${index + 1}`"
|
|
303
|
+
:class="style.dot({ class: props.ui?.dot, active: selectedIndex === index })"
|
|
304
|
+
@click="scrollTo(index)"
|
|
305
|
+
></button>
|
|
306
|
+
</template>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
</Primitive>
|
|
310
|
+
</template>
|
|
@@ -40,7 +40,6 @@ import { computed, useId } from 'vue'
|
|
|
40
40
|
import { useTheme } from '../composables/useTheme'
|
|
41
41
|
|
|
42
42
|
const props = withDefaults(defineProps<CheckboxProps>(), {
|
|
43
|
-
size: 'md',
|
|
44
43
|
required: false,
|
|
45
44
|
disabled: false,
|
|
46
45
|
})
|
|
@@ -79,11 +78,11 @@ function onUpdate(value: any) {
|
|
|
79
78
|
@update:model-value="onUpdate"
|
|
80
79
|
>
|
|
81
80
|
<CheckboxIndicator as-child force-mount>
|
|
82
|
-
<
|
|
81
|
+
<span
|
|
83
82
|
v-if="modelValue === 'indeterminate'"
|
|
84
83
|
:class="style.icon({ class: [props.indeterminateIcon || theme.app.icons.indeterminate, props.ui?.icon] })"
|
|
85
|
-
></
|
|
86
|
-
<
|
|
84
|
+
></span>
|
|
85
|
+
<span v-else :class="style.icon({ class: [props.icon, theme.app.icons.check, props.ui?.icon] })"></span>
|
|
87
86
|
</CheckboxIndicator>
|
|
88
87
|
</CheckboxRoot>
|
|
89
88
|
</div>
|
|
@@ -23,29 +23,34 @@ export interface ChipSlots {
|
|
|
23
23
|
<script setup lang="ts">
|
|
24
24
|
import { Primitive } from 'reka-ui'
|
|
25
25
|
import { computed } from 'vue'
|
|
26
|
+
import { useButtonGroup } from '../composables/useButtonGroup'
|
|
26
27
|
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
27
28
|
import { useTheme } from '../composables/useTheme'
|
|
28
29
|
|
|
29
30
|
const props = withDefaults(defineProps<ChipProps>(), {
|
|
30
31
|
variant: 'solid',
|
|
31
|
-
size: 'md',
|
|
32
32
|
})
|
|
33
33
|
|
|
34
34
|
const slots = defineSlots<ChipSlots>()
|
|
35
35
|
|
|
36
|
+
const { size, orientation } = useButtonGroup(props)
|
|
36
37
|
const { isPrefix, prefixIconName, isSuffix, suffixIconName } = useComponentIcons(props)
|
|
37
38
|
|
|
38
39
|
const { theme, createStyler } = useTheme()
|
|
39
40
|
const style = computed(() => {
|
|
40
41
|
const styler = createStyler(theme.value.chip)
|
|
41
|
-
return styler(
|
|
42
|
+
return styler({
|
|
43
|
+
...props,
|
|
44
|
+
size: size.value,
|
|
45
|
+
groupOrientation: orientation.value,
|
|
46
|
+
})
|
|
42
47
|
})
|
|
43
48
|
</script>
|
|
44
49
|
|
|
45
50
|
<template>
|
|
46
51
|
<Primitive :as="props.as" :class="style.base({ class: [props.class, props.ui?.base] })">
|
|
47
52
|
<slot name="prefix">
|
|
48
|
-
<
|
|
53
|
+
<span v-if="isPrefix && prefixIconName" :class="style.prefixIcon({ class: [prefixIconName, props.ui?.prefixIcon] })"></span>
|
|
49
54
|
</slot>
|
|
50
55
|
|
|
51
56
|
<span v-if="props.label || slots.default" :class="style.label({ class: props.ui?.label })">
|
|
@@ -53,7 +58,7 @@ const style = computed(() => {
|
|
|
53
58
|
</span>
|
|
54
59
|
|
|
55
60
|
<slot name="suffix">
|
|
56
|
-
<
|
|
61
|
+
<span v-if="isSuffix && suffixIconName" :class="style.suffixIcon({ class: [suffixIconName, props.ui?.suffixIcon] })"></span>
|
|
57
62
|
</slot>
|
|
58
63
|
</Primitive>
|
|
59
64
|
</template>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { CollapsibleRootEmits, CollapsibleRootProps } from 'reka-ui'
|
|
3
|
+
import type { collapsible } from '../theme'
|
|
4
|
+
import type { ComponentAttrs } from '../types'
|
|
5
|
+
|
|
6
|
+
export interface CollapsibleProps extends ComponentAttrs<typeof collapsible>, Pick<CollapsibleRootProps, 'as' | 'defaultOpen' | 'open' | 'disabled' | 'unmountOnHide'> {
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface CollapsibleEmits extends CollapsibleRootEmits {}
|
|
10
|
+
|
|
11
|
+
export interface CollapsibleSlots {
|
|
12
|
+
default?: (props: { open: boolean }) => any
|
|
13
|
+
content?: (props?: {}) => any
|
|
14
|
+
}
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<script setup lang="ts">
|
|
18
|
+
import { reactivePick } from '@vueuse/core'
|
|
19
|
+
import { CollapsibleContent, CollapsibleRoot, CollapsibleTrigger, useForwardPropsEmits } from 'reka-ui'
|
|
20
|
+
import { computed } from 'vue'
|
|
21
|
+
import { useTheme } from '../composables/useTheme'
|
|
22
|
+
|
|
23
|
+
const props = withDefaults(defineProps<CollapsibleProps>(), {
|
|
24
|
+
unmountOnHide: true,
|
|
25
|
+
})
|
|
26
|
+
const emit = defineEmits<CollapsibleEmits>()
|
|
27
|
+
const slots = defineSlots<CollapsibleSlots>()
|
|
28
|
+
|
|
29
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen', 'open', 'disabled', 'unmountOnHide'), emit)
|
|
30
|
+
|
|
31
|
+
const { theme, createStyler } = useTheme()
|
|
32
|
+
const style = computed(() => {
|
|
33
|
+
const styler = createStyler(theme.value.collapsible)
|
|
34
|
+
return styler(props)
|
|
35
|
+
})
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<CollapsibleRoot
|
|
40
|
+
v-slot="{ open }"
|
|
41
|
+
v-bind="rootProps"
|
|
42
|
+
:class="style.root({ class: [props.class, props.ui?.root] })"
|
|
43
|
+
>
|
|
44
|
+
<CollapsibleTrigger v-if="slots.default" as-child>
|
|
45
|
+
<slot :open="open"></slot>
|
|
46
|
+
</CollapsibleTrigger>
|
|
47
|
+
|
|
48
|
+
<CollapsibleContent :class="style.content({ class: props.ui?.content })">
|
|
49
|
+
<slot name="content"></slot>
|
|
50
|
+
</CollapsibleContent>
|
|
51
|
+
</CollapsibleRoot>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<style>
|
|
55
|
+
@keyframes collapsible-up{0%{height:var(--reka-collapsible-content-height)}to{height:0}}@keyframes collapsible-down{0%{height:0}to{height:var(--reka-collapsible-content-height)}}
|
|
56
|
+
</style>
|
|
@@ -15,8 +15,10 @@ export interface DrawerProps extends ComponentAttrs<typeof drawer>, Pick<DrawerR
|
|
|
15
15
|
* @default true
|
|
16
16
|
*/
|
|
17
17
|
overlay?: boolean
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Whether to inset the drawer from the edges.
|
|
20
|
+
*/
|
|
21
|
+
inset?: boolean
|
|
20
22
|
/**
|
|
21
23
|
* Render a handle on the drawer.
|
|
22
24
|
* @default true
|
|
@@ -46,6 +46,7 @@ export interface InputSlots {
|
|
|
46
46
|
<script setup lang="ts">
|
|
47
47
|
import { Primitive } from 'reka-ui'
|
|
48
48
|
import { computed, onMounted, ref } from 'vue'
|
|
49
|
+
import { useButtonGroup } from '../composables/useButtonGroup'
|
|
49
50
|
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
50
51
|
import { useTheme } from '../composables/useTheme'
|
|
51
52
|
import { looseToNumber } from '../utils'
|
|
@@ -56,7 +57,6 @@ defineOptions({
|
|
|
56
57
|
|
|
57
58
|
const props = withDefaults(defineProps<InputProps>(), {
|
|
58
59
|
type: 'text',
|
|
59
|
-
size: 'md',
|
|
60
60
|
variant: 'outline',
|
|
61
61
|
autocomplete: 'off',
|
|
62
62
|
autofocusDelay: 0,
|
|
@@ -68,14 +68,18 @@ const [modelValue, modelModifiers] = defineModel<string | number>()
|
|
|
68
68
|
|
|
69
69
|
const inputRef = ref<HTMLInputElement | null>(null)
|
|
70
70
|
|
|
71
|
+
const { size, orientation } = useButtonGroup(props)
|
|
71
72
|
const { isPrefix, prefixIconName, isSuffix, suffixIconName } = useComponentIcons(props)
|
|
72
73
|
|
|
73
74
|
const { theme, createStyler } = useTheme()
|
|
74
75
|
const style = computed(() => {
|
|
75
76
|
const styler = createStyler(theme.value.input)
|
|
76
|
-
// @ts-expect-error ignore type
|
|
77
77
|
return styler({
|
|
78
78
|
...props,
|
|
79
|
+
// @ts-expect-error ignore type
|
|
80
|
+
type: props.type,
|
|
81
|
+
size: size.value,
|
|
82
|
+
groupOrientation: orientation.value,
|
|
79
83
|
prefix: isPrefix.value || !!slots.prefix,
|
|
80
84
|
suffix: isSuffix.value || !!slots.suffix,
|
|
81
85
|
})
|
|
@@ -131,15 +135,15 @@ onMounted(() => {
|
|
|
131
135
|
<template>
|
|
132
136
|
<Primitive
|
|
133
137
|
:as="as"
|
|
134
|
-
:class="style.
|
|
138
|
+
:class="style.base({ class: [props.class, props.ui?.base] })"
|
|
135
139
|
:aria-disabled="props.disabled ? true : undefined"
|
|
136
140
|
>
|
|
137
141
|
<span v-if="isPrefix || slots.prefix" :class="style.prefix({ class: props.ui?.prefix })">
|
|
138
142
|
<slot name="prefix">
|
|
139
|
-
<
|
|
143
|
+
<span
|
|
140
144
|
v-if="isPrefix && prefixIconName"
|
|
141
145
|
:class="style.prefixIcon({ class: [prefixIconName, props.ui?.prefixIcon] })"
|
|
142
|
-
></
|
|
146
|
+
></span>
|
|
143
147
|
</slot>
|
|
144
148
|
</span>
|
|
145
149
|
|
|
@@ -150,7 +154,7 @@ onMounted(() => {
|
|
|
150
154
|
:value="modelValue"
|
|
151
155
|
:name="props.name"
|
|
152
156
|
:placeholder="props.placeholder"
|
|
153
|
-
:class="style.
|
|
157
|
+
:class="style.input({ class: props.ui?.input })"
|
|
154
158
|
:disabled="props.disabled"
|
|
155
159
|
:required="props.required"
|
|
156
160
|
:autocomplete="props.autocomplete"
|
|
@@ -164,10 +168,10 @@ onMounted(() => {
|
|
|
164
168
|
|
|
165
169
|
<span v-if="isSuffix || slots.suffix" :class="style.suffix({ class: props.ui?.suffix })">
|
|
166
170
|
<slot name="suffix">
|
|
167
|
-
<
|
|
171
|
+
<span
|
|
168
172
|
v-if="isSuffix && suffixIconName"
|
|
169
173
|
:class="style.suffixIcon({ class: [suffixIconName, props.ui?.suffixIcon] })"
|
|
170
|
-
></
|
|
174
|
+
></span>
|
|
171
175
|
</slot>
|
|
172
176
|
</span>
|
|
173
177
|
</Primitive>
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { VariantProps } from '@byyuurin/ui-kit'
|
|
3
|
+
import type { NumberFieldRootProps } from 'reka-ui'
|
|
4
|
+
import type { inputNumber } from '../theme'
|
|
5
|
+
import type { ButtonProps, ComponentAttrs } from '../types'
|
|
6
|
+
|
|
7
|
+
export interface InputNumberEmits {
|
|
8
|
+
(e: 'update:modelValue', payload: number): void
|
|
9
|
+
(e: 'blur', event: FocusEvent): void
|
|
10
|
+
(e: 'change', payload: Event): void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface InputNumberSlots {
|
|
14
|
+
increment?: (props?: {}) => any
|
|
15
|
+
decrement?: (props?: {}) => any
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type InputNumberVariants = VariantProps<typeof inputNumber>
|
|
19
|
+
|
|
20
|
+
export interface InputNumberProps extends ComponentAttrs<typeof inputNumber>, Pick<NumberFieldRootProps, 'as' | 'modelValue' | 'defaultValue' | 'min' | 'max' | 'step' | 'disabled' | 'required' | 'id' | 'name' | 'formatOptions'> {
|
|
21
|
+
/** The placeholder text when the input is empty. */
|
|
22
|
+
placeholder?: string
|
|
23
|
+
variant?: InputNumberVariants['variant']
|
|
24
|
+
size?: InputNumberVariants['size']
|
|
25
|
+
underline?: boolean
|
|
26
|
+
/** Highlight the ring color like a focus state. */
|
|
27
|
+
highlight?: boolean
|
|
28
|
+
/**
|
|
29
|
+
* The orientation of the input menu.
|
|
30
|
+
* @default 'horizontal'
|
|
31
|
+
*/
|
|
32
|
+
orientation?: InputNumberVariants['orientation']
|
|
33
|
+
/**
|
|
34
|
+
* Configure the increment button. The `color` and `size` are inherited.
|
|
35
|
+
* @default { variant: 'link' }
|
|
36
|
+
*/
|
|
37
|
+
increment?: ButtonProps
|
|
38
|
+
/**
|
|
39
|
+
* The icon displayed to increment the value.
|
|
40
|
+
* @default app.icons.plus
|
|
41
|
+
*/
|
|
42
|
+
incrementIcon?: string
|
|
43
|
+
/**
|
|
44
|
+
* Configure the decrement button. The `color` and `size` are inherited.
|
|
45
|
+
* @default { variant: 'link' }
|
|
46
|
+
*/
|
|
47
|
+
decrement?: ButtonProps
|
|
48
|
+
/**
|
|
49
|
+
* The icon displayed to decrement the value.
|
|
50
|
+
* @default app.icons.minus
|
|
51
|
+
*/
|
|
52
|
+
decrementIcon?: string
|
|
53
|
+
autofocus?: boolean
|
|
54
|
+
autofocusDelay?: number
|
|
55
|
+
/**
|
|
56
|
+
* The locale to use for formatting and parsing numbers.
|
|
57
|
+
*/
|
|
58
|
+
locale?: string
|
|
59
|
+
}
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<script setup lang="ts">
|
|
63
|
+
import { reactivePick } from '@vueuse/core'
|
|
64
|
+
import { NumberFieldDecrement, NumberFieldIncrement, NumberFieldInput, NumberFieldRoot, useForwardPropsEmits } from 'reka-ui'
|
|
65
|
+
import { computed, onMounted, ref } from 'vue'
|
|
66
|
+
import { useTheme } from '../composables/useTheme'
|
|
67
|
+
import Button from './Button.vue'
|
|
68
|
+
|
|
69
|
+
defineOptions({
|
|
70
|
+
inheritAttrs: false,
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const props = withDefaults(defineProps<InputNumberProps>(), {
|
|
74
|
+
orientation: 'horizontal',
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const emit = defineEmits<InputNumberEmits>()
|
|
78
|
+
defineSlots<InputNumberSlots>()
|
|
79
|
+
|
|
80
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'formatOptions'), emit)
|
|
81
|
+
|
|
82
|
+
const inputRef = ref<InstanceType<typeof NumberFieldInput> | null>(null)
|
|
83
|
+
|
|
84
|
+
const { theme, createStyler } = useTheme()
|
|
85
|
+
const incrementIcon = computed(() => props.incrementIcon || (props.orientation === 'horizontal' ? theme.value.app.icons.plus : theme.value.app.icons.up))
|
|
86
|
+
const decrementIcon = computed(() => props.decrementIcon || (props.orientation === 'horizontal' ? theme.value.app.icons.minus : theme.value.app.icons.down))
|
|
87
|
+
|
|
88
|
+
const style = computed(() => {
|
|
89
|
+
const styler = createStyler(theme.value.inputNumber)
|
|
90
|
+
return styler(props)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
onMounted(() => {
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
autoFocus()
|
|
96
|
+
}, props.autofocusDelay)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
defineExpose({
|
|
100
|
+
inputRef,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
function autoFocus() {
|
|
104
|
+
if (props.autofocus)
|
|
105
|
+
inputRef.value?.$el?.focus()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function onUpdate(value: number) {
|
|
109
|
+
// @ts-expect-error - 'target' does not exist in type 'EventInit'
|
|
110
|
+
const event = new Event('change', { target: { value } })
|
|
111
|
+
emit('change', event)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function onBlur(event: FocusEvent) {
|
|
115
|
+
emit('blur', event)
|
|
116
|
+
}
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<template>
|
|
120
|
+
<NumberFieldRoot
|
|
121
|
+
v-bind="rootProps"
|
|
122
|
+
:id="props.id"
|
|
123
|
+
:name="props.name"
|
|
124
|
+
:disabled="props.disabled"
|
|
125
|
+
:locale="props.locale"
|
|
126
|
+
:class="style.base({ class: [props.class, props.ui?.base] })"
|
|
127
|
+
:aria-disabled="props.disabled ? true : undefined"
|
|
128
|
+
@update:model-value="onUpdate"
|
|
129
|
+
>
|
|
130
|
+
<NumberFieldInput
|
|
131
|
+
v-bind="$attrs"
|
|
132
|
+
ref="inputRef"
|
|
133
|
+
:placeholder="props.placeholder"
|
|
134
|
+
:required="props.required"
|
|
135
|
+
:class="style.input({ class: props.ui?.input })"
|
|
136
|
+
@blur="onBlur"
|
|
137
|
+
/>
|
|
138
|
+
|
|
139
|
+
<div :class="style.increment({ class: props.ui?.increment })">
|
|
140
|
+
<NumberFieldIncrement as-child :disabled="props.disabled">
|
|
141
|
+
<slot name="increment">
|
|
142
|
+
<Button
|
|
143
|
+
:icon="incrementIcon"
|
|
144
|
+
:size="props.size"
|
|
145
|
+
variant="link"
|
|
146
|
+
aria-label="increment"
|
|
147
|
+
v-bind="typeof props.increment === 'object' ? props.increment : undefined"
|
|
148
|
+
/>
|
|
149
|
+
</slot>
|
|
150
|
+
</NumberFieldIncrement>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<div :class="style.decrement({ class: props.ui?.decrement })">
|
|
154
|
+
<NumberFieldDecrement as-child :disabled="props.disabled">
|
|
155
|
+
<slot name="decrement">
|
|
156
|
+
<Button
|
|
157
|
+
:icon="decrementIcon"
|
|
158
|
+
:size="props.size"
|
|
159
|
+
variant="link"
|
|
160
|
+
aria-label="decrement"
|
|
161
|
+
v-bind="typeof props.decrement === 'object' ? props.decrement : undefined"
|
|
162
|
+
/>
|
|
163
|
+
</slot>
|
|
164
|
+
</NumberFieldDecrement>
|
|
165
|
+
</div>
|
|
166
|
+
</NumberFieldRoot>
|
|
167
|
+
</template>
|