pukaad-ui-lib 1.0.1 → 1.1.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.
- package/dist/module.json +1 -1
- package/dist/runtime/components/input/input-autocomplete.d.vue.ts +39 -17
- package/dist/runtime/components/input/input-autocomplete.vue +133 -298
- package/dist/runtime/components/input/input-autocomplete.vue.d.ts +39 -17
- package/dist/runtime/components/input/input-file.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-file.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-password.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-password.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-select.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-select.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-slider.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-slider.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-text-field.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-text-field.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-textarea.d.vue.ts +2 -2
- package/dist/runtime/components/input/input-textarea.vue.d.ts +2 -2
- package/dist/runtime/components/ui/command/CommandInput.vue +7 -3
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -1,29 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { HTMLAttributes } from "vue";
|
|
2
|
+
interface AutocompleteOption {
|
|
3
|
+
label: string;
|
|
3
4
|
value: string | number;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
interface InputAutocompleteProps {
|
|
7
|
+
id?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
class?: HTMLAttributes["class"];
|
|
8
10
|
placeholder?: string;
|
|
9
|
-
|
|
11
|
+
rules?: object | string | Function;
|
|
12
|
+
label?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
disabledErrorMessage?: boolean;
|
|
10
15
|
required?: boolean;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
16
|
+
disabledBorder?: boolean;
|
|
17
|
+
options?: AutocompleteOption[] | string[] | number[];
|
|
18
|
+
}
|
|
19
|
+
type __VLS_Props = InputAutocompleteProps;
|
|
14
20
|
type __VLS_ModelProps = {
|
|
15
|
-
modelValue?: string | number
|
|
21
|
+
modelValue?: string | number;
|
|
16
22
|
};
|
|
17
23
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
18
|
-
declare
|
|
19
|
-
|
|
24
|
+
declare var __VLS_18: {};
|
|
25
|
+
type __VLS_Slots = {} & {
|
|
26
|
+
label?: (props: typeof __VLS_18) => any;
|
|
27
|
+
};
|
|
28
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
29
|
+
setErrors: (errMsg: string[]) => void;
|
|
30
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
31
|
+
"update:modelValue": (value: string | number) => any;
|
|
20
32
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
21
|
-
"onUpdate:modelValue"?: ((value: string | number
|
|
33
|
+
"onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
|
|
22
34
|
}>, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
required: boolean;
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
placeholder: string;
|
|
39
|
+
description: string;
|
|
40
|
+
options: AutocompleteOption[] | string[] | number[];
|
|
41
|
+
disabledErrorMessage: boolean;
|
|
42
|
+
disabledBorder: boolean;
|
|
27
43
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
44
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
28
45
|
declare const _default: typeof __VLS_export;
|
|
29
46
|
export default _default;
|
|
47
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
48
|
+
new (): {
|
|
49
|
+
$slots: S;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
@@ -1,335 +1,170 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
<ShadFormField
|
|
3
|
+
ref="fieldRef"
|
|
4
|
+
:name="props.name"
|
|
5
|
+
:rules="props.rules || defaultRules"
|
|
6
|
+
v-slot="{ componentField }"
|
|
7
|
+
v-model="modelValue"
|
|
6
8
|
>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
:full-width="props.fullWidth"
|
|
12
|
-
v-model="searchQuery"
|
|
13
|
-
:placeholder="selectedItems.length === 0 ? getPlaceholder : ''"
|
|
14
|
-
:label="props.label"
|
|
15
|
-
:required="props.required"
|
|
16
|
-
@focus="onFocusInput"
|
|
17
|
-
@blur="onBlurInput"
|
|
18
|
-
@backspace="onBackspace"
|
|
19
|
-
:reset="false"
|
|
20
|
-
>
|
|
21
|
-
<template #inside>
|
|
22
|
-
<div
|
|
23
|
-
v-if="selectedItems.length > 0"
|
|
24
|
-
class="flex flex-wrap items-center gap-2"
|
|
25
|
-
>
|
|
26
|
-
<span
|
|
27
|
-
v-for="(item, index) in selectedItems"
|
|
28
|
-
:key="item.value"
|
|
9
|
+
<ShadFormItem>
|
|
10
|
+
<ShadFormLabel v-if="$slots.label || props.label" class="w-full">
|
|
11
|
+
<slot name="label">
|
|
12
|
+
<div
|
|
29
13
|
:class="[
|
|
30
|
-
'
|
|
31
|
-
|
|
14
|
+
'flex-1',
|
|
15
|
+
props.disabledBorder && 'font-body-small-prominent'
|
|
32
16
|
]"
|
|
33
17
|
>
|
|
34
|
-
{{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
18
|
+
{{ props.label }}
|
|
19
|
+
<span v-if="props.required" class="text-destructive">*</span>
|
|
20
|
+
</div>
|
|
21
|
+
</slot>
|
|
22
|
+
</ShadFormLabel>
|
|
38
23
|
|
|
39
|
-
<
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
24
|
+
<ShadPopover v-model:open="open" :modal="false">
|
|
25
|
+
<ShadPopoverAnchor as-child>
|
|
26
|
+
<div ref="containerRef">
|
|
27
|
+
<InputTextField
|
|
28
|
+
v-model="searchText"
|
|
29
|
+
:placeholder="props.placeholder"
|
|
30
|
+
@focus="onFocus"
|
|
31
|
+
@click="onFocus"
|
|
32
|
+
>
|
|
33
|
+
<template #append>
|
|
34
|
+
<Icon
|
|
35
|
+
:name="open ? 'lucide:chevron-up' : 'lucide:chevron-down'"
|
|
36
|
+
size="16"
|
|
37
|
+
class="opacity-50 cursor-pointer"
|
|
38
|
+
@mousedown.prevent="toggleDropdown"
|
|
39
|
+
/>
|
|
40
|
+
</template>
|
|
41
|
+
</InputTextField>
|
|
42
|
+
</div>
|
|
43
|
+
</ShadPopoverAnchor>
|
|
54
44
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
v-model="displayValue"
|
|
70
|
-
/>
|
|
45
|
+
<ShadPopoverContent
|
|
46
|
+
class="p-0 max-h-60 overflow-auto"
|
|
47
|
+
:style="{ width: containerRef?.offsetWidth + 'px' }"
|
|
48
|
+
@openAutoFocus.prevent
|
|
49
|
+
@closeAutoFocus.prevent
|
|
50
|
+
>
|
|
51
|
+
<!-- Empty State -->
|
|
52
|
+
<div
|
|
53
|
+
v-if="filteredOptions.length === 0"
|
|
54
|
+
class="flex flex-col items-center justify-center py-6"
|
|
55
|
+
>
|
|
56
|
+
<Icon name="pukaad:page-not-found" size="50" />
|
|
57
|
+
<div class="font-body-large text-center mt-2">ไม่พบข้อมูล</div>
|
|
58
|
+
</div>
|
|
71
59
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
60
|
+
<!-- Options List -->
|
|
61
|
+
<div v-else class="py-1">
|
|
62
|
+
<div
|
|
63
|
+
v-for="option in filteredOptions"
|
|
64
|
+
:key="option.value"
|
|
65
|
+
class="px-3 py-2 cursor-pointer hover:bg-accent flex items-center gap-2"
|
|
66
|
+
@click="selectOption(option)"
|
|
67
|
+
>
|
|
68
|
+
<Icon
|
|
69
|
+
name="lucide:check"
|
|
70
|
+
size="16"
|
|
71
|
+
:class="[
|
|
72
|
+
modelValue === option.value ? 'opacity-100' : 'opacity-0'
|
|
83
73
|
]"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
<div v-if="props.multiple" class="flex items-center">
|
|
88
|
-
<InputCheckbox
|
|
89
|
-
:model-value="isItemSelected(item)"
|
|
90
|
-
@change="() => toggleItemSelection(item)"
|
|
91
|
-
:label="String(item.label)"
|
|
92
|
-
label-position="right"
|
|
93
|
-
:label-gap="8"
|
|
94
|
-
:key="`checkbox-${item.value}-${isItemSelected(item)}`"
|
|
95
|
-
/>
|
|
74
|
+
/>
|
|
75
|
+
<span>{{ option.label }}</span>
|
|
76
|
+
</div>
|
|
96
77
|
</div>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</template>
|
|
100
|
-
</li>
|
|
101
|
-
</ul>
|
|
78
|
+
</ShadPopoverContent>
|
|
79
|
+
</ShadPopover>
|
|
102
80
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
</div>
|
|
110
|
-
</template>
|
|
111
|
-
</Dropdown>
|
|
81
|
+
<ShadFormDescription v-if="props.description">
|
|
82
|
+
{{ props.description }}
|
|
83
|
+
</ShadFormDescription>
|
|
84
|
+
<ShadFormMessage v-if="!props.disabledErrorMessage" />
|
|
85
|
+
</ShadFormItem>
|
|
86
|
+
</ShadFormField>
|
|
112
87
|
</template>
|
|
113
88
|
|
|
114
89
|
<script setup>
|
|
115
|
-
import { ref, computed, watch
|
|
90
|
+
import { ref, computed, watch } from "vue";
|
|
116
91
|
const props = defineProps({
|
|
92
|
+
id: { type: String, required: false, default: "input-autocomplete" },
|
|
93
|
+
name: { type: String, required: false, default: "input-autocomplete" },
|
|
94
|
+
class: { type: null, required: false },
|
|
95
|
+
placeholder: { type: String, required: false, default: "\u0E1E\u0E34\u0E21\u0E1E\u0E4C\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E04\u0E49\u0E19\u0E2B\u0E32..." },
|
|
96
|
+
rules: { type: [Object, String, Function], required: false },
|
|
117
97
|
label: { type: String, required: false },
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
multiple: { type: Boolean, required: false, default: false }
|
|
98
|
+
description: { type: String, required: false, default: "" },
|
|
99
|
+
disabledErrorMessage: { type: Boolean, required: false, default: false },
|
|
100
|
+
required: { type: Boolean, required: false, default: false },
|
|
101
|
+
disabledBorder: { type: Boolean, required: false, default: false },
|
|
102
|
+
options: { type: Array, required: false, default: () => [] }
|
|
124
103
|
});
|
|
125
|
-
const modelValue = defineModel({ type:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return items2;
|
|
137
|
-
}
|
|
138
|
-
return items2.map((item) => ({
|
|
139
|
-
label: item,
|
|
140
|
-
value: item
|
|
141
|
-
}));
|
|
142
|
-
};
|
|
143
|
-
const isArrayOfObjects = (arr) => {
|
|
144
|
-
return Array.isArray(arr) && arr.every(
|
|
145
|
-
(item) => typeof item === "object" && item !== null && !Array.isArray(item)
|
|
146
|
-
);
|
|
147
|
-
};
|
|
148
|
-
const getCurrentSelectedLabel = () => {
|
|
149
|
-
if (!modelValue.value) return "";
|
|
150
|
-
const selectedItem = props.items.find((item) => {
|
|
151
|
-
if (typeof item === "object") {
|
|
152
|
-
return item.value === modelValue.value;
|
|
153
|
-
} else {
|
|
154
|
-
return item === modelValue.value;
|
|
104
|
+
const modelValue = defineModel({ type: [String, Number], ...{
|
|
105
|
+
default: ""
|
|
106
|
+
} });
|
|
107
|
+
const open = ref(false);
|
|
108
|
+
const searchText = ref("");
|
|
109
|
+
const fieldRef = ref();
|
|
110
|
+
const containerRef = ref();
|
|
111
|
+
const normalizedOptions = computed(() => {
|
|
112
|
+
return props.options.map((option) => {
|
|
113
|
+
if (typeof option === "object" && option !== null) {
|
|
114
|
+
return option;
|
|
155
115
|
}
|
|
116
|
+
return {
|
|
117
|
+
label: String(option),
|
|
118
|
+
value: option
|
|
119
|
+
};
|
|
156
120
|
});
|
|
157
|
-
return selectedItem ? typeof selectedItem === "object" ? String(selectedItem.label) : String(selectedItem) : "";
|
|
158
|
-
};
|
|
159
|
-
const getPlaceholder = computed(() => {
|
|
160
|
-
return props.placeholder || "";
|
|
161
121
|
});
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
return
|
|
165
|
-
},
|
|
166
|
-
set(value) {
|
|
167
|
-
onInputChange(value);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
const items = computed(() => {
|
|
171
|
-
const normalizedItems = normalizeItems(props.items);
|
|
172
|
-
const filterText = props.multiple ? searchQuery.value : textFieldValue.value;
|
|
173
|
-
if (!props.multiple && modelValue.value && !isSearching.value) {
|
|
174
|
-
return normalizedItems;
|
|
122
|
+
const filteredOptions = computed(() => {
|
|
123
|
+
if (!searchText.value) {
|
|
124
|
+
return normalizedOptions.value;
|
|
175
125
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
126
|
+
const query = searchText.value.toLowerCase();
|
|
127
|
+
return normalizedOptions.value.filter(
|
|
128
|
+
(option) => option.label.toLowerCase().includes(query)
|
|
129
|
+
);
|
|
179
130
|
});
|
|
180
131
|
watch(
|
|
181
|
-
|
|
132
|
+
modelValue,
|
|
182
133
|
(newValue) => {
|
|
183
|
-
if (
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
);
|
|
190
|
-
textFieldValue.value = selectedItem ? String(selectedItem.label) : String(newValue);
|
|
191
|
-
isSearching.value = false;
|
|
192
|
-
} else {
|
|
193
|
-
textFieldValue.value = "";
|
|
194
|
-
isSearching.value = false;
|
|
134
|
+
if (newValue) {
|
|
135
|
+
const selected = normalizedOptions.value.find(
|
|
136
|
+
(option) => option.value === newValue
|
|
137
|
+
);
|
|
138
|
+
if (selected) {
|
|
139
|
+
searchText.value = selected.label;
|
|
195
140
|
}
|
|
141
|
+
} else {
|
|
142
|
+
searchText.value = "";
|
|
196
143
|
}
|
|
197
144
|
},
|
|
198
145
|
{ immediate: true }
|
|
199
146
|
);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
(newItems) => {
|
|
203
|
-
if (props.multiple) {
|
|
204
|
-
modelValue.value = newItems;
|
|
205
|
-
}
|
|
206
|
-
},
|
|
207
|
-
{ deep: true }
|
|
208
|
-
);
|
|
209
|
-
watch(searchQuery, (newValue) => {
|
|
210
|
-
if (newValue.trim()) {
|
|
211
|
-
chipToDelete.value = false;
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
watch(textFieldValue, (newValue) => {
|
|
215
|
-
if (!props.multiple && (!newValue || newValue.trim() === "")) {
|
|
216
|
-
if (modelValue.value !== void 0) {
|
|
217
|
-
modelValue.value = void 0;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
const onSelectItem = (item) => {
|
|
222
|
-
if (!props.multiple) {
|
|
223
|
-
modelValue.value = item.value;
|
|
224
|
-
textFieldValue.value = String(item.label);
|
|
225
|
-
isSearching.value = false;
|
|
226
|
-
isOpenDropdown.value = false;
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
const isItemSelected = (item) => {
|
|
230
|
-
return selectedItems.value.some((selected) => selected.value === item.value);
|
|
231
|
-
};
|
|
232
|
-
const toggleItemSelection = async (item) => {
|
|
233
|
-
const isSelected = selectedItems.value.some(
|
|
234
|
-
(selected) => selected.value === item.value
|
|
235
|
-
);
|
|
236
|
-
if (isSelected) {
|
|
237
|
-
selectedItems.value = selectedItems.value.filter(
|
|
238
|
-
(selected) => selected.value !== item.value
|
|
239
|
-
);
|
|
240
|
-
} else {
|
|
241
|
-
selectedItems.value = [...selectedItems.value, item];
|
|
242
|
-
}
|
|
243
|
-
searchQuery.value = "";
|
|
244
|
-
chipToDelete.value = false;
|
|
245
|
-
await nextTick();
|
|
246
|
-
if (props.multiple && hiddenInputRef.value?.inputRef) {
|
|
247
|
-
hiddenInputRef.value.inputRef.focus();
|
|
248
|
-
}
|
|
249
|
-
};
|
|
250
|
-
const removeSelectedItem = async (item) => {
|
|
251
|
-
selectedItems.value = selectedItems.value.filter(
|
|
252
|
-
(selected) => selected.value !== item.value
|
|
253
|
-
);
|
|
254
|
-
chipToDelete.value = false;
|
|
255
|
-
await nextTick();
|
|
256
|
-
};
|
|
257
|
-
const clearAllSelections = () => {
|
|
258
|
-
selectedItems.value = [];
|
|
259
|
-
searchQuery.value = "";
|
|
260
|
-
chipToDelete.value = false;
|
|
261
|
-
modelValue.value = [];
|
|
262
|
-
textFieldValue.value = "";
|
|
263
|
-
};
|
|
264
|
-
const onFocusInput = () => {
|
|
265
|
-
isOpenDropdown.value = true;
|
|
266
|
-
chipToDelete.value = false;
|
|
267
|
-
if (!props.multiple && modelValue.value) {
|
|
268
|
-
isSearching.value = false;
|
|
269
|
-
}
|
|
147
|
+
const onFocus = () => {
|
|
148
|
+
open.value = true;
|
|
270
149
|
};
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
return;
|
|
274
|
-
} else {
|
|
275
|
-
setTimeout(() => {
|
|
276
|
-
isOpenDropdown.value = false;
|
|
277
|
-
chipToDelete.value = false;
|
|
278
|
-
}, 200);
|
|
279
|
-
}
|
|
150
|
+
const toggleDropdown = () => {
|
|
151
|
+
open.value = !open.value;
|
|
280
152
|
};
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (isSearchQueryEmpty && hasSelectedItems) {
|
|
286
|
-
event.preventDefault();
|
|
287
|
-
if (!chipToDelete.value) {
|
|
288
|
-
chipToDelete.value = true;
|
|
289
|
-
} else {
|
|
290
|
-
const lastItem = selectedItems.value[selectedItems.value.length - 1];
|
|
291
|
-
if (lastItem) {
|
|
292
|
-
removeSelectedItem(lastItem);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
} else {
|
|
296
|
-
chipToDelete.value = false;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
153
|
+
const selectOption = (option) => {
|
|
154
|
+
modelValue.value = option.value;
|
|
155
|
+
searchText.value = option.label;
|
|
156
|
+
open.value = false;
|
|
299
157
|
};
|
|
300
|
-
const
|
|
301
|
-
if (!props.
|
|
302
|
-
|
|
303
|
-
if (!value || value.trim() === "") {
|
|
304
|
-
modelValue.value = void 0;
|
|
305
|
-
isSearching.value = false;
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
if (value !== String(getCurrentSelectedLabel())) {
|
|
309
|
-
isSearching.value = true;
|
|
310
|
-
} else {
|
|
311
|
-
isSearching.value = false;
|
|
312
|
-
}
|
|
158
|
+
const defaultRules = (v) => {
|
|
159
|
+
if (!v && props.required) {
|
|
160
|
+
return `\u0E01\u0E23\u0E38\u0E13\u0E32\u0E23\u0E30\u0E1A\u0E38 ${props.label || "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25"}`;
|
|
313
161
|
}
|
|
162
|
+
return true;
|
|
314
163
|
};
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
const target = event.target;
|
|
318
|
-
const dropdownEl = document.querySelector("[data-dropdown-content]");
|
|
319
|
-
const inputEl = hiddenInputRef.value?.$el || hiddenInputRef.value?.inputRef;
|
|
320
|
-
if (dropdownEl && inputEl && !dropdownEl.contains(target) && !inputEl.contains(target)) {
|
|
321
|
-
isOpenDropdown.value = false;
|
|
322
|
-
chipToDelete.value = false;
|
|
323
|
-
}
|
|
164
|
+
const setErrors = (errMsg) => {
|
|
165
|
+
fieldRef.value?.setErrors(errMsg);
|
|
324
166
|
};
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
document.addEventListener("click", handleClickOutside);
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
onUnmounted(() => {
|
|
331
|
-
if (props.multiple) {
|
|
332
|
-
document.removeEventListener("click", handleClickOutside);
|
|
333
|
-
}
|
|
167
|
+
defineExpose({
|
|
168
|
+
setErrors
|
|
334
169
|
});
|
|
335
170
|
</script>
|
|
@@ -1,29 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { HTMLAttributes } from "vue";
|
|
2
|
+
interface AutocompleteOption {
|
|
3
|
+
label: string;
|
|
3
4
|
value: string | number;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
interface InputAutocompleteProps {
|
|
7
|
+
id?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
class?: HTMLAttributes["class"];
|
|
8
10
|
placeholder?: string;
|
|
9
|
-
|
|
11
|
+
rules?: object | string | Function;
|
|
12
|
+
label?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
disabledErrorMessage?: boolean;
|
|
10
15
|
required?: boolean;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
16
|
+
disabledBorder?: boolean;
|
|
17
|
+
options?: AutocompleteOption[] | string[] | number[];
|
|
18
|
+
}
|
|
19
|
+
type __VLS_Props = InputAutocompleteProps;
|
|
14
20
|
type __VLS_ModelProps = {
|
|
15
|
-
modelValue?: string | number
|
|
21
|
+
modelValue?: string | number;
|
|
16
22
|
};
|
|
17
23
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
18
|
-
declare
|
|
19
|
-
|
|
24
|
+
declare var __VLS_18: {};
|
|
25
|
+
type __VLS_Slots = {} & {
|
|
26
|
+
label?: (props: typeof __VLS_18) => any;
|
|
27
|
+
};
|
|
28
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
29
|
+
setErrors: (errMsg: string[]) => void;
|
|
30
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
31
|
+
"update:modelValue": (value: string | number) => any;
|
|
20
32
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
21
|
-
"onUpdate:modelValue"?: ((value: string | number
|
|
33
|
+
"onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
|
|
22
34
|
}>, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
required: boolean;
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
placeholder: string;
|
|
39
|
+
description: string;
|
|
40
|
+
options: AutocompleteOption[] | string[] | number[];
|
|
41
|
+
disabledErrorMessage: boolean;
|
|
42
|
+
disabledBorder: boolean;
|
|
27
43
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
44
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
28
45
|
declare const _default: typeof __VLS_export;
|
|
29
46
|
export default _default;
|
|
47
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
48
|
+
new (): {
|
|
49
|
+
$slots: S;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
@@ -27,10 +27,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
27
27
|
label: string;
|
|
28
28
|
name: string;
|
|
29
29
|
limit: number;
|
|
30
|
+
disabledErrorMessage: boolean;
|
|
30
31
|
accept: string;
|
|
31
32
|
labelIcon: string;
|
|
32
33
|
disabledDrop: boolean;
|
|
33
|
-
disabledErrorMessage: boolean;
|
|
34
34
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
35
35
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
36
36
|
declare const _default: typeof __VLS_export;
|
|
@@ -27,10 +27,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
27
27
|
label: string;
|
|
28
28
|
name: string;
|
|
29
29
|
limit: number;
|
|
30
|
+
disabledErrorMessage: boolean;
|
|
30
31
|
accept: string;
|
|
31
32
|
labelIcon: string;
|
|
32
33
|
disabledDrop: boolean;
|
|
33
|
-
disabledErrorMessage: boolean;
|
|
34
34
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
35
35
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
36
36
|
declare const _default: typeof __VLS_export;
|
|
@@ -18,8 +18,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
18
18
|
}>, {
|
|
19
19
|
id: string;
|
|
20
20
|
name: string;
|
|
21
|
-
disabledForgotPassword: boolean;
|
|
22
21
|
new: boolean;
|
|
22
|
+
disabledForgotPassword: boolean;
|
|
23
23
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
24
24
|
declare const _default: typeof __VLS_export;
|
|
25
25
|
export default _default;
|
|
@@ -18,8 +18,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
18
18
|
}>, {
|
|
19
19
|
id: string;
|
|
20
20
|
name: string;
|
|
21
|
-
disabledForgotPassword: boolean;
|
|
22
21
|
new: boolean;
|
|
22
|
+
disabledForgotPassword: boolean;
|
|
23
23
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
24
24
|
declare const _default: typeof __VLS_export;
|
|
25
25
|
export default _default;
|
|
@@ -36,8 +36,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
36
36
|
id: string;
|
|
37
37
|
name: string;
|
|
38
38
|
description: string;
|
|
39
|
-
disabledBorder: boolean;
|
|
40
39
|
disabledErrorMessage: boolean;
|
|
40
|
+
disabledBorder: boolean;
|
|
41
41
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
42
42
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
43
43
|
declare const _default: typeof __VLS_export;
|
|
@@ -36,8 +36,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
36
36
|
id: string;
|
|
37
37
|
name: string;
|
|
38
38
|
description: string;
|
|
39
|
-
disabledBorder: boolean;
|
|
40
39
|
disabledErrorMessage: boolean;
|
|
40
|
+
disabledBorder: boolean;
|
|
41
41
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
42
42
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
43
43
|
declare const _default: typeof __VLS_export;
|
|
@@ -12,9 +12,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
12
12
|
color: InputSliderColor;
|
|
13
13
|
fullWidth: boolean;
|
|
14
14
|
label: string;
|
|
15
|
-
step: number;
|
|
16
15
|
min: number;
|
|
17
16
|
max: number;
|
|
17
|
+
step: number;
|
|
18
18
|
lineHeight: number | string;
|
|
19
19
|
appearance: boolean;
|
|
20
20
|
thumbSize: number | string;
|
|
@@ -12,9 +12,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
12
12
|
color: InputSliderColor;
|
|
13
13
|
fullWidth: boolean;
|
|
14
14
|
label: string;
|
|
15
|
-
step: number;
|
|
16
15
|
min: number;
|
|
17
16
|
max: number;
|
|
17
|
+
step: number;
|
|
18
18
|
lineHeight: number | string;
|
|
19
19
|
appearance: boolean;
|
|
20
20
|
thumbSize: number | string;
|
|
@@ -55,8 +55,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
55
55
|
name: string;
|
|
56
56
|
disabled: boolean;
|
|
57
57
|
limit: number;
|
|
58
|
-
disabledBorder: boolean;
|
|
59
58
|
disabledErrorMessage: boolean;
|
|
59
|
+
disabledBorder: boolean;
|
|
60
60
|
readonly: boolean;
|
|
61
61
|
showCounter: boolean;
|
|
62
62
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -55,8 +55,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
55
55
|
name: string;
|
|
56
56
|
disabled: boolean;
|
|
57
57
|
limit: number;
|
|
58
|
-
disabledBorder: boolean;
|
|
59
58
|
disabledErrorMessage: boolean;
|
|
59
|
+
disabledBorder: boolean;
|
|
60
60
|
readonly: boolean;
|
|
61
61
|
showCounter: boolean;
|
|
62
62
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -27,9 +27,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
27
27
|
disabled: boolean;
|
|
28
28
|
disabledPadding: boolean;
|
|
29
29
|
rows: number | string;
|
|
30
|
-
resize: "none" | "both" | "horizontal" | "vertical";
|
|
31
|
-
disabledBorder: boolean;
|
|
32
30
|
disabledErrorMessage: boolean;
|
|
31
|
+
disabledBorder: boolean;
|
|
32
|
+
resize: "none" | "both" | "horizontal" | "vertical";
|
|
33
33
|
readonly: boolean;
|
|
34
34
|
showCounter: boolean;
|
|
35
35
|
standalone: boolean;
|
|
@@ -27,9 +27,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
27
27
|
disabled: boolean;
|
|
28
28
|
disabledPadding: boolean;
|
|
29
29
|
rows: number | string;
|
|
30
|
-
resize: "none" | "both" | "horizontal" | "vertical";
|
|
31
|
-
disabledBorder: boolean;
|
|
32
30
|
disabledErrorMessage: boolean;
|
|
31
|
+
disabledBorder: boolean;
|
|
32
|
+
resize: "none" | "both" | "horizontal" | "vertical";
|
|
33
33
|
readonly: boolean;
|
|
34
34
|
showCounter: boolean;
|
|
35
35
|
standalone: boolean;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { reactiveOmit } from "@vueuse/core";
|
|
3
|
-
import { MagnifyingGlassIcon } from "@radix-icons/vue";
|
|
4
3
|
import { ListboxFilter, useForwardProps } from "reka-ui";
|
|
5
4
|
import { cn } from "@/runtime/plugins/shadcn";
|
|
6
5
|
import { useCommand } from ".";
|
|
@@ -25,13 +24,18 @@ const { filterState } = useCommand();
|
|
|
25
24
|
data-slot="command-input-wrapper"
|
|
26
25
|
class="flex h-9 items-center gap-2 border-b px-3"
|
|
27
26
|
>
|
|
28
|
-
<MagnifyingGlassIcon class="size-4 shrink-0 opacity-50" />
|
|
27
|
+
<!-- <MagnifyingGlassIcon class="size-4 shrink-0 opacity-50" /> -->
|
|
29
28
|
<ListboxFilter
|
|
30
29
|
v-bind="{ ...forwardedProps, ...$attrs }"
|
|
31
30
|
v-model="filterState.search"
|
|
32
31
|
data-slot="command-input"
|
|
33
32
|
auto-focus
|
|
34
|
-
:class="
|
|
33
|
+
:class="
|
|
34
|
+
cn(
|
|
35
|
+
'placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
|
|
36
|
+
props.class
|
|
37
|
+
)
|
|
38
|
+
"
|
|
35
39
|
/>
|
|
36
40
|
</div>
|
|
37
41
|
</template>
|