@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.
Files changed (129) hide show
  1. package/README.md +23 -29
  2. package/dist/index.d.ts +28 -2
  3. package/dist/index.mjs +28 -2
  4. package/dist/nuxt.d.mts +1 -1
  5. package/dist/nuxt.d.ts +1 -1
  6. package/dist/nuxt.mjs +15 -10
  7. package/dist/nuxt.mjs.map +1 -0
  8. package/dist/runtime/components/Accordion.vue +1 -1
  9. package/dist/runtime/components/Alert.vue +120 -0
  10. package/dist/runtime/components/App.vue +1 -1
  11. package/dist/runtime/components/Badge.vue +70 -0
  12. package/dist/runtime/components/Button.vue +7 -3
  13. package/dist/runtime/components/ButtonGroup.vue +47 -0
  14. package/dist/runtime/components/Card.vue +4 -4
  15. package/dist/runtime/components/Carousel.vue +310 -0
  16. package/dist/runtime/components/Checkbox.vue +1 -2
  17. package/dist/runtime/components/Chip.vue +64 -0
  18. package/dist/runtime/components/Drawer.vue +2 -2
  19. package/dist/runtime/components/Input.vue +10 -5
  20. package/dist/runtime/components/Link.vue +1 -1
  21. package/dist/runtime/components/Modal.vue +4 -5
  22. package/dist/runtime/components/Pagination.vue +167 -0
  23. package/dist/runtime/components/PinInput.vue +85 -0
  24. package/dist/runtime/components/Popover.vue +1 -1
  25. package/dist/runtime/components/RadioGroup.vue +1 -2
  26. package/dist/runtime/components/ScrollArea.vue +2 -2
  27. package/dist/runtime/components/Select.vue +7 -2
  28. package/dist/runtime/components/Slider.vue +96 -0
  29. package/dist/runtime/components/Switch.vue +2 -4
  30. package/dist/runtime/components/Tabs.vue +1 -2
  31. package/dist/runtime/components/Textarea.vue +2 -4
  32. package/dist/runtime/components/Toast.vue +21 -10
  33. package/dist/runtime/components/Toaster.vue +5 -5
  34. package/dist/runtime/components/Tooltip.vue +1 -1
  35. package/dist/runtime/composables/useButtonGroup.d.ts +13 -0
  36. package/dist/runtime/composables/useButtonGroup.mjs +14 -0
  37. package/dist/runtime/composables/useTheme.d.ts +2 -2
  38. package/dist/runtime/composables/useTheme.mjs +1 -1
  39. package/dist/runtime/composables/useToast.d.ts +4 -4
  40. package/dist/runtime/composables/useToast.mjs +19 -6
  41. package/dist/runtime/theme/accordion.d.ts +17 -0
  42. package/dist/runtime/theme/accordion.mjs +24 -21
  43. package/dist/runtime/theme/alert.d.ts +125 -0
  44. package/dist/runtime/theme/alert.mjs +47 -0
  45. package/dist/runtime/theme/app.d.ts +5 -0
  46. package/dist/runtime/theme/app.mjs +7 -1
  47. package/dist/runtime/theme/badge.d.ts +82 -0
  48. package/dist/runtime/theme/badge.mjs +92 -0
  49. package/dist/runtime/theme/button-group.d.ts +66 -0
  50. package/dist/runtime/theme/button-group.mjs +42 -0
  51. package/dist/runtime/theme/button.d.ts +15 -1
  52. package/dist/runtime/theme/button.mjs +135 -119
  53. package/dist/runtime/theme/card.d.ts +21 -2
  54. package/dist/runtime/theme/card.mjs +12 -9
  55. package/dist/runtime/theme/carousel.d.ts +113 -0
  56. package/dist/runtime/theme/carousel.mjs +43 -0
  57. package/dist/runtime/theme/checkbox.d.ts +3 -0
  58. package/dist/runtime/theme/checkbox.mjs +47 -41
  59. package/dist/runtime/theme/chip.d.ts +67 -0
  60. package/dist/runtime/theme/chip.mjs +68 -0
  61. package/dist/runtime/theme/drawer.d.ts +38 -0
  62. package/dist/runtime/theme/drawer.mjs +69 -66
  63. package/dist/runtime/theme/index.d.ts +10 -2
  64. package/dist/runtime/theme/index.mjs +10 -2
  65. package/dist/runtime/theme/input.d.ts +41 -22
  66. package/dist/runtime/theme/input.mjs +139 -121
  67. package/dist/runtime/theme/link.d.ts +14 -1
  68. package/dist/runtime/theme/link.mjs +23 -20
  69. package/dist/runtime/theme/modal.d.ts +3 -0
  70. package/dist/runtime/theme/modal.mjs +53 -47
  71. package/dist/runtime/theme/pagination.d.ts +56 -0
  72. package/dist/runtime/theme/pagination.mjs +13 -0
  73. package/dist/runtime/theme/pinInput.d.ts +100 -0
  74. package/dist/runtime/theme/pinInput.mjs +111 -0
  75. package/dist/runtime/theme/popover.d.ts +11 -0
  76. package/dist/runtime/theme/popover.mjs +11 -8
  77. package/dist/runtime/theme/{radioGroup.d.ts → radio-group.d.ts} +3 -0
  78. package/dist/runtime/theme/radio-group.mjs +61 -0
  79. package/dist/runtime/theme/{scrollArea.d.ts → scroll-area.d.ts} +22 -0
  80. package/dist/runtime/theme/scroll-area.mjs +33 -0
  81. package/dist/runtime/theme/select.d.ts +16 -2
  82. package/dist/runtime/theme/select.mjs +160 -142
  83. package/dist/runtime/theme/slider.d.ts +76 -0
  84. package/dist/runtime/theme/slider.mjs +52 -0
  85. package/dist/runtime/theme/switch.d.ts +3 -0
  86. package/dist/runtime/theme/switch.mjs +69 -63
  87. package/dist/runtime/theme/tabs.d.ts +15 -2
  88. package/dist/runtime/theme/tabs.mjs +134 -112
  89. package/dist/runtime/theme/textarea.d.ts +8 -2
  90. package/dist/runtime/theme/textarea.mjs +105 -89
  91. package/dist/runtime/theme/toast.d.ts +44 -6
  92. package/dist/runtime/theme/toast.mjs +30 -22
  93. package/dist/runtime/theme/toaster.d.ts +51 -2
  94. package/dist/runtime/theme/toaster.mjs +88 -80
  95. package/dist/runtime/theme/tooltip.d.ts +13 -0
  96. package/dist/runtime/theme/tooltip.mjs +9 -6
  97. package/dist/runtime/types/components.d.ts +27 -20
  98. package/dist/runtime/types/components.mjs +27 -0
  99. package/dist/runtime/types/index.d.ts +1 -3
  100. package/dist/runtime/types/utils.d.ts +1 -1
  101. package/dist/runtime/utils/extend-theme.mjs +1 -1
  102. package/dist/runtime/utils/link.d.ts +1 -1
  103. package/dist/runtime/utils/styler.d.ts +2 -2
  104. package/dist/shared/ui.D4zm1r0C.mjs +4 -0
  105. package/dist/shared/ui.D4zm1r0C.mjs.map +1 -0
  106. package/dist/{unocss-preset.d.mts → unocss.d.mts} +4 -4
  107. package/dist/{unocss-preset.d.ts → unocss.d.ts} +4 -4
  108. package/dist/{unocss-preset.mjs → unocss.mjs} +58 -36
  109. package/dist/unocss.mjs.map +1 -0
  110. package/dist/unplugin.d.mts +26 -0
  111. package/dist/unplugin.d.ts +26 -0
  112. package/dist/unplugin.mjs +72 -0
  113. package/dist/unplugin.mjs.map +1 -0
  114. package/dist/vite.d.mts +10 -0
  115. package/dist/vite.d.ts +10 -0
  116. package/dist/vite.mjs +14 -0
  117. package/dist/vite.mjs.map +1 -0
  118. package/package.json +46 -26
  119. package/dist/resolver.d.mts +0 -13
  120. package/dist/resolver.d.ts +0 -13
  121. package/dist/resolver.mjs +0 -21
  122. package/dist/runtime/components/index.d.ts +0 -20
  123. package/dist/runtime/components/index.mjs +0 -20
  124. package/dist/runtime/composables/index.d.ts +0 -5
  125. package/dist/runtime/composables/index.mjs +0 -5
  126. package/dist/runtime/theme/radioGroup.mjs +0 -55
  127. package/dist/runtime/theme/scrollArea.mjs +0 -30
  128. package/dist/shared/ui.Cmq14xN9.mjs +0 -25
  129. /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 || (props.title || slots.title) || (props.description || slots.description)"
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 { useComponentIcons, useTheme } from '../composables'
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.root({ class: [props.class, props.ui?.root] })"
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.base({ class: props.ui?.base })"
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 UButton from './Button.vue'
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 || (props.title || slots.title) || (props.description || slots.description) || (props.close || slots.close)"
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
- <UButton
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>