@bitrix24/b24ui-nuxt 0.5.10 → 0.5.11

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 (190) hide show
  1. package/dist/meta.cjs +72112 -0
  2. package/dist/meta.d.cts +72110 -0
  3. package/dist/meta.d.mts +5060 -5060
  4. package/dist/meta.d.ts +72110 -0
  5. package/dist/meta.mjs +5060 -5060
  6. package/dist/module.cjs +63 -0
  7. package/dist/module.d.cts +15 -0
  8. package/dist/module.d.ts +15 -0
  9. package/dist/module.json +3 -3
  10. package/dist/module.mjs +1 -1
  11. package/dist/runtime/components/Advice.vue +54 -47
  12. package/dist/runtime/components/Alert.vue +96 -71
  13. package/dist/runtime/components/App.vue +34 -37
  14. package/dist/runtime/components/Avatar.vue +81 -69
  15. package/dist/runtime/components/AvatarGroup.vue +76 -53
  16. package/dist/runtime/components/Badge.vue +83 -83
  17. package/dist/runtime/components/Button.vue +157 -220
  18. package/dist/runtime/components/ButtonGroup.vue +51 -35
  19. package/dist/runtime/components/Calendar.vue +152 -186
  20. package/dist/runtime/components/Checkbox.vue +73 -84
  21. package/dist/runtime/components/Chip.vue +74 -59
  22. package/dist/runtime/components/Collapsible.vue +41 -44
  23. package/dist/runtime/components/Container.vue +27 -18
  24. package/dist/runtime/components/Countdown.vue +378 -198
  25. package/dist/runtime/components/DescriptionList.vue +149 -102
  26. package/dist/runtime/components/DropdownMenu.vue +139 -83
  27. package/dist/runtime/components/DropdownMenuContent.vue +84 -137
  28. package/dist/runtime/components/Form.vue +216 -162
  29. package/dist/runtime/components/FormField.vue +80 -76
  30. package/dist/runtime/components/Input.vue +179 -160
  31. package/dist/runtime/components/InputMenu.vue +380 -300
  32. package/dist/runtime/components/InputNumber.vue +175 -178
  33. package/dist/runtime/components/Kbd.vue +45 -33
  34. package/dist/runtime/components/Link.vue +173 -179
  35. package/dist/runtime/components/LinkBase.vue +42 -64
  36. package/dist/runtime/components/Modal.vue +127 -105
  37. package/dist/runtime/components/ModalDialogClose.vue +8 -4
  38. package/dist/runtime/components/Navbar.vue +33 -24
  39. package/dist/runtime/components/NavbarDivider.vue +33 -24
  40. package/dist/runtime/components/NavbarSection.vue +33 -24
  41. package/dist/runtime/components/NavbarSpacer.vue +33 -24
  42. package/dist/runtime/components/NavigationMenu.vue +210 -144
  43. package/dist/runtime/components/OverlayProvider.vue +17 -13
  44. package/dist/runtime/components/Popover.vue +81 -81
  45. package/dist/runtime/components/Progress.vue +136 -109
  46. package/dist/runtime/components/RadioGroup.vue +134 -120
  47. package/dist/runtime/components/Range.vue +85 -94
  48. package/dist/runtime/components/Select.vue +260 -212
  49. package/dist/runtime/components/SelectMenu.vue +365 -272
  50. package/dist/runtime/components/Separator.vue +71 -61
  51. package/dist/runtime/components/Sidebar.vue +33 -24
  52. package/dist/runtime/components/SidebarBody.vue +38 -30
  53. package/dist/runtime/components/SidebarFooter.vue +33 -24
  54. package/dist/runtime/components/SidebarHeader.vue +33 -24
  55. package/dist/runtime/components/SidebarHeading.vue +33 -24
  56. package/dist/runtime/components/SidebarLayout.vue +70 -40
  57. package/dist/runtime/components/SidebarSection.vue +33 -24
  58. package/dist/runtime/components/SidebarSpacer.vue +33 -24
  59. package/dist/runtime/components/Skeleton.vue +22 -17
  60. package/dist/runtime/components/Slideover.vue +131 -108
  61. package/dist/runtime/components/StackedLayout.vue +73 -40
  62. package/dist/runtime/components/Switch.vue +95 -100
  63. package/dist/runtime/components/Tabs.vue +107 -81
  64. package/dist/runtime/components/Textarea.vue +201 -177
  65. package/dist/runtime/components/Toast.vue +105 -94
  66. package/dist/runtime/components/Toaster.vue +116 -94
  67. package/dist/runtime/components/Tooltip.vue +64 -78
  68. package/dist/runtime/components/content/TableWrapper.vue +70 -58
  69. package/dist/runtime/composables/useAvatarGroup.d.ts +1 -1
  70. package/dist/runtime/composables/useButtonGroup.d.ts +2 -2
  71. package/dist/runtime/composables/useComponentIcons.d.ts +3 -3
  72. package/dist/runtime/composables/useFormField.d.ts +1 -1
  73. package/dist/runtime/prose/A.vue +23 -18
  74. package/dist/runtime/prose/Blockquote.vue +23 -18
  75. package/dist/runtime/prose/Code.vue +31 -23
  76. package/dist/runtime/prose/Em.vue +23 -18
  77. package/dist/runtime/prose/H1.vue +23 -18
  78. package/dist/runtime/prose/H2.vue +23 -18
  79. package/dist/runtime/prose/H3.vue +23 -18
  80. package/dist/runtime/prose/H4.vue +23 -18
  81. package/dist/runtime/prose/H5.vue +23 -18
  82. package/dist/runtime/prose/H6.vue +23 -18
  83. package/dist/runtime/prose/Hr.vue +19 -18
  84. package/dist/runtime/prose/Img.vue +23 -18
  85. package/dist/runtime/prose/Li.vue +23 -18
  86. package/dist/runtime/prose/Ol.vue +23 -18
  87. package/dist/runtime/prose/P.vue +23 -18
  88. package/dist/runtime/prose/Pre.vue +33 -28
  89. package/dist/runtime/prose/Strong.vue +23 -18
  90. package/dist/runtime/prose/Table.vue +54 -44
  91. package/dist/runtime/prose/Tbody.vue +23 -18
  92. package/dist/runtime/prose/Td.vue +23 -18
  93. package/dist/runtime/prose/Th.vue +23 -18
  94. package/dist/runtime/prose/Thead.vue +23 -18
  95. package/dist/runtime/prose/Tr.vue +23 -18
  96. package/dist/runtime/prose/Ul.vue +23 -18
  97. package/dist/runtime/vue/components/Link.vue +202 -201
  98. package/dist/shared/b24ui-nuxt.DrKwIWoc.cjs +7721 -0
  99. package/dist/types.d.mts +5 -3
  100. package/dist/types.d.ts +7 -0
  101. package/dist/unplugin.cjs +236 -0
  102. package/dist/unplugin.d.cts +33 -0
  103. package/dist/unplugin.d.ts +33 -0
  104. package/dist/vite.cjs +21 -0
  105. package/dist/vite.d.cts +14 -0
  106. package/dist/vite.d.ts +14 -0
  107. package/package.json +25 -13
  108. package/dist/runtime/components/Advice.vue.d.ts +0 -170
  109. package/dist/runtime/components/Alert.vue.d.ts +0 -464
  110. package/dist/runtime/components/App.vue.d.ts +0 -23
  111. package/dist/runtime/components/Avatar.vue.d.ts +0 -281
  112. package/dist/runtime/components/AvatarGroup.vue.d.ts +0 -204
  113. package/dist/runtime/components/Badge.vue.d.ts +0 -517
  114. package/dist/runtime/components/Button.vue.d.ts +0 -640
  115. package/dist/runtime/components/ButtonGroup.vue.d.ts +0 -116
  116. package/dist/runtime/components/Calendar.vue.d.ts +0 -437
  117. package/dist/runtime/components/Checkbox.vue.d.ts +0 -354
  118. package/dist/runtime/components/Chip.vue.d.ts +0 -271
  119. package/dist/runtime/components/Collapsible.vue.d.ts +0 -118
  120. package/dist/runtime/components/Container.vue.d.ts +0 -27
  121. package/dist/runtime/components/Countdown.vue.d.ts +0 -356
  122. package/dist/runtime/components/DescriptionList.vue.d.ts +0 -379
  123. package/dist/runtime/components/DropdownMenu.vue.d.ts +0 -533
  124. package/dist/runtime/components/DropdownMenuContent.vue.d.ts +0 -228
  125. package/dist/runtime/components/Form.vue.d.ts +0 -55
  126. package/dist/runtime/components/FormField.vue.d.ts +0 -282
  127. package/dist/runtime/components/Input.vue.d.ts +0 -755
  128. package/dist/runtime/components/InputMenu.vue.d.ts +0 -1504
  129. package/dist/runtime/components/InputNumber.vue.d.ts +0 -658
  130. package/dist/runtime/components/Kbd.vue.d.ts +0 -109
  131. package/dist/runtime/components/Link.vue.d.ts +0 -129
  132. package/dist/runtime/components/LinkBase.vue.d.ts +0 -48
  133. package/dist/runtime/components/Modal.vue.d.ts +0 -327
  134. package/dist/runtime/components/ModalDialogClose.vue.d.ts +0 -10
  135. package/dist/runtime/components/Navbar.vue.d.ts +0 -101
  136. package/dist/runtime/components/NavbarDivider.vue.d.ts +0 -101
  137. package/dist/runtime/components/NavbarSection.vue.d.ts +0 -101
  138. package/dist/runtime/components/NavbarSpacer.vue.d.ts +0 -101
  139. package/dist/runtime/components/NavigationMenu.vue.d.ts +0 -824
  140. package/dist/runtime/components/OverlayProvider.vue.d.ts +0 -2
  141. package/dist/runtime/components/Popover.vue.d.ts +0 -147
  142. package/dist/runtime/components/Progress.vue.d.ts +0 -592
  143. package/dist/runtime/components/RadioGroup.vue.d.ts +0 -723
  144. package/dist/runtime/components/Range.vue.d.ts +0 -417
  145. package/dist/runtime/components/Select.vue.d.ts +0 -1200
  146. package/dist/runtime/components/SelectMenu.vue.d.ts +0 -1298
  147. package/dist/runtime/components/Separator.vue.d.ts +0 -400
  148. package/dist/runtime/components/Sidebar.vue.d.ts +0 -101
  149. package/dist/runtime/components/SidebarBody.vue.d.ts +0 -90
  150. package/dist/runtime/components/SidebarFooter.vue.d.ts +0 -101
  151. package/dist/runtime/components/SidebarHeader.vue.d.ts +0 -101
  152. package/dist/runtime/components/SidebarHeading.vue.d.ts +0 -101
  153. package/dist/runtime/components/SidebarLayout.vue.d.ts +0 -222
  154. package/dist/runtime/components/SidebarSection.vue.d.ts +0 -101
  155. package/dist/runtime/components/SidebarSpacer.vue.d.ts +0 -101
  156. package/dist/runtime/components/Skeleton.vue.d.ts +0 -26
  157. package/dist/runtime/components/Slideover.vue.d.ts +0 -360
  158. package/dist/runtime/components/StackedLayout.vue.d.ts +0 -192
  159. package/dist/runtime/components/Switch.vue.d.ts +0 -587
  160. package/dist/runtime/components/Tabs.vue.d.ts +0 -453
  161. package/dist/runtime/components/Textarea.vue.d.ts +0 -601
  162. package/dist/runtime/components/Toast.vue.d.ts +0 -438
  163. package/dist/runtime/components/Toaster.vue.d.ts +0 -219
  164. package/dist/runtime/components/Tooltip.vue.d.ts +0 -186
  165. package/dist/runtime/components/content/TableWrapper.vue.d.ts +0 -237
  166. package/dist/runtime/prose/A.vue.d.ts +0 -84
  167. package/dist/runtime/prose/Blockquote.vue.d.ts +0 -84
  168. package/dist/runtime/prose/Code.vue.d.ts +0 -97
  169. package/dist/runtime/prose/Em.vue.d.ts +0 -84
  170. package/dist/runtime/prose/H1.vue.d.ts +0 -97
  171. package/dist/runtime/prose/H2.vue.d.ts +0 -123
  172. package/dist/runtime/prose/H3.vue.d.ts +0 -123
  173. package/dist/runtime/prose/H4.vue.d.ts +0 -123
  174. package/dist/runtime/prose/H5.vue.d.ts +0 -123
  175. package/dist/runtime/prose/H6.vue.d.ts +0 -123
  176. package/dist/runtime/prose/Hr.vue.d.ts +0 -74
  177. package/dist/runtime/prose/Img.vue.d.ts +0 -77
  178. package/dist/runtime/prose/Li.vue.d.ts +0 -84
  179. package/dist/runtime/prose/Ol.vue.d.ts +0 -84
  180. package/dist/runtime/prose/P.vue.d.ts +0 -84
  181. package/dist/runtime/prose/Pre.vue.d.ts +0 -117
  182. package/dist/runtime/prose/Strong.vue.d.ts +0 -84
  183. package/dist/runtime/prose/Table.vue.d.ts +0 -144
  184. package/dist/runtime/prose/Tbody.vue.d.ts +0 -84
  185. package/dist/runtime/prose/Td.vue.d.ts +0 -84
  186. package/dist/runtime/prose/Th.vue.d.ts +0 -84
  187. package/dist/runtime/prose/Thead.vue.d.ts +0 -84
  188. package/dist/runtime/prose/Tr.vue.d.ts +0 -84
  189. package/dist/runtime/prose/Ul.vue.d.ts +0 -84
  190. package/dist/runtime/vue/components/Link.vue.d.ts +0 -129
