@byyuurin/ui 0.0.7 → 0.0.9

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 (151) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +8 -7
  3. package/dist/module.mjs.map +1 -1
  4. package/dist/runtime/app/injections.d.ts +11 -0
  5. package/dist/runtime/app/injections.js +26 -0
  6. package/dist/runtime/components/Accordion.vue +28 -26
  7. package/dist/runtime/components/Alert.vue +27 -23
  8. package/dist/runtime/components/App.vue +21 -26
  9. package/dist/runtime/components/Avatar.vue +70 -0
  10. package/dist/runtime/components/AvatarGroup.vue +87 -0
  11. package/dist/runtime/components/Badge.vue +17 -15
  12. package/dist/runtime/components/Breadcrumb.vue +108 -0
  13. package/dist/runtime/components/Button.vue +15 -16
  14. package/dist/runtime/components/ButtonGroup.vue +14 -15
  15. package/dist/runtime/components/Calendar.vue +176 -0
  16. package/dist/runtime/components/Card.vue +9 -7
  17. package/dist/runtime/components/Carousel.vue +22 -22
  18. package/dist/runtime/components/Checkbox.vue +15 -14
  19. package/dist/runtime/components/Chip.vue +23 -21
  20. package/dist/runtime/components/Collapsible.vue +5 -8
  21. package/dist/runtime/components/Drawer.vue +91 -49
  22. package/dist/runtime/components/Input.vue +33 -36
  23. package/dist/runtime/components/InputNumber.vue +9 -10
  24. package/dist/runtime/components/Kbd.vue +47 -0
  25. package/dist/runtime/components/Link.vue +15 -12
  26. package/dist/runtime/components/LinkBase.vue +1 -1
  27. package/dist/runtime/components/Modal.vue +31 -19
  28. package/dist/runtime/components/OverlayProvider.vue +29 -0
  29. package/dist/runtime/components/Pagination.vue +60 -53
  30. package/dist/runtime/components/PinInput.vue +9 -12
  31. package/dist/runtime/components/Popover.vue +9 -12
  32. package/dist/runtime/components/Progress.vue +162 -0
  33. package/dist/runtime/components/RadioGroup.vue +38 -35
  34. package/dist/runtime/components/ScrollArea.vue +2 -6
  35. package/dist/runtime/components/Select.vue +48 -51
  36. package/dist/runtime/components/Separator.vue +2 -6
  37. package/dist/runtime/components/Skeleton.vue +30 -0
  38. package/dist/runtime/components/Slider.vue +8 -11
  39. package/dist/runtime/components/Switch.vue +17 -17
  40. package/dist/runtime/components/Table.vue +21 -16
  41. package/dist/runtime/components/Tabs.vue +24 -23
  42. package/dist/runtime/components/Textarea.vue +13 -16
  43. package/dist/runtime/components/Toast.vue +21 -24
  44. package/dist/runtime/components/{Toaster.vue → ToastProvider.vue} +22 -20
  45. package/dist/runtime/components/Tooltip.vue +9 -12
  46. package/dist/runtime/composables/useAvatarGroup.d.ts +4 -0
  47. package/dist/runtime/composables/useAvatarGroup.js +8 -0
  48. package/dist/runtime/composables/useButtonGroup.d.ts +4 -12
  49. package/dist/runtime/composables/useButtonGroup.js +1 -6
  50. package/dist/runtime/composables/useComponentIcons.d.ts +9 -9
  51. package/dist/runtime/composables/useComponentIcons.js +11 -11
  52. package/dist/runtime/composables/useKbd.d.ts +35 -0
  53. package/dist/runtime/composables/useKbd.js +49 -0
  54. package/dist/runtime/composables/useLocale.d.ts +8 -0
  55. package/dist/runtime/composables/useLocale.js +22 -0
  56. package/dist/runtime/composables/useOverlay.d.ts +29 -0
  57. package/dist/runtime/composables/useOverlay.js +69 -0
  58. package/dist/runtime/composables/useTheme.d.ts +6 -6
  59. package/dist/runtime/composables/useTheme.js +11 -15
  60. package/dist/runtime/composables/useToast.d.ts +4 -20
  61. package/dist/runtime/composables/useToast.js +6 -5
  62. package/dist/runtime/index.d.ts +9 -2
  63. package/dist/runtime/index.js +9 -2
  64. package/dist/runtime/locale/en.d.ts +2 -0
  65. package/dist/runtime/locale/en.js +34 -0
  66. package/dist/runtime/locale/index.d.ts +2 -0
  67. package/dist/runtime/locale/index.js +2 -0
  68. package/dist/runtime/locale/zh-tw.d.ts +2 -0
  69. package/dist/runtime/locale/zh-tw.js +34 -0
  70. package/dist/runtime/theme/accordion.d.ts +6 -6
  71. package/dist/runtime/theme/accordion.js +5 -5
  72. package/dist/runtime/theme/alert.js +3 -3
  73. package/dist/runtime/theme/app.d.ts +6 -6
  74. package/dist/runtime/theme/app.js +7 -7
  75. package/dist/runtime/theme/avatar-group.d.ts +52 -0
  76. package/dist/runtime/theme/avatar-group.js +32 -0
  77. package/dist/runtime/theme/avatar.d.ts +56 -0
  78. package/dist/runtime/theme/avatar.js +34 -0
  79. package/dist/runtime/theme/breadcrumb.d.ts +67 -0
  80. package/dist/runtime/theme/breadcrumb.js +44 -0
  81. package/dist/runtime/theme/button.d.ts +8 -8
  82. package/dist/runtime/theme/button.js +22 -22
  83. package/dist/runtime/theme/calendar.d.ts +56 -0
  84. package/dist/runtime/theme/calendar.js +69 -0
  85. package/dist/runtime/theme/card.js +6 -6
  86. package/dist/runtime/theme/carousel.js +1 -1
  87. package/dist/runtime/theme/checkbox.js +5 -5
  88. package/dist/runtime/theme/chip.d.ts +4 -4
  89. package/dist/runtime/theme/chip.js +5 -5
  90. package/dist/runtime/theme/drawer.d.ts +24 -21
  91. package/dist/runtime/theme/drawer.js +47 -20
  92. package/dist/runtime/theme/index.d.ts +8 -1
  93. package/dist/runtime/theme/index.js +8 -1
  94. package/dist/runtime/theme/input-number.d.ts +6 -0
  95. package/dist/runtime/theme/input-number.js +6 -3
  96. package/dist/runtime/theme/input.d.ts +12 -12
  97. package/dist/runtime/theme/input.js +26 -26
  98. package/dist/runtime/theme/kbd.d.ts +39 -0
  99. package/dist/runtime/theme/kbd.js +26 -0
  100. package/dist/runtime/theme/link.d.ts +1 -1
  101. package/dist/runtime/theme/link.js +3 -3
  102. package/dist/runtime/theme/modal.js +5 -5
  103. package/dist/runtime/theme/pagination.d.ts +27 -3
  104. package/dist/runtime/theme/pagination.js +6 -2
  105. package/dist/runtime/theme/pinInput.js +13 -13
  106. package/dist/runtime/theme/popover.js +1 -1
  107. package/dist/runtime/theme/progress.d.ts +122 -0
  108. package/dist/runtime/theme/progress.js +95 -0
  109. package/dist/runtime/theme/radio-group.d.ts +2 -2
  110. package/dist/runtime/theme/radio-group.js +7 -7
  111. package/dist/runtime/theme/select.d.ts +18 -18
  112. package/dist/runtime/theme/select.js +34 -34
  113. package/dist/runtime/theme/separator.js +1 -1
  114. package/dist/runtime/theme/skeleton.d.ts +8 -0
  115. package/dist/runtime/theme/skeleton.js +7 -0
  116. package/dist/runtime/theme/slider.js +1 -1
  117. package/dist/runtime/theme/switch.js +6 -6
  118. package/dist/runtime/theme/table.js +7 -7
  119. package/dist/runtime/theme/tabs.d.ts +2 -2
  120. package/dist/runtime/theme/tabs.js +11 -11
  121. package/dist/runtime/theme/textarea.js +13 -13
  122. package/dist/runtime/theme/toast.js +6 -6
  123. package/dist/runtime/theme/tooltip.js +1 -1
  124. package/dist/runtime/types/components.d.ts +9 -1
  125. package/dist/runtime/types/index.d.ts +1 -0
  126. package/dist/runtime/types/index.js +1 -0
  127. package/dist/runtime/types/locale.d.ts +29 -0
  128. package/dist/runtime/types/locale.js +0 -0
  129. package/dist/runtime/types/utils.d.ts +5 -3
  130. package/dist/runtime/utils/index.d.ts +6 -1
  131. package/dist/runtime/utils/index.js +6 -4
  132. package/dist/runtime/utils/link.d.ts +1 -1
  133. package/dist/runtime/utils/translator.d.ts +18 -0
  134. package/dist/runtime/utils/translator.js +8 -0
  135. package/dist/shared/ui.1a1f119c.mjs +5 -0
  136. package/dist/shared/ui.1a1f119c.mjs.map +1 -0
  137. package/dist/unocss.mjs +19 -14
  138. package/dist/unocss.mjs.map +1 -1
  139. package/dist/unplugin.mjs +3 -12
  140. package/dist/unplugin.mjs.map +1 -1
  141. package/dist/vite.mjs +1 -1
  142. package/package.json +30 -19
  143. package/dist/runtime/components/ModalProvider.vue +0 -10
  144. package/dist/runtime/composables/useModal.d.ts +0 -15
  145. package/dist/runtime/composables/useModal.js +0 -52
  146. package/dist/shared/ui.d1728164.mjs +0 -4
  147. package/dist/shared/ui.d1728164.mjs.map +0 -1
  148. /package/dist/runtime/theme/{toaster.d.ts → toast-provider.d.ts} +0 -0
  149. /package/dist/runtime/theme/{toaster.js → toast-provider.js} +0 -0
  150. /package/dist/runtime/{composables/defineInjection.d.ts → utils/vue.d.ts} +0 -0
  151. /package/dist/runtime/{composables/defineInjection.js → utils/vue.js} +0 -0
