@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,143 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { VariantProps } from 'tailwind-variants'
|
|
3
|
+
import type { ToastProviderProps } from 'reka-ui'
|
|
4
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
5
|
+
import _appConfig from '#build/app.config'
|
|
6
|
+
import theme from '#build/b24ui/toaster'
|
|
7
|
+
import { tv } from '../utils/tv'
|
|
8
|
+
|
|
9
|
+
const appConfigToaster = _appConfig as AppConfig & { b24ui: { toaster: Partial<typeof theme> } }
|
|
10
|
+
|
|
11
|
+
const toaster = tv({ extend: tv(theme), ...(appConfigToaster.b24ui?.toaster || {}) })
|
|
12
|
+
|
|
13
|
+
type ToasterVariants = VariantProps<typeof toaster>
|
|
14
|
+
|
|
15
|
+
export interface ToasterProps extends Omit<ToastProviderProps, 'swipeDirection'> {
|
|
16
|
+
position?: ToasterVariants['position']
|
|
17
|
+
/**
|
|
18
|
+
* Expand the toasts to show multiple toasts at once.
|
|
19
|
+
* @defaultValue true
|
|
20
|
+
*/
|
|
21
|
+
expand?: boolean
|
|
22
|
+
/**
|
|
23
|
+
* Render the toaster in a portal.
|
|
24
|
+
* @defaultValue true
|
|
25
|
+
*/
|
|
26
|
+
portal?: boolean
|
|
27
|
+
class?: any
|
|
28
|
+
b24ui?: Partial<typeof toaster.slots>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ToasterSlots {
|
|
32
|
+
default(props?: {}): any
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default {
|
|
36
|
+
name: 'Toaster'
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<script setup lang="ts">
|
|
41
|
+
import { ref, computed } from 'vue'
|
|
42
|
+
import { ToastProvider, ToastViewport, ToastPortal, useForwardProps } from 'reka-ui'
|
|
43
|
+
import { reactivePick } from '@vueuse/core'
|
|
44
|
+
import { useToast } from '../composables/useToast'
|
|
45
|
+
import { omit } from '../utils'
|
|
46
|
+
import B24Toast from './Toast.vue'
|
|
47
|
+
|
|
48
|
+
const props = withDefaults(defineProps<ToasterProps>(), {
|
|
49
|
+
expand: true,
|
|
50
|
+
portal: true,
|
|
51
|
+
duration: 5000
|
|
52
|
+
})
|
|
53
|
+
defineSlots<ToasterSlots>()
|
|
54
|
+
|
|
55
|
+
const providerProps = useForwardProps(reactivePick(props, 'duration', 'label', 'swipeThreshold'))
|
|
56
|
+
|
|
57
|
+
const { toasts, remove } = useToast()
|
|
58
|
+
|
|
59
|
+
const swipeDirection = computed(() => {
|
|
60
|
+
switch (props.position) {
|
|
61
|
+
case 'top-center':
|
|
62
|
+
return 'up'
|
|
63
|
+
case 'top-right':
|
|
64
|
+
case 'bottom-right':
|
|
65
|
+
return 'right'
|
|
66
|
+
case 'bottom-center':
|
|
67
|
+
return 'down'
|
|
68
|
+
case 'top-left':
|
|
69
|
+
case 'bottom-left':
|
|
70
|
+
return 'left'
|
|
71
|
+
}
|
|
72
|
+
return 'right'
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const b24ui = computed(() => toaster({
|
|
76
|
+
position: props.position,
|
|
77
|
+
swipeDirection: swipeDirection.value
|
|
78
|
+
}))
|
|
79
|
+
|
|
80
|
+
function onUpdateOpen(value: boolean, id: string | number) {
|
|
81
|
+
if (value) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
remove(id)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const hovered = ref(false)
|
|
89
|
+
const expanded = computed(() => props.expand || hovered.value)
|
|
90
|
+
|
|
91
|
+
const refs = ref<{ height: number }[]>([])
|
|
92
|
+
|
|
93
|
+
const height = computed(() => refs.value.reduce((acc, { height }) => acc + height + 16, 0))
|
|
94
|
+
const frontHeight = computed(() => refs.value[refs.value.length - 1]?.height || 0)
|
|
95
|
+
|
|
96
|
+
function getOffset(index: number) {
|
|
97
|
+
return refs.value.slice(index + 1).reduce((acc, { height }) => acc + height + 16, 0)
|
|
98
|
+
}
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<template>
|
|
102
|
+
<ToastProvider :swipe-direction="swipeDirection" v-bind="providerProps">
|
|
103
|
+
<slot />
|
|
104
|
+
|
|
105
|
+
<B24Toast
|
|
106
|
+
v-for="(toast, index) of toasts"
|
|
107
|
+
:key="toast.id"
|
|
108
|
+
ref="refs"
|
|
109
|
+
v-bind="omit(toast, ['id'])"
|
|
110
|
+
:data-expanded="expanded"
|
|
111
|
+
:data-front="!expanded && index === toasts.length - 1"
|
|
112
|
+
:style="{
|
|
113
|
+
'--index': (index - toasts.length) + toasts.length,
|
|
114
|
+
'--before': toasts.length - 1 - index,
|
|
115
|
+
'--offset': getOffset(index),
|
|
116
|
+
'--scale': expanded ? '1' : 'calc(1 - var(--before) * var(--scale-factor))',
|
|
117
|
+
'--translate': expanded ? 'calc(var(--offset) * var(--translate-factor))' : 'calc(var(--before) * var(--gap))',
|
|
118
|
+
'--transform': 'translateY(var(--translate)) scale(var(--scale))'
|
|
119
|
+
}"
|
|
120
|
+
:class="[b24ui.base(), {
|
|
121
|
+
'cursor-pointer': !!toast.click
|
|
122
|
+
}]"
|
|
123
|
+
@update:open="onUpdateOpen($event, toast.id)"
|
|
124
|
+
@click="toast.click && toast.click(toast)"
|
|
125
|
+
/>
|
|
126
|
+
|
|
127
|
+
<ToastPortal :disabled="!portal">
|
|
128
|
+
<ToastViewport
|
|
129
|
+
:data-expanded="expanded"
|
|
130
|
+
:class="b24ui.viewport({ class: [props.class, props.b24ui?.viewport] })"
|
|
131
|
+
:style="{
|
|
132
|
+
'--scale-factor': '0.05',
|
|
133
|
+
'--translate-factor': position?.startsWith('top') ? '1px' : '-1px',
|
|
134
|
+
'--gap': position?.startsWith('top') ? '16px' : '-16px',
|
|
135
|
+
'--front-height': `${frontHeight}px`,
|
|
136
|
+
'--height': `${height}px`
|
|
137
|
+
}"
|
|
138
|
+
@mouseenter="hovered = true"
|
|
139
|
+
@mouseleave="hovered = false"
|
|
140
|
+
/>
|
|
141
|
+
</ToastPortal>
|
|
142
|
+
</ToastProvider>
|
|
143
|
+
</template>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { TooltipRootProps, TooltipRootEmits, TooltipContentProps, TooltipArrowProps } from 'reka-ui'
|
|
3
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
4
|
+
import _appConfig from '#build/app.config'
|
|
5
|
+
import theme from '#build/b24ui/tooltip'
|
|
6
|
+
import { tv } from '../utils/tv'
|
|
7
|
+
import type { KbdProps } from '../types'
|
|
8
|
+
|
|
9
|
+
const appConfigTooltip = _appConfig as AppConfig & { b24ui: { tooltip: Partial<typeof theme> } }
|
|
10
|
+
|
|
11
|
+
const tooltip = tv({ extend: tv(theme), ...(appConfigTooltip.b24ui?.tooltip || {}) })
|
|
12
|
+
|
|
13
|
+
export interface TooltipProps extends TooltipRootProps {
|
|
14
|
+
/** The text content of the tooltip. */
|
|
15
|
+
text?: string
|
|
16
|
+
/** The keyboard keys to display in the tooltip. */
|
|
17
|
+
kbds?: KbdProps['value'][] | KbdProps[]
|
|
18
|
+
/**
|
|
19
|
+
* The content of the tooltip.
|
|
20
|
+
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
|
|
21
|
+
*/
|
|
22
|
+
content?: Omit<TooltipContentProps, 'as' | 'asChild'>
|
|
23
|
+
/**
|
|
24
|
+
* Display an arrow alongside the tooltip.
|
|
25
|
+
* @defaultValue false
|
|
26
|
+
*/
|
|
27
|
+
arrow?: boolean | Omit<TooltipArrowProps, 'as' | 'asChild'>
|
|
28
|
+
/**
|
|
29
|
+
* Render the tooltip in a portal.
|
|
30
|
+
* @defaultValue true
|
|
31
|
+
*/
|
|
32
|
+
portal?: boolean
|
|
33
|
+
class?: any
|
|
34
|
+
b24ui?: Partial<typeof tooltip.slots>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface TooltipEmits extends TooltipRootEmits {}
|
|
38
|
+
|
|
39
|
+
export interface TooltipSlots {
|
|
40
|
+
default(props: { open: boolean }): any
|
|
41
|
+
content(props?: {}): any
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<script setup lang="ts">
|
|
46
|
+
import { computed, toRef } from 'vue'
|
|
47
|
+
import { defu } from 'defu'
|
|
48
|
+
import { TooltipRoot, TooltipTrigger, TooltipPortal, TooltipContent, TooltipArrow, useForwardPropsEmits } from 'reka-ui'
|
|
49
|
+
import { reactivePick } from '@vueuse/core'
|
|
50
|
+
import B24Kbd from './Kbd.vue'
|
|
51
|
+
|
|
52
|
+
const props = withDefaults(defineProps<TooltipProps>(), {
|
|
53
|
+
portal: true
|
|
54
|
+
})
|
|
55
|
+
const emits = defineEmits<TooltipEmits>()
|
|
56
|
+
const slots = defineSlots<TooltipSlots>()
|
|
57
|
+
|
|
58
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultOpen', 'open', 'delayDuration', 'disableHoverableContent', 'disableClosingTrigger', 'disabled', 'ignoreNonKeyboardFocus'), emits)
|
|
59
|
+
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8 }) as TooltipContentProps)
|
|
60
|
+
const arrowProps = toRef(() => props.arrow as TooltipArrowProps)
|
|
61
|
+
|
|
62
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
63
|
+
const b24ui = computed(() => tooltip({
|
|
64
|
+
side: contentProps.value.side
|
|
65
|
+
}))
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<template>
|
|
69
|
+
<TooltipRoot v-slot="{ open }" v-bind="rootProps">
|
|
70
|
+
<TooltipTrigger v-if="!!slots.default" as-child :class="props.class">
|
|
71
|
+
<slot :open="open" />
|
|
72
|
+
</TooltipTrigger>
|
|
73
|
+
|
|
74
|
+
<TooltipPortal :disabled="!portal">
|
|
75
|
+
<TooltipContent v-bind="contentProps" :class="b24ui.content({ class: [!slots.default && props.class, props.b24ui?.content] })">
|
|
76
|
+
<slot name="content">
|
|
77
|
+
<span v-if="text" :class="b24ui.text({ class: props.b24ui?.text })">{{ text }}</span>
|
|
78
|
+
|
|
79
|
+
<span v-if="kbds?.length" :class="b24ui.kbds({ class: props.b24ui?.kbds })">
|
|
80
|
+
<B24Kbd
|
|
81
|
+
v-for="(kbd, index) in kbds"
|
|
82
|
+
:key="index"
|
|
83
|
+
:size="((props.b24ui?.kbdsSize || b24ui.kbdsSize()) as KbdProps['size'])"
|
|
84
|
+
:depth="((props.b24ui?.kbdsDepth || b24ui.kbdsDepth()) as KbdProps['depth'])"
|
|
85
|
+
v-bind="typeof kbd === 'string' ? { value: kbd } : kbd"
|
|
86
|
+
/>
|
|
87
|
+
</span>
|
|
88
|
+
</slot>
|
|
89
|
+
|
|
90
|
+
<TooltipArrow v-if="!!arrow" v-bind="arrowProps" :class="b24ui.arrow({ class: props.b24ui?.arrow })" />
|
|
91
|
+
</TooltipContent>
|
|
92
|
+
</TooltipPortal>
|
|
93
|
+
</TooltipRoot>
|
|
94
|
+
</template>
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { VariantProps } from 'tailwind-variants'
|
|
3
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
4
|
+
import _appConfig from '#build/app.config'
|
|
5
|
+
import theme from '#build/b24ui/content/description-list'
|
|
6
|
+
import { tv } from '../../utils/tv'
|
|
7
|
+
import type { AvatarProps, ButtonProps, IconComponent } from '../../types'
|
|
8
|
+
import type { DynamicSlots } from '../../types/utils'
|
|
9
|
+
|
|
10
|
+
const appConfigDescriptionList = _appConfig as AppConfig & { b24ui: { descriptionList: Partial<typeof theme> } }
|
|
11
|
+
|
|
12
|
+
const descriptionList = tv({ extend: tv(theme), ...(appConfigDescriptionList.b24ui?.descriptionList || {}) })
|
|
13
|
+
|
|
14
|
+
type DescriptionListVariants = VariantProps<typeof descriptionList>
|
|
15
|
+
|
|
16
|
+
export interface DescriptionListItem {
|
|
17
|
+
label?: string
|
|
18
|
+
icon?: IconComponent
|
|
19
|
+
avatar?: AvatarProps
|
|
20
|
+
slot?: string
|
|
21
|
+
description?: string
|
|
22
|
+
/**
|
|
23
|
+
* Display a list of actions:
|
|
24
|
+
* - under the description if multiline
|
|
25
|
+
* - next to the description if not multiline
|
|
26
|
+
* `{ size: 'xs' }`{lang="ts-type"}
|
|
27
|
+
*/
|
|
28
|
+
actions?: ButtonProps[]
|
|
29
|
+
class?: any
|
|
30
|
+
b24ui?: Partial<typeof descriptionList.slots>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface DescriptionListProps<T> {
|
|
34
|
+
legend?: string
|
|
35
|
+
text?: string
|
|
36
|
+
/**
|
|
37
|
+
* The key used to get the label from the item.
|
|
38
|
+
* @defaultValue 'label'
|
|
39
|
+
*/
|
|
40
|
+
labelKey?: string
|
|
41
|
+
/**
|
|
42
|
+
* The key used to get the description from the item.
|
|
43
|
+
* @defaultValue 'description'
|
|
44
|
+
*/
|
|
45
|
+
descriptionKey?: string
|
|
46
|
+
items?: T[]
|
|
47
|
+
size?: DescriptionListVariants['size']
|
|
48
|
+
class?: any
|
|
49
|
+
b24ui?: Partial<typeof descriptionList.slots>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type SlotProps<T> = (props: { item: T, index: number }) => any
|
|
53
|
+
|
|
54
|
+
export type DescriptionListSlots<T extends { slot?: string }> = {
|
|
55
|
+
legend(props?: {}): any
|
|
56
|
+
text(props?: {}): any
|
|
57
|
+
leading: SlotProps<T>
|
|
58
|
+
label: SlotProps<T>
|
|
59
|
+
description: SlotProps<T>
|
|
60
|
+
actions: SlotProps<T>
|
|
61
|
+
footer(props?: { b24ui: any }): any
|
|
62
|
+
} & DynamicSlots<T, SlotProps<T>>
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<script setup lang="ts" generic="T extends DescriptionListItem">
|
|
66
|
+
import { computed } from 'vue'
|
|
67
|
+
import { get } from '../../utils'
|
|
68
|
+
import B24Avatar from '../Avatar.vue'
|
|
69
|
+
import B24Button from '../Button.vue'
|
|
70
|
+
|
|
71
|
+
const props = withDefaults(defineProps<DescriptionListProps<T>>(), {
|
|
72
|
+
labelKey: 'label',
|
|
73
|
+
descriptionKey: 'description'
|
|
74
|
+
})
|
|
75
|
+
const slots = defineSlots<DescriptionListSlots<T>>()
|
|
76
|
+
|
|
77
|
+
const b24ui = computed(() => descriptionList({
|
|
78
|
+
size: props.size
|
|
79
|
+
}))
|
|
80
|
+
|
|
81
|
+
function normalizeItem(item: any) {
|
|
82
|
+
const label = get(item, props.labelKey as string)
|
|
83
|
+
const description = get(item, props.descriptionKey as string)
|
|
84
|
+
const multiline = (item.actions || []).length > 1
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
...item,
|
|
88
|
+
label,
|
|
89
|
+
description,
|
|
90
|
+
multiline
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const normalizedItems = computed(() => {
|
|
95
|
+
if (!props.items) {
|
|
96
|
+
return []
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return props.items.map(normalizeItem)
|
|
100
|
+
})
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<template>
|
|
104
|
+
<div
|
|
105
|
+
:class="b24ui.root({ class: [props.class, props.b24ui?.root] })"
|
|
106
|
+
>
|
|
107
|
+
<h2 v-if="legend || !!slots.legend" :class="b24ui.legend({ class: props.b24ui?.legend })">
|
|
108
|
+
<slot name="legend">
|
|
109
|
+
{{ legend }}
|
|
110
|
+
</slot>
|
|
111
|
+
</h2>
|
|
112
|
+
<p v-if="text || !!slots.text" :class="b24ui.text({ class: props.b24ui?.text })">
|
|
113
|
+
<slot name="text">
|
|
114
|
+
{{ text }}
|
|
115
|
+
</slot>
|
|
116
|
+
</p>
|
|
117
|
+
|
|
118
|
+
<dl :class="b24ui.container({ class: props.b24ui?.container })">
|
|
119
|
+
<template
|
|
120
|
+
v-for="(item, index) in normalizedItems"
|
|
121
|
+
:key="index"
|
|
122
|
+
>
|
|
123
|
+
<dt
|
|
124
|
+
:class="b24ui.labelWrapper({
|
|
125
|
+
class: [
|
|
126
|
+
props.b24ui?.labelWrapper,
|
|
127
|
+
item?.b24ui?.labelWrapper
|
|
128
|
+
]
|
|
129
|
+
})"
|
|
130
|
+
>
|
|
131
|
+
<slot name="leading" :item="item" :index="index">
|
|
132
|
+
<Component
|
|
133
|
+
:is="item.icon"
|
|
134
|
+
v-if="item.icon"
|
|
135
|
+
:class="b24ui.icon({
|
|
136
|
+
class: [
|
|
137
|
+
props.b24ui?.icon,
|
|
138
|
+
item?.b24ui?.icon
|
|
139
|
+
]
|
|
140
|
+
})"
|
|
141
|
+
/>
|
|
142
|
+
<B24Avatar
|
|
143
|
+
v-else-if="item.avatar"
|
|
144
|
+
:size="((props.b24ui?.avatarSize || b24ui.avatarSize()) as AvatarProps['size'])"
|
|
145
|
+
v-bind="item.avatar"
|
|
146
|
+
:class="b24ui.avatar({
|
|
147
|
+
class: [
|
|
148
|
+
props.b24ui?.avatar,
|
|
149
|
+
item?.b24ui?.avatar
|
|
150
|
+
]
|
|
151
|
+
})"
|
|
152
|
+
/>
|
|
153
|
+
</slot>
|
|
154
|
+
<span
|
|
155
|
+
:class="b24ui.label({
|
|
156
|
+
class: [
|
|
157
|
+
item?.class,
|
|
158
|
+
props.b24ui?.label,
|
|
159
|
+
item?.b24ui?.label
|
|
160
|
+
]
|
|
161
|
+
})"
|
|
162
|
+
>
|
|
163
|
+
<slot name="label" :item="item" :index="index">
|
|
164
|
+
{{ item.label }}
|
|
165
|
+
</slot>
|
|
166
|
+
</span>
|
|
167
|
+
</dt>
|
|
168
|
+
<dd
|
|
169
|
+
:class="b24ui.descriptionWrapper({
|
|
170
|
+
class: [
|
|
171
|
+
props.b24ui?.descriptionWrapper,
|
|
172
|
+
item?.b24ui?.descriptionWrapper
|
|
173
|
+
],
|
|
174
|
+
multiline: item.multiline
|
|
175
|
+
})"
|
|
176
|
+
>
|
|
177
|
+
<span
|
|
178
|
+
:class="b24ui.description({
|
|
179
|
+
class: [
|
|
180
|
+
item?.class,
|
|
181
|
+
props.b24ui?.description,
|
|
182
|
+
item?.b24ui?.description
|
|
183
|
+
],
|
|
184
|
+
multiline: item.multiline
|
|
185
|
+
})"
|
|
186
|
+
>
|
|
187
|
+
<slot name="description" :item="item" :index="index">
|
|
188
|
+
{{ item.description }}
|
|
189
|
+
</slot>
|
|
190
|
+
</span>
|
|
191
|
+
<span
|
|
192
|
+
v-if="item.actions?.length || !!slots.actions"
|
|
193
|
+
:class="b24ui.actions({
|
|
194
|
+
class: [
|
|
195
|
+
props.b24ui?.actions,
|
|
196
|
+
item?.b24ui?.actions
|
|
197
|
+
],
|
|
198
|
+
multiline: item.multiline
|
|
199
|
+
})"
|
|
200
|
+
>
|
|
201
|
+
<slot name="actions" :item="item" :index="index">
|
|
202
|
+
<B24Button
|
|
203
|
+
v-for="(action, indexActions) in item.actions"
|
|
204
|
+
:key="indexActions"
|
|
205
|
+
size="xs"
|
|
206
|
+
v-bind="action"
|
|
207
|
+
/>
|
|
208
|
+
</slot>
|
|
209
|
+
</span>
|
|
210
|
+
</dd>
|
|
211
|
+
</template>
|
|
212
|
+
</dl>
|
|
213
|
+
<div
|
|
214
|
+
v-if="!!slots.footer"
|
|
215
|
+
:class="b24ui.footer({ class: props.b24ui?.footer })"
|
|
216
|
+
>
|
|
217
|
+
<slot name="footer" :b24ui="b24ui" />
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</template>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Locale, Direction, Messages } from '../types/locale';
|
|
2
|
+
interface DefineLocaleOptions {
|
|
3
|
+
name: string;
|
|
4
|
+
code: string;
|
|
5
|
+
dir?: Direction;
|
|
6
|
+
messages: Messages;
|
|
7
|
+
}
|
|
8
|
+
export declare function defineLocale(options: DefineLocaleOptions): Locale;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MaybeRef } from 'vue';
|
|
2
|
+
type Handler = (e?: any) => void;
|
|
3
|
+
export interface ShortcutConfig {
|
|
4
|
+
handler: Handler;
|
|
5
|
+
usingInput?: string | boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ShortcutsConfig {
|
|
8
|
+
[key: string]: ShortcutConfig | Handler | false | null | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface ShortcutsOptions {
|
|
11
|
+
chainDelay?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function extractShortcuts(items: any[] | any[][]): Record<string, Handler>;
|
|
14
|
+
export declare function defineShortcuts(config: MaybeRef<ShortcutsConfig>, options?: ShortcutsOptions): import("@vueuse/core").Fn;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { ref, computed, toValue } from "vue";
|
|
2
|
+
import { useEventListener, useActiveElement, useDebounceFn } from "@vueuse/core";
|
|
3
|
+
const chainedShortcutRegex = /^[^-]+.*-.*[^-]+$/;
|
|
4
|
+
const combinedShortcutRegex = /^[^_]+.*_.*[^_]+$/;
|
|
5
|
+
export function extractShortcuts(items) {
|
|
6
|
+
const shortcuts = {};
|
|
7
|
+
function traverse(items2) {
|
|
8
|
+
items2.forEach((item) => {
|
|
9
|
+
if (item.kbds?.length && (item.onSelect || item.onClick)) {
|
|
10
|
+
const shortcutKey = item.kbds.join("_");
|
|
11
|
+
shortcuts[shortcutKey] = item.onSelect || item.onClick;
|
|
12
|
+
}
|
|
13
|
+
if (item.children) {
|
|
14
|
+
traverse(item.children.flat());
|
|
15
|
+
}
|
|
16
|
+
if (item.items) {
|
|
17
|
+
traverse(item.items.flat());
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
traverse(items.flat());
|
|
22
|
+
return shortcuts;
|
|
23
|
+
}
|
|
24
|
+
export function defineShortcuts(config, options = {}) {
|
|
25
|
+
const chainedInputs = ref([]);
|
|
26
|
+
const clearChainedInput = () => {
|
|
27
|
+
chainedInputs.value.splice(0, chainedInputs.value.length);
|
|
28
|
+
};
|
|
29
|
+
const debouncedClearChainedInput = useDebounceFn(clearChainedInput, options.chainDelay ?? 800);
|
|
30
|
+
const activeElement = useActiveElement();
|
|
31
|
+
const onKeyDown = (e) => {
|
|
32
|
+
if (!e.key) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const alphabeticalKey = /^[a-z]{1}$/i.test(e.key);
|
|
36
|
+
let chainedKey;
|
|
37
|
+
chainedInputs.value.push(e.key);
|
|
38
|
+
if (chainedInputs.value.length >= 2) {
|
|
39
|
+
chainedKey = chainedInputs.value.slice(-2).join("-");
|
|
40
|
+
for (const shortcut of shortcuts.value.filter((s) => s.chained)) {
|
|
41
|
+
if (shortcut.key !== chainedKey) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (shortcut.enabled) {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
shortcut.handler(e);
|
|
47
|
+
}
|
|
48
|
+
clearChainedInput();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
for (const shortcut of shortcuts.value.filter((s) => !s.chained)) {
|
|
53
|
+
if (e.key.toLowerCase() !== shortcut.key) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (e.metaKey !== shortcut.metaKey) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (e.ctrlKey !== shortcut.ctrlKey) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (alphabeticalKey && e.shiftKey !== shortcut.shiftKey) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (shortcut.enabled) {
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
shortcut.handler();
|
|
68
|
+
}
|
|
69
|
+
clearChainedInput();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
debouncedClearChainedInput();
|
|
73
|
+
};
|
|
74
|
+
const usingInput = computed(() => {
|
|
75
|
+
const tagName = activeElement.value?.tagName;
|
|
76
|
+
const contentEditable = activeElement.value?.contentEditable;
|
|
77
|
+
const usingInput2 = !!(tagName === "INPUT" || tagName === "TEXTAREA" || contentEditable === "true" || contentEditable === "plaintext-only");
|
|
78
|
+
if (usingInput2) {
|
|
79
|
+
return activeElement.value?.name || true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
});
|
|
83
|
+
const shortcuts = computed(() => {
|
|
84
|
+
return Object.entries(toValue(config)).map(([key, shortcutConfig]) => {
|
|
85
|
+
if (!shortcutConfig) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
let shortcut;
|
|
89
|
+
if (key.includes("-") && key !== "-" && !key.match(chainedShortcutRegex)?.length) {
|
|
90
|
+
console.trace(`[Shortcut] Invalid key: "${key}"`);
|
|
91
|
+
}
|
|
92
|
+
if (key.includes("_") && key !== "_" && !key.match(combinedShortcutRegex)?.length) {
|
|
93
|
+
console.trace(`[Shortcut] Invalid key: "${key}"`);
|
|
94
|
+
}
|
|
95
|
+
const chained = key.includes("-") && key !== "-";
|
|
96
|
+
if (chained) {
|
|
97
|
+
shortcut = {
|
|
98
|
+
key: key.toLowerCase(),
|
|
99
|
+
metaKey: false,
|
|
100
|
+
ctrlKey: false,
|
|
101
|
+
shiftKey: false,
|
|
102
|
+
altKey: false
|
|
103
|
+
};
|
|
104
|
+
} else {
|
|
105
|
+
const keySplit = key.toLowerCase().split("_").map((k) => k);
|
|
106
|
+
shortcut = {
|
|
107
|
+
key: keySplit.filter((k) => !["meta", "command", "ctrl", "shift", "alt", "option"].includes(k)).join("_"),
|
|
108
|
+
metaKey: keySplit.includes("meta") || keySplit.includes("command"),
|
|
109
|
+
ctrlKey: keySplit.includes("ctrl"),
|
|
110
|
+
shiftKey: keySplit.includes("shift"),
|
|
111
|
+
altKey: keySplit.includes("alt") || keySplit.includes("option")
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
shortcut.chained = chained;
|
|
115
|
+
if (typeof shortcutConfig === "function") {
|
|
116
|
+
shortcut.handler = shortcutConfig;
|
|
117
|
+
} else if (typeof shortcutConfig === "object") {
|
|
118
|
+
shortcut = { ...shortcut, handler: shortcutConfig.handler };
|
|
119
|
+
}
|
|
120
|
+
if (!shortcut.handler) {
|
|
121
|
+
console.trace("[Shortcut] Invalid value");
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
let enabled = true;
|
|
125
|
+
if (!shortcutConfig.usingInput) {
|
|
126
|
+
enabled = !usingInput.value;
|
|
127
|
+
} else if (typeof shortcutConfig.usingInput === "string") {
|
|
128
|
+
enabled = usingInput.value === shortcutConfig.usingInput;
|
|
129
|
+
}
|
|
130
|
+
shortcut.enabled = enabled;
|
|
131
|
+
return shortcut;
|
|
132
|
+
}).filter(Boolean);
|
|
133
|
+
});
|
|
134
|
+
return useEventListener("keydown", onKeyDown);
|
|
135
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ComputedRef, type InjectionKey } from 'vue';
|
|
2
|
+
import type { AvatarGroupProps } from '../types';
|
|
3
|
+
export declare const avatarGroupInjectionKey: InjectionKey<ComputedRef<{
|
|
4
|
+
size: AvatarGroupProps['size'];
|
|
5
|
+
}>>;
|
|
6
|
+
export declare function useAvatarGroup(props: {
|
|
7
|
+
size: AvatarGroupProps['size'];
|
|
8
|
+
}): {
|
|
9
|
+
size: ComputedRef<any>;
|
|
10
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { inject, provide, computed } from "vue";
|
|
2
|
+
export const avatarGroupInjectionKey = Symbol("bitrix24-ui.avatar-group");
|
|
3
|
+
export function useAvatarGroup(props) {
|
|
4
|
+
const avatarGroup = inject(avatarGroupInjectionKey, void 0);
|
|
5
|
+
const size = computed(() => props.size ?? avatarGroup?.value.size);
|
|
6
|
+
provide(avatarGroupInjectionKey, computed(() => ({ size: size.value })));
|
|
7
|
+
return {
|
|
8
|
+
size
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { InjectionKey, ComputedRef } from 'vue';
|
|
2
|
+
import type { ButtonGroupProps } from '../components/ButtonGroup.vue';
|
|
3
|
+
import type { GetObjectField } from '../types/utils';
|
|
4
|
+
export declare const buttonGroupInjectionKey: InjectionKey<ComputedRef<{
|
|
5
|
+
size: ButtonGroupProps['size'];
|
|
6
|
+
orientation: ButtonGroupProps['orientation'];
|
|
7
|
+
noSplit: ButtonGroupProps['noSplit'];
|
|
8
|
+
}>>;
|
|
9
|
+
type Props<T> = {
|
|
10
|
+
size?: GetObjectField<T, 'size'>;
|
|
11
|
+
};
|
|
12
|
+
export declare function useButtonGroup<T>(props: Props<T>): {
|
|
13
|
+
orientation: ComputedRef<any>;
|
|
14
|
+
size: ComputedRef<any>;
|
|
15
|
+
noSplit: ComputedRef<boolean>;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { inject, computed } from "vue";
|
|
2
|
+
export const buttonGroupInjectionKey = Symbol("bitrix24-ui.button-group");
|
|
3
|
+
export function useButtonGroup(props) {
|
|
4
|
+
const buttonGroup = inject(buttonGroupInjectionKey, void 0);
|
|
5
|
+
return {
|
|
6
|
+
orientation: computed(() => buttonGroup?.value.orientation),
|
|
7
|
+
size: computed(() => props?.size ?? buttonGroup?.value.size),
|
|
8
|
+
noSplit: computed(() => buttonGroup?.value.orientation !== "horizontal" || buttonGroup?.value.noSplit === true)
|
|
9
|
+
};
|
|
10
|
+
}
|