@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.
- package/.nuxt/b24ui/advice.ts +52 -0
- package/.nuxt/b24ui/alert.ts +118 -0
- package/.nuxt/b24ui/avatar-group.ts +52 -0
- package/.nuxt/b24ui/avatar.ts +63 -0
- package/.nuxt/b24ui/badge.ts +256 -0
- package/.nuxt/b24ui/button-group.ts +27 -0
- package/.nuxt/b24ui/button.ts +342 -0
- package/.nuxt/b24ui/checkbox.ts +128 -0
- package/.nuxt/b24ui/chip.ts +205 -0
- package/.nuxt/b24ui/container.ts +3 -0
- package/.nuxt/b24ui/content/description-list.ts +62 -0
- package/.nuxt/b24ui/countdown.ts +94 -0
- package/.nuxt/b24ui/form-field.ts +57 -0
- package/.nuxt/b24ui/form.ts +3 -0
- package/.nuxt/b24ui/index.ts +28 -0
- package/.nuxt/b24ui/input.ts +472 -0
- package/.nuxt/b24ui/kbd.ts +31 -0
- package/.nuxt/b24ui/link.ts +20 -0
- package/.nuxt/b24ui/progress.ts +303 -0
- package/.nuxt/b24ui/radio-group.ts +135 -0
- package/.nuxt/b24ui/range.ts +172 -0
- package/.nuxt/b24ui/select.ts +550 -0
- package/.nuxt/b24ui/separator.ts +176 -0
- package/.nuxt/b24ui/skeleton.ts +3 -0
- package/.nuxt/b24ui/switch.ts +134 -0
- package/.nuxt/b24ui/tabs.ts +341 -0
- package/.nuxt/b24ui/textarea.ts +332 -0
- package/.nuxt/b24ui/toast.ts +89 -0
- package/.nuxt/b24ui/toaster.ts +91 -0
- package/.nuxt/b24ui/tooltip.ts +16 -0
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/cli/commands/make/component.mjs +95 -0
- package/cli/commands/make/index.mjs +14 -0
- package/cli/commands/make/locale.mjs +64 -0
- package/cli/index.mjs +15 -0
- package/cli/package.json +13 -0
- package/cli/templates.mjs +240 -0
- package/cli/utils.mjs +31 -0
- package/dist/meta.cjs +23610 -0
- package/dist/meta.d.cts +23608 -0
- package/dist/meta.d.mts +23608 -0
- package/dist/meta.d.ts +23608 -0
- package/dist/meta.mjs +23608 -0
- package/dist/module.cjs +54 -0
- package/dist/module.d.cts +14 -0
- package/dist/module.d.mts +14 -0
- package/dist/module.d.ts +14 -0
- package/dist/module.json +13 -0
- package/dist/module.mjs +51 -0
- package/dist/runtime/components/Advice.vue +115 -0
- package/dist/runtime/components/Alert.vue +136 -0
- package/dist/runtime/components/App.vue +52 -0
- package/dist/runtime/components/Avatar.vue +118 -0
- package/dist/runtime/components/AvatarGroup.vue +99 -0
- package/dist/runtime/components/Badge.vue +114 -0
- package/dist/runtime/components/Button.vue +177 -0
- package/dist/runtime/components/ButtonGroup.vue +58 -0
- package/dist/runtime/components/Checkbox.vue +110 -0
- package/dist/runtime/components/Chip.vue +81 -0
- package/dist/runtime/components/Container.vue +36 -0
- package/dist/runtime/components/Countdown.vue +498 -0
- package/dist/runtime/components/Form.vue +271 -0
- package/dist/runtime/components/FormField.vue +128 -0
- package/dist/runtime/components/Input.vue +224 -0
- package/dist/runtime/components/Kbd.vue +50 -0
- package/dist/runtime/components/Link.vue +219 -0
- package/dist/runtime/components/LinkBase.vue +63 -0
- package/dist/runtime/components/Progress.vue +182 -0
- package/dist/runtime/components/RadioGroup.vue +178 -0
- package/dist/runtime/components/Range.vue +114 -0
- package/dist/runtime/components/Select.vue +328 -0
- package/dist/runtime/components/Separator.vue +82 -0
- package/dist/runtime/components/Skeleton.vue +31 -0
- package/dist/runtime/components/Switch.vue +133 -0
- package/dist/runtime/components/Tabs.vue +127 -0
- package/dist/runtime/components/Textarea.vue +216 -0
- package/dist/runtime/components/Toast.vue +168 -0
- package/dist/runtime/components/Toaster.vue +143 -0
- package/dist/runtime/components/Tooltip.vue +94 -0
- package/dist/runtime/components/content/DescriptionList.vue +220 -0
- package/dist/runtime/composables/defineLocale.d.ts +9 -0
- package/dist/runtime/composables/defineLocale.js +4 -0
- package/dist/runtime/composables/defineShortcuts.d.ts +15 -0
- package/dist/runtime/composables/defineShortcuts.js +135 -0
- package/dist/runtime/composables/useAvatarGroup.d.ts +10 -0
- package/dist/runtime/composables/useAvatarGroup.js +10 -0
- package/dist/runtime/composables/useButtonGroup.d.ts +17 -0
- package/dist/runtime/composables/useButtonGroup.js +10 -0
- package/dist/runtime/composables/useComponentIcons.d.ts +20 -0
- package/dist/runtime/composables/useComponentIcons.js +25 -0
- package/dist/runtime/composables/useFormField.d.ts +42 -0
- package/dist/runtime/composables/useFormField.js +65 -0
- package/dist/runtime/composables/useKbd.d.ts +35 -0
- package/dist/runtime/composables/useKbd.js +52 -0
- package/dist/runtime/composables/useLocale.d.ts +4 -0
- package/dist/runtime/composables/useLocale.js +10 -0
- package/dist/runtime/composables/useToast.d.ts +12 -0
- package/dist/runtime/composables/useToast.js +62 -0
- package/dist/runtime/dictionary/icons.d.ts +20 -0
- package/dist/runtime/dictionary/icons.js +35 -0
- package/dist/runtime/index.css +1 -0
- package/dist/runtime/keyframes.css +1 -0
- package/dist/runtime/locale/en.d.ts +2 -0
- package/dist/runtime/locale/en.js +48 -0
- package/dist/runtime/locale/es.d.ts +2 -0
- package/dist/runtime/locale/es.js +48 -0
- package/dist/runtime/locale/index.d.ts +3 -0
- package/dist/runtime/locale/index.js +3 -0
- package/dist/runtime/locale/ru.d.ts +2 -0
- package/dist/runtime/locale/ru.js +48 -0
- package/dist/runtime/plugins/colors.d.ts +2 -0
- package/dist/runtime/plugins/colors.js +40 -0
- package/dist/runtime/types/app.config.d.ts +6 -0
- package/dist/runtime/types/form.d.ts +84 -0
- package/dist/runtime/types/form.js +12 -0
- package/dist/runtime/types/icons.d.ts +3 -0
- package/dist/runtime/types/icons.js +0 -0
- package/dist/runtime/types/index.d.ts +33 -0
- package/dist/runtime/types/index.js +33 -0
- package/dist/runtime/types/locale.d.ts +50 -0
- package/dist/runtime/types/locale.js +0 -0
- package/dist/runtime/types/utils.d.ts +22 -0
- package/dist/runtime/types/utils.js +0 -0
- package/dist/runtime/utils/form.d.ts +17 -0
- package/dist/runtime/utils/form.js +153 -0
- package/dist/runtime/utils/fuse.d.ts +4 -0
- package/dist/runtime/utils/fuse.js +63 -0
- package/dist/runtime/utils/index.d.ts +6 -0
- package/dist/runtime/utils/index.js +63 -0
- package/dist/runtime/utils/link.d.ts +29 -0
- package/dist/runtime/utils/link.js +4 -0
- package/dist/runtime/utils/locale.d.ts +15 -0
- package/dist/runtime/utils/locale.js +25 -0
- package/dist/runtime/utils/tv.d.ts +1 -0
- package/dist/runtime/utils/tv.js +4 -0
- package/dist/runtime/vue/components/Link.vue +203 -0
- package/dist/runtime/vue/plugins/color-mode.d.ts +4 -0
- package/dist/runtime/vue/plugins/color-mode.js +6 -0
- package/dist/runtime/vue/plugins/head.d.ts +4 -0
- package/dist/runtime/vue/plugins/head.js +6 -0
- package/dist/runtime/vue/stubs.d.ts +15 -0
- package/dist/runtime/vue/stubs.js +27 -0
- package/dist/shared/b24ui-nuxt.CNGvMe2S.mjs +4074 -0
- package/dist/shared/b24ui-nuxt.D22QQtm8.cjs +4079 -0
- package/dist/types.d.mts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/unplugin.cjs +213 -0
- package/dist/unplugin.d.cts +22 -0
- package/dist/unplugin.d.mts +22 -0
- package/dist/unplugin.d.ts +22 -0
- package/dist/unplugin.mjs +202 -0
- package/dist/vite.cjs +21 -0
- package/dist/vite.d.cts +12 -0
- package/dist/vite.d.mts +12 -0
- package/dist/vite.d.ts +12 -0
- package/dist/vite.mjs +19 -0
- package/package.json +166 -0
- 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 ?? ' ' }}
|
|
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>
|