@@ -4,17 +4,19 @@ import type { DialogContentProps, DialogRootEmits, DialogRootProps } from 'reka-
4
4
  import type { modal } from '../theme'
5
5
  import type { ButtonProps, ComponentAttrs } from '../types'
6
6
 
7
- export interface ModalEmits extends DialogRootEmits {}
7
+ export interface ModalEmits extends DialogRootEmits {
8
+ 'after-leave': []
9
+ }
8
10
 
9
11
  export interface ModalSlots {
10
12
  default?: (props: { open: boolean }) => any
11
- content?: (props?: any) => any
12
- header?: (props?: any) => any
13
- title?: (props?: any) => any
14
- description?: (props?: any) => any
15
- close?: (props?: any) => any
16
- body?: (props?: any) => any
17
- footer?: (props?: any) => any
13
+ content?: (props?: {}) => any
14
+ header?: (props?: {}) => any
15
+ title?: (props?: {}) => any
16
+ description?: (props?: {}) => any
17
+ close?: (props?: {}) => any
18
+ body?: (props?: {}) => any
19
+ footer?: (props?: {}) => any
18
20
  }
19
21
 
20
22
  type ModalVariants = VariantProps<typeof modal>
@@ -35,16 +37,21 @@ export interface ModalProps extends ComponentAttrs<typeof modal>, DialogRootProp
35
37
  * @default true