@@ -1,213 +1,276 @@
1
- <script>
2
- import _appConfig from "#build/app.config";
3
- import theme from "#build/b24ui/select-menu";
4
- import { tv } from "../utils/tv";
5
- const appConfigSelectMenu = _appConfig;
6
- const selectMenu = tv({ extend: tv(theme), ...appConfigSelectMenu.b24ui?.selectMenu || {} });
1
+ <script lang="ts">
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxContentEmits, ComboboxArrowProps } from 'reka-ui'
4
+ import type { AppConfig } from '@nuxt/schema'
5
+ import _appConfig from '#build/app.config'
6
+ import theme from '#build/b24ui/select-menu'
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 {
11
+ AcceptableValue,
12
+ ArrayOrNested,
13
+ GetItemKeys,
14
+ GetItemValue,
15
+ GetModelValue,
16
+ GetModelValueEmits,
17
+ NestedItem,
18
+ PartialString,
19
+ EmitsToProps
20
+ } from '../types/utils'
21
+
22
+ const appConfigSelectMenu = _appConfig as AppConfig & { b24ui: { selectMenu: Partial<typeof theme> } }
23
+
24
+ const selectMenu = tv({ extend: tv(theme), ...(appConfigSelectMenu.b24ui?.selectMenu || {}) })
25
+
26
+ interface _SelectMenuItem {
27
+ label?: string
28
+ /**
29
+ * Display an icon on the left side.
30
+ * @IconComponent
31
+ */
32
+ icon?: IconComponent
33
+ avatar?: AvatarProps
34
+ color?: SelectMenuVariants['color']
35
+ chip?: ChipProps
36
+ /**
37
+ * The item type.
38
+ * @defaultValue 'item'
39
+ */
40
+ type?: 'label' | 'separator' | 'item'
41
+ disabled?: boolean
42
+ onSelect?(e?: Event): void
43
+ [key: string]: any
44
+ }
45
+ export type SelectMenuItem = _SelectMenuItem | AcceptableValue | boolean
46
+
47
+ type SelectMenuVariants = VariantProps<typeof selectMenu>
48
+
49
+ export interface SelectMenuProps<T extends ArrayOrNested<SelectMenuItem> = ArrayOrNested<SelectMenuItem>, VK extends GetItemKeys<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'open' | 'defaultOpen' | 'disabled' | 'name' | 'resetSearchTermOnBlur' | 'highlightOnHover'>, UseComponentIconsProps {
50
+ id?: string
51
+ /** The placeholder text when the select is empty. */
52
+ placeholder?: string
53
+ /**
54
+ * Whether to display the search input or not.
55
+ * Can be an object to pass additional props to the input.
56
+ * `{ placeholder: 'Search...', type: 'search' }`{lang="ts"}
57
+ * @defaultValue true
58
+ */
59
+ searchInput?: boolean | InputProps
60
+ /**
61
+ * @defaultValue 'primary'
62
+ */
63
+ color?: SelectMenuVariants['color']
64
+ /**
65
+ * @defaultValue 'md'
66
+ */
67
+ size?: SelectMenuVariants['size']
68
+ /**
69
+ * Removes padding from input
70
+ * @defaultValue false
71
+ */
72
+ noPadding?: boolean
73
+ /**
74
+ * Removes all borders (rings)
75
+ * @defaultValue false
76
+ */
77
+ noBorder?: boolean
78
+ /**
79
+ * Removes all borders (rings) except the bottom one
80
+ * @defaultValue false
81
+ */
82
+ underline?: boolean
83
+ /**
84
+ * Rounds the corners of the button
85
+ * @defaultValue false
86
+ */
87
+ rounded?: boolean
88
+ tag?: string
89
+ /**
90
+ * @defaultValue 'primary'
91
+ */
92
+ tagColor?: SelectMenuVariants['tagColor']
93
+ /**
94
+ * @defaultValue false
95
+ */
96
+ required?: boolean
97
+ /**
98
+ * The icon displayed to open the menu.
99
+ * @defaultValue icons.chevronDown
100
+ * @IconComponent
101
+ */
102
+ trailingIcon?: IconComponent
103
+ /**
104
+ * The icon displayed when an item is selected.
105
+ * @defaultValue icons.check
106
+ * @IconComponent
107
+ */
108
+ selectedIcon?: IconComponent
109
+ /**
110
+ * The content of the menu.
111
+ * @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
112
+ */
113
+ content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ComboboxContentEmits>>
114
+ /**
115
+ * Display an arrow alongside the menu.
116
+ * @defaultValue false
117
+ */
118
+ arrow?: boolean | Omit<ComboboxArrowProps, 'as' | 'asChild'>
119
+ /**
120
+ * Render the menu in a portal.
121
+ * @defaultValue true
122
+ */
123
+ portal?: boolean
124
+ /**
125
+ * When `items` is an array of objects, select the field to use as the value instead of the object itself.
126
+ * @defaultValue undefined
127
+ */
128
+ valueKey?: VK
129
+ /**
130
+ * When `items` is an array of objects, select the field to use as the label.
131
+ * @defaultValue 'label'
132
+ */
133
+ labelKey?: keyof NestedItem<T>
134
+ items?: T
135
+ /**
136
+ * The value of the SelectMenu when initially rendered. Use when you do not need to control the state of the SelectMenu
137
+ */
138
+ defaultValue?: GetModelValue<T, VK, M>
139
+ /**
140
+ * The controlled value of the SelectMenu. Can be binded-with with `v-model`
141
+ */
142
+ modelValue?: GetModelValue<T, VK, M>
143
+ /**
144
+ * Whether multiple options can be selected or not
145
+ * @defaultValue false
146
+ */
147
+ multiple?: M & boolean
148
+ /**
149
+ * Highlight the ring color like a focus state
150
+ * @defaultValue false
151
+ */
152
+ highlight?: boolean
153
+ /**
154
+ * Determines if custom user input that does not exist in options can be added.
155
+ * @defaultValue false
156
+ */
157
+ createItem?: boolean | 'always' | { position?: 'top' | 'bottom', when?: 'empty' | 'always' }
158
+ /**
159
+ * Fields to filter items by.
160
+ * @defaultValue [labelKey]
161
+ */
162
+ filterFields?: string[]
163
+ /**
164
+ * When `true`, disable the default filters, useful for custom filtering (useAsyncData, useFetch, etc.).
165
+ * @defaultValue false
166
+ */
167
+ ignoreFilter?: boolean
168
+ class?: any
169
+ b24ui?: PartialString<typeof selectMenu.slots>
170
+ }
171
+
172
+ export type SelectMenuEmits<A extends ArrayOrNested<SelectMenuItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Pick<ComboboxRootEmits, 'update:open'> & {
173
+ change: [payload: Event]
174
+ blur: [payload: FocusEvent]
175
+ focus: [payload: FocusEvent]
176
+ create: [item: string]
177
+ /** Event handler when highlighted element changes. */
178
+ highlight: [payload: {
179
+ ref: HTMLElement
180
+ value: GetModelValue<A, VK, M>
181
+ } | undefined]
182
+ } & GetModelValueEmits<A, VK, M>
183
+
184
+ type SlotProps<T extends SelectMenuItem> = (props: { item: T, index: number }) => any
185
+
186
+ export interface SelectMenuSlots<
187
+ A extends ArrayOrNested<SelectMenuItem> = ArrayOrNested<SelectMenuItem>,
188
+ VK extends GetItemKeys<A> | undefined = undefined,
189
+ M extends boolean = false,
190
+ T extends NestedItem<A> = NestedItem<A>
191
+ > {
192
+ 'leading'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, b24ui: ReturnType<typeof selectMenu> }): any
193
+ 'default'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean }): any
194
+ 'trailing'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, b24ui: ReturnType<typeof selectMenu> }): any
195
+ 'empty'(props: { searchTerm?: string }): any
196
+ 'item': SlotProps<T>
197
+ 'item-leading': SlotProps<T>
198
+ 'item-label': SlotProps<T>
199
+ 'item-trailing': SlotProps<T>
200
+ 'create-item-label'(props: { item: string }): any
201
+ }
7
202
  </script>
