@byyuurin/ui 0.0.8 → 0.0.10

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/README.md +0 -3
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +4 -3
  4. package/dist/module.mjs.map +1 -1
  5. package/dist/runtime/app/injections.d.ts +9299 -8
  6. package/dist/runtime/app/injections.js +35 -5
  7. package/dist/runtime/components/Accordion.vue +17 -19
  8. package/dist/runtime/components/Alert.vue +6 -9
  9. package/dist/runtime/components/App.vue +14 -19
  10. package/dist/runtime/components/Avatar.vue +5 -8
  11. package/dist/runtime/components/AvatarGroup.vue +2 -5
  12. package/dist/runtime/components/Badge.vue +3 -6
  13. package/dist/runtime/components/Breadcrumb.vue +22 -23
  14. package/dist/runtime/components/Button.vue +2 -3
  15. package/dist/runtime/components/ButtonGroup.vue +2 -5
  16. package/dist/runtime/components/Calendar.vue +185 -0
  17. package/dist/runtime/components/Card.vue +2 -5
  18. package/dist/runtime/components/Carousel.vue +11 -16
  19. package/dist/runtime/components/Checkbox.vue +13 -11
  20. package/dist/runtime/components/Chip.vue +6 -9
  21. package/dist/runtime/components/Collapsible.vue +2 -5
  22. package/dist/runtime/components/Drawer.vue +88 -45
  23. package/dist/runtime/components/DropdownMenu.vue +143 -0
  24. package/dist/runtime/components/DropdownMenuContent.vue +188 -0
  25. package/dist/runtime/components/Form.vue +311 -0
  26. package/dist/runtime/components/FormItem.vue +129 -0
  27. package/dist/runtime/components/Input.vue +34 -23
  28. package/dist/runtime/components/InputNumber.vue +23 -18
  29. package/dist/runtime/components/Kbd.vue +2 -6
  30. package/dist/runtime/components/Link.vue +25 -7
  31. package/dist/runtime/components/Modal.vue +31 -22
  32. package/dist/runtime/components/OverlayProvider.vue +29 -0
  33. package/dist/runtime/components/Pagination.vue +34 -27
  34. package/dist/runtime/components/PinInput.vue +23 -17
  35. package/dist/runtime/components/Popover.vue +5 -8
  36. package/dist/runtime/components/Progress.vue +2 -5
  37. package/dist/runtime/components/RadioGroup.vue +52 -49
  38. package/dist/runtime/components/ScrollArea.vue +2 -6
  39. package/dist/runtime/components/Select.vue +96 -89
  40. package/dist/runtime/components/Separator.vue +2 -6
  41. package/dist/runtime/components/Skeleton.vue +2 -5
  42. package/dist/runtime/components/Slider.vue +13 -11
  43. package/dist/runtime/components/Switch.vue +18 -11
  44. package/dist/runtime/components/Table.vue +23 -13
  45. package/dist/runtime/components/Tabs.vue +14 -16
  46. package/dist/runtime/components/Textarea.vue +20 -17
  47. package/dist/runtime/components/Toast.vue +12 -13
  48. package/dist/runtime/components/{Toaster.vue → ToastProvider.vue} +18 -16
  49. package/dist/runtime/components/Tooltip.vue +5 -8
  50. package/dist/runtime/composables/useFormItem.d.ts +27 -0
  51. package/dist/runtime/composables/useFormItem.js +64 -0
  52. package/dist/runtime/composables/useKbd.d.ts +1 -1
  53. package/dist/runtime/composables/useOverlay.d.ts +29 -0
  54. package/dist/runtime/composables/useOverlay.js +69 -0
  55. package/dist/runtime/composables/useTheme.d.ts +6 -2
  56. package/dist/runtime/composables/useTheme.js +10 -3
  57. package/dist/runtime/composables/useToast.d.ts +4 -20
  58. package/dist/runtime/composables/useToast.js +6 -5
  59. package/dist/runtime/index.d.ts +6 -2
  60. package/dist/runtime/index.js +6 -2
  61. package/dist/runtime/locale/en.js +6 -0
  62. package/dist/runtime/locale/zh-tw.js +6 -0
  63. package/dist/runtime/theme/accordion.js +3 -3
  64. package/dist/runtime/theme/alert.js +3 -3
  65. package/dist/runtime/theme/app.d.ts +1 -0
  66. package/dist/runtime/theme/app.js +2 -1
  67. package/dist/runtime/theme/avatar.js +2 -2
  68. package/dist/runtime/theme/badge.d.ts +21 -45
  69. package/dist/runtime/theme/breadcrumb.d.ts +3 -3
  70. package/dist/runtime/theme/breadcrumb.js +5 -5
  71. package/dist/runtime/theme/button.d.ts +111 -57
  72. package/dist/runtime/theme/button.js +13 -13
  73. package/dist/runtime/theme/calendar.d.ts +56 -0
  74. package/dist/runtime/theme/calendar.js +69 -0
  75. package/dist/runtime/theme/card.js +6 -6
  76. package/dist/runtime/theme/carousel.js +1 -1
  77. package/dist/runtime/theme/checkbox.js +5 -5
  78. package/dist/runtime/theme/chip.d.ts +11 -44
  79. package/dist/runtime/theme/chip.js +3 -3
  80. package/dist/runtime/theme/drawer.d.ts +85 -47
  81. package/dist/runtime/theme/drawer.js +46 -19
  82. package/dist/runtime/theme/dropdown-menu.d.ts +71 -0
  83. package/dist/runtime/theme/dropdown-menu.js +83 -0
  84. package/dist/runtime/theme/form-item.d.ts +76 -0
  85. package/dist/runtime/theme/form-item.js +34 -0
  86. package/dist/runtime/theme/form.d.ts +8 -0
  87. package/dist/runtime/theme/form.js +7 -0
  88. package/dist/runtime/theme/index.d.ts +5 -1
  89. package/dist/runtime/theme/index.js +5 -1
  90. package/dist/runtime/theme/input-number.d.ts +41 -61
  91. package/dist/runtime/theme/input-number.js +1 -1
  92. package/dist/runtime/theme/input.d.ts +99 -71
  93. package/dist/runtime/theme/input.js +15 -15
  94. package/dist/runtime/theme/kbd.d.ts +2 -2
  95. package/dist/runtime/theme/kbd.js +1 -1
  96. package/dist/runtime/theme/link.d.ts +1 -1
  97. package/dist/runtime/theme/link.js +3 -3
  98. package/dist/runtime/theme/modal.d.ts +5 -33
  99. package/dist/runtime/theme/modal.js +4 -4
  100. package/dist/runtime/theme/pagination.d.ts +27 -3
  101. package/dist/runtime/theme/pagination.js +6 -2
  102. package/dist/runtime/theme/pinInput.d.ts +42 -42
  103. package/dist/runtime/theme/pinInput.js +13 -13
  104. package/dist/runtime/theme/progress.d.ts +117 -53
  105. package/dist/runtime/theme/progress.js +4 -4
  106. package/dist/runtime/theme/radio-group.d.ts +2 -2
  107. package/dist/runtime/theme/radio-group.js +7 -7
  108. package/dist/runtime/theme/select.d.ts +100 -84
  109. package/dist/runtime/theme/select.js +21 -20
  110. package/dist/runtime/theme/separator.d.ts +13 -28
  111. package/dist/runtime/theme/separator.js +1 -1
  112. package/dist/runtime/theme/skeleton.d.ts +1 -1
  113. package/dist/runtime/theme/skeleton.js +1 -1
  114. package/dist/runtime/theme/slider.js +1 -1
  115. package/dist/runtime/theme/switch.js +5 -5
  116. package/dist/runtime/theme/table.d.ts +3 -0
  117. package/dist/runtime/theme/table.js +8 -7
  118. package/dist/runtime/theme/tabs.d.ts +51 -68
  119. package/dist/runtime/theme/tabs.js +10 -10
  120. package/dist/runtime/theme/textarea.d.ts +37 -43
  121. package/dist/runtime/theme/textarea.js +13 -13
  122. package/dist/runtime/theme/{toaster.d.ts → toast-provider.d.ts} +26 -41
  123. package/dist/runtime/theme/toast.js +5 -5
  124. package/dist/runtime/theme/tooltip.js +1 -1
  125. package/dist/runtime/types/components.d.ts +6 -1
  126. package/dist/runtime/types/form.d.ts +45 -0
  127. package/dist/runtime/types/form.js +0 -0
  128. package/dist/runtime/types/index.d.ts +5 -2
  129. package/dist/runtime/types/index.js +1 -0
  130. package/dist/runtime/types/locale.d.ts +6 -0
  131. package/dist/runtime/types/utils.d.ts +35 -12
  132. package/dist/runtime/utils/extend-theme.js +15 -4
  133. package/dist/runtime/utils/form.d.ts +5 -0
  134. package/dist/runtime/utils/form.js +24 -0
  135. package/dist/runtime/utils/index.d.ts +2 -0
  136. package/dist/runtime/utils/index.js +4 -0
  137. package/dist/runtime/utils/link.d.ts +4 -26
  138. package/dist/runtime/utils/link.js +10 -3
  139. package/dist/shared/ui.3e7fad19.mjs +5 -0
  140. package/dist/shared/ui.3e7fad19.mjs.map +1 -0
  141. package/dist/unocss.mjs +21 -16
  142. package/dist/unocss.mjs.map +1 -1
  143. package/dist/unplugin.mjs +1 -1
  144. package/dist/vite.mjs +1 -1
  145. package/package.json +20 -18
  146. package/dist/runtime/components/ModalProvider.vue +0 -11
  147. package/dist/runtime/composables/useModal.d.ts +0 -10
  148. package/dist/runtime/composables/useModal.js +0 -47
  149. package/dist/shared/ui.ba24b380.mjs +0 -4
  150. package/dist/shared/ui.ba24b380.mjs.map +0 -1
  151. /package/dist/runtime/theme/{toaster.js → toast-provider.js} +0 -0