36
38
  */
37
39
  dismissible?: boolean
40
+ /**
41
+ * Display a close button to dismiss the modal.
42
+ * @default true
43
+ */
38
44
  close?: ButtonProps | boolean
39
- /** @default `app.icons.close` */
45
+ /** @default app.icons.close */
40
46
  closeIcon?: string
41
47
  }
42
48
  </script>
43
49
 
44
50
  <script setup lang="ts">
45
51
  import { reactivePick } from '@vueuse/core'
46
- import { DialogClose, DialogContent, DialogDescription, DialogOverlay, DialogPortal, DialogRoot, DialogTitle, DialogTrigger, useForwardPropsEmits } from 'reka-ui'
52
+ import { DialogClose, DialogContent, DialogDescription, DialogOverlay, DialogPortal, DialogRoot, DialogTitle, DialogTrigger, useForwardPropsEmits, VisuallyHidden } from 'reka-ui'
47
53
  import { computed, toRef } from 'vue'
54
+ import { useLocale } from '../composables/useLocale'
48
55
  import { useTheme } from '../composables/useTheme'
49
56
  import Button from './Button.vue'
50
57
 
@@ -59,7 +66,10 @@ const props = withDefaults(defineProps<ModalProps>(), {
59
66
  const emit = defineEmits<ModalEmits>()
60
67
  const slots = defineSlots<ModalSlots>()
61
68
  const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'modal'), emit)
