@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,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,4 @@
1
+ import { defu } from "defu";
2
+ export function defineLocale(options) {
3
+ return defu(options, { dir: "ltr" });
4
+ }
@@ -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
+ }