@bitrix24/b24ui-nuxt 0.1.1

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 (159) hide show
  1. package/.nuxt/b24ui/advice.ts +52 -0
  2. package/.nuxt/b24ui/alert.ts +118 -0
  3. package/.nuxt/b24ui/avatar-group.ts +52 -0
  4. package/.nuxt/b24ui/avatar.ts +63 -0
  5. package/.nuxt/b24ui/badge.ts +256 -0
  6. package/.nuxt/b24ui/button-group.ts +27 -0
  7. package/.nuxt/b24ui/button.ts +342 -0
  8. package/.nuxt/b24ui/checkbox.ts +128 -0
  9. package/.nuxt/b24ui/chip.ts +205 -0
  10. package/.nuxt/b24ui/container.ts +3 -0
  11. package/.nuxt/b24ui/content/description-list.ts +62 -0
  12. package/.nuxt/b24ui/countdown.ts +94 -0
  13. package/.nuxt/b24ui/form-field.ts +57 -0
  14. package/.nuxt/b24ui/form.ts +3 -0
  15. package/.nuxt/b24ui/index.ts +28 -0
  16. package/.nuxt/b24ui/input.ts +472 -0
  17. package/.nuxt/b24ui/kbd.ts +31 -0
  18. package/.nuxt/b24ui/link.ts +20 -0
  19. package/.nuxt/b24ui/progress.ts +303 -0
  20. package/.nuxt/b24ui/radio-group.ts +135 -0
  21. package/.nuxt/b24ui/range.ts +172 -0
  22. package/.nuxt/b24ui/select.ts +550 -0
  23. package/.nuxt/b24ui/separator.ts +176 -0
  24. package/.nuxt/b24ui/skeleton.ts +3 -0
  25. package/.nuxt/b24ui/switch.ts +134 -0
  26. package/.nuxt/b24ui/tabs.ts +341 -0
  27. package/.nuxt/b24ui/textarea.ts +332 -0
  28. package/.nuxt/b24ui/toast.ts +89 -0
  29. package/.nuxt/b24ui/toaster.ts +91 -0
  30. package/.nuxt/b24ui/tooltip.ts +16 -0
  31. package/LICENSE +21 -0
  32. package/README.md +101 -0
  33. package/cli/commands/make/component.mjs +95 -0
  34. package/cli/commands/make/index.mjs +14 -0
  35. package/cli/commands/make/locale.mjs +64 -0
  36. package/cli/index.mjs +15 -0
  37. package/cli/package.json +13 -0
  38. package/cli/templates.mjs +240 -0
  39. package/cli/utils.mjs +31 -0
  40. package/dist/meta.cjs +23610 -0
  41. package/dist/meta.d.cts +23608 -0
  42. package/dist/meta.d.mts +23608 -0
  43. package/dist/meta.d.ts +23608 -0
  44. package/dist/meta.mjs +23608 -0
  45. package/dist/module.cjs +54 -0
  46. package/dist/module.d.cts +14 -0
  47. package/dist/module.d.mts +14 -0
  48. package/dist/module.d.ts +14 -0
  49. package/dist/module.json +13 -0
  50. package/dist/module.mjs +51 -0
  51. package/dist/runtime/components/Advice.vue +115 -0
  52. package/dist/runtime/components/Alert.vue +136 -0
  53. package/dist/runtime/components/App.vue +52 -0
  54. package/dist/runtime/components/Avatar.vue +118 -0
  55. package/dist/runtime/components/AvatarGroup.vue +99 -0
  56. package/dist/runtime/components/Badge.vue +114 -0
  57. package/dist/runtime/components/Button.vue +177 -0
  58. package/dist/runtime/components/ButtonGroup.vue +58 -0
  59. package/dist/runtime/components/Checkbox.vue +110 -0
  60. package/dist/runtime/components/Chip.vue +81 -0
  61. package/dist/runtime/components/Container.vue +36 -0
  62. package/dist/runtime/components/Countdown.vue +498 -0
  63. package/dist/runtime/components/Form.vue +271 -0
  64. package/dist/runtime/components/FormField.vue +128 -0
  65. package/dist/runtime/components/Input.vue +224 -0
  66. package/dist/runtime/components/Kbd.vue +50 -0
  67. package/dist/runtime/components/Link.vue +219 -0
  68. package/dist/runtime/components/LinkBase.vue +63 -0
  69. package/dist/runtime/components/Progress.vue +182 -0
  70. package/dist/runtime/components/RadioGroup.vue +178 -0
  71. package/dist/runtime/components/Range.vue +114 -0
  72. package/dist/runtime/components/Select.vue +328 -0
  73. package/dist/runtime/components/Separator.vue +82 -0
  74. package/dist/runtime/components/Skeleton.vue +31 -0
  75. package/dist/runtime/components/Switch.vue +133 -0
  76. package/dist/runtime/components/Tabs.vue +127 -0
  77. package/dist/runtime/components/Textarea.vue +216 -0
  78. package/dist/runtime/components/Toast.vue +168 -0
  79. package/dist/runtime/components/Toaster.vue +143 -0
  80. package/dist/runtime/components/Tooltip.vue +94 -0
  81. package/dist/runtime/components/content/DescriptionList.vue +220 -0
  82. package/dist/runtime/composables/defineLocale.d.ts +9 -0
  83. package/dist/runtime/composables/defineLocale.js +4 -0
  84. package/dist/runtime/composables/defineShortcuts.d.ts +15 -0
  85. package/dist/runtime/composables/defineShortcuts.js +135 -0
  86. package/dist/runtime/composables/useAvatarGroup.d.ts +10 -0
  87. package/dist/runtime/composables/useAvatarGroup.js +10 -0
  88. package/dist/runtime/composables/useButtonGroup.d.ts +17 -0
  89. package/dist/runtime/composables/useButtonGroup.js +10 -0
  90. package/dist/runtime/composables/useComponentIcons.d.ts +20 -0
  91. package/dist/runtime/composables/useComponentIcons.js +25 -0
  92. package/dist/runtime/composables/useFormField.d.ts +42 -0
  93. package/dist/runtime/composables/useFormField.js +65 -0
  94. package/dist/runtime/composables/useKbd.d.ts +35 -0
  95. package/dist/runtime/composables/useKbd.js +52 -0
  96. package/dist/runtime/composables/useLocale.d.ts +4 -0
  97. package/dist/runtime/composables/useLocale.js +10 -0
  98. package/dist/runtime/composables/useToast.d.ts +12 -0
  99. package/dist/runtime/composables/useToast.js +62 -0
  100. package/dist/runtime/dictionary/icons.d.ts +20 -0
  101. package/dist/runtime/dictionary/icons.js +35 -0
  102. package/dist/runtime/index.css +1 -0
  103. package/dist/runtime/keyframes.css +1 -0
  104. package/dist/runtime/locale/en.d.ts +2 -0
  105. package/dist/runtime/locale/en.js +48 -0
  106. package/dist/runtime/locale/es.d.ts +2 -0
  107. package/dist/runtime/locale/es.js +48 -0
  108. package/dist/runtime/locale/index.d.ts +3 -0
  109. package/dist/runtime/locale/index.js +3 -0
  110. package/dist/runtime/locale/ru.d.ts +2 -0
  111. package/dist/runtime/locale/ru.js +48 -0
  112. package/dist/runtime/plugins/colors.d.ts +2 -0
  113. package/dist/runtime/plugins/colors.js +40 -0
  114. package/dist/runtime/types/app.config.d.ts +6 -0
  115. package/dist/runtime/types/form.d.ts +84 -0
  116. package/dist/runtime/types/form.js +12 -0
  117. package/dist/runtime/types/icons.d.ts +3 -0
  118. package/dist/runtime/types/icons.js +0 -0
  119. package/dist/runtime/types/index.d.ts +33 -0
  120. package/dist/runtime/types/index.js +33 -0
  121. package/dist/runtime/types/locale.d.ts +50 -0
  122. package/dist/runtime/types/locale.js +0 -0
  123. package/dist/runtime/types/utils.d.ts +22 -0
  124. package/dist/runtime/types/utils.js +0 -0
  125. package/dist/runtime/utils/form.d.ts +17 -0
  126. package/dist/runtime/utils/form.js +153 -0
  127. package/dist/runtime/utils/fuse.d.ts +4 -0
  128. package/dist/runtime/utils/fuse.js +63 -0
  129. package/dist/runtime/utils/index.d.ts +6 -0
  130. package/dist/runtime/utils/index.js +63 -0
  131. package/dist/runtime/utils/link.d.ts +29 -0
  132. package/dist/runtime/utils/link.js +4 -0
  133. package/dist/runtime/utils/locale.d.ts +15 -0
  134. package/dist/runtime/utils/locale.js +25 -0
  135. package/dist/runtime/utils/tv.d.ts +1 -0
  136. package/dist/runtime/utils/tv.js +4 -0
  137. package/dist/runtime/vue/components/Link.vue +203 -0
  138. package/dist/runtime/vue/plugins/color-mode.d.ts +4 -0
  139. package/dist/runtime/vue/plugins/color-mode.js +6 -0
  140. package/dist/runtime/vue/plugins/head.d.ts +4 -0
  141. package/dist/runtime/vue/plugins/head.js +6 -0
  142. package/dist/runtime/vue/stubs.d.ts +15 -0
  143. package/dist/runtime/vue/stubs.js +27 -0
  144. package/dist/shared/b24ui-nuxt.CNGvMe2S.mjs +4074 -0
  145. package/dist/shared/b24ui-nuxt.D22QQtm8.cjs +4079 -0
  146. package/dist/types.d.mts +1 -0
  147. package/dist/types.d.ts +1 -0
  148. package/dist/unplugin.cjs +213 -0
  149. package/dist/unplugin.d.cts +22 -0
  150. package/dist/unplugin.d.mts +22 -0
  151. package/dist/unplugin.d.ts +22 -0
  152. package/dist/unplugin.mjs +202 -0
  153. package/dist/vite.cjs +21 -0
  154. package/dist/vite.d.cts +12 -0
  155. package/dist/vite.d.mts +12 -0
  156. package/dist/vite.d.ts +12 -0
  157. package/dist/vite.mjs +19 -0
  158. package/package.json +166 -0
  159. package/vue-plugin.d.ts +5 -0