62
- const contentProps = toRef(() => props.content)
69
+ const contentProps = toRef(() => ({
70
+ ...props.content,
71
+ ...(slots.content || slots.header || (!props.description && !slots.description)) ? { 'aria-describedby': undefined } : {},
72
+ }))
63
73
  const contentEvents = computed(() => {
64
74
  if (props.dismissible)
65
75
  return {}
@@ -71,11 +81,9 @@ const contentEvents = computed(() => {
71
81
  }
72
82
  })
73
83
 
74
- const { theme, createStyler } = useTheme()
75
- const style = computed(() => {
76
- const styler = createStyler(theme.value.modal)
77
- return styler(props)
78
- })
84
+ const { t } = useLocale()
85
+ const { theme, generateStyle } = useTheme()
86
+ const style = computed(() => generateStyle('modal', props))
79
87
  </script>
80
88
 
81
89
  <template>
@@ -90,7 +98,11 @@ const style = computed(() => {
90
98
  <DialogPortal :disabled="!props.portal">
91
99
  <DialogOverlay v-if="props.overlay" :class="style.overlay({ class: props.ui?.overlay })" />
92
100
 
93
- <DialogContent :class="style.content({ class: props.ui?.content })" v-bind="contentProps" v-on="contentEvents">
101
+ <DialogContent :class="style.content({ class: props.ui?.content })" v-bind="contentProps" v-on="contentEvents" @after-leave="emit('after-leave')">
102
+ <VisuallyHidden v-if="slots.content || slots.header || (!props.title && !slots.title)">
103
+ <DialogTitle />
104
+ </VisuallyHidden>
105
+
94
106
  <slot name="content">
95
107
  <div
96
108
  v-if="slots.header || props.title || slots.title || props.description || slots.description || props.close || slots.close"
@@ -106,14 +118,14 @@ const style = computed(() => {
106
118
  </slot>
107
119
  </DialogTitle>
108
120
 
109
- <DialogClose as-child>
121
+ <DialogClose v-if="props.close || slots.close" as-child>
110
122
  <slot name="close">
111
123
  <Button
112
- v-if="props.close"
113
124
  variant="ghost"
114
125
  :icon="props.closeIcon || theme.app.icons.close"
115
126
  v-bind="typeof props.close === 'boolean' ? {} : props.close"
116
127
  :class="style.close({ class: props.ui?.close })"
128
+ :aria-label="t('modal.close')"
117
129
  />
118
130
  </slot>
119
131
  </DialogClose>
@@ -0,0 +1,29 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import type { OverlayComponentState } from '../composables/useOverlay'
4
+ import { useOverlay } from '../composables/useOverlay'
5
+
6
+ const { overlays, unmount, close } = useOverlay()
7
+ const mountedOverlays = computed(() => overlays.filter((overlay) => overlay.isMounted))
8
+
9
+ function onOverlayUnmount(id: OverlayComponentState['id']) {
10
+ close(id)
11
+ unmount(id)
12
+ }
13
+
14
+ function onClose(id: OverlayComponentState['id'], value: any) {
15
+ close(id, value)
16
+ }
17
+ </script>
18
+
19
+ <template>
20
+ <component
21
+ :is="overlay.component"
22
+ v-for="overlay in mountedOverlays"
23
+ :key="overlay.id"
24
+ v-bind="overlay.props"
25
+ v-model:open="overlay.modelValue"
26
+ @close="onClose(overlay.id, $event)"
27
+ @after-leave="onOverlayUnmount(overlay.id)"
28
+ />
29
+ </template>
@@ -3,6 +3,27 @@ import type { PaginationRootEmits, PaginationRootProps } from 'reka-ui'
3
3
  import type { pagination } from '../theme'
4
4
  import type { ButtonProps, ComponentAttrs } from '../types'
5
5
 
6
+ export interface PaginationEmits extends PaginationRootEmits {}
7
+
8
+ export interface PaginationSlots {
9
+ first?: (props?: {}) => any
10
+ prev?: (props?: {}) => any
11
+ next?: (props?: {}) => any
12
+ last?: (props?: {}) => any
13
+ ellipsis?: (props?: {}) => any
14
+ item?: (props: {
15
+ page: number
16
+ pageCount: number
17
+ item: {
18
+ type: 'ellipsis'
19
+ } | {
20
+ type: 'page'
21
+ value: number
22
+ }
23
+ index: number
24
+ }) => any
25
+ }
26
+
6
27
  export interface PaginationProps extends ComponentAttrs<typeof pagination>, Pick<PaginationRootProps, 'as' | 'defaultPage' | 'disabled' | 'itemsPerPage' | 'page' | 'showEdges' | 'siblingCount' | 'total'> {
7
28
  /**
8
29
  * The icon to use for the first page control.
@@ -16,12 +37,12 @@ export interface PaginationProps extends ComponentAttrs<typeof pagination>, Pick
16
37
  lastIcon?: string
17
38
  /**
18
39
  * The icon to use for the previous page control.
19
- * @default app.icons.arrowLeft
40
+ * @default app.icons.chevronLeft
20
41
  */
21
42
  prevIcon?: string
22
43
  /**
23
44
  * The icon to use for the next page control.
24
- * @default app.icons.arrowRight
45
+ * @default app.icons.chevronRight
25
46
  */
26
47
  nextIcon?: string
27
48
  /**
@@ -31,17 +52,17 @@ export interface PaginationProps extends ComponentAttrs<typeof pagination>, Pick
31
52
  ellipsisIcon?: string
32
53
  /**
33
54
  * The size of the pagination controls.
34
- * @default 'md'
55
+ * @default "md"
35
56
  */
36
57
  size?: ButtonProps['size']
37
58
  /**
38
59
  * The variant of the pagination controls.
39
- * @default 'outline'
60
+ * @default "outline"
40
61
  */
41
62
  variant?: ButtonProps['variant']
42
63
  /**
43
64
  * The variant of the active pagination control.
44
- * @default 'solid'
65
+ * @default "solid"
45
66
  */
46
67
  activeVariant?: ButtonProps['variant']
47
68
  /**
@@ -49,27 +70,10 @@ export interface PaginationProps extends ComponentAttrs<typeof pagination>, Pick
49
70
  * @default true
50
71
  */
51
72
  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
+ * A function to render page controls as links.
75
+ */
76
+ to?: (page: number) => ButtonProps['to']
73
77
  }
74
78
  </script>
75
79
 
@@ -77,6 +81,7 @@ export interface PaginationSlots {
77
81
  import { reactivePick } from '@vueuse/core'
78
82
  import { PaginationEllipsis, PaginationFirst, PaginationLast, PaginationList, PaginationListItem, PaginationNext, PaginationPrev, PaginationRoot, useForwardPropsEmits } from 'reka-ui'
79
83
  import { computed } from 'vue'
84
+ import { useLocale } from '../composables/useLocale'
80
85
  import { useTheme } from '../composables/useTheme'
81
86
  import Button from './Button.vue'
82
87
 
@@ -95,71 +100,73 @@ const slots = defineSlots<PaginationSlots>()
95
100
 
96
101
  const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultPage', 'disabled', 'itemsPerPage', 'page', 'showEdges', 'siblingCount', 'total'), emit)
97
102
 
98
- const { theme, createStyler } = useTheme()
103
+ const { dir } = useLocale()
104
+ const { theme, generateStyle } = useTheme()
105
+ const style = computed(() => generateStyle('pagination', props))
99
106
 
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)
107
+ const firstIcon = computed(() => props.firstIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronDoubleRight : theme.value.app.icons.chevronDoubleLeft))
108
+ const prevIcon = computed(() => props.prevIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronRight : theme.value.app.icons.chevronLeft))
109
+ const nextIcon = computed(() => props.nextIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronLeft : theme.value.app.icons.chevronRight))
110
+ const lastIcon = computed(() => props.lastIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronDoubleLeft : theme.value.app.icons.chevronDoubleRight))
104
111
  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
112
  </script>
111
113
 
112
114
  <template>
113
115
  <PaginationRoot v-slot="{ page, pageCount }" v-bind="rootProps" :class="style.root({ class: [props.class, props.ui?.root] })">
114
116
  <PaginationList v-slot="{ items }" :class="style.list({ class: props.ui?.list })">
115
- <PaginationFirst v-if="props.showControls || !!slots.first" as-child>
117
+ <PaginationFirst v-if="props.showControls || !!slots.first" :class="style.first({ class: props.ui?.first })" as-child>
116
118
  <slot name="first">
117
- <Button :class="style.item({ class: props.ui?.item })" :variant="props.variant" :size="props.size" :icon="firstIcon" />
119
+ <Button :variant="props.variant" :size="props.size" :icon="firstIcon" :to="props.to?.(1)" />
118
120
  </slot>
119
121
  </PaginationFirst>
120
- <PaginationPrev v-if="props.showControls || !!slots.prev" as-child>
122
+ <PaginationPrev v-if="props.showControls || !!slots.prev" :class="style.prev({ class: props.ui?.prev })" as-child>
121
123
  <slot name="prev">
122
- <Button :class="style.item({ class: props.ui?.item })" :variant="props.variant" :size="props.size" :icon="prevIcon" />
124
+ <Button :variant="props.variant" :size="props.size" :icon="prevIcon" :to="page > 1 ? props.to?.(page - 1) : undefined" />
123
125
  </slot>
124
126
  </PaginationPrev>
125
127
 
126
128
  <template v-for="(item, index) in items">
127
- <PaginationListItem v-if="item.type === 'page'" :key="index" as-child :value="item.value">
129
+ <PaginationListItem v-if="item.type === 'page'" :key="index" :class="style.item({ class: props.ui?.item })" :value="item.value" as-child>
128
130
  <slot name="item" v-bind="{ item, index, page, pageCount }">
129
131
  <Button
130
- :class="style.item({ class: props.ui?.item })"
131
132
  :variant="props.page === item.value ? props.activeVariant : props.variant"
132
133
  :size="props.size"
133
134
  :label="String(item.value)"
134
- :ui="{ label: style.label() }"
135
+ :to="props.to?.(item.value)"
136
+ :ui="{ label: style.label({ class: props.ui?.label }) }"
135
137
  />
136
138
  </slot>
137
139
  </PaginationListItem>
138
140
 
139
- <PaginationEllipsis v-else :key="item.type" :index="index" as-child>
141
+ <PaginationEllipsis
142
+ v-else
143
+ :key="item.type"
144
+ :class="[
145
+ style.item({ class: props.ui?.item }),
146
+ style.ellipsis({ class: props.ui?.ellipsis }),
147
+ ]"
148
+ :index="index"
149
+ :disabled="props.disabled"
150
+ as-child
151
+ >
140
152
  <slot name="ellipsis">
