@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.
Files changed (160) hide show
  1. package/README.md +15 -11
  2. package/dist/module.cjs +5 -0
  3. package/dist/module.json +12 -0
  4. package/dist/{nuxt.mjs → module.mjs} +7 -6
  5. package/dist/module.mjs.map +1 -0
  6. package/dist/runtime/components/Accordion.vue +20 -31
  7. package/dist/runtime/components/Alert.vue +1 -1
  8. package/dist/runtime/components/App.vue +1 -1
  9. package/dist/runtime/components/Badge.vue +0 -1
  10. package/dist/runtime/components/Button.vue +14 -12
  11. package/dist/runtime/components/ButtonGroup.vue +47 -0
  12. package/dist/runtime/components/Card.vue +9 -6
  13. package/dist/runtime/components/Carousel.vue +310 -0
  14. package/dist/runtime/components/Checkbox.vue +3 -4
  15. package/dist/runtime/components/Chip.vue +9 -4
  16. package/dist/runtime/components/Collapsible.vue +56 -0
  17. package/dist/runtime/components/Drawer.vue +4 -2
  18. package/dist/runtime/components/Input.vue +12 -8
  19. package/dist/runtime/components/InputNumber.vue +167 -0
  20. package/dist/runtime/components/Link.vue +301 -72
  21. package/dist/runtime/components/LinkBase.vue +88 -0
  22. package/dist/runtime/components/Modal.vue +2 -4
  23. package/dist/runtime/components/Pagination.vue +167 -0
  24. package/dist/runtime/components/PinInput.vue +0 -1
  25. package/dist/runtime/components/RadioGroup.vue +0 -1
  26. package/dist/runtime/components/ScrollArea.vue +1 -1
  27. package/dist/runtime/components/Select.vue +9 -5
  28. package/dist/runtime/components/Separator.vue +63 -0
  29. package/dist/runtime/components/Slider.vue +0 -1
  30. package/dist/runtime/components/Switch.vue +4 -6
  31. package/dist/runtime/components/Table.vue +292 -0
  32. package/dist/runtime/components/Tabs.vue +17 -18
  33. package/dist/runtime/components/Textarea.vue +0 -1
  34. package/dist/runtime/components/Toast.vue +21 -10
  35. package/dist/runtime/components/Toaster.vue +4 -39
  36. package/dist/runtime/composables/useButtonGroup.d.ts +13 -0
  37. package/dist/runtime/composables/useButtonGroup.js +14 -0
  38. package/dist/runtime/composables/{useComponentIcons.mjs → useComponentIcons.js} +1 -1
  39. package/dist/runtime/composables/useModal.d.ts +1 -1
  40. package/dist/runtime/composables/{useModal.mjs → useModal.js} +1 -1
  41. package/dist/runtime/composables/useTheme.d.ts +4 -4
  42. package/dist/runtime/composables/{useTheme.mjs → useTheme.js} +4 -4
  43. package/dist/runtime/composables/useToast.d.ts +4 -4
  44. package/dist/runtime/composables/{useToast.mjs → useToast.js} +19 -6
  45. package/dist/runtime/index.d.ts +34 -0
  46. package/dist/runtime/index.js +34 -0
  47. package/dist/runtime/theme/accordion.d.ts +22 -5
  48. package/dist/runtime/theme/{accordion.mjs → accordion.js} +2 -2
  49. package/dist/runtime/theme/alert.d.ts +41 -1
  50. package/dist/runtime/theme/{alert.mjs → alert.js} +4 -4
  51. package/dist/runtime/theme/app.d.ts +8 -0
  52. package/dist/runtime/theme/app.js +18 -0
  53. package/dist/runtime/theme/badge.d.ts +48 -21
  54. package/dist/runtime/theme/{badge.mjs → badge.js} +5 -2
  55. package/dist/runtime/theme/button-group.d.ts +66 -0
  56. package/dist/runtime/theme/button-group.js +42 -0
  57. package/dist/runtime/theme/button.d.ts +68 -111
  58. package/dist/runtime/theme/button.js +164 -0
  59. package/dist/runtime/theme/card.d.ts +38 -19
  60. package/dist/runtime/theme/card.js +37 -0
  61. package/dist/runtime/theme/carousel.d.ts +113 -0
  62. package/dist/runtime/theme/carousel.js +43 -0
  63. package/dist/runtime/theme/checkbox.d.ts +4 -1
  64. package/dist/runtime/theme/{checkbox.mjs → checkbox.js} +7 -4
  65. package/dist/runtime/theme/chip.d.ts +56 -12
  66. package/dist/runtime/theme/{chip.mjs → chip.js} +10 -7
  67. package/dist/runtime/theme/collapsible.d.ts +38 -0
  68. package/dist/runtime/theme/collapsible.js +10 -0
  69. package/dist/runtime/theme/drawer.d.ts +71 -33
  70. package/dist/runtime/theme/{drawer.mjs → drawer.js} +33 -22
  71. package/dist/runtime/theme/index.d.ts +31 -24
  72. package/dist/runtime/theme/index.js +31 -0
  73. package/dist/runtime/theme/input-number.d.ts +135 -0
  74. package/dist/runtime/theme/input-number.js +92 -0
  75. package/dist/runtime/theme/input.d.ts +94 -111
  76. package/dist/runtime/theme/input.js +151 -0
  77. package/dist/runtime/theme/link.d.ts +14 -1
  78. package/dist/runtime/theme/{link.mjs → link.js} +1 -1
  79. package/dist/runtime/theme/modal.d.ts +33 -7
  80. package/dist/runtime/theme/{modal.mjs → modal.js} +8 -10
  81. package/dist/runtime/theme/pagination.d.ts +56 -0
  82. package/dist/runtime/theme/pagination.js +13 -0
  83. package/dist/runtime/theme/pinInput.d.ts +45 -42
  84. package/dist/runtime/theme/{pinInput.mjs → pinInput.js} +14 -11
  85. package/dist/runtime/theme/popover.d.ts +16 -5
  86. package/dist/runtime/theme/{radioGroup.d.ts → radio-group.d.ts} +4 -1
  87. package/dist/runtime/theme/{radioGroup.mjs → radio-group.js} +3 -0
  88. package/dist/runtime/theme/scroll-area.d.ts +73 -0
  89. package/dist/runtime/theme/{scrollArea.mjs → scroll-area.js} +2 -2
  90. package/dist/runtime/theme/select.d.ts +95 -99
  91. package/dist/runtime/theme/{select.mjs → select.js} +22 -17
  92. package/dist/runtime/theme/separator.d.ts +95 -0
  93. package/dist/runtime/theme/separator.js +53 -0
  94. package/dist/runtime/theme/slider.d.ts +4 -1
  95. package/dist/runtime/theme/{slider.mjs → slider.js} +6 -3
  96. package/dist/runtime/theme/switch.d.ts +4 -1
  97. package/dist/runtime/theme/{switch.mjs → switch.js} +5 -2
  98. package/dist/runtime/theme/table.d.ts +89 -0
  99. package/dist/runtime/theme/table.js +35 -0
  100. package/dist/runtime/theme/tabs.d.ts +72 -52
  101. package/dist/runtime/theme/{tabs.mjs → tabs.js} +15 -12
  102. package/dist/runtime/theme/textarea.d.ts +46 -37
  103. package/dist/runtime/theme/{textarea.mjs → textarea.js} +14 -11
  104. package/dist/runtime/theme/toast.d.ts +45 -7
  105. package/dist/runtime/theme/{toast.mjs → toast.js} +12 -7
  106. package/dist/runtime/theme/toaster.d.ts +89 -25
  107. package/dist/runtime/theme/{toaster.mjs → toaster.js} +5 -0
  108. package/dist/runtime/theme/tooltip.d.ts +20 -7
  109. package/dist/runtime/theme/{tooltip.mjs → tooltip.js} +2 -2
  110. package/dist/runtime/types/components.d.ts +7 -1
  111. package/dist/runtime/types/index.d.ts +4 -4
  112. package/dist/runtime/types/index.js +2 -0
  113. package/dist/runtime/types/utils.d.ts +1 -1
  114. package/dist/runtime/utils/index.d.ts +3 -3
  115. package/dist/runtime/utils/{index.mjs → index.js} +3 -3
  116. package/dist/runtime/utils/link.d.ts +22 -7
  117. package/dist/runtime/utils/link.js +30 -0
  118. package/dist/runtime/utils/styler.d.ts +2 -2
  119. package/dist/runtime/vue/stubs.d.ts +9 -0
  120. package/dist/runtime/vue/stubs.js +16 -0
  121. package/dist/shared/ui.d1728164.mjs +4 -0
  122. package/dist/shared/ui.d1728164.mjs.map +1 -0
  123. package/dist/types.d.mts +1 -0
  124. package/dist/types.d.ts +1 -0
  125. package/dist/{unocss-preset.d.ts → unocss.d.mts} +10 -15
  126. package/dist/{unocss-preset.d.mts → unocss.d.ts} +10 -15
  127. package/dist/{unocss-preset.mjs → unocss.mjs} +53 -21
  128. package/dist/unocss.mjs.map +1 -0
  129. package/dist/unplugin.d.mts +4 -3
  130. package/dist/unplugin.d.ts +4 -3
  131. package/dist/unplugin.mjs +49 -5
  132. package/dist/unplugin.mjs.map +1 -1
  133. package/dist/vite.d.mts +1 -1
  134. package/dist/vite.d.ts +1 -1
  135. package/dist/vite.mjs +7 -5
  136. package/dist/vite.mjs.map +1 -1
  137. package/package.json +59 -45
  138. package/dist/index.d.ts +0 -26
  139. package/dist/index.mjs +0 -26
  140. package/dist/nuxt.mjs.map +0 -1
  141. package/dist/runtime/theme/app.mjs +0 -10
  142. package/dist/runtime/theme/button.mjs +0 -143
  143. package/dist/runtime/theme/card.mjs +0 -14
  144. package/dist/runtime/theme/index.mjs +0 -24
  145. package/dist/runtime/theme/input.mjs +0 -146
  146. package/dist/runtime/theme/scrollArea.d.ts +0 -51
  147. package/dist/runtime/types/index.mjs +0 -2
  148. package/dist/runtime/utils/link.mjs +0 -4
  149. package/dist/shared/ui.CzDyI29e.mjs +0 -8
  150. package/dist/shared/ui.CzDyI29e.mjs.map +0 -1
  151. package/dist/unocss-preset.mjs.map +0 -1
  152. /package/{LICENSE.md → LICENSE} +0 -0
  153. /package/dist/{nuxt.d.mts → module.d.mts} +0 -0
  154. /package/dist/{nuxt.d.ts → module.d.ts} +0 -0
  155. /package/dist/runtime/composables/{defineInjection.mjs → defineInjection.js} +0 -0
  156. /package/dist/runtime/theme/{popover.mjs → popover.js} +0 -0
  157. /package/dist/runtime/types/{components.mjs → components.js} +0 -0
  158. /package/dist/runtime/types/{utils.mjs → utils.js} +0 -0
  159. /package/dist/runtime/utils/{extend-theme.mjs → extend-theme.js} +0 -0
  160. /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