8
203
 
9
- <script setup>
10
- import { computed, toRef, toRaw } from "vue";
204
+ <script setup lang="ts" generic="T extends ArrayOrNested<SelectMenuItem>, VK extends GetItemKeys<T> | undefined = undefined, M extends boolean = false">
205
+ import { computed, toRef, toRaw } from 'vue'
11
206
  import {
207
+ ComboboxRoot,
208
+ ComboboxArrow,
209
+ ComboboxAnchor,
210
+ ComboboxInput,
211
+ ComboboxTrigger,
212
+ ComboboxPortal,
213
+ ComboboxContent,
214
+ ComboboxViewport,
215
+ ComboboxEmpty,
216
+ ComboboxGroup,
217
+ ComboboxLabel,
218
+ ComboboxSeparator,
219
+ ComboboxItem,
220
+ ComboboxItemIndicator,
221
+ FocusScope,
12
222
  useForwardPropsEmits,
13
- useFilter
14
- } from "reka-ui";
15
- import { defu } from "defu";
16
- import { reactivePick, createReusableTemplate } from "@vueuse/core";
17
- import { useButtonGroup } from "../composables/useButtonGroup";
18
- import { useComponentIcons } from "../composables/useComponentIcons";
19
- import { useFormField } from "../composables/useFormField";
20
- import { useLocale } from "../composables/useLocale";
21
- import { compare, get, isArrayOfArray } from "../utils";
22
- import icons from "../dictionary/icons";
23
- defineOptions({ inheritAttrs: false });
24
- const props = defineProps({
25
- id: {
26
- type: String,
27
- required: false
28
- },
29
- placeholder: {
30
- type: String,
31
- required: false
32
- },
33
- searchInput: {
34
- type: [Boolean, Object],
35
- required: false,
36
- default: true
37
- },
38
- color: {
39
- type: null,
40
- required: false
41
- },
42
- size: {
43
- type: null,
44
- required: false
45
- },
46
- noPadding: {
47
- type: Boolean,
48
- required: false
49
- },
50
- noBorder: {
51
- type: Boolean,
52
- required: false
53
- },
54
- underline: {
55
- type: Boolean,
56
- required: false
57
- },
58
- rounded: {
59
- type: Boolean,
60
- required: false
61
- },
62
- tag: {
63
- type: String,
64
- required: false
65
- },
66
- tagColor: {
67
- type: null,
68
- required: false
69
- },
70
- required: {
71
- type: Boolean,
72
- required: false
73
- },
74
- trailingIcon: {
75
- type: [Function, Object],
76
- required: false
77
- },
78
- selectedIcon: {
79
- type: [Function, Object],
80
- required: false
81
- },
82
- content: {
83
- type: Object,
84
- required: false
85
- },
86
- arrow: {
87
- type: [Boolean, Object],
88
- required: false
89
- },
90
- portal: {
91
- type: Boolean,
92
- required: false,
93
- default: true
94
- },
95
- valueKey: {
96
- type: null,
97
- required: false
98
- },
99
- labelKey: {
100
- type: null,
101
- required: false,
102
- default: "label"
103
- },
104
- items: {
105
- type: null,
106
- required: false
107
- },
108
- defaultValue: {
109
- type: null,
110
- required: false
111
- },
112
- modelValue: {
113
- type: null,
114
- required: false
115
- },
116
- multiple: {
117
- type: Boolean,
118
- required: false
119
- },
120
- highlight: {
121
- type: Boolean,
122
- required: false
123
- },
124
- createItem: {
125
- type: [Boolean, String, Object],
126
- required: false
127
- },
128
- filterFields: {
129
- type: Array,
130
- required: false
131
- },
132
- ignoreFilter: {
133
- type: Boolean,
134
- required: false
135
- },
136
- class: {
137
- type: null,
138
- required: false
139
- },
140
- b24ui: {
141
- type: null,
142
- required: false
143
- },
144
- open: {
145
- type: Boolean,
146
- required: false
147
- },
148
- defaultOpen: {
149
- type: Boolean,
150
- required: false
151
- },
152
- disabled: {
153
- type: Boolean,
154
- required: false
155
- },
156
- name: {
157
- type: String,
158
- required: false
159
- },
160
- resetSearchTermOnBlur: {
161
- type: Boolean,
162
- required: false,
163
- default: true
164
- },
165
- highlightOnHover: {
166
- type: Boolean,
167
- required: false
168
- },
169
- icon: {
170
- type: [Function, Object],
171
- required: false
172
- },
173
- avatar: {
174
- type: Object,
175
- required: false
176
- },
177
- loading: {
178
- type: Boolean,
179
- required: false
180
- },
181
- trailing: {
182
- type: Boolean,
183
- required: false
184
- }
185
- });
186
- const emits = defineEmits(["update:open", "change", "blur", "focus", "create", "highlight", "update:modelValue"]);
187
- const slots = defineSlots();
188
- const searchTerm = defineModel("searchTerm", {
189
- "type": String,
190
- ...{
191
- default: ""
192
- }
193
- });
194
- const { t } = useLocale();
195
- const { contains } = useFilter({ sensitivity: "base" });
196
- const rootProps = useForwardPropsEmits(reactivePick(props, "modelValue", "defaultValue", "open", "defaultOpen", "required", "multiple", "resetSearchTermOnBlur", "highlightOnHover"), emits);
197
- const contentProps = toRef(() => defu(props.content, { side: "bottom", sideOffset: 8, collisionPadding: 8, position: "popper" }));
198
- const arrowProps = toRef(() => props.arrow);
199
- const searchInputProps = toRef(() => defu(props.searchInput, { placeholder: t("selectMenu.search"), type: "search" }));
200
- const { emitFormBlur, emitFormFocus, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props);
201
- const { orientation, size: buttonGroupSize } = useButtonGroup(props);
223
+ useFilter,
224
+ Primitive
225
+ } from 'reka-ui'
226
+ import { defu } from 'defu'
227
+ import { reactivePick, createReusableTemplate } from '@vueuse/core'
228
+ import { useButtonGroup } from '../composables/useButtonGroup'
229
+ import { useComponentIcons } from '../composables/useComponentIcons'
230
+ import { useFormField } from '../composables/useFormField'
231
+ import { useLocale } from '../composables/useLocale'
232
+ import { compare, get, isArrayOfArray } from '../utils'
233
+ import icons from '../dictionary/icons'
234
+ import B24Avatar from './Avatar.vue'
235
+ import B24Chip from './Chip.vue'
236
+ import B24Input from './Input.vue'
237
+
238
+ defineOptions({ inheritAttrs: false })
239
+
240
+ const props = withDefaults(defineProps<SelectMenuProps<T, VK, M>>(), {
241
+ portal: true,
242
+ searchInput: true,
243
+ labelKey: 'label' as never,
244
+ resetSearchTermOnBlur: true
245
+ })
246
+ const emits = defineEmits<SelectMenuEmits<T, VK, M>>()
247
+ const slots = defineSlots<SelectMenuSlots<T, VK, M>>()
248
+
249
+ const searchTerm = defineModel<string>('searchTerm', { default: '' })
250
+
251
+ const { t } = useLocale()
252
+ const { contains } = useFilter({ sensitivity: 'base' })
253
+
254
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'required', 'multiple', 'resetSearchTermOnBlur', 'highlightOnHover'), emits)
255
+ const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }) as ComboboxContentProps)
256
+ const arrowProps = toRef(() => props.arrow as ComboboxArrowProps)
257
+ const searchInputProps = toRef(() => defu(props.searchInput, { placeholder: t('selectMenu.search'), type: 'search' }) as InputProps)
258
+
259
+ const { emitFormBlur, emitFormFocus, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField<InputProps>(props)
260
+ const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
202
261
  const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(
203
262
  props,
204
263
  { trailingIcon: icons.chevronDown }
205
- )));
206
- const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value);
207
- const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate();
264
+ )))
265
+
266
+ const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value)
267
+
268
+ const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate()
269
+
208
270
  const isTag = computed(() => {
209
- return props.tag;
210
- });
271
+ return props.tag
272
+ })
273
+
211
274
  const b24ui = computed(() => selectMenu({
212
275
  color: color.value,
213
276
  size: selectSize?.value,
@@ -221,85 +284,115 @@ const b24ui = computed(() => selectMenu({
221
284
  leading: Boolean(isLeading.value || !!props.avatar || !!slots.leading),
222
285
  trailing: Boolean(isTrailing.value || !!slots.trailing),
223
286
  buttonGroup: orientation.value
224
- }));
225
- function displayValue(value) {
287
+ }))
288
+
289
+ function displayValue(value: GetItemValue<T, VK> | GetItemValue<T, VK>[]): string {
226
290
  if (props.multiple && Array.isArray(value)) {
227
- return value.map((v) => displayValue(v)).filter(Boolean).join(", ");
291
+ return value.map(v => displayValue(v)).filter(Boolean).join(', ')
228
292
  }
293
+
229
294
  if (!props.valueKey) {
230
- return value && (typeof value === "object" ? get(value, props.labelKey) : value);
295
+ return value && (typeof value === 'object' ? get(value, props.labelKey as string) : value)
231
296
  }
232
- const item = items.value.find((item2) => compare(typeof item2 === "object" ? get(item2, props.valueKey) : item2, value));
233
- return item && (typeof item === "object" ? get(item, props.labelKey) : item);
297
+
298
+ const item = items.value.find(item => compare(typeof item === 'object' ? get(item as Record<string, any>, props.valueKey as string) : item, value))
299
+ return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
234
300
  }
235
- const groups = computed(
236
- () => props.items?.length ? isArrayOfArray(props.items) ? props.items : [props.items] : []
237
- );
238
- const items = computed(() => groups.value.flatMap((group) => group));
301
+
302
+ const groups = computed<SelectMenuItem[][]>(() =>
303
+ props.items?.length
304
+ ? isArrayOfArray(props.items)
305
+ ? props.items
306
+ : [props.items]
307
+ : []
308
+ )
309
+ // eslint-disable-next-line vue/no-dupe-keys
310
+ const items = computed(() => groups.value.flatMap(group => group) as T[])
311
+
239
312
  const filteredGroups = computed(() => {
240
313
  if (props.ignoreFilter || !searchTerm.value) {
241
- return groups.value;
314
+ return groups.value
242
315
  }
243
- const fields = Array.isArray(props.filterFields) ? props.filterFields : [props.labelKey];
244
- return groups.value.map((items2) => items2.filter((item) => {
245
- if (typeof item !== "object" || item === null) {
246
- return contains(String(item), searchTerm.value);
316
+
317
+ const fields = Array.isArray(props.filterFields) ? props.filterFields : [props.labelKey] as string[]
318
+
319
+ return groups.value.map(items => items.filter((item) => {
320
+ if (typeof item !== 'object' || item === null) {
321
+ return contains(String(item), searchTerm.value)
247
322
  }
248
- if (item.type && ["label", "separator"].includes(item.type)) {
249
- return true;
323
+
324
+ if (item.type && ['label', 'separator'].includes(item.type)) {
325
+ return true
250
326
  }
251
- return fields.some((field) => contains(get(item, field), searchTerm.value));
252
- })).filter((group) => group.filter(
253
- (item) => !isSelectItem(item) || isSelectItem(item) && (!item.type || !["label", "separator"].includes(item.type))
254
- ).length > 0);
255
- });
256
- const filteredItems = computed(() => filteredGroups.value.flatMap((group) => group));
327
+
328
+ return fields.some(field => contains(get(item, field), searchTerm.value))
329
+ })).filter(group => group.filter(item =>
330
+ !isSelectItem(item) || (isSelectItem(item) && (!item.type || !['label', 'separator'].includes(item.type)))
331
+ ).length > 0)
332
+ })
333
+ const filteredItems = computed(() => filteredGroups.value.flatMap(group => group))
334
+
257
335
  const createItem = computed(() => {
258
336
  if (!props.createItem || !searchTerm.value) {
259
- return false;
337
+ return false
260
338
  }
261
- const newItem = props.valueKey ? { [props.valueKey]: searchTerm.value } : searchTerm.value;
262
- if (typeof props.createItem === "object" && props.createItem.when === "always" || props.createItem === "always") {
263
- return !filteredItems.value.find((item) => compare(item, newItem, String(props.valueKey)));
339
+
340
+ const newItem = props.valueKey ? { [props.valueKey]: searchTerm.value } as NestedItem<T> : searchTerm.value
341
+
342
+ if ((typeof props.createItem === 'object' && props.createItem.when === 'always') || props.createItem === 'always') {
343
+ return !filteredItems.value.find(item => compare(item, newItem, String(props.valueKey)))
264
344
  }
265
- return !filteredItems.value.length;
266
- });
267
- const createItemPosition = computed(() => typeof props.createItem === "object" ? props.createItem.position : "bottom");
268
- function onUpdate(value) {
345
+
346
+ return !filteredItems.value.length
347
+ })
348
+ const createItemPosition = computed(() => typeof props.createItem === 'object' ? props.createItem.position : 'bottom')
349
+
350
+ function onUpdate(value: any) {
269
351
  if (toRaw(props.modelValue) === value) {
270
- return;
352
+ return
271
353
  }
272
- const event = new Event("change", { target: { value } });
273
- emits("change", event);
274
- emitFormChange();
275
- emitFormInput();
354
+ // @ts-expect-error - 'target' does not exist in type 'EventInit'
355
+ const event = new Event('change', { target: { value } })
356
+ emits('change', event)
357
+
358
+ emitFormChange()
359
+ emitFormInput()
276
360
  }
277
- function onUpdateOpen(value) {
278
- let timeoutId;
361
+
362
+ function onUpdateOpen(value: boolean) {
363
+ let timeoutId: ReturnType<typeof setTimeout> | undefined
364
+
279
365
  if (!value) {
280
- const event = new FocusEvent("blur");
281
- emits("blur", event);
282
- emitFormBlur();
366
+ const event = new FocusEvent('blur')
367
+
368
+ emits('blur', event)
369
+ emitFormBlur()
370
+
371
+ // Since we use `displayValue` prop inside ComboboxInput we should reset searchTerm manually
372
+ // https://reka-ui.com/docs/components/combobox#api-reference
283
373
  if (props.resetSearchTermOnBlur) {
284
- const STATE_ANIMATION_DELAY_MS = 100;
374
+ const STATE_ANIMATION_DELAY_MS = 100
375
+
285
376
  timeoutId = setTimeout(() => {
286
- searchTerm.value = "";
287
- }, STATE_ANIMATION_DELAY_MS);
377
+ searchTerm.value = ''
378
+ }, STATE_ANIMATION_DELAY_MS)
288
379
  }
289
380
  } else {
290
- const event = new FocusEvent("focus");
291
- emits("focus", event);
292
- emitFormFocus();
381
+ const event = new FocusEvent('focus')
382
+ emits('focus', event)
383
+ emitFormFocus()
293
384
  if (timeoutId) {
294
- clearTimeout(timeoutId);
385
+ clearTimeout(timeoutId)
295
386
  }
296
387
  }
297
388
  }