141
153
  <Button
142
154
  :variant="props.variant"
143
155
  :size="props.size"
144
156
  :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
157
  />
151
158
  </slot>
152
159
  </PaginationEllipsis>
153
160
  </template>
154
161
 
155
- <PaginationNext v-if="props.showControls || !!slots.next" as-child>
162
+ <PaginationNext v-if="props.showControls || !!slots.next" :class="style.next({ class: props.ui?.next })" as-child>
156
163
  <slot name="next">
157
- <Button :class="style.item({ class: props.ui?.item })" :variant="props.variant" :size="props.size" :icon="nextIcon" />
164
+ <Button :variant="props.variant" :size="props.size" :icon="nextIcon" :to="page < pageCount ? props.to?.(page + 1) : undefined" />
158
165
  </slot>
159
166
  </PaginationNext>
160
- <PaginationLast v-if="props.showControls || !!slots.last" as-child>
167
+ <PaginationLast v-if="props.showControls || !!slots.last" :class="style.last({ class: props.ui?.last })" as-child>
161
168
  <slot name="last">
162
- <Button :class="style.item({ class: props.ui?.item })" :variant="props.variant" :size="props.size" :icon="lastIcon" />
169
+ <Button :variant="props.variant" :size="props.size" :icon="lastIcon" :to="props.to?.(pageCount)" />
163
170
  </slot>
