@byyuurin/ui 0.0.4 → 0.0.6
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 +23 -29
- package/dist/index.d.ts +28 -2
- package/dist/index.mjs +28 -2
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/nuxt.mjs +15 -10
- package/dist/nuxt.mjs.map +1 -0
- package/dist/runtime/components/Accordion.vue +1 -1
- package/dist/runtime/components/Alert.vue +120 -0
- package/dist/runtime/components/App.vue +1 -1
- package/dist/runtime/components/Badge.vue +70 -0
- package/dist/runtime/components/Button.vue +7 -3
- package/dist/runtime/components/ButtonGroup.vue +47 -0
- package/dist/runtime/components/Card.vue +4 -4
- package/dist/runtime/components/Carousel.vue +310 -0
- package/dist/runtime/components/Checkbox.vue +1 -2
- package/dist/runtime/components/Chip.vue +64 -0
- package/dist/runtime/components/Drawer.vue +2 -2
- package/dist/runtime/components/Input.vue +10 -5
- package/dist/runtime/components/Link.vue +1 -1
- package/dist/runtime/components/Modal.vue +4 -5
- package/dist/runtime/components/Pagination.vue +167 -0
- package/dist/runtime/components/PinInput.vue +85 -0
- package/dist/runtime/components/Popover.vue +1 -1
- package/dist/runtime/components/RadioGroup.vue +1 -2
- package/dist/runtime/components/ScrollArea.vue +2 -2
- package/dist/runtime/components/Select.vue +7 -2
- package/dist/runtime/components/Slider.vue +96 -0
- package/dist/runtime/components/Switch.vue +2 -4
- package/dist/runtime/components/Tabs.vue +1 -2
- package/dist/runtime/components/Textarea.vue +2 -4
- package/dist/runtime/components/Toast.vue +21 -10
- package/dist/runtime/components/Toaster.vue +5 -5
- package/dist/runtime/components/Tooltip.vue +1 -1
- package/dist/runtime/composables/useButtonGroup.d.ts +13 -0
- package/dist/runtime/composables/useButtonGroup.mjs +14 -0
- package/dist/runtime/composables/useTheme.d.ts +2 -2
- package/dist/runtime/composables/useTheme.mjs +1 -1
- package/dist/runtime/composables/useToast.d.ts +4 -4
- package/dist/runtime/composables/useToast.mjs +19 -6
- package/dist/runtime/theme/accordion.d.ts +17 -0
- package/dist/runtime/theme/accordion.mjs +24 -21
- package/dist/runtime/theme/alert.d.ts +125 -0
- package/dist/runtime/theme/alert.mjs +47 -0
- package/dist/runtime/theme/app.d.ts +5 -0
- package/dist/runtime/theme/app.mjs +7 -1
- package/dist/runtime/theme/badge.d.ts +82 -0
- package/dist/runtime/theme/badge.mjs +92 -0
- package/dist/runtime/theme/button-group.d.ts +66 -0
- package/dist/runtime/theme/button-group.mjs +42 -0
- package/dist/runtime/theme/button.d.ts +15 -1
- package/dist/runtime/theme/button.mjs +135 -119
- package/dist/runtime/theme/card.d.ts +21 -2
- package/dist/runtime/theme/card.mjs +12 -9
- package/dist/runtime/theme/carousel.d.ts +113 -0
- package/dist/runtime/theme/carousel.mjs +43 -0
- package/dist/runtime/theme/checkbox.d.ts +3 -0
- package/dist/runtime/theme/checkbox.mjs +47 -41
- package/dist/runtime/theme/chip.d.ts +67 -0
- package/dist/runtime/theme/chip.mjs +68 -0
- package/dist/runtime/theme/drawer.d.ts +38 -0
- package/dist/runtime/theme/drawer.mjs +69 -66
- package/dist/runtime/theme/index.d.ts +10 -2
- package/dist/runtime/theme/index.mjs +10 -2
- package/dist/runtime/theme/input.d.ts +41 -22
- package/dist/runtime/theme/input.mjs +139 -121
- package/dist/runtime/theme/link.d.ts +14 -1
- package/dist/runtime/theme/link.mjs +23 -20
- package/dist/runtime/theme/modal.d.ts +3 -0
- package/dist/runtime/theme/modal.mjs +53 -47
- package/dist/runtime/theme/pagination.d.ts +56 -0
- package/dist/runtime/theme/pagination.mjs +13 -0
- package/dist/runtime/theme/pinInput.d.ts +100 -0
- package/dist/runtime/theme/pinInput.mjs +111 -0
- package/dist/runtime/theme/popover.d.ts +11 -0
- package/dist/runtime/theme/popover.mjs +11 -8
- package/dist/runtime/theme/{radioGroup.d.ts → radio-group.d.ts} +3 -0
- package/dist/runtime/theme/radio-group.mjs +61 -0
- package/dist/runtime/theme/{scrollArea.d.ts → scroll-area.d.ts} +22 -0
- package/dist/runtime/theme/scroll-area.mjs +33 -0
- package/dist/runtime/theme/select.d.ts +16 -2
- package/dist/runtime/theme/select.mjs +160 -142
- package/dist/runtime/theme/slider.d.ts +76 -0
- package/dist/runtime/theme/slider.mjs +52 -0
- package/dist/runtime/theme/switch.d.ts +3 -0
- package/dist/runtime/theme/switch.mjs +69 -63
- package/dist/runtime/theme/tabs.d.ts +15 -2
- package/dist/runtime/theme/tabs.mjs +134 -112
- package/dist/runtime/theme/textarea.d.ts +8 -2
- package/dist/runtime/theme/textarea.mjs +105 -89
- package/dist/runtime/theme/toast.d.ts +44 -6
- package/dist/runtime/theme/toast.mjs +30 -22
- package/dist/runtime/theme/toaster.d.ts +51 -2
- package/dist/runtime/theme/toaster.mjs +88 -80
- package/dist/runtime/theme/tooltip.d.ts +13 -0
- package/dist/runtime/theme/tooltip.mjs +9 -6
- package/dist/runtime/types/components.d.ts +27 -20
- package/dist/runtime/types/components.mjs +27 -0
- package/dist/runtime/types/index.d.ts +1 -3
- package/dist/runtime/types/utils.d.ts +1 -1
- package/dist/runtime/utils/extend-theme.mjs +1 -1
- package/dist/runtime/utils/link.d.ts +1 -1
- package/dist/runtime/utils/styler.d.ts +2 -2
- package/dist/shared/ui.D4zm1r0C.mjs +4 -0
- package/dist/shared/ui.D4zm1r0C.mjs.map +1 -0
- package/dist/{unocss-preset.d.mts → unocss.d.mts} +4 -4
- package/dist/{unocss-preset.d.ts → unocss.d.ts} +4 -4
- package/dist/{unocss-preset.mjs → unocss.mjs} +58 -36
- package/dist/unocss.mjs.map +1 -0
- package/dist/unplugin.d.mts +26 -0
- package/dist/unplugin.d.ts +26 -0
- package/dist/unplugin.mjs +72 -0
- package/dist/unplugin.mjs.map +1 -0
- package/dist/vite.d.mts +10 -0
- package/dist/vite.d.ts +10 -0
- package/dist/vite.mjs +14 -0
- package/dist/vite.mjs.map +1 -0
- package/package.json +46 -26
- package/dist/resolver.d.mts +0 -13
- package/dist/resolver.d.ts +0 -13
- package/dist/resolver.mjs +0 -21
- package/dist/runtime/components/index.d.ts +0 -20
- package/dist/runtime/components/index.mjs +0 -20
- package/dist/runtime/composables/index.d.ts +0 -5
- package/dist/runtime/composables/index.mjs +0 -5
- package/dist/runtime/theme/radioGroup.mjs +0 -55
- package/dist/runtime/theme/scrollArea.mjs +0 -30
- package/dist/shared/ui.Cmq14xN9.mjs +0 -25
- /package/{LICENSE.md → LICENSE} +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>
|
|
@@ -37,10 +37,9 @@ export interface CheckboxSlots {
|
|
|
37
37
|
import { reactivePick } from '@vueuse/core'
|
|
38
38
|
import { CheckboxIndicator, CheckboxRoot, Label, Primitive, useForwardProps } from 'reka-ui'
|
|
39
39
|
import { computed, useId } from 'vue'
|
|
40
|
-
import { useTheme } from '../composables'
|
|
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
|
})
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { VariantProps } from '@byyuurin/ui-kit'
|
|
3
|
+
import type { PrimitiveProps } from 'reka-ui'
|
|
4
|
+
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
|
5
|
+
import type { chip } from '../theme'
|
|
6
|
+
import type { ComponentAttrs } from '../types'
|
|
7
|
+
|
|
8
|
+
type ChipVariants = VariantProps<typeof chip>
|
|
9
|
+
|
|
10
|
+
export interface ChipProps extends ComponentAttrs<typeof chip>, Pick<PrimitiveProps, 'as'>, Omit<UseComponentIconsProps, 'loading' | 'loadingIcon'> {
|
|
11
|
+
variant?: ChipVariants['variant']
|
|
12
|
+
size?: ChipVariants['size']
|
|
13
|
+
label?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ChipSlots {
|
|
17
|
+
prefix?: (props?: {}) => any
|
|
18
|
+
default?: (props?: {}) => any
|
|
19
|
+
suffix?: (props?: {}) => any
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
import { Primitive } from 'reka-ui'
|
|
25
|
+
import { computed } from 'vue'
|
|
26
|
+
import { useButtonGroup } from '../composables/useButtonGroup'
|
|
27
|
+
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
28
|
+
import { useTheme } from '../composables/useTheme'
|
|
29
|
+
|
|
30
|
+
const props = withDefaults(defineProps<ChipProps>(), {
|
|
31
|
+
variant: 'solid',
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const slots = defineSlots<ChipSlots>()
|
|
35
|
+
|
|
36
|
+
const { size, orientation } = useButtonGroup(props)
|
|
37
|
+
const { isPrefix, prefixIconName, isSuffix, suffixIconName } = useComponentIcons(props)
|
|
38
|
+
|
|
39
|
+
const { theme, createStyler } = useTheme()
|
|
40
|
+
const style = computed(() => {
|
|
41
|
+
const styler = createStyler(theme.value.chip)
|
|
42
|
+
return styler({
|
|
43
|
+
...props,
|
|
44
|
+
size: size.value,
|
|
45
|
+
groupOrientation: orientation.value,
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<Primitive :as="props.as" :class="style.base({ class: [props.class, props.ui?.base] })">
|
|
52
|
+
<slot name="prefix">
|
|
53
|
+
<i v-if="isPrefix && prefixIconName" :class="style.prefixIcon({ class: [prefixIconName, props.ui?.prefixIcon] })"></i>
|
|
54
|
+
</slot>
|
|
55
|
+
|
|
56
|
+
<span v-if="props.label || slots.default" :class="style.label({ class: props.ui?.label })">
|
|
57
|
+
<slot>{{ props.label }}</slot>
|
|
58
|
+
</span>
|
|
59
|
+
|
|
60
|
+
<slot name="suffix">
|
|
61
|
+
<i v-if="isSuffix && suffixIconName" :class="style.suffixIcon({ class: [suffixIconName, props.ui?.suffixIcon] })"></i>
|
|
62
|
+
</slot>
|
|
63
|
+
</Primitive>
|
|
64
|
+
</template>
|
|
@@ -53,7 +53,7 @@ import { reactivePick } from '@vueuse/core'
|
|
|
53
53
|
import { useForwardPropsEmits } from 'reka-ui'
|
|
54
54
|
import { DrawerContent, DrawerDescription, DrawerOverlay, DrawerPortal, DrawerRoot, DrawerTitle, DrawerTrigger } from 'vaul-vue'
|
|
55
55
|
import { computed, toRef } from 'vue'
|
|
56
|
-
import { useTheme } from '../composables'
|
|
56
|
+
import { useTheme } from '../composables/useTheme'
|
|
57
57
|
|
|
58
58
|
const props = withDefaults(defineProps<DrawerProps>(), {
|
|
59
59
|
direction: 'bottom',
|
|
@@ -94,7 +94,7 @@ const style = computed(() => {
|
|
|
94
94
|
<slot name="content">
|
|
95
95
|
<div :class="style.container({ class: props.ui?.container })">
|
|
96
96
|
<div
|
|
97
|
-
v-if="slots.header ||
|
|
97
|
+
v-if="slots.header || props.title || slots.title || props.description || slots.description"
|
|
98
98
|
:class="style.header({ class: props.ui?.header })"
|
|
99
99
|
>
|
|
100
100
|
<slot name="header">
|
|
@@ -46,7 +46,9 @@ 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 {
|
|
49
|
+
import { useButtonGroup } from '../composables/useButtonGroup'
|
|
50
|
+
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
51
|
+
import { useTheme } from '../composables/useTheme'
|
|
50
52
|
import { looseToNumber } from '../utils'
|
|
51
53
|
|
|
52
54
|
defineOptions({
|
|
@@ -55,7 +57,6 @@ defineOptions({
|
|
|
55
57
|
|
|
56
58
|
const props = withDefaults(defineProps<InputProps>(), {
|
|
57
59
|
type: 'text',
|
|
58
|
-
size: 'md',
|
|
59
60
|
variant: 'outline',
|
|
60
61
|
autocomplete: 'off',
|
|
61
62
|
autofocusDelay: 0,
|
|
@@ -67,14 +68,18 @@ const [modelValue, modelModifiers] = defineModel<string | number>()
|
|
|
67
68
|
|
|
68
69
|
const inputRef = ref<HTMLInputElement | null>(null)
|
|
69
70
|
|
|
71
|
+
const { size, orientation } = useButtonGroup(props)
|
|
70
72
|
const { isPrefix, prefixIconName, isSuffix, suffixIconName } = useComponentIcons(props)
|
|
71
73
|
|
|
72
74
|
const { theme, createStyler } = useTheme()
|
|
73
75
|
const style = computed(() => {
|
|
74
76
|
const styler = createStyler(theme.value.input)
|
|
75
|
-
// @ts-expect-error ignore type
|
|
76
77
|
return styler({
|
|
77
78
|
...props,
|
|
79
|
+
// @ts-expect-error ignore type
|
|
80
|
+
type: props.type,
|
|
81
|
+
size: size.value,
|
|
82
|
+
groupOrientation: orientation.value,
|
|
78
83
|
prefix: isPrefix.value || !!slots.prefix,
|
|
79
84
|
suffix: isSuffix.value || !!slots.suffix,
|
|
80
85
|
})
|
|
@@ -130,7 +135,7 @@ onMounted(() => {
|
|
|
130
135
|
<template>
|
|
131
136
|
<Primitive
|
|
132
137
|
:as="as"
|
|
133
|
-
:class="style.
|
|
138
|
+
:class="style.base({ class: [props.class, props.ui?.base] })"
|
|
134
139
|
:aria-disabled="props.disabled ? true : undefined"
|
|
135
140
|
>
|
|
136
141
|
<span v-if="isPrefix || slots.prefix" :class="style.prefix({ class: props.ui?.prefix })">
|
|
@@ -149,7 +154,7 @@ onMounted(() => {
|
|
|
149
154
|
:value="modelValue"
|
|
150
155
|
:name="props.name"
|
|
151
156
|
:placeholder="props.placeholder"
|
|
152
|
-
:class="style.
|
|
157
|
+
:class="style.input({ class: props.ui?.input })"
|
|
153
158
|
:disabled="props.disabled"
|
|
154
159
|
:required="props.required"
|
|
155
160
|
:autocomplete="props.autocomplete"
|
|
@@ -32,7 +32,7 @@ export interface LinkProps extends Omit<ComponentAttrs<typeof link>, 'ui'> {
|
|
|
32
32
|
<script setup lang="ts">
|
|
33
33
|
import { Primitive } from 'reka-ui'
|
|
34
34
|
import { computed } from 'vue'
|
|
35
|
-
import { useTheme } from '../composables'
|
|
35
|
+
import { useTheme } from '../composables/useTheme'
|
|
36
36
|
|
|
37
37
|
const props = withDefaults(defineProps<LinkProps>(), {
|
|
38
38
|
as: 'button',
|
|
@@ -46,12 +46,11 @@ export interface ModalProps extends ComponentAttrs<typeof modal>, DialogRootProp
|
|
|
46
46
|
import { reactivePick } from '@vueuse/core'
|
|
47
47
|
import { DialogClose, DialogContent, DialogDescription, DialogOverlay, DialogPortal, DialogRoot, DialogTitle, DialogTrigger, useForwardPropsEmits } from 'reka-ui'
|
|
48
48
|
import { computed, toRef } from 'vue'
|
|
49
|
-
import { useTheme } from '../composables'
|
|
50
|
-
import
|
|
49
|
+
import { useTheme } from '../composables/useTheme'
|
|
50
|
+
import Button from './Button.vue'
|
|
51
51
|
|
|
52
52
|
const props = withDefaults(defineProps<ModalProps>(), {
|
|
53
53
|
modal: true,
|
|
54
|
-
size: 'md',
|
|
55
54
|
portal: true,
|
|
56
55
|
overlay: true,
|
|
57
56
|
transition: true,
|
|
@@ -95,7 +94,7 @@ const style = computed(() => {
|
|
|
95
94
|
<DialogContent :class="style.content({ class: props.ui?.content })" v-bind="contentProps" v-on="contentEvents">
|
|
96
95
|
<slot name="content">
|
|
97
96
|
<div
|
|
98
|
-
v-if="slots.header ||
|
|
97
|
+
v-if="slots.header || props.title || slots.title || props.description || slots.description || props.close || slots.close"
|
|
99
98
|
:class="style.header({ class: props.ui?.header })"
|
|
100
99
|
>
|
|
101
100
|
<slot name="header">
|
|
@@ -110,7 +109,7 @@ const style = computed(() => {
|
|
|
110
109
|
|
|
111
110
|
<DialogClose as-child>
|
|
112
111
|
<slot name="close">
|
|
113
|
-
<
|
|
112
|
+
<Button
|
|
114
113
|
v-if="props.close"
|
|
115
114
|
variant="ghost"
|
|
116
115
|
:icon="props.closeIcon || theme.app.icons.close"
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { PaginationRootEmits, PaginationRootProps } from 'reka-ui'
|
|
3
|
+
import type { pagination } from '../theme'
|
|
4
|
+
import type { ButtonProps, ComponentAttrs } from '../types'
|
|
5
|
+
|
|
6
|
+
export interface PaginationProps extends ComponentAttrs<typeof pagination>, Pick<PaginationRootProps, 'as' | 'defaultPage' | 'disabled' | 'itemsPerPage' | 'page' | 'showEdges' | 'siblingCount' | 'total'> {
|
|
7
|
+
/**
|
|
8
|
+
* The icon to use for the first page control.
|
|
9
|
+
* @default app.icons.doubleLeft
|
|
10
|
+
*/
|
|
11
|
+
firstIcon?: string
|
|
12
|
+
/**
|
|
13
|
+
* The icon to use for the last page control.
|
|
14
|
+
* @default app.icons.doubleRight
|
|
15
|
+
*/
|
|
16
|
+
lastIcon?: string
|
|
17
|
+
/**
|
|
18
|
+
* The icon to use for the previous page control.
|
|
19
|
+
* @default app.icons.arrowLeft
|
|
20
|
+
*/
|
|
21
|
+
prevIcon?: string
|
|
22
|
+
/**
|
|
23
|
+
* The icon to use for the next page control.
|
|
24
|
+
* @default app.icons.arrowRight
|
|
25
|
+
*/
|
|
26
|
+
nextIcon?: string
|
|
27
|
+
/**
|
|
28
|
+
* The icon to use for the ellipsis control.
|
|
29
|
+
* @default app.icons.ellipsis
|
|
30
|
+
*/
|
|
31
|
+
ellipsisIcon?: string
|
|
32
|
+
/**
|
|
33
|
+
* The size of the pagination controls.
|
|
34
|
+
* @default 'md'
|
|
35
|
+
*/
|
|
36
|
+
size?: ButtonProps['size']
|
|
37
|
+
/**
|
|
38
|
+
* The variant of the pagination controls.
|
|
39
|
+
* @default 'outline'
|
|
40
|
+
*/
|
|
41
|
+
variant?: ButtonProps['variant']
|
|
42
|
+
/**
|
|
43
|
+
* The variant of the active pagination control.
|
|
44
|
+
* @default 'solid'
|
|
45
|
+
*/
|
|
46
|
+
activeVariant?: ButtonProps['variant']
|
|
47
|
+
/**
|
|
48
|
+
* Whether to show the first, previous, next, and last controls.
|
|
49
|
+
* @default true
|
|
50
|
+
*/
|
|
51
|
+
showControls?: boolean
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface PaginationEmits extends PaginationRootEmits {}
|
|
55
|
+
|
|
56
|
+
export interface PaginationSlots {
|
|
57
|
+
first?: (props?: {}) => any
|
|
58
|
+
prev?: (props?: {}) => any
|
|
59
|
+
next?: (props?: {}) => any
|
|
60
|
+
last?: (props?: {}) => any
|
|
61
|
+
ellipsis?: (props?: {}) => any
|
|
62
|
+
item?: (props: {
|
|
63
|
+
page: number
|
|
64
|
+
pageCount: number
|
|
65
|
+
item: {
|
|
66
|
+
type: 'ellipsis'
|
|
67
|
+
} | {
|
|
68
|
+
type: 'page'
|
|
69
|
+
value: number
|
|
70
|
+
}
|
|
71
|
+
index: number
|
|
72
|
+
}) => any
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<script setup lang="ts">
|
|
77
|
+
import { reactivePick } from '@vueuse/core'
|
|
78
|
+
import { PaginationEllipsis, PaginationFirst, PaginationLast, PaginationList, PaginationListItem, PaginationNext, PaginationPrev, PaginationRoot, useForwardPropsEmits } from 'reka-ui'
|
|
79
|
+
import { computed } from 'vue'
|
|
80
|
+
import { useTheme } from '../composables/useTheme'
|
|
81
|
+
import Button from './Button.vue'
|
|
82
|
+
|
|
83
|
+
const props = withDefaults(defineProps<PaginationProps>(), {
|
|
84
|
+
variant: 'outline',
|
|
85
|
+
activeVariant: 'solid',
|
|
86
|
+
showControls: true,
|
|
87
|
+
showEdges: false,
|
|
88
|
+
itemsPerPage: 10,
|
|
89
|
+
siblingCount: 2,
|
|
90
|
+
total: 0,
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const emit = defineEmits<PaginationEmits>()
|
|
94
|
+
const slots = defineSlots<PaginationSlots>()
|
|
95
|
+
|
|
96
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultPage', 'disabled', 'itemsPerPage', 'page', 'showEdges', 'siblingCount', 'total'), emit)
|
|
97
|
+
|
|
98
|
+
const { theme, createStyler } = useTheme()
|
|
99
|
+
|
|
100
|
+
const firstIcon = computed(() => props.firstIcon || theme.value.app.icons.doubleLeft)
|
|
101
|
+
const prevIcon = computed(() => props.prevIcon || theme.value.app.icons.arrowLeft)
|
|
102
|
+
const nextIcon = computed(() => props.nextIcon || theme.value.app.icons.arrowRight)
|
|
103
|
+
const lastIcon = computed(() => props.lastIcon || theme.value.app.icons.doubleRight)
|
|
104
|
+
const ellipsisIcon = computed(() => props.ellipsisIcon || theme.value.app.icons.ellipsis)
|
|
105
|
+
|
|
106
|
+
const style = computed(() => {
|
|
107
|
+
const styler = createStyler(theme.value.pagination)
|
|
108
|
+
return styler(props)
|
|
109
|
+
})
|
|
110
|
+
</script>
|
|
111
|
+
|
|
112
|
+
<template>
|
|
113
|
+
<PaginationRoot v-slot="{ page, pageCount }" v-bind="rootProps" :class="style.root({ class: [props.class, props.ui?.root] })">
|
|
114
|
+
<PaginationList v-slot="{ items }" :class="style.list({ class: props.ui?.list })">
|
|
115
|
+
<PaginationFirst v-if="props.showControls || !!slots.first" as-child>
|
|
116
|
+
<slot name="first">
|
|
117
|
+
<Button :class="style.item({ class: props.ui?.item })" :variant="props.variant" :size="props.size" :icon="firstIcon" />
|
|
118
|
+
</slot>
|
|
119
|
+
</PaginationFirst>
|
|
120
|
+
<PaginationPrev v-if="props.showControls || !!slots.prev" as-child>
|
|
121
|
+
<slot name="prev">
|
|
122
|
+
<Button :class="style.item({ class: props.ui?.item })" :variant="props.variant" :size="props.size" :icon="prevIcon" />
|
|
123
|
+
</slot>
|
|
124
|
+
</PaginationPrev>
|
|
125
|
+
|
|
126
|
+
<template v-for="(item, index) in items">
|
|
127
|
+
<PaginationListItem v-if="item.type === 'page'" :key="index" as-child :value="item.value">
|
|
128
|
+
<slot name="item" v-bind="{ item, index, page, pageCount }">
|
|
129
|
+
<Button
|
|
130
|
+
:class="style.item({ class: props.ui?.item })"
|
|
131
|
+
:variant="props.page === item.value ? props.activeVariant : props.variant"
|
|
132
|
+
:size="props.size"
|
|
133
|
+
:label="String(item.value)"
|
|
134
|
+
:ui="{ label: style.label() }"
|
|
135
|
+
/>
|
|
136
|
+
</slot>
|
|
137
|
+
</PaginationListItem>
|
|
138
|
+
|
|
139
|
+
<PaginationEllipsis v-else :key="item.type" :index="index" as-child>
|
|
140
|
+
<slot name="ellipsis">
|
|
141
|
+
<Button
|
|
142
|
+
:variant="props.variant"
|
|
143
|
+
:size="props.size"
|
|
144
|
+
:icon="ellipsisIcon"
|
|
145
|
+
:disabled="props.disabled /* TODO: remove after reka-ui update */"
|
|
146
|
+
:class="[
|
|
147
|
+
style.item({ class: props.ui?.item }),
|
|
148
|
+
style.ellipsis({ class: props.ui?.ellipsis }),
|
|
149
|
+
]"
|
|
150
|
+
/>
|
|
151
|
+
</slot>
|
|
152
|
+
</PaginationEllipsis>
|
|
153
|
+
</template>
|
|
154
|
+
|
|
155
|
+
<PaginationNext v-if="props.showControls || !!slots.next" as-child>
|
|
156
|
+
<slot name="next">
|
|
157
|
+
<Button :class="style.item({ class: props.ui?.item })" :variant="props.variant" :size="props.size" :icon="nextIcon" />
|
|
158
|
+
</slot>
|
|
159
|
+
</PaginationNext>
|
|
160
|
+
<PaginationLast v-if="props.showControls || !!slots.last" as-child>
|
|
161
|
+
<slot name="last">
|
|
162
|
+
<Button :class="style.item({ class: props.ui?.item })" :variant="props.variant" :size="props.size" :icon="lastIcon" />
|
|
163
|
+
</slot>
|
|
164
|
+
</PaginationLast>
|
|
165
|
+
</PaginationList>
|
|
166
|
+
</PaginationRoot>
|
|
167
|
+
</template>
|