- <i
81
+ <span
83
82
  v-if="modelValue === 'indeterminate'"
84
83
  :class="style.icon({ class: [props.indeterminateIcon || theme.app.icons.indeterminate, props.ui?.icon] })"
85
- ></i>
86
- <i v-else :class="style.icon({ class: [props.icon, theme.app.icons.check, props.ui?.icon] })"></i>
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(props)
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
- <i v-if="isPrefix && prefixIconName" :class="style.prefixIcon({ class: [prefixIconName, props.ui?.prefixIcon] })"></i>
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
- <i v-if="isSuffix && suffixIconName" :class="style.suffixIcon({ class: [suffixIconName, props.ui?.suffixIcon] })"></i>
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
- blur?: boolean
19
- full?: boolean
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.root({ class: [props.class, props.ui?.root] })"
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
- <i
143
+ <span
140
144
  v-if="isPrefix && prefixIconName"
141
145
  :class="style.prefixIcon({ class: [prefixIconName, props.ui?.prefixIcon] })"
142
- ></i>
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.base({ class: props.ui?.base })"
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
- <i
171
+ <span
168
172
  v-if="isSuffix && suffixIconName"
169
173
  :class="style.suffixIcon({ class: [suffixIconName, props.ui?.suffixIcon] })"
170
- ></i>
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>