164
171
  </PaginationLast>
165
172
  </PaginationList>
@@ -4,6 +4,13 @@ import type { PinInputRootProps } from 'reka-ui'
4
4
  import type { pinInput } from '../theme'
5
5
  import type { ComponentAttrs } from '../types'
6
6
 
7
+ export interface PinInputEmits {
8
+ (event: 'update:modelValue', value: string[]): void
9
+ (event: 'complete', value: string[]): void
10
+ (event: 'change', payload: Event): void
11
+ (event: 'blur', payload: Event): void
12
+ }
13
+
7
14
  type PinInputVariants = VariantProps<typeof pinInput>
8
15
 
9
16
  export interface PinInputProps extends ComponentAttrs<typeof pinInput>, Pick<PinInputRootProps, 'as' | 'defaultValue' | 'disabled' | 'id' | 'mask' | 'modelValue' | 'name' | 'otp' | 'placeholder' | 'required' | 'type'> {
@@ -13,13 +20,6 @@ export interface PinInputProps extends ComponentAttrs<typeof pinInput>, Pick<Pin
13
20
  underline?: boolean
14
21
  highlight?: boolean
15
22
  }
16
-
17
- export interface PinInputEmits {
18
- (event: 'update:modelValue', value: string[]): void
19
- (event: 'complete', value: string[]): void
20
- (event: 'change', payload: Event): void
21
- (event: 'blur', payload: Event): void
22
- }
23
23
  </script>