@@ -0,0 +1,114 @@
1
+ <script lang="ts">
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { SliderRootProps } from 'reka-ui'
4
+ import type { AppConfig } from '@nuxt/schema'
5
+ import _appConfig from '#build/app.config'
6
+ import theme from '#build/b24ui/range'
7
+ import { tv } from '../utils/tv'
8
+
9
+ const appConfigRange = _appConfig as AppConfig & { b24ui: { range: Partial<typeof theme> } }
10
+
11
+ const range = tv({ extend: tv(theme), ...(appConfigRange.b24ui?.range || {}) })
12
+
13
+ type RangeVariants = VariantProps<typeof range>
14
+
15
+ export interface RangeProps extends Pick<SliderRootProps, 'name' | 'disabled' | 'inverted' | 'min' | 'max' | 'step' | 'minStepsBetweenThumbs'> {
16
+ /**
17
+ * The element or component this component should render as.
18
+ * @defaultValue 'div'
19
+ */
20
+ as?: any
21
+ size?: RangeVariants['size']
22
+ color?: RangeVariants['color']
23
+ /**
24
+ * The orientation of the Range.
25
+ * @defaultValue 'horizontal'
26
+ */
27
+ orientation?: SliderRootProps['orientation']
28
+ /** The value of the Range when initially rendered. Use when you do not need to control the state of the Range. */
29
+ defaultValue?: number | number[]
30
+ class?: any
31
+ b24ui?: Partial<typeof range.slots>
32
+ }
33
+
34
+ export interface RangeEmits {
35
+ (e: 'update:modelValue', payload: number | number[]): void
36
+ (e: 'change', payload: Event): void
37
+ }
38
+ </script>
39
+
40
+ <script setup lang="ts">
41
+ import { computed } from 'vue'
42
+ import { SliderRoot, SliderRange, SliderTrack, SliderThumb, useForwardPropsEmits } from 'reka-ui'
43
+ import { reactivePick } from '@vueuse/core'
44
+ import { useFormField } from '../composables/useFormField'
45
+
46
+ const props = withDefaults(defineProps<RangeProps>(), {
47
+ min: 0,
48
+ max: 100,
49
+ step: 1,
50
+ orientation: 'horizontal'
51
+ })
52
+ const emits = defineEmits<RangeEmits>()
53
+
54
+ const modelValue = defineModel<number | number[]>()
55
+
56
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'orientation', 'min', 'max', 'step', 'minStepsBetweenThumbs', 'inverted'), emits)
57
+
58
+ const { id, emitFormChange, emitFormInput, size, color, name, disabled, ariaAttrs } = useFormField<RangeProps>(props)
59
+
60
+ const defaultRangeValue = computed(() => {
61
+ if (typeof props.defaultValue === 'number') {
62
+ return [props.defaultValue]
63
+ }
64
+ return props.defaultValue
65
+ })
66
+
67
+ const rangeValue = computed({
68
+ get() {
69
+ if (typeof modelValue.value === 'number') {
70
+ return [modelValue.value]
71
+ }
72
+ return modelValue.value ?? defaultRangeValue.value
73
+ },
74
+ set(value) {
75
+ modelValue.value = value?.length !== 1 ? value : value[0]
76
+ }
77
+ })
78
+
79
+ const thumbsCount = computed(() => rangeValue.value?.length ?? 1)
80
+
81
+ const b24ui = computed(() => range({
82
+ disabled: disabled.value,
83
+ size: size.value,
84
+ color: color.value,
85
+ orientation: props.orientation
86
+ }))
87
+
88
+ function onChange(value: any) {
89
+ // @ts-expect-error - 'target' does not exist in type 'EventInit'
90
+ const event = new Event('change', { target: { value } })
91
+ emits('change', event)
92
+ emitFormChange()
93
+ }
94
+ </script>
95
+
96
+ <template>
97
+ <SliderRoot
98
+ v-bind="{ ...rootProps, ...ariaAttrs }"
99
+ :id="id"
100
+ v-model="rangeValue"
101
+ :name="name"
102
+ :disabled="disabled"
103
+ :class="b24ui.root({ class: [props.class, props.b24ui?.root] })"
104
+ :default-value="defaultRangeValue"
105
+ @update:model-value="emitFormInput()"
106
+ @value-commit="onChange"
107
+ >
108
+ <SliderTrack :class="b24ui.track({ class: props.b24ui?.track })">
109
+ <SliderRange :class="b24ui.range({ class: props.b24ui?.range })" />
110
+ </SliderTrack>
111
+
112
+ <SliderThumb v-for="count in thumbsCount" :key="count" :class="b24ui.thumb({ class: props.b24ui?.thumb })" />
113
+ </SliderRoot>
114
+ </template>
@@ -0,0 +1,328 @@
1
+ <script lang="ts">
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectArrowProps, AcceptableValue } from 'reka-ui'
4
+ import type { AppConfig } from '@nuxt/schema'
5
+ import _appConfig from '#build/app.config'
6
+ import theme from '#build/b24ui/select'
7
+ import type { UseComponentIconsProps } from '../composables/useComponentIcons'
8
+ import { tv } from '../utils/tv'
9
+ import type { AvatarProps, ChipProps, InputProps, IconComponent } from '../types'
10
+ import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
11
+
12
+ const appConfigSelect = _appConfig as AppConfig & { b24ui: { select: Partial<typeof theme> } }
13
+
14
+ const select = tv({ extend: tv(theme), ...(appConfigSelect.b24ui?.select || {}) })
15
+
16
+ export interface SelectItem {
17
+ label?: string
18
+ icon?: IconComponent
19
+ avatar?: AvatarProps
20
+ chip?: ChipProps
21
+ /**
22
+ * The item type.
23
+ * @defaultValue 'item'
24
+ */
25
+ type?: 'label' | 'separator' | 'item'
26
+ value?: string
27
+ disabled?: boolean
28
+ }
29
+
30
+ type SelectVariants = VariantProps<typeof select>
31
+
32
+ export interface SelectProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectItem | AcceptableValue | boolean> = MaybeArrayOfArray<SelectItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false> extends Omit<SelectRootProps<T>, 'dir' | 'multiple' | 'modelValue' | 'defaultValue' | 'by'>, UseComponentIconsProps {
33
+ id?: string
34
+ /** The placeholder text when the select is empty. */
35
+ placeholder?: string
36
+ color?: SelectVariants['color']
37
+ size?: SelectVariants['size']
38
+ /** Removes padding from input. */
39
+ noPadding?: boolean
40
+ /** removes all borders (rings). */
41
+ noBorder?: boolean
42
+ /** removes all borders (rings) except the bottom one. */
43
+ underline?: boolean
44
+ /** Rounds the corners of the button. */
45
+ rounded?: boolean
46
+ tag?: string
47
+ tagColor?: SelectVariants['tagColor']
48
+ /**
49
+ * The icon displayed to open the menu.
50
+ * @defaultValue icons.chevronDown = `ChevronDownIcon`
51
+ */
52
+ trailingIcon?: IconComponent
53
+ /**
54
+ * The icon displayed when an item is selected.
55
+ * @defaultValue icons.check = `CheckIcon`
56
+ */
57
+ selectedIcon?: IconComponent
58
+ /**
59
+ * The content of the menu.
60
+ * @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
61
+ */
62
+ content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'>
63
+ /**
64
+ * Display an arrow alongside the menu.
65
+ * @defaultValue false
66
+ */
67
+ arrow?: boolean | Omit<SelectArrowProps, 'as' | 'asChild'>
68
+ /**
69
+ * Render the menu in a portal.
70
+ * @defaultValue true
71
+ */
72
+ portal?: boolean
73
+ /**
74
+ * When `items` is an array of objects, select the field to use as the value.
75
+ * @defaultValue 'value'
76
+ */
77
+ valueKey?: V
78
+ /**
79
+ * When `items` is an array of objects, select the field to use as the label.
80
+ * @defaultValue 'label'
81
+ */
82
+ labelKey?: V
83
+ items?: I
84
+ /** The value of the Select when initially rendered. Use when you do not need to control the state of the Select. */
85
+ defaultValue?: SelectModelValue<T, V, M, T extends { value: infer U } ? U : never>
86
+ /** The controlled value of the Select. Can be bind as `v-model`. */
87
+ modelValue?: SelectModelValue<T, V, M, T extends { value: infer U } ? U : never>
88
+ /** Whether multiple options can be selected or not. */
89
+ multiple?: M & boolean
90
+ /** Highlight the ring color like a focus state. */
91
+ highlight?: boolean
92
+ class?: any
93
+ b24ui?: PartialString<typeof select.slots>
94
+ }
95
+
96
+ export type SelectEmits<T, V, M extends boolean> = Omit<SelectRootEmits<T>, 'update:modelValue'> & {
97
+ change: [payload: Event]
98
+ blur: [payload: FocusEvent]
99
+ focus: [payload: FocusEvent]
100
+ } & SelectModelValueEmits<T, V, M, T extends { value: infer U } ? U : never>
101
+
102
+ type SlotProps<T> = (props: { item: T, index: number }) => any
103
+
104
+ export interface SelectSlots<T, M extends boolean> {
105
+ 'leading'(props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean, b24ui: any }): any
106
+ 'default'(props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean }): any
107
+ 'trailing'(props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean, b24ui: any }): any
108
+ 'item': SlotProps<T>
109
+ 'item-leading': SlotProps<T>
110
+ 'item-label': SlotProps<T>
111
+ 'item-trailing': SlotProps<T>
112
+ }
113
+ </script>
114
+
115
+ <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectItem | AcceptableValue | boolean> = MaybeArrayOfArray<SelectItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
116
+ import { computed, toRef } from 'vue'
117
+ import { Primitive, SelectRoot, SelectArrow, SelectTrigger, SelectPortal, SelectContent, SelectViewport, SelectScrollUpButton, SelectScrollDownButton, SelectLabel, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectSeparator, useForwardPropsEmits } from 'reka-ui'
118
+ import { defu } from 'defu'
119
+ import { reactivePick } from '@vueuse/core'
120
+ import { useButtonGroup } from '../composables/useButtonGroup'
121
+ import { useComponentIcons } from '../composables/useComponentIcons'
122
+ import { useFormField } from '../composables/useFormField'
123
+ import { get, compare } from '../utils'
124
+ import icons from '../dictionary/icons'
125
+ import B24Avatar from './Avatar.vue'
126
+ import B24Chip from './Chip.vue'
127
+
128
+ const props = withDefaults(defineProps<SelectProps<T, I, V, M>>(), {
129
+ valueKey: 'value' as never,
130
+ labelKey: 'label' as never,
131
+ portal: true
132
+ })
133
+ const emits = defineEmits<SelectEmits<T, V, M>>()
134
+ const slots = defineSlots<SelectSlots<T, M>>()
135
+
136
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'disabled', 'autocomplete', 'required', 'multiple'), emits)
137
+ const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }) as SelectContentProps)
138
+ const arrowProps = toRef(() => props.arrow as SelectArrowProps)
139
+
140
+ const { emitFormChange, emitFormInput, emitFormBlur, emitFormFocus, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField<InputProps>(props, { deferInputValidation: true })
141
+ const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
142
+ const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(
143
+ props,
144
+ { trailingIcon: icons.chevronDown }
145
+ )))
146
+
147
+ const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value)
148
+
149
+ const isTag = computed(() => {
150
+ return props.tag
151
+ })
152
+
153
+ const b24ui = computed(() => select({
154
+ color: color.value,
155
+ size: selectSize?.value,
156
+ loading: props.loading,
157
+ rounded: Boolean(props.rounded),
158
+ noPadding: Boolean(props.noPadding),
159
+ noBorder: Boolean(props.noBorder),
160
+ underline: Boolean(props.underline),
161
+ highlight: highlight.value,
162
+ tagColor: props.tagColor,
163
+ leading: Boolean(isLeading.value || !!props.avatar || !!slots.leading),
164
+ trailing: Boolean(isTrailing.value || !!slots.trailing),
165
+ buttonGroup: orientation.value
166
+ }))
167
+
168
+ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as SelectItem[][] : [])
169
+ // eslint-disable-next-line vue/no-dupe-keys
170
+ const items = computed(() => groups.value.flatMap(group => group) as T[])
171
+
172
+ function displayValue(value?: AcceptableValue | AcceptableValue[]): string | undefined {
173
+ if (props.multiple && Array.isArray(value)) {
174
+ return value.map(v => displayValue(v)).filter(Boolean).join(', ')
175
+ }
176
+
177
+ const item = items.value.find(item => compare(typeof item === 'object' ? get(item as Record<string, any>, props.valueKey as string) : item, value))
178
+ return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
179
+ }
180
+
181
+ function onUpdate(value: any) {
182
+ // @ts-expect-error - 'target' does not exist in type 'EventInit'
183
+ const event = new Event('change', { target: { value } })
184
+ emits('change', event)
185
+
186
+ emitFormChange()
187
+ emitFormInput()
188
+ }
189
+
190
+ function onUpdateOpen(value: boolean) {
191
+ if (!value) {
192
+ const event = new FocusEvent('blur')
193
+ emits('blur', event)
194
+ emitFormBlur()
195
+ } else {
196
+ const event = new FocusEvent('focus')
197
+ emits('focus', event)
198
+ emitFormFocus()
199
+ }
200
+ }
201
+ </script>
202
+
203
+ <!-- eslint-disable vue/no-template-shadow -->
204
+ <template>
205
+ <Primitive as="div" :class="b24ui.root({ class: [props.b24ui?.root] })">
206
+ <SelectRoot
207
+ v-slot="{ modelValue, open }"
208
+ :name="name"
209
+ v-bind="rootProps"
210
+ :autocomplete="autocomplete"
211
+ :disabled="disabled"
212
+ :default-value="(defaultValue as (AcceptableValue | AcceptableValue[] | undefined))"
213
+ :model-value="(modelValue as (AcceptableValue | AcceptableValue[] | undefined))"
214
+ @update:model-value="onUpdate"
215
+ @update:open="onUpdateOpen"
216
+ >
217
+ <SelectTrigger :id="id" :class="b24ui.base({ class: [props.class, props.b24ui?.base] })" v-bind="ariaAttrs">
218
+ <div v-if="isTag" :class="b24ui.tag({ class: props.b24ui?.tag })">
219
+ {{ props.tag }}
220
+ </div>
221
+
222
+ <span v-if="isLeading || !!avatar || !!slots.leading" :class="b24ui.leading({ class: props.b24ui?.leading })">
223
+ <slot name="leading" :model-value="(modelValue as M extends true ? AcceptableValue[] : AcceptableValue)" :open="open" :b24ui="b24ui">
224
+ <Component
225
+ :is="leadingIconName"
226
+ v-if="isLeading && leadingIconName"
227
+ :class="b24ui.leadingIcon({ class: props.b24ui?.leadingIcon })"
228
+ />
229
+ <B24Avatar v-else-if="!!avatar" :size="((props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="b24ui.itemLeadingAvatar({ class: props.b24ui?.itemLeadingAvatar })" />
230
+ </slot>
231
+ </span>
232
+
233
+ <slot :model-value="(modelValue as M extends true ? AcceptableValue[] : AcceptableValue)" :open="open">
234
+ <template v-for="displayedModelValue in [displayValue(modelValue)]" :key="displayedModelValue">
235
+ <span v-if="displayedModelValue" :class="b24ui.value({ class: props.b24ui?.value })">
236
+ {{ displayedModelValue }}
237
+ </span>
238
+ <span v-else :class="b24ui.placeholder({ class: props.b24ui?.placeholder })">
239
+ {{ placeholder ?? '&nbsp;' }}
240
+ </span>
241
+ </template>
242
+ </slot>
243
+
244
+ <span v-if="isTrailing || !!slots.trailing" :class="b24ui.trailing({ class: props.b24ui?.trailing })">
245
+ <slot name="trailing" :model-value="(modelValue as M extends true ? AcceptableValue[] : AcceptableValue)" :open="open" :b24ui="b24ui">
246
+ <Component
247
+ :is="trailingIconName"
248
+ v-if="trailingIconName"
249
+ :class="b24ui.trailingIcon({ class: props.b24ui?.trailingIcon })"
250
+ />
251
+ </slot>
252
+ </span>
253
+ </SelectTrigger>
254
+
255
+ <SelectPortal :disabled="!portal">
256
+ <SelectContent :class="b24ui.content({ class: props.b24ui?.content })" v-bind="contentProps">
257
+ <SelectScrollUpButton :class="b24ui.scrollUpDownButton({ class: props.b24ui?.scrollUpDownButton })">
258
+ <Component
259
+ :is="icons.chevronUp"
260
+ :class="b24ui.scrollUpDownButtonIcon({ class: props.b24ui?.scrollUpDownButtonIcon })"
261
+ />
262
+ </SelectScrollUpButton>
263
+ <SelectViewport :class="b24ui.viewport({ class: props.b24ui?.viewport })">
264
+ <SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="b24ui.group({ class: props.b24ui?.group })">
265
+ <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
266
+ <SelectLabel v-if="item?.type === 'label'" :class="b24ui.label({ class: props.b24ui?.label })">
267
+ {{ get(item, props.labelKey as string) }}
268
+ </SelectLabel>
269
+
270
+ <SelectSeparator v-else-if="item?.type === 'separator'" :class="b24ui.separator({ class: props.b24ui?.separator })" />
271
+
272
+ <SelectItem
273
+ v-else
274
+ :class="b24ui.item({ class: props.b24ui?.item })"
275
+ :disabled="item.disabled"
276
+ :value="typeof item === 'object' ? get(item, props.valueKey as string) : item"
277
+ >
278
+ <slot name="item" :item="(item as T)" :index="index">
279
+ <slot name="item-leading" :item="(item as T)" :index="index">
280
+ <Component
281
+ :is="item.icon"
282
+ v-if="item.icon"
283
+ :class="b24ui.itemLeadingIcon({ class: props.b24ui?.itemLeadingIcon })"
284
+ />
285
+ <B24Avatar v-else-if="item.avatar" :size="((props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="b24ui.itemLeadingAvatar({ class: props.b24ui?.itemLeadingAvatar })" />
286
+ <B24Chip
287
+ v-else-if="item.chip"
288
+ :size="((props.b24ui?.itemLeadingChipSize || b24ui.itemLeadingChipSize()) as ChipProps['size'])"
289
+ inset
290
+ standalone
291
+ v-bind="item.chip"
292
+ :class="b24ui.itemLeadingChip({ class: props.b24ui?.itemLeadingChip })"
293
+ />
294
+ </slot>
295
+
296
+ <SelectItemText :class="b24ui.itemLabel({ class: props.b24ui?.itemLabel })">
297
+ <slot name="item-label" :item="(item as T)" :index="index">
298
+ {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
299
+ </slot>
300
+ </SelectItemText>
301
+
302
+ <span :class="b24ui.itemTrailing({ class: props.b24ui?.itemTrailing })">
303
+ <slot name="item-trailing" :item="(item as T)" :index="index" />
304
+
305
+ <SelectItemIndicator as-child>
306
+ <Component
307
+ :is="selectedIcon || icons.check"
308
+ :class="b24ui.itemTrailingIcon({ class: props.b24ui?.itemTrailingIcon })"
309
+ />
310
+ </SelectItemIndicator>
311
+ </span>
312
+ </slot>
313
+ </SelectItem>
314
+ </template>
315
+ </SelectGroup>
316
+ </SelectViewport>
317
+ <SelectScrollDownButton :class="b24ui.scrollUpDownButton({ class: props.b24ui?.scrollUpDownButton })">
318
+ <Component
319
+ :is="icons.chevronDown"
320
+ :class="b24ui.scrollUpDownButtonIcon({ class: props.b24ui?.scrollUpDownButtonIcon })"
321
+ />
322
+ </SelectScrollDownButton>
323
+ <SelectArrow v-if="!!arrow" v-bind="arrowProps" :class="b24ui.arrow({ class: props.b24ui?.arrow })" />
324
+ </SelectContent>
325
+ </SelectPortal>
326
+ </SelectRoot>
327
+ </Primitive>
328
+ </template>
@@ -0,0 +1,82 @@
1
+ <script lang="ts">
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { SeparatorProps as _SeparatorProps } from 'reka-ui'
4
+ import type { AppConfig } from '@nuxt/schema'
5
+ import _appConfig from '#build/app.config'
6
+ import theme from '#build/b24ui/separator'
7
+ import { tv } from '../utils/tv'
8
+ import type { AvatarProps, IconComponent } from '../types'
9
+
10
+ const appConfigSeparator = _appConfig as AppConfig & { b24ui: { separator: Partial<typeof theme> } }
11
+
12
+ const separator = tv({ extend: tv(theme), ...(appConfigSeparator.b24ui?.separator || {}) })
13
+
14
+ type SeparatorVariants = VariantProps<typeof separator>
15
+
16
+ export interface SeparatorProps extends Pick<_SeparatorProps, 'decorative'> {
17
+ /**
18
+ * The element or component this component should render as.
19
+ * @defaultValue 'div'
20
+ */
21
+ as?: any
22
+ /** Display a label in the middle. */
23
+ label?: string
24
+ /** Display an icon in the middle. */
25
+ icon?: IconComponent
26
+ /** Display an avatar in the middle. */
27
+ avatar?: AvatarProps
28
+ color?: SeparatorVariants['color']
29
+ size?: SeparatorVariants['size']
30
+ type?: SeparatorVariants['type']
31
+ /**
32
+ * The orientation of the separator.
33
+ * @defaultValue 'horizontal'
34
+ */
35
+ orientation?: _SeparatorProps['orientation']
36
+ class?: any
37
+ b24ui?: Partial<typeof separator.slots>
38
+ }
39
+
40
+ export interface SeparatorSlots {
41
+ default(props?: {}): any
42
+ }
43
+ </script>
44
+
45
+ <script setup lang="ts">
46
+ import { computed } from 'vue'
47
+ import { Separator, useForwardProps } from 'reka-ui'
48
+ import { reactivePick } from '@vueuse/core'
49
+ import B24Avatar from './Avatar.vue'
50
+
51
+ const props = withDefaults(defineProps<SeparatorProps>(), {
52
+ orientation: 'horizontal'
53
+ })
54
+ const slots = defineSlots<SeparatorSlots>()
55
+
56
+ const rootProps = useForwardProps(reactivePick(props, 'as', 'decorative', 'orientation'))
57
+
58
+ const b24ui = computed(() => separator({
59
+ color: props.color,
60
+ orientation: props.orientation,
61
+ size: props.size,
62
+ type: props.type
63
+ }))
64
+ </script>
65
+
66
+ <template>
67
+ <Separator v-bind="rootProps" :class="b24ui.root({ class: [props.class, props.b24ui?.root] })">
68
+ <div :class="b24ui.border({ class: props.b24ui?.border })" />
69
+
70
+ <template v-if="label || icon || avatar || !!slots.default">
71
+ <div :class="b24ui.container({ class: props.b24ui?.container })">
72
+ <slot>
73
+ <span v-if="label" :class="b24ui.label({ class: props.b24ui?.label })">{{ label }}</span>
74
+ <Component :is="icon" v-else-if="icon" :class="b24ui.icon({ class: props.b24ui?.icon })" />
75
+ <B24Avatar v-else-if="avatar" :size="((props.b24ui?.avatarSize || b24ui.avatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="b24ui.avatar({ class: props.b24ui?.avatar })" />
76
+ </slot>
77
+ </div>
78
+
79
+ <div :class="b24ui.border({ class: props.b24ui?.border })" />
80
+ </template>
81
+ </Separator>
82
+ </template>
@@ -0,0 +1,31 @@
1
+ <script lang="ts">
2
+ import type { AppConfig } from '@nuxt/schema'
3
+ import _appConfig from '#build/app.config'
4
+ import theme from '#build/b24ui/skeleton'
5
+ import { tv } from '../utils/tv'
6
+
7
+ const appConfigSkeleton = _appConfig as AppConfig & { b24ui: { skeleton: Partial<typeof theme> } }
8
+
9
+ const skeleton = tv({ extend: tv(theme), ...(appConfigSkeleton.b24ui?.skeleton || {}) })
10
+
11
+ export interface SkeletonProps {
12
+ /**
13
+ * The element or component this component should render as.
14
+ * @defaultValue 'div'
15
+ */
16
+ as?: any
17
+ class?: any
18
+ }
19
+ </script>
20
+
21
+ <script setup lang="ts">
22
+ import { Primitive } from 'reka-ui'
23
+
24
+ const props = defineProps<SkeletonProps>()
25
+ </script>
26
+
27
+ <template>
28
+ <Primitive :as="as" :class="skeleton({ class: props.class })">
29
+ <slot />
30
+ </Primitive>
31
+ </template>