@nuxt/ui 0.4.1 → 2.8.0

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 (143) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +63 -50
  3. package/dist/module.cjs +5 -0
  4. package/dist/module.d.mts +1234 -0
  5. package/dist/module.d.ts +1234 -0
  6. package/dist/module.json +8 -0
  7. package/dist/module.mjs +407 -0
  8. package/dist/runtime/app.config.d.ts +1203 -0
  9. package/dist/runtime/app.config.mjs +1057 -0
  10. package/dist/runtime/components/data/Table.vue +251 -0
  11. package/dist/runtime/components/data/Table.vue.d.ts +215 -0
  12. package/dist/runtime/components/elements/Accordion.vue +138 -0
  13. package/dist/runtime/components/elements/Accordion.vue.d.ts +80 -0
  14. package/dist/runtime/components/elements/Alert.vue +120 -0
  15. package/dist/runtime/components/elements/Alert.vue.d.ts +107 -0
  16. package/dist/runtime/components/elements/Avatar.vue +149 -0
  17. package/dist/runtime/components/elements/Avatar.vue.d.ts +115 -0
  18. package/dist/runtime/components/elements/AvatarGroup.d.ts +37 -0
  19. package/dist/runtime/components/elements/AvatarGroup.mjs +53 -0
  20. package/dist/runtime/components/elements/Badge.vue +69 -0
  21. package/dist/runtime/components/elements/Badge.vue.d.ts +63 -0
  22. package/dist/runtime/components/elements/Button.vue +182 -0
  23. package/dist/runtime/components/elements/Button.vue.d.ts +187 -0
  24. package/dist/runtime/components/elements/ButtonGroup.d.ts +39 -0
  25. package/dist/runtime/components/elements/ButtonGroup.mjs +70 -0
  26. package/dist/runtime/components/elements/Dropdown.vue +172 -0
  27. package/dist/runtime/components/elements/Dropdown.vue.d.ts +96 -0
  28. package/dist/runtime/components/elements/Icon.vue +15 -0
  29. package/dist/runtime/components/elements/Icon.vue.d.ts +12 -0
  30. package/dist/runtime/components/elements/Kbd.vue +55 -0
  31. package/dist/runtime/components/elements/Kbd.vue.d.ts +42 -0
  32. package/dist/runtime/components/elements/Link.vue +80 -0
  33. package/dist/runtime/components/elements/Link.vue.d.ts +9 -0
  34. package/dist/runtime/components/forms/Checkbox.vue +136 -0
  35. package/dist/runtime/components/forms/Checkbox.vue.d.ts +129 -0
  36. package/dist/runtime/components/forms/Form.vue +186 -0
  37. package/dist/runtime/components/forms/Form.vue.d.ts +50 -0
  38. package/dist/runtime/components/forms/FormGroup.vue +97 -0
  39. package/dist/runtime/components/forms/FormGroup.vue.d.ts +98 -0
  40. package/dist/runtime/components/forms/Input.vue +250 -0
  41. package/dist/runtime/components/forms/Input.vue.d.ts +214 -0
  42. package/dist/runtime/components/forms/Radio.vue +122 -0
  43. package/dist/runtime/components/forms/Radio.vue.d.ts +109 -0
  44. package/dist/runtime/components/forms/Range.vue +163 -0
  45. package/dist/runtime/components/forms/Range.vue.d.ts +119 -0
  46. package/dist/runtime/components/forms/Select.vue +307 -0
  47. package/dist/runtime/components/forms/Select.vue.d.ts +229 -0
  48. package/dist/runtime/components/forms/SelectMenu.vue +429 -0
  49. package/dist/runtime/components/forms/SelectMenu.vue.d.ts +330 -0
  50. package/dist/runtime/components/forms/Textarea.vue +184 -0
  51. package/dist/runtime/components/forms/Textarea.vue.d.ts +161 -0
  52. package/dist/runtime/components/forms/Toggle.vue +113 -0
  53. package/dist/runtime/components/forms/Toggle.vue.d.ts +83 -0
  54. package/dist/runtime/components/layout/Card.vue +58 -0
  55. package/dist/runtime/components/layout/Card.vue.d.ts +31 -0
  56. package/dist/runtime/components/layout/Container.vue +43 -0
  57. package/dist/runtime/components/layout/Container.vue.d.ts +31 -0
  58. package/dist/runtime/components/layout/Skeleton.vue +37 -0
  59. package/dist/runtime/components/layout/Skeleton.vue.d.ts +22 -0
  60. package/dist/runtime/components/navigation/CommandPalette.vue +304 -0
  61. package/dist/runtime/components/navigation/CommandPalette.vue.d.ts +224 -0
  62. package/dist/runtime/components/navigation/CommandPaletteGroup.vue +152 -0
  63. package/dist/runtime/components/navigation/CommandPaletteGroup.vue.d.ts +63 -0
  64. package/dist/runtime/components/navigation/Pagination.vue +197 -0
  65. package/dist/runtime/components/navigation/Pagination.vue.d.ts +125 -0
  66. package/dist/runtime/components/navigation/Tabs.vue +138 -0
  67. package/dist/runtime/components/navigation/Tabs.vue.d.ts +69 -0
  68. package/dist/runtime/components/navigation/VerticalNavigation.vue +79 -0
  69. package/dist/runtime/components/navigation/VerticalNavigation.vue.d.ts +37 -0
  70. package/dist/runtime/components/overlays/ContextMenu.vue +74 -0
  71. package/dist/runtime/components/overlays/ContextMenu.vue.d.ts +54 -0
  72. package/dist/runtime/components/overlays/Modal.vue +113 -0
  73. package/dist/runtime/components/overlays/Modal.vue.d.ts +82 -0
  74. package/dist/runtime/components/overlays/Notification.vue +197 -0
  75. package/dist/runtime/components/overlays/Notification.vue.d.ts +126 -0
  76. package/dist/runtime/components/overlays/Notifications.vue +61 -0
  77. package/dist/runtime/components/overlays/Notifications.vue.d.ts +41 -0
  78. package/dist/runtime/components/overlays/Popover.vue +139 -0
  79. package/dist/runtime/components/overlays/Popover.vue.d.ts +82 -0
  80. package/dist/runtime/components/overlays/Slideover.vue +103 -0
  81. package/dist/runtime/components/overlays/Slideover.vue.d.ts +84 -0
  82. package/dist/runtime/components/overlays/Tooltip.vue +118 -0
  83. package/dist/runtime/components/overlays/Tooltip.vue.d.ts +82 -0
  84. package/dist/runtime/composables/defineShortcuts.d.ts +13 -0
  85. package/dist/runtime/composables/defineShortcuts.mjs +108 -0
  86. package/dist/runtime/composables/useCopyToClipboard.d.ts +10 -0
  87. package/dist/runtime/composables/useCopyToClipboard.mjs +26 -0
  88. package/dist/runtime/composables/useFormGroup.d.ts +6 -0
  89. package/dist/runtime/composables/useFormGroup.mjs +30 -0
  90. package/dist/runtime/composables/usePopper.d.ts +232 -0
  91. package/dist/runtime/composables/usePopper.mjs +78 -0
  92. package/dist/runtime/composables/useShortcuts.d.ts +12 -0
  93. package/dist/runtime/composables/useShortcuts.mjs +24 -0
  94. package/dist/runtime/composables/useTimer.d.ts +8 -0
  95. package/dist/runtime/composables/useTimer.mjs +51 -0
  96. package/dist/runtime/composables/useToast.d.ts +18 -0
  97. package/dist/runtime/composables/useToast.mjs +22 -0
  98. package/dist/runtime/plugins/colors.d.ts +2 -0
  99. package/dist/runtime/plugins/colors.mjs +46 -0
  100. package/dist/runtime/types/accordion.d.ts +9 -0
  101. package/dist/runtime/types/avatar.d.ts +9 -0
  102. package/dist/runtime/types/button.d.ts +23 -0
  103. package/dist/runtime/types/clipboard.d.ts +3 -0
  104. package/dist/runtime/types/command-palette.d.ts +26 -0
  105. package/dist/runtime/types/dropdown.d.ts +13 -0
  106. package/dist/runtime/types/form.d.ts +21 -0
  107. package/dist/runtime/types/index.d.ts +12 -0
  108. package/dist/runtime/types/link.d.ts +8 -0
  109. package/dist/runtime/types/notification.d.ts +22 -0
  110. package/dist/runtime/types/popper.d.ts +14 -0
  111. package/dist/runtime/types/tabs.d.ts +6 -0
  112. package/dist/runtime/types/vertical-navigation.d.ts +11 -0
  113. package/dist/runtime/ui.css +13 -0
  114. package/dist/runtime/utils/StateEmitter.d.ts +17 -0
  115. package/dist/runtime/utils/StateEmitter.mjs +21 -0
  116. package/dist/runtime/utils/index.d.ts +11 -0
  117. package/dist/runtime/utils/index.mjs +33 -0
  118. package/dist/types.d.mts +15 -0
  119. package/dist/types.d.ts +15 -0
  120. package/package.json +56 -39
  121. package/LICENSE +0 -21
  122. package/dist/assets/styles.css +0 -14
  123. package/dist/components/NButton.vue +0 -22
  124. package/dist/components/NCard.vue +0 -5
  125. package/dist/components/NCheckbox.vue +0 -35
  126. package/dist/components/NDarkToggle.vue +0 -28
  127. package/dist/components/NDialog.vue +0 -59
  128. package/dist/components/NDropdown.vue +0 -31
  129. package/dist/components/NIcon.vue +0 -9
  130. package/dist/components/NLink.vue +0 -20
  131. package/dist/components/NRadio.vue +0 -40
  132. package/dist/components/NSwitch.vue +0 -37
  133. package/dist/components/NTextInput.vue +0 -34
  134. package/dist/components/NTip.vue +0 -16
  135. package/dist/components/NuxtContentLogo.vue +0 -7
  136. package/dist/components/NuxtExampleLayout.vue +0 -82
  137. package/dist/components/NuxtLogo.vue +0 -20
  138. package/dist/components/nuxt/NDarkToggle.vue +0 -28
  139. package/dist/nuxt.d.ts +0 -16
  140. package/dist/nuxt.mjs +0 -36
  141. package/dist/unocss.d.ts +0 -7
  142. package/dist/unocss.mjs +0 -127
  143. package/nuxt.cjs +0 -7