24
24
 
25
25
  <script setup lang="ts">
@@ -41,11 +41,8 @@ const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultValue', 'disa
41
41
 
42
42
  const completed = ref(false)
43
43
 
44
- const { theme, createStyler } = useTheme()
45
- const style = computed(() => {
46
- const styler = createStyler(theme.value.pinInput)
47
- return styler(props)
48
- })
44
+ const { generateStyle } = useTheme()
45
+ const style = computed(() => generateStyle('pinInput', props))
49
46
 
50
47
  function onComplete(value: string[]) {
51
48
  // @ts-expect-error - 'target' does not exist in type 'EventInit'
@@ -3,6 +3,13 @@ import type { HoverCardRootProps, PopoverArrowProps, PopoverContentProps, Popove
3
3
  import type { popover } from '../theme'
4
4
  import type { ComponentAttrs } from '../types'
5
5
 
6
+ export interface PopoverEmits extends PopoverRootEmits {}
7
+
8
+ export interface PopoverSlots {
9
+ default?: (props: { open: boolean }) => any
10
+ content?: (props?: {}) => any
11
+ }
12
+
6
13
  export interface PopoverProps extends ComponentAttrs<typeof popover>, PopoverRootProps, Pick<HoverCardRootProps, 'openDelay' | 'closeDelay'> {
7
14
  /**
8
15
  * The display mode of the popover.
@@ -20,13 +27,6 @@ export interface PopoverProps extends ComponentAttrs<typeof popover>, PopoverRoo
20
27
  */
21
28
  dismissible?: boolean
22
29
  }
23
-
24
- export interface PopoverEmits extends PopoverRootEmits {}
25
-
26
- export interface PopoverSlots {
27
- default?: (props: { open: boolean }) => any
28
- content?: (props?: {}) => any
29
- }
30
30
  </script>
31
31
 
32
32
  <script setup lang="ts">
@@ -69,11 +69,8 @@ const arrowProps = toRef(() => props.arrow as PopoverArrowProps)
69
69
 
70
70
  const Component = computed(() => props.mode === 'hover' ? HoverCard : Popover)
71
71
 
72
- const { theme, createStyler } = useTheme()
73
- const style = computed(() => {
74
- const styler = createStyler(theme.value.popover)
75
- return styler(props)
76
- })
72
+ const { generateStyle } = useTheme()
73
+ const style = computed(() => generateStyle('popover', props))
77
74
  </script>
78
75
 
79
76
  <template>
@@ -0,0 +1,162 @@
1
+ <script lang="ts">
2
+ import type { VariantProps } from '@byyuurin/ui-kit'
3
+ import type { PrimitiveProps, ProgressRootEmits, ProgressRootProps } from 'reka-ui'
4
+ import type { progress } from '../theme'
5
+ import type { ComponentAttrs } from '../types'
6
+
7
+ export interface ProgressEmits extends ProgressRootEmits {}
8
+
9
+ export type ProgressSlots = {
10
+ status?: (props: { percent?: number }) => any
11
+ } & {
12
+ [key: `step-${number}`]: (props: { step: string | number }) => any
13
+ }
14
+
15
+ type ProgressVariants = VariantProps<typeof progress>
16
+
17
+ export interface ProgressProps extends ComponentAttrs<typeof progress>, Pick<ProgressRootProps, 'getValueLabel' | 'modelValue'> {
18
+ /**
19
+ * The element or component this component should render as.
20
+ * @default "div"
21
+ */
22
+ as?: PrimitiveProps['as']
23
+ /** The maximum progress value. */
24
+ max?: number | string[]
25
+ /**
26
+ * @default "md"
27
+ */
28
+ size?: ProgressVariants['size']
29
+ /**
30
+ * The orientation of the progress bar.
31
+ * @default "horizontal"
32
+ */
33
+ orientation?: ProgressVariants['orientation']
34
+ /** Display the current progress value. */
35
+ status?: boolean
36
+ /** Whether the progress is visually inverted. */
37
+ inverted?: boolean
38
+ }
39
+ </script>
40
+
41
+ <script setup lang="ts">
42
+ import { reactivePick } from '@vueuse/core'
43
+ import { Primitive, ProgressIndicator, ProgressRoot, useForwardPropsEmits } from 'reka-ui'
44
+ import { computed } from 'vue'
45
+ import { useLocale } from '../composables/useLocale'
46
+ import { useTheme } from '../composables/useTheme'
47
+
48
+ const props = withDefaults(defineProps<ProgressProps>(), {
49
+ modelValue: null,
50
+ orientation: 'horizontal',
51
+ })
52
+ const emit = defineEmits<ProgressEmits>()
53
+ const slots = defineSlots<ProgressSlots>()
54
+
55
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'getValueLabel', 'modelValue'), emit)
56
+
57
+ const isIndeterminate = computed(() => rootProps.value.modelValue === null || Number.isNaN(+rootProps.value.modelValue))
58
+ const hasSteps = computed(() => Array.isArray(props.max))
59
+
60
+ const max = computed(() => {
61
+ if (isIndeterminate.value || !props.max)
62
+ return
63
+
64
+ if (Array.isArray(props.max))
65
+ return props.max.length - 1
66
+
67
+ return Number(props.max)
68
+ })
69
+
70
+ const percent = computed(() => {
71
+ if (isIndeterminate.value)
72
+ return
73
+
74
+ if (rootProps.value.modelValue! < 0)
75
+ return 0
76
+
77
+ const _max = max.value ?? 100
78
+
79
+ if (rootProps.value.modelValue! > _max)
80
+ return 100
81
+
82
+ return Math.round((rootProps.value.modelValue! / _max) * 100)
83
+ })
84
+
85
+ const { dir } = useLocale()
86
+ const { generateStyle } = useTheme()
87
+ const style = computed(() => generateStyle('progress', props))
88
+
89
+ const indicatorStyle = computed(() => {
90
+ if (percent.value === undefined)
91
+ return
92
+
93
+ if (props.orientation === 'vertical')
94
+ return { transform: `translateY(${props.inverted ? '' : '-'}${100 - percent.value}%)` }
95
+
96
+ if (dir.value === 'rtl')
97
+ return { transform: `translateX(${props.inverted ? '-' : ''}${100 - percent.value}%)` }
98
+
99
+ return { transform: `translateX(${props.inverted ? '' : '-'}${100 - percent.value}%)` }
100
+ })
101
+
102
+ const statusStyle = computed(() => {
103
+ return {
104
+ [props.orientation === 'vertical' ? 'height' : 'width']: percent.value ? `${percent.value}%` : 'fit-content',
105
+ }
106
+ })
107
+
108
+ function isActive(index: number) {
109
+ return index === Number(props.modelValue)
110
+ }
111
+
112
+ function isFirst(index: number) {
113
+ return index === 0
114
+ }
115
+
116
+ function isLast(index: number) {
117
+ return index === max.value
118
+ }
119
+
120
+ function stepVariant(index: number | string) {
121
+ index = Number(index)
122
+
123
+ if (isActive(index) && !isFirst(index))
124
+ return 'active'
125
+
126
+ if (isFirst(index) && isActive(index))
127
+ return 'first'
128
+
129
+ if (isLast(index) && isActive(index))
130
+ return 'last'
131
+
132
+ return 'other'
133
+ }
134
+ </script>
135
+
136
+ <template>
137
+ <Primitive :as="props.as" :class="style.wrapper({ class: [props.class, props.ui?.wrapper] })">
138
+ <div v-if="!isIndeterminate && (props.status || slots.status)" :class="style.status({ class: props.ui?.status })" :style="statusStyle">
139
+ <slot name="status" :percent="percent">
140
+ {{ percent }}%
141
+ </slot>
142
+ </div>
143
+
144
+ <ProgressRoot
145
+ v-bind="rootProps"
146
+ :model-value="Number.isNaN(rootProps.modelValue) ? null : rootProps.modelValue"
147
+ :max="max"
148
+ :class="style.root({ class: props.ui?.root })"
149
+ style="transform: translateZ(0)"
150
+ >
151
+ <ProgressIndicator :class="style.indicator({ class: props.ui?.indicator })" :style="indicatorStyle" />
152
+ </ProgressRoot>
153
+
154
+ <div v-if="hasSteps" :class="style.steps({ class: props.ui?.steps })">
155
+ <div v-for="(step, index) in props.max" :key="index" :class="style.step({ class: props.ui?.step, step: stepVariant(index) })">
156
+ <slot :name="`step-${index}`" :step="step">
157
+ {{ step }}
158
+ </slot>
159
+ </div>
160
+ </div>
161
+ </Primitive>
162
+ </template>