@@ -5,7 +5,7 @@ import type { switch as _switch } from '../theme'
5
5
  import type { ComponentAttrs } from '../types'
6
6
 
7
7
  export interface SwitchEmits {
8
- (event: 'change', payload: Event): void
8
+ change: [payload: Event]
9
9
  }
10
10
 
11
11
  export interface SwitchSlots {
@@ -37,6 +37,7 @@ export interface SwitchProps extends ComponentAttrs<typeof _switch>, Pick<Switch
37
37
  import { reactivePick } from '@vueuse/core'
38
38
  import { Label, Primitive, SwitchRoot, SwitchThumb, useForwardProps } from 'reka-ui'
39
39
  import { computed, useId } from 'vue'
40
+ import { useFormItem } from '../composables/useFormItem'
40
41
  import { useTheme } from '../composables/useTheme'
41
42
 
42
43
  const props = withDefaults(defineProps<SwitchProps>(), {})
@@ -45,18 +46,26 @@ const slots = defineSlots<SwitchSlots>()
45
46
  const modelValue = defineModel<boolean>({ default: undefined })
46
47
 
47
48
  const rootProps = useForwardProps(reactivePick(props, 'required', 'value', 'defaultValue'))
48
- const id = useId()
49
49
 
50
- const { theme, createStyler } = useTheme()
51
- const style = computed(() => {
52
- const styler = createStyler(theme.value.switch)
53
- return styler({ ...props, checked: false, unchecked: false })
54
- })
50
+ const { id: _id, size, name, disabled, ariaAttrs, emitFormChange, emitFormInput } = useFormItem<SwitchProps>(props)
51
+ const id = _id.value ?? useId()
52
+
53
+ const { theme, generateStyle } = useTheme()
54
+ const style = computed(() => generateStyle('switch', {
55
+ ...props,
56
+ size: size.value,
57
+ disabled: disabled.value,
58
+ checked: false,
59
+ unchecked: false,
60
+ }))
55
61
 
56
62
  function onUpdate(value: any) {
57
63
  // @ts-expect-error - 'target' does not exist in type 'EventInit'
58
64
  const event = new Event('change', { target: { value } })
65
+
59
66
  emit('change', event)
67
+ emitFormChange()
68
+ emitFormInput()
60
69
  }
61
70
  </script>
62
71
 
@@ -64,12 +73,10 @@ function onUpdate(value: any) {
64
73
  <Primitive :as="props.as" :class="style.root({ class: [props.class, props.ui?.root] })">
65
74
  <div :class="style.container({ class: props.ui?.container })">
66
75
  <SwitchRoot
67
- :id="id"
68
- v-bind="rootProps"
76
+ v-bind="{ ...rootProps, ...ariaAttrs, id, name }"
69
77
  v-model="modelValue"
70
- :name="props.name"
71
- :disabled="props.disabled || props.loading"
72
78
  :class="style.base({ class: props.ui?.base })"
79
+ :disabled="disabled || props.loading"
73
80
  @update:model-value="onUpdate"
74
81
  >
75
82
  <SwitchThumb :class="style.thumb({ class: props.ui?.thumb })">
@@ -10,9 +10,10 @@ type DynamicHeaderSlots<T, K = keyof T> = Record<string, (props: HeaderContext<T
10
10
  type DynamicCellSlots<T, K = keyof T> = Record<string, (props: CellContext<T, unknown>) => any> & Record<`${K extends string ? K : never}-cell`, (props: CellContext<T, unknown>) => any>
11
11
 
12
12
  export type TableSlots<T> = {
13
- expanded: (props: { row: Row<T> }) => any
14
- empty: (props?: {}) => any
15
- caption: (props?: {}) => any
13
+ expanded?: (props: { row: Row<T> }) => any
14
+ empty?: any
15
+ loading?: any
16
+ caption?: any
16
17
  } & DynamicHeaderSlots<T> & DynamicCellSlots<T>
17
18
 
18
19
  export type TableData = RowData
@@ -33,11 +34,18 @@ export interface TableProps<T extends TableData> extends ComponentAttrs<typeof t
33
34
  data?: T[]
34
35
  columns?: TableColumn<T>[]
35
36
  caption?: string
37
+ /**
38
+ * The text to display when the table is empty.
39
+ * @default t('table.noData')
40
+ */
41
+ empty?: string
36
42
  /**
37
43
  * Whether the table should have a sticky header.
38
44
  * @default false
39
45
  */
40
46
  sticky?: boolean
47
+ /** Whether the table should be in loading state. */
48
+ loading?: boolean
41
49
  /**
42
50
  * @link [API Docs](https://tanstack.com/table/v8/docs/api/features/global-filtering#table-options)
43
51
  * @link [Guide](https://tanstack.com/table/v8/docs/guide/global-filtering)
@@ -111,8 +119,7 @@ import { useLocale } from '../composables/useLocale'
111
119
  import { useTheme } from '../composables/useTheme'
112
120
 
113
121
  const props = defineProps<TableProps<T>>()
114
-
115
- defineSlots<TableSlots<T>>()
122
+ const slots = defineSlots<TableSlots<T>>()
116
123
 
117
124
  const globalFilterState = defineModel<string>('globalFilter', { default: undefined })
118
125
  const columnFiltersState = defineModel<ColumnFiltersState>('columnFilters', { default: [] })
@@ -137,7 +144,7 @@ const columns = computed<TableColumn<T>[]>(
137
144
  )
138
145
 
139
146
  const tableApi = useVueTable({
140
- ...reactiveOmit(props, 'data', 'columns', 'caption', 'sticky', 'class', 'ui'),
147
+ ...reactiveOmit(props, 'data', 'columns', 'caption', 'sticky', 'loading', 'class', 'ui'),
141
148
  data,
142
149
  columns: columns.value,
143
150
  getCoreRowModel: getCoreRowModel(),
@@ -229,11 +236,8 @@ function valueUpdater<T extends Updater<any>>(updaterOrValue: T, ref: Ref) {
229
236
  }
230
237
 
231
238
  const { t } = useLocale()
232
- const { theme, createStyler } = useTheme()
233
- const style = computed(() => {
234
- const styler = createStyler(theme.value.table)
235
- return styler(props)
236
- })
239
+ const { generateStyle } = useTheme()
240
+ const style = computed(() => generateStyle('table', props))
237
241
 
238
242
  defineExpose({
239
243
  tableApi,
@@ -243,7 +247,7 @@ defineExpose({
243
247
  <template>
244
248
  <Primitive :as="props.as" :class="style.root({ class: [props.class, props.ui?.root] })">
245
249
  <table :class="style.base({ class: props.ui?.base })">
246
- <caption v-if="props.caption" :class="style.caption({ class: props.caption })">
250
+ <caption v-if="props.caption || slots.caption" :class="style.caption({ class: props.caption })">
247
251
  <slot name="caption">
248
252
  {{ props.caption }}
249
253
  </slot>
@@ -287,10 +291,16 @@ defineExpose({
287
291
  </template>
288
292
  </template>
289
293
 
294
+ <tr v-else-if="props.loading && slots.loading">
295
+ <td :colspan="columns.length" :class="style.loading({ class: props.ui?.loading })">
296
+ <slot name="loading"></slot>
297
+ </td>
298
+ </tr>
299
+
290
300
  <tr v-else :class="style.tr({ class: props.ui?.tr })">
291
301
  <td :colspan="columns.length" :class="style.empty({ class: props.ui?.empty })">
292
302
  <slot name="empty">
293
- {{ t('table.noData') }}
303
+ {{ props.empty || t('table.noData') }}
294
304
  </slot>
295
305
  </td>
296
306
  </tr>
@@ -6,15 +6,6 @@ import type { ComponentAttrs, DynamicSlots } from '../types'
6
6
 
7
7
  export interface TabsEmits extends TabsRootEmits<string | number> {}
8
8
 
9
- type SlotProps<T> = (props: { item: T, index: number }) => any
10
-
11
- export type TabsSlots<T extends { slot?: string }> = {
12
- leading?: SlotProps<T>
13
- default?: SlotProps<T>
14
- trailing?: SlotProps<T>
15
- content?: SlotProps<T>
16
- } & DynamicSlots<T, SlotProps<T>>
17
-
18
9
  export interface TabsItem {
19
10
  label?: string
20
11
  icon?: string
@@ -23,11 +14,21 @@ export interface TabsItem {
23
14
  /** A unique value for the tab item. Defaults to the index. */
24
15
  value?: string | number
25
16
  disabled?: boolean
17
+ [key: string]: any
26
18
  }
27
19
 
20
+ type SlotProps<T extends TabsItem> = (props: { item: T, index: number }) => any
21
+
22
+ export type TabsSlots<T extends TabsItem = TabsItem> = {
23
+ leading?: SlotProps<T>
24
+ default?: SlotProps<T>
25
+ trailing?: SlotProps<T>
26
+ content?: SlotProps<T>
27
+ } & DynamicSlots<T, undefined, SlotProps<T>>
28
+
28
29
  type TabsVariants = VariantProps<typeof tabs>
29
30
 
30
- export interface TabsProps<T> extends ComponentAttrs<typeof tabs>, Pick<TabsRootProps<string | number>, 'defaultValue' | 'modelValue' | 'activationMode' | 'unmountOnHide'> {
31
+ export interface TabsProps<T extends TabsItem = TabsItem> extends ComponentAttrs<typeof tabs>, Pick<TabsRootProps<string | number>, 'defaultValue' | 'modelValue' | 'activationMode' | 'unmountOnHide'> {
31
32
  /**
32
33
  * The element or component this component should render as.
33
34
  * @default "div"
@@ -73,11 +74,8 @@ const slots = defineSlots<TabsSlots<T>>()
73
74
 
74
75
  const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'orientation', 'activationMode', 'unmountOnHide'), emit)
75
76
 
76
- const { theme, createStyler } = useTheme()
77
- const style = computed(() => {
78
- const styler = createStyler(theme.value.tabs)
79
- return styler(props)
80
- })
77
+ const { generateStyle } = useTheme()
78
+ const style = computed(() => generateStyle('tabs', props))
81
79
  </script>
82
80
 
83
81
  <template>
@@ -111,7 +109,7 @@ const style = computed(() => {
111
109
  :value="item.value || String(index)"
112
110
  :class="style.content({ class: props.ui?.content })"
113
111
  >
114
- <slot :name="item.slot || 'content'" :item="item" :index="index">
112
+ <slot :name="((item.slot || 'content') as keyof TabsSlots<T>)" :item="(item as Extract<T, { slot: string }>)" :index="index">
115
113
  {{ item.content }}
116
114
  </slot>
117
115
  </TabsContent>
@@ -5,9 +5,9 @@ import type { textarea } from '../theme'
5
5
  import type { ComponentAttrs } from '../types'
6
6
 
7
7
  export interface TextareaEmits {
8
- (e: 'update:modelValue', payload: string): void
9
- (e: 'blur', event: FocusEvent): void
10
- (e: 'change', event: Event): void
8
+ 'update:modelValue': [payload: string]
9
+ 'blur': [event: FocusEvent]
10
+ 'change': [event: Event]
11
11
  }
12
12
 
13
13
  export interface TextareaSlots {
@@ -41,7 +41,8 @@ export interface TextareaProps extends ComponentAttrs<typeof textarea> {
41
41
 
42
42
  <script setup lang="ts">
43
43
  import { Primitive } from 'reka-ui'
44
- import { computed, nextTick, onMounted, ref, watch } from 'vue'
44
+ import { computed, nextTick, onMounted, useTemplateRef, watch } from 'vue'
45
+ import { useFormItem } from '../composables/useFormItem'
45
46
  import { useTheme } from '../composables/useTheme'
46
47
 
47
48
  defineOptions({
@@ -59,13 +60,15 @@ const emit = defineEmits<TextareaEmits>()
59
60
  defineSlots<TextareaSlots>()
60
61
  const [modelValue, modelModifiers] = defineModel<string | number>()
61
62
 
62
- const textareaRef = ref<HTMLTextAreaElement | null>(null)
63
+ const textareaRef = useTemplateRef('textareaRef')
63
64
 
64
- const { theme, createStyler } = useTheme()
65
- const style = computed(() => {
66
- const styler = createStyler(theme.value.textarea)
67
- return styler(props)
68
- })
65
+ const { id, name, size, highlight, disabled, ariaAttrs, emitFormInput, emitFormChange, emitFormBlur, emitFormFocus } = useFormItem<TextareaProps>(props)
66
+ const { generateStyle } = useTheme()
67
+ const style = computed(() => generateStyle('textarea', {
68
+ ...props,
69
+ size: size.value,
70
+ highlight: highlight.value,
71
+ }))
69
72
 
70
73
  function autoFocus() {
71
74
  if (props.autofocus)
@@ -77,6 +80,7 @@ function updateInput(value: string) {
77
80
  value = value.trim()
78
81
 
79
82
  modelValue.value = value
83
+ emitFormInput()
80
84
  }
81
85
 
82
86
  function onInput(event: Event) {
@@ -96,10 +100,12 @@ function onChange(event: Event) {
96
100
  (event.target as HTMLInputElement).value = value.trim()
97
101
 
98
102
  emit('change', event)
103
+ emitFormChange()
99
104
  }
100
105
 
101
106
  function onBlur(event: FocusEvent) {
102
107
  emit('blur', event)
108
+ emitFormBlur()
103
109
  }
104
110
 
105
111
  function autoResize() {
@@ -147,23 +153,20 @@ onMounted(() => {
147
153
  <Primitive
148
154
  :as="props.as"
149
155
  :class="style.root({ class: [props.class, props.ui?.root] })"
150
- :aria-disabled="props.disabled ? true : undefined"
156
+ :aria-disabled="disabled ? true : undefined"
151
157
  >
152
158
  <textarea
153
- :id="props.id"
154
159
  ref="textareaRef"
160
+ :class="style.base({ class: props.ui?.base })"
155
161
  :value="modelValue"
156
- :name="props.name"
157
162
  :rows="props.rows"
158
163
  :placeholder="props.placeholder"
159
- :class="style.base({ class: props.ui?.base })"
160
- :disabled="props.disabled"
161
164
  :required="props.required"
162
- v-bind="$attrs"
165
+ v-bind="{ ...$attrs, ...ariaAttrs, id, name, disabled }"
163
166
  @input="onInput"
164
167
  @blur="onBlur"
165
168
  @change="onChange"
166
- @focus="autoResize"
169
+ @focus="emitFormFocus"
167
170
  ></textarea>
168
171
 
169
172
  <slot></slot>
@@ -11,7 +11,7 @@ export interface ToastSlots {
11
11
  title?: (props?: {}) => any
12
12
  description?: (props?: {}) => any
13
13
  actions?: (props?: {}) => any
14
- close?: (props: { ui: any }) => any
14
+ close?: (props: { ui: ComponentAttrs<typeof toast>['ui'] }) => any
15
15
  }
16
16
 
17
17
  type ToastVariants = VariantProps<typeof toast>
@@ -61,14 +61,11 @@ const el = ref<InstanceType<typeof ToastRoot>>()
61
61
  const { height } = useElementBounding(() => el.value?.$el.getBoundingClientRect ? el.value.$el : undefined)
62
62
 
63
63
  const { t } = useLocale()
64
- const { theme, createStyler } = useTheme()
65
- const style = computed(() => {
66
- const styler = createStyler(theme.value.toast)
67
- return styler({
68
- ...props,
69
- title: !!(props.title || slots.title),
70
- })
71
- })
64
+ const { theme, generateStyle } = useTheme()
65
+ const style = computed(() => generateStyle('toast', {
66
+ ...props,
67
+ title: !!(props.title || slots.title),
68
+ }))
72
69
 
73
70
  defineExpose({
74
71
  height,
@@ -108,7 +105,10 @@ defineExpose({
108
105
  </div>
109
106
  </div>
110
107
 
111
- <div v-if="(props.orientation === 'horizontal' && actions?.length) || props.close !== null" :class="style.actions({ class: props.ui?.actions })">
108
+ <div
109
+ v-if="(props.orientation === 'horizontal' && actions?.length) || props.close || slots.close"
110
+ :class="style.actions({ class: props.ui?.actions })"
111
+ >
112
112
  <template v-if="props.orientation === 'horizontal'">
113
113
  <slot name="actions">
114
114
  <ToastAction v-for="(action, index) in props.actions" :key="index" :alt-text="action.label || 'Action'" as-child @click.stop>
@@ -117,10 +117,9 @@ defineExpose({
117
117
  </slot>
118
118
  </template>
119
119
 
120
- <ToastClose as-child>
121
- <slot name="close" :ui="ui">
120
+ <ToastClose v-if="props.close || slots.close" as-child>
121
+ <slot name="close" :ui="props.ui">
122
122
  <Button
123
- v-if="props.close"
124
123
  :icon="props.closeIcon || theme.app.icons.close"
125
124
  size="sm"
126
125
  variant="link"
@@ -1,16 +1,21 @@
1
1
  <script lang="ts">
2
2
  import type { VariantProps } from '@byyuurin/ui-kit'
3
- import type { ToastProviderProps } from 'reka-ui'
4
- import type { toaster } from '../theme'
5
- import type { ComponentAttrs } from '../types'
3
+ import type { ToastProviderProps as RekaToastProviderProps } from 'reka-ui'
4
+ import type { toastProvider } from '../theme'
5
+ import type { ComponentAttrs, ToastProps } from '../types'
6
+
7
+ export interface ToastState extends Omit<ToastProps, 'defaultOpen'> {
8
+ id: string | number
9
+ onClick?: (toast: ToastState) => void
10
+ }
6
11
 
7
12
  export interface ToasterSlots {
8
13
  default?: (props?: {}) => any
9
14
  }
10
15
 
11
- type ToasterVariants = VariantProps<typeof toaster>
16
+ type ToasterVariants = VariantProps<typeof toastProvider>
12
17
 
13
- export interface ToasterProps extends ComponentAttrs<typeof toaster>, Omit<ToastProviderProps, 'swipeDirection'> {
18
+ export interface ToastProviderProps extends ComponentAttrs<typeof toastProvider>, Omit<RekaToastProviderProps, 'swipeDirection'> {
14
19
  /** @default "bottom-right" */
15
20
  position?: ToasterVariants['position']
16
21
  /**
@@ -35,7 +40,7 @@ import { useToast } from '../composables/useToast'
35
40
  import { omit } from '../utils'
36
41
  import Toast from './Toast.vue'
37
42
 
38
- const props = withDefaults(defineProps<ToasterProps>(), {
43
+ const props = withDefaults(defineProps<ToastProviderProps>(), {
39
44
  position: 'bottom-right',
40
45
  expand: true,
41
46
  portal: true,
@@ -61,20 +66,17 @@ const swipeDirection = computed(() => {
61
66
  return 'left'
62
67
  }
63
68
 
64
- console.warn(`[Toaster] Unknown position "${props.position}"`)
69
+ console.warn(`[ToastProvider] Unknown position "${props.position}"`)
65
70
 
66
71
  return 'right'
67
72
  })
68
73
 
69
- const { theme, createStyler } = useTheme()
70
- const style = computed(() => {
71
- const styler = createStyler(theme.value.toaster)
72
- return styler({
73
- ...props,
74
- swipeDirection: swipeDirection.value,
75
- clickable: false,
76
- })
77
- })
74
+ const { generateStyle } = useTheme()
75
+ const style = computed(() => generateStyle('toastProvider', {
76
+ ...props,
77
+ swipeDirection: swipeDirection.value,
78
+ clickable: false,
79
+ }))
78
80
 
79
81
  function onUpdateOpen(value: boolean, id: string | number) {
80
82
  if (value)
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
- import type { TooltipArrowProps, TooltipContentProps, TooltipRootEmits, TooltipRootProps } from 'reka-ui'
2
+ import type { TooltipArrowProps, TooltipContentEmits, TooltipContentProps, TooltipRootEmits, TooltipRootProps } from 'reka-ui'
3
3
  import type { tooltip } from '../theme'
4
- import type { ComponentAttrs } from '../types'
4
+ import type { ComponentAttrs, EmitsToProps } from '../types'
5
5
 
6
6
  export interface TooltipEmits extends TooltipRootEmits {}
7
7
 
@@ -12,7 +12,7 @@ export interface TooltipSlots {
12
12
 
13
13
  export interface TooltipProps extends ComponentAttrs<typeof tooltip>, TooltipRootProps {
14
14
  text?: string
15
- content?: Omit<TooltipContentProps, 'as' | 'asChild'>
15
+ content?: Omit<TooltipContentProps, 'as' | 'asChild'> & Partial<EmitsToProps<TooltipContentEmits>>
16
16
  arrow?: boolean | Omit<TooltipArrowProps, 'as' | 'asChild'>
17
17
  /** @default true */
18
18
  portal?: boolean
@@ -44,11 +44,8 @@ const contentProps = toRef(() => defu(props.content, contentDefaults) as Tooltip
44
44
 
45
45
  const arrowProps = toRef(() => props.arrow as TooltipArrowProps)
46
46
 
47
- const { theme, createStyler } = useTheme()
48
- const style = computed(() => {
49
- const styler = createStyler(theme.value.tooltip)
50
- return styler(props)
51
- })
47
+ const { generateStyle } = useTheme()
48
+ const style = computed(() => generateStyle('tooltip', props))
52
49
  </script>
53
50
 
54
51
  <template>
@@ -0,0 +1,27 @@
1
+ import type { GetObjectField } from '../types/index.js';
2
+ interface Props<T> {
3
+ id?: string;
4
+ name?: string;
5
+ size?: GetObjectField<T, 'size'>;
6
+ highlight?: boolean;
7
+ disabled?: boolean;
8
+ }
9
+ export declare function useFormItem<T>(props?: Props<T>, options?: {
10
+ bind?: boolean;
11
+ deferInputValidation?: boolean;
12
+ }): {
13
+ id: import("vue").ComputedRef<string | undefined>;
14
+ name: import("vue").ComputedRef<string | undefined>;
15
+ size: import("vue").ComputedRef<any>;
16
+ highlight: import("vue").ComputedRef<boolean | undefined>;
17
+ disabled: import("vue").ComputedRef<boolean | undefined>;
18
+ emitFormBlur: () => void;
19
+ emitFormInput: import("@vueuse/core").PromisifyFn<() => void>;
20
+ emitFormChange: () => void;
21
+ emitFormFocus: () => void;
22
+ ariaAttrs: import("vue").ComputedRef<{
23
+ 'aria-describedby': string;
24
+ 'aria-invalid': boolean;
25
+ } | undefined>;
26
+ };
27
+ export {};
@@ -0,0 +1,64 @@
1
+ import { useDebounceFn } from "@vueuse/core";
2
+ import { computed } from "vue";
3
+ import {
4
+ injectFormBus,
5
+ injectFormInputId,
6
+ injectFormInputs,
7
+ injectFormItem,
8
+ injectFormOptions
9
+ } from "../app/injections.js";
10
+ export function useFormItem(props, options) {
11
+ const formOptions = injectFormOptions();
12
+ const formBus = injectFormBus();
13
+ const formItem = injectFormItem();
14
+ const formInputs = injectFormInputs();
15
+ const inputId = injectFormInputId();
16
+ if (formItem && inputId) {
17
+ if (options?.bind === false) {
18
+ inputId.value = void 0;
19
+ } else if (props?.id) {
20
+ inputId.value = props?.id;
21
+ }
22
+ if (formInputs && formItem.value.name && inputId.value)
23
+ formInputs.value[formItem.value.name] = { id: inputId.value, pattern: formItem.value.errorPattern };
24
+ }
25
+ function emitFormEvent(type, name, eager) {
26
+ if (formBus && formItem && name)
27
+ formBus.emit({ type, name, eager });
28
+ }
29
+ function emitFormBlur() {
30
+ emitFormEvent("blur", formItem?.value.name);
31
+ }
32
+ function emitFormFocus() {
33
+ emitFormEvent("focus", formItem?.value.name);
34
+ }
35
+ function emitFormChange() {
36
+ emitFormEvent("change", formItem?.value.name);
37
+ }
38
+ const emitFormInput = useDebounceFn(
39
+ () => {
40
+ emitFormEvent("input", formItem?.value.name, !options?.deferInputValidation || formItem?.value.eagerValidation);
41
+ },
42
+ formItem?.value.validateOnInputDelay ?? formOptions?.value.validateOnInputDelay ?? 0
43
+ );
44
+ return {
45
+ id: computed(() => props?.id ?? inputId?.value),
46
+ name: computed(() => props?.name ?? formItem?.value.name),
47
+ size: computed(() => props?.size ?? formItem?.value.size),
48
+ highlight: computed(() => formItem?.value.error ? true : props?.highlight),
49
+ disabled: computed(() => formOptions?.value.disabled || props?.disabled),
50
+ emitFormBlur,
51
+ emitFormInput,
52
+ emitFormChange,
53
+ emitFormFocus,
54
+ ariaAttrs: computed(() => {
55
+ if (!formItem?.value)
56
+ return;
57
+ const descriptiveAttrs = ["error", "hint", "help", "description"].filter((type) => formItem?.value?.[type]).map((type) => `${formItem?.value.ariaId}-${type}`) || [];
58
+ return {
59
+ "aria-describedby": descriptiveAttrs.join(" "),
60
+ "aria-invalid": !!formItem?.value.error
61
+ };
62
+ })
63
+ };
64
+ }
@@ -29,7 +29,7 @@ export declare const kbdKeysMap: {
29
29
  export type KbdKey = keyof typeof kbdKeysMap;
30
30
  export type KbdKeySpecific = keyof KbdKeysSpecificMap;
31
31
  export declare const useKbd: () => {
32
- macOS: import("vue").ComputedRef<any>;
32
+ macOS: import("vue").ComputedRef<false | "" | RegExpMatchArray | null | undefined>;
33
33
  getKbdKey: (value?: KbdKey | (string & {})) => string | undefined;
34
34
  };
35
35
  export {};
@@ -0,0 +1,29 @@
1
+ import type { Component } from 'vue';
2
+ import type { ComponentProps } from 'vue-component-type-helpers';
3
+ export interface OverlayOptions<ComponentProps = Record<string, any>> {
4
+ defaultOpen?: boolean;
5
+ props?: ComponentProps;
6
+ unmountOnHide?: boolean;
7
+ }
8
+ interface _ComponentState<T extends Component> {
9
+ component?: T;
10
+ id: string | number;
11
+ isMounted: boolean;
12
+ modelValue: boolean;
13
+ resolve?: (value: unknown) => void;
14
+ }
15
+ export type OverlayComponentState = OverlayOptions<Component> & _ComponentState<Component>;
16
+ export interface OverlayComponentInstance<T> {
17
+ open: (props?: ComponentProps<T>) => Promise<any>;
18
+ close: (value?: any) => void;
19
+ patch: (props: Partial<ComponentProps<T>>) => void;
20
+ }
21
+ export declare const useOverlay: () => {
22
+ overlays: import("vue").ShallowReactive<OverlayComponentState[]>;
23
+ open: <T extends Component>(id: OverlayComponentState["id"], props?: ComponentProps<T>) => Promise<any>;
24
+ close: (id: OverlayComponentState["id"], value?: any) => void;
25
+ create: <T extends Component>(component: T, options?: OverlayOptions<ComponentProps<T>>) => OverlayComponentInstance<T>;
26
+ patch: <T extends Component>(id: OverlayComponentState["id"], props: Partial<ComponentProps<T>>) => void;
27
+ unmount: (id: OverlayComponentState["id"]) => void;
28
+ };
29
+ export {};
@@ -0,0 +1,69 @@
1
+ import { createSharedComposable } from "@vueuse/core";
2
+ import { markRaw, reactive, shallowReactive } from "vue";
3
+ export const useOverlay = createSharedComposable(() => {
4
+ const overlays = shallowReactive([]);
5
+ const generateId = () => `overlay-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
6
+ function create(component, options = {}) {
7
+ const { props = {}, defaultOpen = false, unmountOnHide = true } = options;
8
+ const state = reactive({
9
+ id: generateId(),
10
+ modelValue: defaultOpen,
11
+ component: markRaw(component),
12
+ isMounted: defaultOpen,
13
+ unmountOnHide,
14
+ props
15
+ });
16
+ overlays.push(state);
17
+ return {
18
+ open: (props2) => open(state.id, props2),
19
+ close: (value) => close(state.id, value),
20
+ patch: (props2) => patch(state.id, props2)
21
+ };
22
+ }
23
+ function open(id, props) {
24
+ const overlay = getOverlay(id);
25
+ if (props)
26
+ patch(id, props);
27
+ overlay.modelValue = true;
28
+ overlay.isMounted = true;
29
+ return new Promise((resolve) => {
30
+ overlay.resolve = resolve;
31
+ });
32
+ }
33
+ function close(id, value) {
34
+ const overlay = getOverlay(id);
35
+ overlay.modelValue = false;
36
+ if (overlay.resolve) {
37
+ overlay.resolve(value);
38
+ overlay.resolve = void 0;
39
+ }
40
+ }
41
+ function unmount(id) {
42
+ const overlay = getOverlay(id);
43
+ overlay.isMounted = false;
44
+ if (overlay.unmountOnHide) {
45
+ const index = overlays.findIndex((item) => item.id === id);
46
+ overlays.splice(index, 1);
47
+ }
48
+ }
49
+ function patch(id, props) {
50
+ const overlay = getOverlay(id);
51
+ Object.entries(props).forEach(([key, value]) => {
52
+ overlay.props[key] = value;
53
+ });
54
+ }
55
+ function getOverlay(id) {
56
+ const item = overlays.find((item2) => item2.id === id);
57
+ if (!item)
58
+ throw new Error("Overlay not found");
59
+ return item;
60
+ }
61
+ return {
62
+ overlays,
63
+ open,
64
+ close,
65
+ create,
66
+ patch,
67
+ unmount
68
+ };
69
+ });