298
- function isSelectItem(item) {
299
- return typeof item === "object" && item !== null;
389
+
390
+ function isSelectItem(item: SelectMenuItem): item is _SelectMenuItem {
391
+ return typeof item === 'object' && item !== null
300
392
  }
301
393
  </script>
302
394
 
395
+ <!-- eslint-disable vue/no-template-shadow -->
303
396
  <template>
304
397
  <Primitive as="div" :class="b24ui.root({ addNew: true, class: [props.b24ui?.root] })">
305
398
  <DefineCreateItemTemplate>
@@ -315,7 +408,7 @@ function isSelectItem(item) {
315
408
  :is="icons.plus"
316
409
  :class="b24ui.itemLeadingIcon({ addNew: true, class: props.b24ui?.itemLeadingIcon })"
317
410
  />
318
- {{ t("selectMenu.create", { label: searchTerm }) }}
411
+ {{ t('selectMenu.create', { label: searchTerm }) }}
319
412
  </slot>
320
413
  </span>
321
414
  </ComboboxItem>
@@ -339,29 +432,29 @@ function isSelectItem(item) {
339
432
  {{ props.tag }}
340
433
  </div>
341
434
  <span v-if="isLeading || !!avatar || !!slots.leading" :class="b24ui.leading({ class: props.b24ui?.leading })">
342
- <slot name="leading" :model-value="modelValue" :open="open" :b24ui="b24ui">
435
+ <slot name="leading" :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open" :b24ui="b24ui">
343
436
  <Component
344
437
  :is="leadingIconName"
345
438
  v-if="isLeading && leadingIconName"
346
439
  :class="b24ui.leadingIcon({ class: props.b24ui?.leadingIcon })"
347
440
  />
348
- <B24Avatar v-else-if="!!avatar" :size="props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()" v-bind="avatar" :class="b24ui.itemLeadingAvatar({ class: props.b24ui?.itemLeadingAvatar })" />
441
+ <B24Avatar v-else-if="!!avatar" :size="((props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="b24ui.itemLeadingAvatar({ class: props.b24ui?.itemLeadingAvatar })" />
349
442
  </slot>
350
443
  </span>
351
444
 
352
- <slot :model-value="modelValue" :open="open">
353
- <template v-for="displayedModelValue in [displayValue(modelValue)]" :key="displayedModelValue">
445
+ <slot :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open">
446
+ <template v-for="displayedModelValue in [displayValue(modelValue as GetModelValue<T, VK, M>)]" :key="displayedModelValue">
354
447
  <span v-if="displayedModelValue" :class="b24ui.value({ class: props.b24ui?.value })">
355
448
  {{ displayedModelValue }}
356
449
  </span>
357
450
  <span v-else :class="b24ui.placeholder({ class: props.b24ui?.placeholder })">
358
- {{ placeholder ?? "\xA0" }}
451
+ {{ placeholder ?? '&nbsp;' }}
359
452
  </span>
360
453
  </template>
361
454
  </slot>
362
455
 
363
456
  <span v-if="isTrailing || !!slots.trailing" :class="b24ui.trailing({ class: props.b24ui?.trailing })">
364
- <slot name="trailing" :model-value="modelValue" :open="open" :b24ui="b24ui">
457
+ <slot name="trailing" :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open" :b24ui="b24ui">
365
458
  <Component
366
459
  :is="trailingIconName"
367
460
  v-if="trailingIconName"
@@ -381,7 +474,7 @@ function isSelectItem(item) {
381
474
 
382
475
  <ComboboxEmpty :class="b24ui.empty({ class: props.b24ui?.empty })">
383
476
  <slot name="empty" :search-term="searchTerm">
384
- {{ searchTerm ? t("selectMenu.noMatch", { searchTerm }) : t("selectMenu.noData") }}
477
+ {{ searchTerm ? t('selectMenu.noMatch', { searchTerm }) : t('selectMenu.noData') }}
385
478
  </slot>
386
479
  </ComboboxEmpty>
387
480
 
@@ -391,29 +484,29 @@ function isSelectItem(item) {
391
484
  <ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="b24ui.group({ class: props.b24ui?.group })">
392
485
  <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
393
486
  <ComboboxLabel v-if="isSelectItem(item) && item.type === 'label'" :class="b24ui.label({ class: props.b24ui?.label })">
394
- {{ get(item, props.labelKey) }}
487
+ {{ get(item, props.labelKey as string) }}
395
488
  </ComboboxLabel>
396
489
 
397
490
  <ComboboxSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="b24ui.separator({ class: props.b24ui?.separator })" />
398
491
 
399
492
  <ComboboxItem
400
493
  v-else
401
- :class="b24ui.item({ class: props.b24ui?.item, colorItem: isSelectItem(item) ? item?.color : void 0 })"
494
+ :class="b24ui.item({ class: props.b24ui?.item, colorItem: isSelectItem(item) ? item?.color : undefined })"
402
495
  :disabled="isSelectItem(item) && item.disabled"
403
- :value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey) : item"
496
+ :value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey as string) : item"
404
497
  @select="isSelectItem(item) && item.onSelect?.($event)"
405
498
  >
406
- <slot name="item" :item="item" :index="index">
407
- <slot name="item-leading" :item="item" :index="index">
499
+ <slot name="item" :item="(item as NestedItem<T>)" :index="index">
500
+ <slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
408
501
  <Component
409
502
  :is="item.icon"
410
503
  v-if="isSelectItem(item) && item.icon"
411
504
  :class="b24ui.itemLeadingIcon({ class: props.b24ui?.itemLeadingIcon, colorItem: item?.color })"
412
505
  />
413
- <B24Avatar v-else-if="isSelectItem(item) && item.avatar" :size="props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()" v-bind="item.avatar" :class="b24ui.itemLeadingAvatar({ class: props.b24ui?.itemLeadingAvatar, colorItem: item?.color })" />
506
+ <B24Avatar v-else-if="isSelectItem(item) && item.avatar" :size="((props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="b24ui.itemLeadingAvatar({ class: props.b24ui?.itemLeadingAvatar, colorItem: item?.color })" />
414
507
  <B24Chip
415
508
  v-else-if="isSelectItem(item) && item.chip"
416
- :size="props.b24ui?.itemLeadingChipSize || b24ui.itemLeadingChipSize()"
509
+ :size="((props.b24ui?.itemLeadingChipSize || b24ui.itemLeadingChipSize()) as ChipProps['size'])"
417
510
  inset
418
511
  standalone
419
512
  v-bind="item.chip"
@@ -422,18 +515,18 @@ function isSelectItem(item) {
422
515
  </slot>
423
516
 
424
517
  <span :class="b24ui.itemLabel({ class: props.b24ui?.itemLabel })">
425
- <slot name="item-label" :item="item" :index="index">
426
- {{ isSelectItem(item) ? get(item, props.labelKey) : item }}
518
+ <slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
519
+ {{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
427
520
  </slot>
428
521
  </span>
429
522
 
430
- <span :class="b24ui.itemTrailing({ class: props.b24ui?.itemTrailing, colorItem: isSelectItem(item) ? item?.color : void 0 })">
431
- <slot name="item-trailing" :item="item" :index="index" />
523
+ <span :class="b24ui.itemTrailing({ class: props.b24ui?.itemTrailing, colorItem: isSelectItem(item) ? item?.color : undefined })">
524
+ <slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
432
525
 
433
526
  <ComboboxItemIndicator as-child>
434
527
  <Component
435
528
  :is="selectedIcon || icons.check"
436
- :class="b24ui.itemTrailingIcon({ class: props.b24ui?.itemTrailingIcon, colorItem: isSelectItem(item) ? item?.color : void 0 })"
529
+ :class="b24ui.itemTrailingIcon({ class: props.b24ui?.itemTrailingIcon, colorItem: isSelectItem(item) ? item?.color : undefined })"
437
530
  />
438
531
  </ComboboxItemIndicator>
439
532
  </span>