@@ -0,0 +1,229 @@
1
+ /// <reference types="lodash" />
2
+ import type { PropType, ComputedRef } from 'vue';
3
+ declare const _default: import("vue").DefineComponent<{
4
+ modelValue: {
5
+ type: (ObjectConstructor | StringConstructor | NumberConstructor)[];
6
+ default: string;
7
+ };
8
+ name: {
9
+ type: StringConstructor;
10
+ default: null;
11
+ };
12
+ placeholder: {
13
+ type: StringConstructor;
14
+ default: null;
15
+ };
16
+ required: {
17
+ type: BooleanConstructor;
18
+ default: boolean;
19
+ };
20
+ disabled: {
21
+ type: BooleanConstructor;
22
+ default: boolean;
23
+ };
24
+ icon: {
25
+ type: StringConstructor;
26
+ default: null;
27
+ };
28
+ loadingIcon: {
29
+ type: StringConstructor;
30
+ default: () => any;
31
+ };
32
+ leadingIcon: {
33
+ type: StringConstructor;
34
+ default: null;
35
+ };
36
+ trailingIcon: {
37
+ type: StringConstructor;
38
+ default: () => any;
39
+ };
40
+ trailing: {
41
+ type: BooleanConstructor;
42
+ default: boolean;
43
+ };
44
+ leading: {
45
+ type: BooleanConstructor;
46
+ default: boolean;
47
+ };
48
+ loading: {
49
+ type: BooleanConstructor;
50
+ default: boolean;
51
+ };
52
+ padded: {
53
+ type: BooleanConstructor;
54
+ default: boolean;
55
+ };
56
+ options: {
57
+ type: ArrayConstructor;
58
+ default: () => never[];
59
+ };
60
+ size: {
61
+ type: StringConstructor;
62
+ default: () => any;
63
+ validator(value: string): boolean;
64
+ };
65
+ color: {
66
+ type: StringConstructor;
67
+ default: () => any;
68
+ validator(value: string): boolean;
69
+ };
70
+ variant: {
71
+ type: StringConstructor;
72
+ default: () => any;
73
+ validator(value: string): boolean;
74
+ };
75
+ optionAttribute: {
76
+ type: StringConstructor;
77
+ default: string;
78
+ };
79
+ valueAttribute: {
80
+ type: StringConstructor;
81
+ default: string;
82
+ };
83
+ selectClass: {
84
+ type: StringConstructor;
85
+ default: null;
86
+ };
87
+ ui: {
88
+ type: PropType<any>;
89
+ default: () => {};
90
+ };
91
+ }, {
92
+ attrs: import("lodash").Omit<{
93
+ [x: string]: unknown;
94
+ }, "class">;
95
+ ui: ComputedRef<any>;
96
+ normalizedOptionsWithPlaceholder: ComputedRef<{
97
+ disabled?: boolean | undefined;
98
+ children: {
99
+ disabled?: boolean;
100
+ }[];
101
+ }[]>;
102
+ normalizedValue: ComputedRef<any>;
103
+ isLeading: ComputedRef<string | true>;
104
+ isTrailing: ComputedRef<string | true | undefined>;
105
+ wrapperClass: ComputedRef<string>;
106
+ selectClass: ComputedRef<string>;
107
+ leadingIconName: ComputedRef<string | undefined>;
108
+ leadingIconClass: ComputedRef<string>;
109
+ leadingWrapperIconClass: ComputedRef<string>;
110
+ trailingIconName: ComputedRef<string | undefined>;
111
+ trailingIconClass: ComputedRef<string>;
112
+ trailingWrapperIconClass: ComputedRef<string>;
113
+ onInput: (event: InputEvent) => void;
114
+ onChange: (event: Event) => void;
115
+ }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("change" | "update:modelValue")[], "change" | "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
116
+ modelValue: {
117
+ type: (ObjectConstructor | StringConstructor | NumberConstructor)[];
118
+ default: string;
119
+ };
120
+ name: {
121
+ type: StringConstructor;
122
+ default: null;
123
+ };
124
+ placeholder: {
125
+ type: StringConstructor;
126
+ default: null;
127
+ };
128
+ required: {
129
+ type: BooleanConstructor;
130
+ default: boolean;
131
+ };
132
+ disabled: {
133
+ type: BooleanConstructor;
134
+ default: boolean;
135
+ };
136
+ icon: {
137
+ type: StringConstructor;
138
+ default: null;
139
+ };
140
+ loadingIcon: {
141
+ type: StringConstructor;
142
+ default: () => any;
143
+ };
144
+ leadingIcon: {
145
+ type: StringConstructor;
146
+ default: null;
147
+ };
148
+ trailingIcon: {
149
+ type: StringConstructor;
150
+ default: () => any;
151
+ };
152
+ trailing: {
153
+ type: BooleanConstructor;
154
+ default: boolean;
155
+ };
156
+ leading: {
157
+ type: BooleanConstructor;
158
+ default: boolean;
159
+ };
160
+ loading: {
161
+ type: BooleanConstructor;
162
+ default: boolean;
163
+ };
164
+ padded: {
165
+ type: BooleanConstructor;
166
+ default: boolean;
167
+ };
168
+ options: {
169
+ type: ArrayConstructor;
170
+ default: () => never[];
171
+ };
172
+ size: {
173
+ type: StringConstructor;
174
+ default: () => any;
175
+ validator(value: string): boolean;
176
+ };
177
+ color: {
178
+ type: StringConstructor;
179
+ default: () => any;
180
+ validator(value: string): boolean;
181
+ };
182
+ variant: {
183
+ type: StringConstructor;
184
+ default: () => any;
185
+ validator(value: string): boolean;
186
+ };
187
+ optionAttribute: {
188
+ type: StringConstructor;
189
+ default: string;
190
+ };
191
+ valueAttribute: {
192
+ type: StringConstructor;
193
+ default: string;
194
+ };
195
+ selectClass: {
196
+ type: StringConstructor;
197
+ default: null;
198
+ };
199
+ ui: {
200
+ type: PropType<any>;
201
+ default: () => {};
202
+ };
203
+ }>> & {
204
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
205
+ onChange?: ((...args: any[]) => any) | undefined;
206
+ }, {
207
+ icon: string;
208
+ color: string;
209
+ ui: any;
210
+ name: string;
211
+ options: unknown[];
212
+ modelValue: string | number | Record<string, any>;
213
+ loading: boolean;
214
+ disabled: boolean;
215
+ variant: string;
216
+ required: boolean;
217
+ size: string;
218
+ placeholder: string;
219
+ padded: boolean;
220
+ loadingIcon: string;
221
+ leadingIcon: string;
222
+ trailingIcon: string;
223
+ trailing: boolean;
224
+ leading: boolean;
225
+ optionAttribute: string;
226
+ valueAttribute: string;
227
+ selectClass: string;
228
+ }, {}>;
229
+ export default _default;
@@ -0,0 +1,429 @@
1
+ <template>
2
+ <component
3
+ :is="searchable ? 'HCombobox' : 'HListbox'"
4
+ v-slot="{ open }"
5
+ :by="by"
6
+ :name="name"
7
+ :model-value="modelValue"
8
+ :multiple="multiple"
9
+ :disabled="disabled || loading"
10
+ as="div"
11
+ :class="wrapperClass"
12
+ @update:model-value="onUpdate"
13
+ >
14
+ <input
15
+ v-if="required"
16
+ :value="modelValue"
17
+ :required="required"
18
+ class="absolute inset-0 w-px opacity-0 cursor-default"
19
+ tabindex="-1"
20
+ aria-hidden="true"
21
+ >
22
+
23
+ <component
24
+ :is="searchable ? 'HComboboxButton' : 'HListboxButton'"
25
+ ref="trigger"
26
+ as="div"
27
+ role="button"
28
+ class="inline-flex w-full"
29
+ >
30
+ <slot :open="open" :disabled="disabled" :loading="loading">
31
+ <button :class="selectClass" :disabled="disabled || loading" type="button" v-bind="attrs">
32
+ <span v-if="(isLeading && leadingIconName) || $slots.leading" :class="leadingWrapperIconClass">
33
+ <slot name="leading" :disabled="disabled" :loading="loading">
34
+ <UIcon :name="leadingIconName" :class="leadingIconClass" />
35
+ </slot>
36
+ </span>
37
+
38
+ <slot name="label">
39
+ <span v-if="multiple && Array.isArray(modelValue) && modelValue.length" class="block truncate">{{ modelValue.length }} selected</span>
40
+ <span v-else-if="!multiple && modelValue" class="block truncate">{{ typeof modelValue === 'string' ? modelValue : modelValue[optionAttribute] }}</span>
41
+ <span v-else class="block truncate" :class="uiMenu.placeholder">{{ placeholder || '&nbsp;' }}</span>
42
+ </slot>
43
+
44
+ <span v-if="(isTrailing && trailingIconName) || $slots.trailing" :class="trailingWrapperIconClass">
45
+ <slot name="trailing" :disabled="disabled" :loading="loading">
46
+ <UIcon :name="trailingIconName" :class="trailingIconClass" aria-hidden="true" />
47
+ </slot>
48
+ </span>
49
+ </button>
50
+ </slot>
51
+ </component>
52
+
53
+ <div v-if="open" ref="container" :class="[uiMenu.container, uiMenu.width]">
54
+ <Transition appear v-bind="uiMenu.transition">
55
+ <component :is="searchable ? 'HComboboxOptions' : 'HListboxOptions'" static :class="[uiMenu.base, uiMenu.divide, uiMenu.ring, uiMenu.rounded, uiMenu.shadow, uiMenu.background, uiMenu.padding, uiMenu.height]">
56
+ <HComboboxInput
57
+ v-if="searchable"
58
+ ref="searchInput"
59
+ :display-value="() => query"
60
+ name="q"
61
+ :placeholder="searchablePlaceholder"
62
+ autofocus
63
+ autocomplete="off"
64
+ :class="uiMenu.input"
65
+ @change="query = $event.target.value"
66
+ />
67
+ <component
68
+ :is="searchable ? 'HComboboxOption' : 'HListboxOption'"
69
+ v-for="(option, index) in filteredOptions"
70
+ v-slot="{ active, selected, disabled: optionDisabled }"
71
+ :key="index"
72
+ as="template"
73
+ :value="valueAttribute ? option[valueAttribute] : option"
74
+ :disabled="option.disabled"
75
+ >
76
+ <li :class="[uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive, selected && uiMenu.option.selected, optionDisabled && uiMenu.option.disabled]">
77
+ <div :class="uiMenu.option.container">
78
+ <slot name="option" :option="option" :active="active" :selected="selected">
79
+ <UIcon v-if="option.icon" :name="option.icon" :class="[uiMenu.option.icon.base, active ? uiMenu.option.icon.active : uiMenu.option.icon.inactive, option.iconClass]" aria-hidden="true" />
80
+ <UAvatar
81
+ v-else-if="option.avatar"
82
+ v-bind="{ size: uiMenu.option.avatar.size, ...option.avatar }"
83
+ :class="uiMenu.option.avatar.base"
84
+ aria-hidden="true"
85
+ />
86
+ <span v-else-if="option.chip" :class="uiMenu.option.chip.base" :style="{ background: `#${option.chip}` }" />
87
+
88
+ <span class="truncate">{{ typeof option === 'string' ? option : option[optionAttribute] }}</span>
89
+ </slot>
90
+ </div>
91
+
92
+ <span v-if="selected" :class="[uiMenu.option.selectedIcon.wrapper, uiMenu.option.selectedIcon.padding]">
93
+ <UIcon :name="selectedIcon" :class="uiMenu.option.selectedIcon.base" aria-hidden="true" />
94
+ </span>
95
+ </li>
96
+ </component>
97
+
98
+ <component :is="searchable ? 'HComboboxOption' : 'HListboxOption'" v-if="creatable && queryOption && !filteredOptions.length" v-slot="{ active, selected }" :value="queryOption" as="template">
99
+ <li :class="[uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive]">
100
+ <div :class="uiMenu.option.container">
101
+ <slot name="option-create" :option="queryOption" :active="active" :selected="selected">
102
+ <span class="block truncate">Create "{{ queryOption[optionAttribute] }}"</span>
103
+ </slot>
104
+ </div>
105
+ </li>
106
+ </component>
107
+ <p v-else-if="searchable && query && !filteredOptions.length" :class="uiMenu.option.empty">
108
+ <slot name="option-empty" :query="query">
109
+ No results for "{{ query }}".
110
+ </slot>
111
+ </p>
112
+ </component>
113
+ </Transition>
114
+ </div>
115
+ </component>
116
+ </template>
117
+
118
+ <script>
119
+ import { ref, computed, watch, defineComponent } from "vue";
120
+ import {
121
+ Combobox as HCombobox,
122
+ ComboboxButton as HComboboxButton,
123
+ ComboboxOptions as HComboboxOptions,
124
+ ComboboxOption as HComboboxOption,
125
+ ComboboxInput as HComboboxInput,
126
+ Listbox as HListbox,
127
+ ListboxButton as HListboxButton,
128
+ ListboxOptions as HListboxOptions,
129
+ ListboxOption as HListboxOption
130
+ } from "@headlessui/vue";
131
+ import { computedAsync, useDebounceFn } from "@vueuse/core";
132
+ import { defu } from "defu";
133
+ import { omit } from "lodash-es";
134
+ import { twMerge, twJoin } from "tailwind-merge";
135
+ import UIcon from "../elements/Icon.vue";
136
+ import UAvatar from "../elements/Avatar.vue";
137
+ import { defuTwMerge } from "../../utils";
138
+ import { usePopper } from "../../composables/usePopper";
139
+ import { useFormGroup } from "../../composables/useFormGroup";
140
+ import { useAppConfig } from "#imports";
141
+ import appConfig from "#build/app.config";
142
+ export default defineComponent({
143
+ components: {
144
+ HCombobox,
145
+ HComboboxButton,
146
+ HComboboxOptions,
147
+ HComboboxOption,
148
+ HComboboxInput,
149
+ HListbox,
150
+ HListboxButton,
151
+ HListboxOptions,
152
+ HListboxOption,
153
+ UIcon,
154
+ UAvatar
155
+ },
156
+ inheritAttrs: false,
157
+ props: {
158
+ modelValue: {
159
+ type: [String, Number, Object, Array],
160
+ default: ""
161
+ },
162
+ by: {
163
+ type: String,
164
+ default: void 0
165
+ },
166
+ options: {
167
+ type: Array,
168
+ default: () => []
169
+ },
170
+ name: {
171
+ type: String,
172
+ default: null
173
+ },
174
+ required: {
175
+ type: Boolean,
176
+ default: false
177
+ },
178
+ icon: {
179
+ type: String,
180
+ default: null
181
+ },
182
+ loadingIcon: {
183
+ type: String,
184
+ default: () => appConfig.ui.input.default.loadingIcon
185
+ },
186
+ leadingIcon: {
187
+ type: String,
188
+ default: null
189
+ },
190
+ trailingIcon: {
191
+ type: String,
192
+ default: () => appConfig.ui.select.default.trailingIcon
193
+ },
194
+ trailing: {
195
+ type: Boolean,
196
+ default: false
197
+ },
198
+ leading: {
199
+ type: Boolean,
200
+ default: false
201
+ },
202
+ loading: {
203
+ type: Boolean,
204
+ default: false
205
+ },
206
+ selectedIcon: {
207
+ type: String,
208
+ default: () => appConfig.ui.selectMenu.default.selectedIcon
209
+ },
210
+ disabled: {
211
+ type: Boolean,
212
+ default: false
213
+ },
214
+ multiple: {
215
+ type: Boolean,
216
+ default: false
217
+ },
218
+ searchable: {
219
+ type: [Boolean, Function],
220
+ default: false
221
+ },
222
+ searchablePlaceholder: {
223
+ type: String,
224
+ default: "Search..."
225
+ },
226
+ debounce: {
227
+ type: Number,
228
+ default: 200
229
+ },
230
+ creatable: {
231
+ type: Boolean,
232
+ default: false
233
+ },
234
+ placeholder: {
235
+ type: String,
236
+ default: null
237
+ },
238
+ padded: {
239
+ type: Boolean,
240
+ default: true
241
+ },
242
+ size: {
243
+ type: String,
244
+ default: () => appConfig.ui.select.default.size,
245
+ validator(value) {
246
+ return Object.keys(appConfig.ui.select.size).includes(value);
247
+ }
248
+ },
249
+ color: {
250
+ type: String,
251
+ default: () => appConfig.ui.select.default.color,
252
+ validator(value) {
253
+ return [...appConfig.ui.colors, ...Object.keys(appConfig.ui.select.color)].includes(value);
254
+ }
255
+ },
256
+ variant: {
257
+ type: String,
258
+ default: () => appConfig.ui.select.default.variant,
259
+ validator(value) {
260
+ return [
261
+ ...Object.keys(appConfig.ui.select.variant),
262
+ ...Object.values(appConfig.ui.select.color).flatMap((value2) => Object.keys(value2))
263
+ ].includes(value);
264
+ }
265
+ },
266
+ optionAttribute: {
267
+ type: String,
268
+ default: "label"
269
+ },
270
+ valueAttribute: {
271
+ type: String,
272
+ default: null
273
+ },
274
+ searchAttributes: {
275
+ type: Array,
276
+ default: null
277
+ },
278
+ popper: {
279
+ type: Object,
280
+ default: () => ({})
281
+ },
282
+ selectClass: {
283
+ type: String,
284
+ default: null
285
+ },
286
+ ui: {
287
+ type: Object,
288
+ default: () => ({})
289
+ },
290
+ uiMenu: {
291
+ type: Object,
292
+ default: () => ({})
293
+ }
294
+ },
295
+ emits: ["update:modelValue", "open", "close", "change"],
296
+ setup(props, { emit, attrs, slots }) {
297
+ const appConfig2 = useAppConfig();
298
+ const ui = computed(() => defuTwMerge({}, props.ui, appConfig2.ui.select));
299
+ const uiMenu = computed(() => defuTwMerge({}, props.uiMenu, appConfig2.ui.selectMenu));
300
+ const popper = computed(() => defu({}, props.popper, uiMenu.value.popper));
301
+ const [trigger, container] = usePopper(popper.value);
302
+ const { emitFormBlur, emitFormChange, formGroup } = useFormGroup();
303
+ const color = computed(() => formGroup?.error?.value ? "red" : props.color);
304
+ const size = computed(() => formGroup?.size?.value ?? props.size);
305
+ const query = ref("");
306
+ const searchInput = ref();
307
+ const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class));
308
+ const selectClass = computed(() => {
309
+ const variant = ui.value.color?.[color.value]?.[props.variant] || ui.value.variant[props.variant];
310
+ return twMerge(twJoin(
311
+ ui.value.base,
312
+ ui.value.rounded,
313
+ "text-left cursor-default",
314
+ ui.value.size[size.value],
315
+ ui.value.gap[size.value],
316
+ props.padded ? ui.value.padding[size.value] : "p-0",
317
+ variant?.replaceAll("{color}", color.value),
318
+ (isLeading.value || slots.leading) && ui.value.leading.padding[size.value],
319
+ (isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value],
320
+ "inline-flex items-center"
321
+ ), props.selectClass);
322
+ });
323
+ const isLeading = computed(() => {
324
+ return props.icon && props.leading || props.icon && !props.trailing || props.loading && !props.trailing || props.leadingIcon;
325
+ });
326
+ const isTrailing = computed(() => {
327
+ return props.icon && props.trailing || props.loading && props.trailing || props.trailingIcon;
328
+ });
329
+ const leadingIconName = computed(() => {
330
+ if (props.loading) {
331
+ return props.loadingIcon;
332
+ }
333
+ return props.leadingIcon || props.icon;
334
+ });
335
+ const trailingIconName = computed(() => {
336
+ if (props.loading && !isLeading.value) {
337
+ return props.loadingIcon;
338
+ }
339
+ return props.trailingIcon || props.icon;
340
+ });
341
+ const leadingWrapperIconClass = computed(() => {
342
+ return twJoin(
343
+ ui.value.icon.leading.wrapper,
344
+ ui.value.icon.leading.pointer,
345
+ ui.value.icon.leading.padding[size.value]
346
+ );
347
+ });
348
+ const leadingIconClass = computed(() => {
349
+ return twJoin(
350
+ ui.value.icon.base,
351
+ appConfig2.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll("{color}", color.value),
352
+ ui.value.icon.size[size.value],
353
+ props.loading && "animate-spin"
354
+ );
355
+ });
356
+ const trailingWrapperIconClass = computed(() => {
357
+ return twJoin(
358
+ ui.value.icon.trailing.wrapper,
359
+ ui.value.icon.trailing.pointer,
360
+ ui.value.icon.trailing.padding[size.value]
361
+ );
362
+ });
363
+ const trailingIconClass = computed(() => {
364
+ return twJoin(
365
+ ui.value.icon.base,
366
+ appConfig2.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll("{color}", color.value),
367
+ ui.value.icon.size[size.value],
368
+ props.loading && !isLeading.value && "animate-spin"
369
+ );
370
+ });
371
+ const debouncedSearch = typeof props.searchable === "function" ? useDebounceFn(props.searchable, props.debounce) : void 0;
372
+ const filteredOptions = computedAsync(async () => {
373
+ if (props.searchable && debouncedSearch) {
374
+ return await debouncedSearch(query.value);
375
+ }
376
+ if (query.value === "") {
377
+ return props.options;
378
+ }
379
+ return props.options.filter((option) => {
380
+ return (props.searchAttributes?.length ? props.searchAttributes : [props.optionAttribute]).some((searchAttribute) => {
381
+ return typeof option === "string" ? option.search(new RegExp(query.value, "i")) !== -1 : option[searchAttribute] && option[searchAttribute].search(new RegExp(query.value, "i")) !== -1;
382
+ });
383
+ });
384
+ });
385
+ const queryOption = computed(() => {
386
+ return query.value === "" ? null : { [props.optionAttribute]: query.value };
387
+ });
388
+ watch(container, (value) => {
389
+ if (value) {
390
+ emit("open");
391
+ } else {
392
+ emit("close");
393
+ emitFormBlur();
394
+ }
395
+ });
396
+ function onUpdate(event) {
397
+ if (query.value && searchInput.value?.$el) {
398
+ query.value = "";
399
+ searchInput.value.$el.value = "";
400
+ }
401
+ emit("update:modelValue", event);
402
+ emit("change", event);
403
+ emitFormChange();
404
+ }
405
+ return {
406
+ attrs: omit(attrs, ["class"]),
407
+ // eslint-disable-next-line vue/no-dupe-keys
408
+ uiMenu,
409
+ trigger,
410
+ container,
411
+ isLeading,
412
+ isTrailing,
413
+ wrapperClass,
414
+ // eslint-disable-next-line vue/no-dupe-keys
415
+ selectClass,
416
+ leadingIconName,
417
+ leadingIconClass,
418
+ leadingWrapperIconClass,
419
+ trailingIconName,
420
+ trailingIconClass,
421
+ trailingWrapperIconClass,
422
+ filteredOptions,
423
+ queryOption,
424
+ query,
425
+ onUpdate
426
+ };
427
+ }
428
+ });
429
+ </script>