@antify/ui 1.1.0 → 1.3.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/components/AntAccordion.vue +15 -7
- package/dist/components/AntAccordionItem.vue +19 -5
- package/dist/components/AntAlert.vue +8 -6
- package/dist/components/AntDropdown.vue +50 -36
- package/dist/components/AntIcon.vue +8 -6
- package/dist/components/AntKeycap.vue +10 -10
- package/dist/components/AntListGroup.vue +5 -3
- package/dist/components/AntModal.vue +17 -7
- package/dist/components/AntPopover.vue +118 -42
- package/dist/components/AntSkeleton.vue +1 -1
- package/dist/components/AntTooltip.vue +127 -80
- package/dist/components/__stories/AntAccordion.stories.js +12 -3
- package/dist/components/__stories/AntAccordion.stories.mjs +12 -3
- package/dist/components/__stories/AntDropdown.stories.js +27 -23
- package/dist/components/__stories/AntDropdown.stories.mjs +26 -22
- package/dist/components/__stories/AntListGroup.stories.js +1 -1
- package/dist/components/__stories/AntListGroup.stories.mjs +1 -1
- package/dist/components/__stories/AntModal.stories.js +2 -1
- package/dist/components/__stories/AntModal.stories.mjs +2 -1
- package/dist/components/__stories/AntPopover.stories.js +22 -21
- package/dist/components/__stories/AntPopover.stories.mjs +22 -20
- package/dist/components/__stories/AntTooltip.stories.d.ts +0 -10
- package/dist/components/__stories/AntTooltip.stories.js +34 -212
- package/dist/components/__stories/AntTooltip.stories.mjs +29 -193
- package/dist/components/buttons/AntButton.vue +41 -44
- package/dist/components/crud/AntCrud.vue +1 -1
- package/dist/components/crud/AntCrudDetailActions.vue +1 -0
- package/dist/components/crud/AntCrudDetailNav.vue +1 -0
- package/dist/components/crud/AntCrudTableFilter.vue +20 -18
- package/dist/components/forms/AntField.vue +7 -2
- package/dist/components/forms/__stories/AntField.stories.js +0 -16
- package/dist/components/forms/__stories/AntField.stories.mjs +2 -16
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.js +7 -7
- package/dist/components/index.mjs +2 -2
- package/dist/components/inputs/AntCheckbox.vue +25 -6
- package/dist/components/inputs/AntDateInput.vue +1 -1
- package/dist/components/inputs/AntRadio.vue +2 -1
- package/dist/components/inputs/AntSelect.vue +25 -22
- package/dist/components/inputs/AntSwitch.vue +2 -7
- package/dist/components/inputs/AntTagInput.vue +91 -114
- package/dist/components/inputs/AntTextarea.vue +16 -4
- package/dist/components/inputs/Elements/AntBaseInput.vue +2 -2
- package/dist/components/inputs/Elements/{AntDropDown.vue → AntSelectMenu.vue} +84 -40
- package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.d.ts +0 -1
- package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.js +1 -29
- package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.mjs +0 -22
- package/dist/components/inputs/Elements/index.d.ts +2 -1
- package/dist/components/inputs/Elements/index.js +7 -0
- package/dist/components/inputs/Elements/index.mjs +3 -1
- package/dist/components/inputs/__stories/AntCheckbox.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntCheckbox.stories.js +1 -43
- package/dist/components/inputs/__stories/AntCheckbox.stories.mjs +0 -35
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.js +1 -31
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.mjs +0 -28
- package/dist/components/inputs/__stories/AntDateInput.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntDateInput.stories.js +1 -32
- package/dist/components/inputs/__stories/AntDateInput.stories.mjs +0 -28
- package/dist/components/inputs/__stories/AntNumberInput.stories.d.ts +0 -2
- package/dist/components/inputs/__stories/AntNumberInput.stories.js +1 -65
- package/dist/components/inputs/__stories/AntNumberInput.stories.mjs +1 -54
- package/dist/components/inputs/__stories/AntPasswordInput.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntPasswordInput.stories.js +1 -35
- package/dist/components/inputs/__stories/AntPasswordInput.stories.mjs +0 -25
- package/dist/components/inputs/__stories/AntRadioGroup.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntRadioGroup.stories.js +1 -47
- package/dist/components/inputs/__stories/AntRadioGroup.stories.mjs +0 -46
- package/dist/components/inputs/__stories/AntRangeSlider.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntRangeSlider.stories.js +1 -33
- package/dist/components/inputs/__stories/AntRangeSlider.stories.mjs +1 -28
- package/dist/components/inputs/__stories/AntSelect.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntSelect.stories.js +18 -46
- package/dist/components/inputs/__stories/AntSelect.stories.mjs +16 -47
- package/dist/components/inputs/__stories/AntSwitch.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntSwitch.stories.js +1 -42
- package/dist/components/inputs/__stories/AntSwitch.stories.mjs +1 -37
- package/dist/components/inputs/__stories/AntSwitcher.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntSwitcher.stories.js +1 -51
- package/dist/components/inputs/__stories/AntSwitcher.stories.mjs +1 -51
- package/dist/components/inputs/__stories/AntTagInput.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntTagInput.stories.js +1 -35
- package/dist/components/inputs/__stories/AntTagInput.stories.mjs +0 -33
- package/dist/components/inputs/__stories/AntTextInput.stories.d.ts +0 -2
- package/dist/components/inputs/__stories/AntTextInput.stories.js +2 -107
- package/dist/components/inputs/__stories/AntTextInput.stories.mjs +1 -104
- package/dist/components/inputs/__stories/AntTextarea.stories.d.ts +0 -2
- package/dist/components/inputs/__stories/AntTextarea.stories.js +7 -66
- package/dist/components/inputs/__stories/AntTextarea.stories.mjs +6 -55
- package/dist/components/inputs/__stories/AntUnitInput.stories.d.ts +0 -2
- package/dist/components/inputs/__stories/AntUnitInput.stories.js +1 -61
- package/dist/components/inputs/__stories/AntUnitInput.stories.mjs +0 -53
- package/dist/components/table/AntTable.vue +17 -15
- package/dist/components/table/AntTd.vue +1 -2
- package/dist/components/table/__stories/AntTable.stories.js +7 -14
- package/dist/components/table/__stories/AntTable.stories.mjs +7 -15
- package/dist/components/tabs/AntTabItem.vue +24 -7
- package/dist/components/tabs/AntTabs.vue +14 -2
- package/dist/components/tabs/__stories/AntTabs.stories.d.ts +1 -0
- package/dist/components/tabs/__stories/AntTabs.stories.js +112 -6
- package/dist/components/tabs/__stories/AntTabs.stories.mjs +120 -5
- package/dist/components/tabs/__types/AntTabItem.types.d.ts +2 -0
- package/dist/components/tabs/__types/AntTabItem.types.js +1 -0
- package/dist/components/tabs/__types/AntTabItem.types.mjs +1 -0
- package/package.json +2 -1
|
@@ -8,7 +8,7 @@ import {computed, onMounted, type Ref, ref, watch} from 'vue';
|
|
|
8
8
|
import AntTag from '../AntTag.vue';
|
|
9
9
|
import AntIcon from '../AntIcon.vue';
|
|
10
10
|
import {AntTagSize, IconSize} from '../__types';
|
|
11
|
-
import
|
|
11
|
+
import AntSelectMenu from './Elements/AntSelectMenu.vue';
|
|
12
12
|
import AntSkeleton from '../AntSkeleton.vue';
|
|
13
13
|
import {vOnClickOutside} from '@vueuse/components';
|
|
14
14
|
import {AntTagInputSize} from './__types/AntTagInput.types';
|
|
@@ -61,7 +61,6 @@ const dropDownOpen = ref(false);
|
|
|
61
61
|
const hasInputState = computed(() => props.skeleton || props.readonly || props.disabled);
|
|
62
62
|
const focusedDropDownItem: Ref<string | number | null> = ref(null);
|
|
63
63
|
const tagInput = ref('');
|
|
64
|
-
const filteredOptions = ref(props.options);
|
|
65
64
|
const inputRef: Ref<HTMLElement | null> = ref(null);
|
|
66
65
|
const inputContainerClasses = computed(() => {
|
|
67
66
|
const variants: Record<InputState, string> = {
|
|
@@ -89,7 +88,6 @@ const inputContainerClasses = computed(() => {
|
|
|
89
88
|
'rounded-none': props.grouped === Grouped.center,
|
|
90
89
|
'rounded-tl-none rounded-bl-none rounded-tr-md rounded-br-md': props.grouped === Grouped.right,
|
|
91
90
|
'rounded-md': props.grouped === Grouped.none,
|
|
92
|
-
'rounded-bl-none rounded-br-none': dropDownOpen.value && (!props.options || props.options.length > 0) && !props.readonly,
|
|
93
91
|
'invisible': props.skeleton,
|
|
94
92
|
};
|
|
95
93
|
});
|
|
@@ -119,13 +117,23 @@ const skeletonGrouped = computed(() => {
|
|
|
119
117
|
return Grouped.left;
|
|
120
118
|
}
|
|
121
119
|
});
|
|
120
|
+
const filteredOptions = computed(() => {
|
|
121
|
+
return props.options.filter(option => {
|
|
122
|
+
// Remove all elements that are in modelValue from the filtered options
|
|
123
|
+
if (_modelValue.value && !props.allowDuplicates) {
|
|
124
|
+
return !_modelValue.value?.includes(option.value);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return option.label.toLowerCase().includes(tagInput.value.toLowerCase())
|
|
128
|
+
});
|
|
129
|
+
})
|
|
122
130
|
|
|
123
131
|
function onClickOutside() {
|
|
124
132
|
if (!dropDownOpen.value) {
|
|
125
133
|
return;
|
|
126
134
|
}
|
|
127
|
-
|
|
128
|
-
dropDownOpen.value = false;
|
|
135
|
+
console.log("click outside");
|
|
136
|
+
// dropDownOpen.value = false;
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
async function checkCreateTag(item: string): Promise<void> {
|
|
@@ -153,14 +161,13 @@ function addTagFromOptions(item: string | number) {
|
|
|
153
161
|
addTag(item);
|
|
154
162
|
|
|
155
163
|
if (props.autoCloseAfterSelection) {
|
|
164
|
+
console.log("HIER");
|
|
156
165
|
dropDownOpen.value = false;
|
|
157
166
|
}
|
|
158
167
|
}
|
|
159
168
|
}
|
|
160
169
|
|
|
161
170
|
function addTag(tagValue: string | number): void {
|
|
162
|
-
_modelValue.value = _modelValue.value || [];
|
|
163
|
-
|
|
164
171
|
if (!props.allowDuplicates && _modelValue.value?.includes(tagValue) || !tagValue) {
|
|
165
172
|
return;
|
|
166
173
|
}
|
|
@@ -172,53 +179,22 @@ function addTag(tagValue: string | number): void {
|
|
|
172
179
|
}
|
|
173
180
|
|
|
174
181
|
tagInput.value = '';
|
|
175
|
-
|
|
176
|
-
filterDropDown();
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
function removeLastTag() {
|
|
180
185
|
if (tagInput.value === '' && Array.isArray(_modelValue.value) && _modelValue.value.length > 0) {
|
|
181
186
|
_modelValue.value.splice(-1, 1);
|
|
182
|
-
|
|
183
|
-
filterDropDown();
|
|
184
187
|
}
|
|
185
188
|
}
|
|
186
189
|
|
|
187
190
|
function removeTag(tag: string | number) {
|
|
188
191
|
if (_modelValue.value && !props.disabled && !props.skeleton && !props.readonly) {
|
|
189
192
|
_modelValue.value.splice(_modelValue.value.findIndex((_value) => _value === tag), 1);
|
|
190
|
-
|
|
191
|
-
filterDropDown();
|
|
192
193
|
}
|
|
193
194
|
}
|
|
194
195
|
|
|
195
196
|
function changeFocus() {
|
|
196
|
-
if (props.openOnFocus) {
|
|
197
|
-
dropDownOpen.value = true;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function filterDropDown() {
|
|
202
|
-
if (!props.options) {
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (props.allowCreate) {
|
|
207
|
-
focusedDropDownItem.value = null;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
197
|
dropDownOpen.value = true;
|
|
211
|
-
|
|
212
|
-
filteredOptions.value = props.options.filter(option => option.label.toLowerCase().includes(tagInput.value.toLowerCase()));
|
|
213
|
-
|
|
214
|
-
// Remove all elements that are in modelValue from the filtered options
|
|
215
|
-
if (_modelValue.value && !props.allowDuplicates) {
|
|
216
|
-
filteredOptions.value = filteredOptions.value.filter(option => !_modelValue.value?.includes(option.value));
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (!props.allowCreate && filteredOptions.value.length > 0) {
|
|
220
|
-
focusedDropDownItem.value = filteredOptions.value[0]?.value;
|
|
221
|
-
}
|
|
222
198
|
}
|
|
223
199
|
|
|
224
200
|
function onBlur(e: FocusEvent) {
|
|
@@ -251,89 +227,90 @@ onMounted(() => {
|
|
|
251
227
|
</script>
|
|
252
228
|
|
|
253
229
|
<template>
|
|
254
|
-
<
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
<div
|
|
264
|
-
v-on-click-outside="onClickOutside"
|
|
265
|
-
class="relative w-full"
|
|
230
|
+
<div>
|
|
231
|
+
<AntField
|
|
232
|
+
:label="label"
|
|
233
|
+
:size="size as unknown as Size"
|
|
234
|
+
:skeleton="_skeleton"
|
|
235
|
+
:description="description"
|
|
236
|
+
:state="state"
|
|
237
|
+
:expanded="expanded"
|
|
238
|
+
:messages="messages"
|
|
266
239
|
>
|
|
267
|
-
<AntSkeleton
|
|
268
|
-
v-if="skeleton"
|
|
269
|
-
absolute
|
|
270
|
-
rounded
|
|
271
|
-
:grouped="skeletonGrouped"
|
|
272
|
-
/>
|
|
273
|
-
|
|
274
240
|
<div
|
|
275
|
-
|
|
276
|
-
class="w-full flex items-center"
|
|
241
|
+
class="relative w-full"
|
|
277
242
|
>
|
|
243
|
+
<AntSkeleton
|
|
244
|
+
v-if="skeleton"
|
|
245
|
+
absolute
|
|
246
|
+
rounded
|
|
247
|
+
:grouped="skeletonGrouped"
|
|
248
|
+
/>
|
|
249
|
+
|
|
278
250
|
<div
|
|
279
|
-
class="
|
|
251
|
+
:class="inputContainerClasses"
|
|
252
|
+
class="w-full flex items-center"
|
|
253
|
+
v-on-click-outside="onClickOutside"
|
|
280
254
|
>
|
|
281
|
-
<
|
|
282
|
-
|
|
283
|
-
:key="`tag-input-tag-${index}`"
|
|
284
|
-
:size="AntTagSize.xs3"
|
|
285
|
-
:state="state as unknown as TagState"
|
|
286
|
-
:dismiss="!readonly"
|
|
287
|
-
@close="removeTag(tag)"
|
|
255
|
+
<div
|
|
256
|
+
class="flex gap-2.5 items-center"
|
|
288
257
|
>
|
|
289
|
-
|
|
290
|
-
|
|
258
|
+
<AntTag
|
|
259
|
+
v-for="(tag, index) in _modelValue"
|
|
260
|
+
:key="`tag-input-tag-${index}`"
|
|
261
|
+
:size="AntTagSize.xs3"
|
|
262
|
+
:state="state as unknown as TagState"
|
|
263
|
+
:dismiss="!readonly"
|
|
264
|
+
@close="removeTag(tag)"
|
|
265
|
+
>
|
|
266
|
+
{{ options.find((option: SelectOption) => option.value === tag)?.label }}
|
|
267
|
+
</AntTag>
|
|
268
|
+
</div>
|
|
269
|
+
|
|
270
|
+
<!-- Input -->
|
|
271
|
+
<div class="flex items-center w-32 shrink grow">
|
|
272
|
+
<AntIcon
|
|
273
|
+
:icon="icon"
|
|
274
|
+
:size="size === AntTagInputSize.sm ? IconSize.xs : IconSize.sm"
|
|
275
|
+
/>
|
|
276
|
+
|
|
277
|
+
<input
|
|
278
|
+
ref="inputRef"
|
|
279
|
+
v-model="tagInput"
|
|
280
|
+
type="text"
|
|
281
|
+
:placeholder="placeholder"
|
|
282
|
+
:class="inputClasses"
|
|
283
|
+
:disabled="disabled"
|
|
284
|
+
:readonly="readonly"
|
|
285
|
+
@focus="changeFocus"
|
|
286
|
+
@keydown.delete="removeLastTag"
|
|
287
|
+
@keydown.enter.prevent="checkCreateTag(tagInput)"
|
|
288
|
+
@blur="onBlur"
|
|
289
|
+
/>
|
|
290
|
+
</div>
|
|
291
291
|
</div>
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
/>
|
|
314
|
-
</div>
|
|
293
|
+
<AntSelectMenu
|
|
294
|
+
v-if="!disabled && !readonly"
|
|
295
|
+
v-model:focused="focusedDropDownItem"
|
|
296
|
+
v-model:open="dropDownOpen"
|
|
297
|
+
:model-value="null"
|
|
298
|
+
:auto-select-first-on-open="!allowCreate"
|
|
299
|
+
:options="filteredOptions"
|
|
300
|
+
:input-ref="inputRef"
|
|
301
|
+
:size="size as unknown as Size"
|
|
302
|
+
:state="state"
|
|
303
|
+
:focus-on-open="false"
|
|
304
|
+
:close-on-select-item="false"
|
|
305
|
+
@select-element="addTagFromOptions"
|
|
306
|
+
>
|
|
307
|
+
<template #empty>
|
|
308
|
+
<span v-if="allowCreate">
|
|
309
|
+
No tag found, create now
|
|
310
|
+
</span>
|
|
311
|
+
</template>
|
|
312
|
+
</AntSelectMenu>
|
|
315
313
|
</div>
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
v-if="filteredOptions && !disabled && !readonly"
|
|
319
|
-
ref="dropDownRef"
|
|
320
|
-
v-model:focused="focusedDropDownItem"
|
|
321
|
-
v-model:open="dropDownOpen"
|
|
322
|
-
:model-value="null"
|
|
323
|
-
:auto-select-first-on-open="!allowCreate"
|
|
324
|
-
:options="filteredOptions"
|
|
325
|
-
:input-ref="inputRef"
|
|
326
|
-
:size="size as unknown as Size"
|
|
327
|
-
:state="state"
|
|
328
|
-
:focus-on-open="false"
|
|
329
|
-
@select-element="addTagFromOptions"
|
|
330
|
-
>
|
|
331
|
-
<template #empty>
|
|
332
|
-
<span v-if="allowCreate">
|
|
333
|
-
No tag found, create now
|
|
334
|
-
</span>
|
|
335
|
-
</template>
|
|
336
|
-
</AntDropDown>
|
|
337
|
-
</div>
|
|
338
|
-
</AntField>
|
|
314
|
+
</AntField>
|
|
315
|
+
</div>
|
|
339
316
|
</template>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import {computed, onMounted, watch} from 'vue';
|
|
2
|
+
import {computed, onMounted, ref, watch} from 'vue';
|
|
3
3
|
import {Size} from '../../enums/Size.enum';
|
|
4
4
|
import AntSkeleton from '../AntSkeleton.vue';
|
|
5
5
|
import AntIcon from '../AntIcon.vue';
|
|
@@ -36,6 +36,7 @@ const props = withDefaults(defineProps<{
|
|
|
36
36
|
limiter?: boolean;
|
|
37
37
|
max?: number;
|
|
38
38
|
messages?: string[];
|
|
39
|
+
resize?: boolean;
|
|
39
40
|
}>(), {
|
|
40
41
|
state: InputState.base,
|
|
41
42
|
disabled: false,
|
|
@@ -45,8 +46,10 @@ const props = withDefaults(defineProps<{
|
|
|
45
46
|
grouped: Grouped.none,
|
|
46
47
|
showIcon: true,
|
|
47
48
|
limiter: false,
|
|
49
|
+
resize: true,
|
|
48
50
|
messages: () => []
|
|
49
51
|
});
|
|
52
|
+
|
|
50
53
|
const _modelValue = useVModel(props, 'modelValue', emit);
|
|
51
54
|
const hasInputState = computed(() => props.skeleton || props.readonly || props.disabled);
|
|
52
55
|
const icons = {
|
|
@@ -67,7 +70,7 @@ const inputClasses = computed(() => {
|
|
|
67
70
|
};
|
|
68
71
|
|
|
69
72
|
return {
|
|
70
|
-
'block transition-colors relative border-none outline w-full focus:z-10': true,
|
|
73
|
+
'block transition-colors relative border-none outline w-full focus:z-10 h-full text-black': true,
|
|
71
74
|
'outline-offset-[-1px] outline-1 focus:outline-offset-[-1px] focus:outline-1': true,
|
|
72
75
|
'disabled:opacity-50 disabled:cursor-not-allowed': props.disabled,
|
|
73
76
|
[variants[props.state]]: true,
|
|
@@ -90,7 +93,8 @@ const inputClasses = computed(() => {
|
|
|
90
93
|
'rounded-none': props.grouped === Grouped.center,
|
|
91
94
|
'rounded-tl-none rounded-bl-none rounded-tr-md rounded-br-md': props.grouped === Grouped.right,
|
|
92
95
|
'rounded-md': props.grouped === Grouped.none,
|
|
93
|
-
'invisible': props.skeleton
|
|
96
|
+
'invisible': props.skeleton,
|
|
97
|
+
'resize-none': !props.resize
|
|
94
98
|
};
|
|
95
99
|
});
|
|
96
100
|
const iconColor = computed(() => {
|
|
@@ -108,6 +112,7 @@ const iconColor = computed(() => {
|
|
|
108
112
|
});
|
|
109
113
|
const _wrapperClass = computed(() => classesToObjectSyntax(props.wrapperClass));
|
|
110
114
|
const icon = computed(() => icons[props.state]);
|
|
115
|
+
const textAreaRef = ref();
|
|
111
116
|
const getIconSize = computed(() => {
|
|
112
117
|
if (props.size === Size.xs || props.size === Size.xs2) {
|
|
113
118
|
return IconSize.xs;
|
|
@@ -141,6 +146,11 @@ function onBlur(e: FocusEvent) {
|
|
|
141
146
|
emit('validate', props.modelValue);
|
|
142
147
|
emit('blur', e);
|
|
143
148
|
}
|
|
149
|
+
|
|
150
|
+
defineExpose({
|
|
151
|
+
getTextAreaRef: () => textAreaRef.value
|
|
152
|
+
});
|
|
153
|
+
|
|
144
154
|
</script>
|
|
145
155
|
|
|
146
156
|
<template>
|
|
@@ -153,9 +163,10 @@ function onBlur(e: FocusEvent) {
|
|
|
153
163
|
:limiter-max-value="limiter && max !== undefined ? max : undefined"
|
|
154
164
|
:limiter-value="limiter ? _modelValue?.length : undefined"
|
|
155
165
|
:messages="messages"
|
|
166
|
+
:expanded-height="!resize"
|
|
156
167
|
>
|
|
157
168
|
<div
|
|
158
|
-
class="block relative w-full"
|
|
169
|
+
class="block relative w-full h-full"
|
|
159
170
|
:class="{...{'-mr-px': grouped !== Grouped.none}, ..._wrapperClass}"
|
|
160
171
|
>
|
|
161
172
|
<textarea
|
|
@@ -164,6 +175,7 @@ function onBlur(e: FocusEvent) {
|
|
|
164
175
|
:placeholder="placeholder !== undefined ? placeholder : label"
|
|
165
176
|
:disabled="disabled || skeleton"
|
|
166
177
|
:readonly="readonly"
|
|
178
|
+
ref="textAreaRef"
|
|
167
179
|
v-bind="$attrs"
|
|
168
180
|
@blur="onBlur"
|
|
169
181
|
/>
|
|
@@ -68,7 +68,7 @@ const inputClasses = computed(() => {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
return {
|
|
71
|
-
'block transition-colors relative border-none outline w-full focus:z-10 text-black': true,
|
|
71
|
+
'block transition-colors relative border-none outline w-full focus:z-10 text-black font-regular': true,
|
|
72
72
|
'outline-offset-[-1px] outline-1 focus:outline-offset-[-1px] focus:outline-1': true,
|
|
73
73
|
'disabled:opacity-50 disabled:cursor-not-allowed': props.disabled,
|
|
74
74
|
'text-right': props.type === BaseInputType.number,
|
|
@@ -235,7 +235,7 @@ function onClickClearIcon() {
|
|
|
235
235
|
<div
|
|
236
236
|
v-if="(nullable && _modelValue !== null && _modelValue !== '') || (showIcon && icon) || hasSlotContent(slot['icon-right'])"
|
|
237
237
|
class="absolute h-full flex items-center justify-center right-0 top-0 transition-all z-20"
|
|
238
|
-
:class="{'w-6': size === Size.xs2, 'w-7': size === Size.
|
|
238
|
+
:class="{'w-6': size === Size.xs2, 'w-7': size === Size.xs, 'w-8': size === Size.sm, 'w-9': size === Size.md, 'w-10': size === Size.lg}"
|
|
239
239
|
>
|
|
240
240
|
<slot name="icon-right">
|
|
241
241
|
<AntIcon
|
|
@@ -6,12 +6,13 @@
|
|
|
6
6
|
* Fix overflow bug (See Ellipsis Text story)
|
|
7
7
|
* TODO:: if the dropdown is open and the user types something, the element with a matching value should be focused.
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
9
|
import {computed, nextTick, onMounted, onUnmounted, ref, watch} from 'vue';
|
|
11
10
|
import {InputState, Size} from '../../../enums';
|
|
12
11
|
import type {SelectOption} from '../__types';
|
|
13
|
-
import {useVModel} from '@vueuse/core';
|
|
12
|
+
import {useElementSize, useVModel, onClickOutside} from '@vueuse/core';
|
|
14
13
|
import type {Validator} from '@antify/validate';
|
|
14
|
+
import {autoUpdate, flip, offset, useFloating} from "@floating-ui/vue";
|
|
15
|
+
import {vOnClickOutside} from '@vueuse/components';
|
|
15
16
|
|
|
16
17
|
const emit = defineEmits(['update:open', 'update:modelValue', 'update:focused', 'selectElement']);
|
|
17
18
|
const props = withDefaults(defineProps<{
|
|
@@ -25,17 +26,39 @@ const props = withDefaults(defineProps<{
|
|
|
25
26
|
inputRef?: HTMLElement | null;
|
|
26
27
|
closeOnEnter?: boolean;
|
|
27
28
|
autoSelectFirstOnOpen?: boolean;
|
|
29
|
+
closeOnSelectItem?: boolean;
|
|
28
30
|
}>(), {
|
|
29
31
|
state: InputState.base,
|
|
30
32
|
focusOnOpen: true,
|
|
31
33
|
closeOnEnter: false,
|
|
32
|
-
autoSelectFirstOnOpen: true
|
|
34
|
+
autoSelectFirstOnOpen: true,
|
|
35
|
+
closeOnSelectItem: true,
|
|
36
|
+
});
|
|
37
|
+
const reference = ref<HTMLElement | null | undefined>(props.inputRef)
|
|
38
|
+
const width = useElementSize(reference);
|
|
39
|
+
const floating = ref<HTMLElement | null>(null)
|
|
40
|
+
const {floatingStyles, middlewareData, placement} = useFloating(reference, floating, {
|
|
41
|
+
placement: 'bottom',
|
|
42
|
+
whileElementsMounted: autoUpdate,
|
|
43
|
+
middleware: [
|
|
44
|
+
offset(8),
|
|
45
|
+
flip({
|
|
46
|
+
fallbackPlacements: ['top'],
|
|
47
|
+
}),
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
onClickOutside(floating, () => {
|
|
52
|
+
if (!props.open) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
emit('update:open', false);
|
|
33
57
|
});
|
|
34
58
|
|
|
35
59
|
const _modelValue = useVModel(props, 'modelValue', emit);
|
|
36
60
|
const isOpen = useVModel(props, 'open', emit);
|
|
37
61
|
const focusedDropDownItem = useVModel(props, 'focused', emit);
|
|
38
|
-
|
|
39
62
|
const dropdownClasses = computed(() => {
|
|
40
63
|
const variants: Record<InputState, string> = {
|
|
41
64
|
[InputState.base]: 'bg-neutral-300 border-neutral-300',
|
|
@@ -46,11 +69,9 @@ const dropdownClasses = computed(() => {
|
|
|
46
69
|
};
|
|
47
70
|
|
|
48
71
|
return {
|
|
49
|
-
'
|
|
50
|
-
'rounded-
|
|
72
|
+
'w-full border flex flex-col gap-px outline-none -mt-px overflow-hidden shadow-md z-[90]': true,
|
|
73
|
+
'rounded-md': true,
|
|
51
74
|
[variants[props.state]]: true,
|
|
52
|
-
// Size
|
|
53
|
-
'text-sm': props.size === Size.sm || props.size === Size.md
|
|
54
75
|
};
|
|
55
76
|
});
|
|
56
77
|
const dropDownItemClasses = computed(() => {
|
|
@@ -66,8 +87,11 @@ const dropDownItemClasses = computed(() => {
|
|
|
66
87
|
'select-none text-ellipsis overflow-hidden whitespace-nowrap': true,
|
|
67
88
|
[variants[props.state]]: true,
|
|
68
89
|
// Size
|
|
69
|
-
'p-1
|
|
70
|
-
'p-
|
|
90
|
+
'p-1 text-xs': props.size === Size.xs2,
|
|
91
|
+
'p-1.5 text-xs': props.size === Size.xs,
|
|
92
|
+
'p-1.5 text-sm': props.size === Size.sm,
|
|
93
|
+
'p-2 text-sm': props.size === Size.md,
|
|
94
|
+
'p-2.5 text-sm': props.size === Size.lg,
|
|
71
95
|
};
|
|
72
96
|
});
|
|
73
97
|
|
|
@@ -86,12 +110,12 @@ watch(isOpen, () => {
|
|
|
86
110
|
|
|
87
111
|
onMounted(() => {
|
|
88
112
|
nextTick(() => {
|
|
89
|
-
|
|
113
|
+
reference.value?.addEventListener('keydown', onKeyDownDropDown);
|
|
90
114
|
});
|
|
91
115
|
});
|
|
92
116
|
|
|
93
117
|
onUnmounted(() => {
|
|
94
|
-
|
|
118
|
+
reference.value?.removeEventListener('keydown', onKeyDownDropDown);
|
|
95
119
|
});
|
|
96
120
|
|
|
97
121
|
function onKeyDownDropDown(e: KeyboardEvent) {
|
|
@@ -100,6 +124,10 @@ function onKeyDownDropDown(e: KeyboardEvent) {
|
|
|
100
124
|
isOpen.value = false;
|
|
101
125
|
}
|
|
102
126
|
|
|
127
|
+
if (!isOpen.value) {
|
|
128
|
+
isOpen.value = true
|
|
129
|
+
}
|
|
130
|
+
|
|
103
131
|
emit('selectElement', focusedDropDownItem.value);
|
|
104
132
|
}
|
|
105
133
|
|
|
@@ -108,6 +136,7 @@ function onKeyDownDropDown(e: KeyboardEvent) {
|
|
|
108
136
|
}
|
|
109
137
|
|
|
110
138
|
if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
|
|
139
|
+
e.preventDefault()
|
|
111
140
|
isOpen.value = true;
|
|
112
141
|
|
|
113
142
|
const index = props.options.findIndex(option => option.value === focusedDropDownItem.value);
|
|
@@ -121,6 +150,7 @@ function onKeyDownDropDown(e: KeyboardEvent) {
|
|
|
121
150
|
}
|
|
122
151
|
|
|
123
152
|
if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
|
|
153
|
+
e.preventDefault()
|
|
124
154
|
isOpen.value = true;
|
|
125
155
|
|
|
126
156
|
const index = props.options.findIndex(option => option.value === focusedDropDownItem.value);
|
|
@@ -138,21 +168,24 @@ function onKeyDownDropDown(e: KeyboardEvent) {
|
|
|
138
168
|
|
|
139
169
|
function getActiveDropDownItemClasses(option: SelectOption) {
|
|
140
170
|
const variants: Record<InputState, string> = {
|
|
141
|
-
[InputState.base]: 'bg-neutral-
|
|
142
|
-
[InputState.success]: 'bg-success-
|
|
143
|
-
[InputState.info]: 'bg-info-
|
|
144
|
-
[InputState.warning]: 'bg-warning-
|
|
145
|
-
[InputState.danger]: 'bg-danger-
|
|
171
|
+
[InputState.base]: '!bg-neutral-100',
|
|
172
|
+
[InputState.success]: 'bg-success-200',
|
|
173
|
+
[InputState.info]: 'bg-info-200',
|
|
174
|
+
[InputState.warning]: 'bg-warning-200',
|
|
175
|
+
[InputState.danger]: 'bg-danger-200',
|
|
146
176
|
};
|
|
147
177
|
|
|
148
|
-
return option.value === focusedDropDownItem.value ? {[variants[props.state]]: true} : {};
|
|
178
|
+
return option.value === focusedDropDownItem.value ? {'bg-white': false, [variants[props.state]]: true} : {};
|
|
149
179
|
}
|
|
150
180
|
|
|
151
181
|
function onClickDropDownItem(e: MouseEvent, value: string | number | null) {
|
|
152
182
|
e.preventDefault();
|
|
153
|
-
|
|
183
|
+
reference.value?.focus();
|
|
184
|
+
|
|
185
|
+
if (props.closeOnSelectItem) {
|
|
186
|
+
isOpen.value = false;
|
|
187
|
+
}
|
|
154
188
|
|
|
155
|
-
isOpen.value = false;
|
|
156
189
|
emit('selectElement', value);
|
|
157
190
|
_modelValue.value = value;
|
|
158
191
|
}
|
|
@@ -164,26 +197,37 @@ watch(_modelValue, (val) => {
|
|
|
164
197
|
|
|
165
198
|
<template>
|
|
166
199
|
<div
|
|
167
|
-
|
|
168
|
-
|
|
200
|
+
ref="reference"
|
|
201
|
+
class="relative"
|
|
169
202
|
>
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
203
|
+
<slot/>
|
|
204
|
+
|
|
205
|
+
<teleport to="body">
|
|
206
|
+
<div
|
|
207
|
+
v-if="isOpen"
|
|
208
|
+
:class="dropdownClasses"
|
|
209
|
+
ref="floating"
|
|
210
|
+
:style="{width: `${width.width.value}px!important`, ...floatingStyles}"
|
|
211
|
+
>
|
|
212
|
+
<div
|
|
213
|
+
v-for="(option, index) in options"
|
|
214
|
+
:key="`option-${index}`"
|
|
215
|
+
:class="{...dropDownItemClasses, ...getActiveDropDownItemClasses(option)}"
|
|
216
|
+
@mousedown="(e) => onClickDropDownItem(e, option.value)"
|
|
217
|
+
@mouseover="() => focusedDropDownItem = option.value"
|
|
218
|
+
>
|
|
219
|
+
{{ option.label }}
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
<div
|
|
223
|
+
v-if="options.length === 0"
|
|
224
|
+
:class="{...dropDownItemClasses}"
|
|
225
|
+
>
|
|
226
|
+
<slot name="empty">
|
|
227
|
+
No options available
|
|
228
|
+
</slot>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
</teleport>
|
|
188
232
|
</div>
|
|
189
233
|
</template>
|
|
@@ -4,7 +4,6 @@ declare const meta: Meta<typeof AntBaseInput>;
|
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof AntBaseInput>;
|
|
6
6
|
export declare const Docs: Story;
|
|
7
|
-
export declare const withValidator: Story;
|
|
8
7
|
export declare const Nullable: Story;
|
|
9
8
|
export declare const IconLeft: Story;
|
|
10
9
|
export declare const IconRight: Story;
|
|
@@ -3,15 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
6
|
+
module.exports = exports.Summary = exports.Nullable = exports.IconRight = exports.IconLeft = exports.Docs = void 0;
|
|
7
7
|
var _Size = require("../../../../enums/Size.enum");
|
|
8
8
|
var _AntBaseInput = require("../__types/AntBaseInput.types");
|
|
9
9
|
var _AntBaseInput2 = _interopRequireDefault(require("../AntBaseInput.vue"));
|
|
10
10
|
var _AntButton = _interopRequireDefault(require("../../../buttons/AntButton.vue"));
|
|
11
11
|
var _AntIcon = _interopRequireDefault(require("../../../AntIcon.vue"));
|
|
12
12
|
var _Grouped2 = require("../../../../enums/Grouped.enum");
|
|
13
|
-
var _validate = require("@antify/validate");
|
|
14
|
-
var _vue = require("vue");
|
|
15
13
|
var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
|
|
16
14
|
var _enums = require("../../../../enums");
|
|
17
15
|
var _AntFormGroup = _interopRequireDefault(require("../../../forms/AntFormGroup.vue"));
|
|
@@ -136,32 +134,6 @@ const Docs = exports.Docs = {
|
|
|
136
134
|
placeholder: "Placeholder"
|
|
137
135
|
}
|
|
138
136
|
};
|
|
139
|
-
const withValidator = exports.withValidator = {
|
|
140
|
-
render: args => ({
|
|
141
|
-
components: {
|
|
142
|
-
AntBaseInput: _AntBaseInput2.default
|
|
143
|
-
},
|
|
144
|
-
setup: () => {
|
|
145
|
-
const validator = (0, _vue.reactive)((0, _validate.useFieldValidator)([_validate.isRequiredRule, _validate.notBlankRule]));
|
|
146
|
-
return {
|
|
147
|
-
args,
|
|
148
|
-
validator,
|
|
149
|
-
InputState: _enums.InputState
|
|
150
|
-
};
|
|
151
|
-
},
|
|
152
|
-
template: `
|
|
153
|
-
<AntBaseInput
|
|
154
|
-
v-model="args.modelValue"
|
|
155
|
-
v-bind="args"
|
|
156
|
-
:state="args.state ? args.state : (validator.hasErrors() ? InputState.danger : undefined)"
|
|
157
|
-
@validate="(val) => validator.validate(val)"
|
|
158
|
-
/>`
|
|
159
|
-
}),
|
|
160
|
-
args: {
|
|
161
|
-
...Docs.args,
|
|
162
|
-
modelValue: ""
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
137
|
const Nullable = exports.Nullable = {
|
|
166
138
|
render: Docs.render,
|
|
167
139
|
args: {
|