@antify/ui 1.0.4 → 1.2.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 (105) hide show
  1. package/dist/components/AntAccordion.vue +32 -7
  2. package/dist/components/AntAccordionItem.vue +48 -15
  3. package/dist/components/AntAlert.vue +8 -6
  4. package/dist/components/AntDropdown.vue +50 -36
  5. package/dist/components/AntIcon.vue +8 -6
  6. package/dist/components/AntKeycap.vue +22 -17
  7. package/dist/components/AntListGroup.vue +5 -3
  8. package/dist/components/AntModal.vue +17 -7
  9. package/dist/components/AntPopover.vue +118 -42
  10. package/dist/components/AntSkeleton.vue +1 -1
  11. package/dist/components/AntTooltip.vue +102 -76
  12. package/dist/components/__stories/AntAccordion.stories.d.ts +1 -0
  13. package/dist/components/__stories/AntAccordion.stories.js +73 -1
  14. package/dist/components/__stories/AntAccordion.stories.mjs +68 -0
  15. package/dist/components/__stories/AntDropdown.stories.js +27 -23
  16. package/dist/components/__stories/AntDropdown.stories.mjs +26 -22
  17. package/dist/components/__stories/AntKeycap.stories.js +13 -15
  18. package/dist/components/__stories/AntKeycap.stories.mjs +13 -13
  19. package/dist/components/__stories/AntListGroup.stories.js +1 -1
  20. package/dist/components/__stories/AntListGroup.stories.mjs +1 -1
  21. package/dist/components/__stories/AntModal.stories.js +2 -1
  22. package/dist/components/__stories/AntModal.stories.mjs +2 -1
  23. package/dist/components/__stories/AntPopover.stories.js +22 -21
  24. package/dist/components/__stories/AntPopover.stories.mjs +22 -20
  25. package/dist/components/__stories/AntTooltip.stories.d.ts +0 -10
  26. package/dist/components/__stories/AntTooltip.stories.js +32 -212
  27. package/dist/components/__stories/AntTooltip.stories.mjs +29 -193
  28. package/dist/components/__types/AntKeycap.types.d.ts +1 -0
  29. package/dist/components/__types/AntKeycap.types.js +1 -0
  30. package/dist/components/__types/AntKeycap.types.mjs +1 -0
  31. package/dist/components/buttons/AntButton.vue +41 -44
  32. package/dist/components/crud/AntCrud.vue +1 -1
  33. package/dist/components/crud/AntCrudDetailActions.vue +1 -0
  34. package/dist/components/crud/AntCrudTableFilter.vue +20 -18
  35. package/dist/components/forms/AntField.vue +7 -2
  36. package/dist/components/forms/__stories/AntField.stories.js +0 -16
  37. package/dist/components/forms/__stories/AntField.stories.mjs +2 -16
  38. package/dist/components/index.d.ts +2 -2
  39. package/dist/components/index.js +7 -7
  40. package/dist/components/index.mjs +2 -2
  41. package/dist/components/inputs/AntCheckbox.vue +25 -6
  42. package/dist/components/inputs/AntDateInput.vue +1 -1
  43. package/dist/components/inputs/AntRadio.vue +2 -1
  44. package/dist/components/inputs/AntSelect.vue +25 -22
  45. package/dist/components/inputs/AntSwitch.vue +2 -7
  46. package/dist/components/inputs/AntTagInput.vue +91 -114
  47. package/dist/components/inputs/AntTextarea.vue +7 -3
  48. package/dist/components/inputs/Elements/AntBaseInput.vue +2 -2
  49. package/dist/components/inputs/Elements/{AntDropDown.vue → AntSelectMenu.vue} +85 -40
  50. package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.d.ts +0 -1
  51. package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.js +1 -29
  52. package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.mjs +0 -22
  53. package/dist/components/inputs/Elements/index.d.ts +2 -1
  54. package/dist/components/inputs/Elements/index.js +7 -0
  55. package/dist/components/inputs/Elements/index.mjs +3 -1
  56. package/dist/components/inputs/__stories/AntCheckbox.stories.d.ts +0 -1
  57. package/dist/components/inputs/__stories/AntCheckbox.stories.js +1 -43
  58. package/dist/components/inputs/__stories/AntCheckbox.stories.mjs +0 -35
  59. package/dist/components/inputs/__stories/AntCheckboxGroup.stories.d.ts +0 -1
  60. package/dist/components/inputs/__stories/AntCheckboxGroup.stories.js +1 -31
  61. package/dist/components/inputs/__stories/AntCheckboxGroup.stories.mjs +0 -28
  62. package/dist/components/inputs/__stories/AntDateInput.stories.d.ts +0 -1
  63. package/dist/components/inputs/__stories/AntDateInput.stories.js +1 -32
  64. package/dist/components/inputs/__stories/AntDateInput.stories.mjs +0 -28
  65. package/dist/components/inputs/__stories/AntNumberInput.stories.d.ts +0 -2
  66. package/dist/components/inputs/__stories/AntNumberInput.stories.js +1 -65
  67. package/dist/components/inputs/__stories/AntNumberInput.stories.mjs +1 -54
  68. package/dist/components/inputs/__stories/AntPasswordInput.stories.d.ts +0 -1
  69. package/dist/components/inputs/__stories/AntPasswordInput.stories.js +1 -35
  70. package/dist/components/inputs/__stories/AntPasswordInput.stories.mjs +0 -25
  71. package/dist/components/inputs/__stories/AntRadioGroup.stories.d.ts +0 -1
  72. package/dist/components/inputs/__stories/AntRadioGroup.stories.js +1 -47
  73. package/dist/components/inputs/__stories/AntRadioGroup.stories.mjs +0 -46
  74. package/dist/components/inputs/__stories/AntRangeSlider.stories.d.ts +0 -1
  75. package/dist/components/inputs/__stories/AntRangeSlider.stories.js +1 -33
  76. package/dist/components/inputs/__stories/AntRangeSlider.stories.mjs +1 -28
  77. package/dist/components/inputs/__stories/AntSelect.stories.d.ts +0 -1
  78. package/dist/components/inputs/__stories/AntSelect.stories.js +18 -46
  79. package/dist/components/inputs/__stories/AntSelect.stories.mjs +16 -47
  80. package/dist/components/inputs/__stories/AntSwitch.stories.d.ts +0 -1
  81. package/dist/components/inputs/__stories/AntSwitch.stories.js +1 -42
  82. package/dist/components/inputs/__stories/AntSwitch.stories.mjs +1 -37
  83. package/dist/components/inputs/__stories/AntSwitcher.stories.d.ts +0 -1
  84. package/dist/components/inputs/__stories/AntSwitcher.stories.js +1 -51
  85. package/dist/components/inputs/__stories/AntSwitcher.stories.mjs +1 -51
  86. package/dist/components/inputs/__stories/AntTagInput.stories.d.ts +0 -1
  87. package/dist/components/inputs/__stories/AntTagInput.stories.js +1 -35
  88. package/dist/components/inputs/__stories/AntTagInput.stories.mjs +0 -33
  89. package/dist/components/inputs/__stories/AntTextInput.stories.d.ts +0 -2
  90. package/dist/components/inputs/__stories/AntTextInput.stories.js +1 -107
  91. package/dist/components/inputs/__stories/AntTextInput.stories.mjs +0 -104
  92. package/dist/components/inputs/__stories/AntTextarea.stories.d.ts +0 -2
  93. package/dist/components/inputs/__stories/AntTextarea.stories.js +7 -66
  94. package/dist/components/inputs/__stories/AntTextarea.stories.mjs +6 -55
  95. package/dist/components/inputs/__stories/AntUnitInput.stories.d.ts +0 -2
  96. package/dist/components/inputs/__stories/AntUnitInput.stories.js +1 -61
  97. package/dist/components/inputs/__stories/AntUnitInput.stories.mjs +0 -53
  98. package/dist/components/table/AntTable.vue +17 -15
  99. package/dist/components/table/AntTd.vue +1 -2
  100. package/dist/components/table/__stories/AntTable.stories.js +7 -14
  101. package/dist/components/table/__stories/AntTable.stories.mjs +7 -15
  102. package/dist/components/tabs/AntTabItem.vue +16 -6
  103. package/dist/components/tabs/AntTabs.vue +8 -0
  104. package/dist/components/tabs/__types/AntTabItem.types.d.ts +1 -0
  105. 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 AntDropDown from './Elements/AntDropDown.vue';
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
- <AntField
255
- :label="label"
256
- :size="size as unknown as Size"
257
- :skeleton="_skeleton"
258
- :description="description"
259
- :state="state"
260
- :expanded="expanded"
261
- :messages="messages"
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
- :class="inputContainerClasses"
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="flex gap-2.5 items-center"
251
+ :class="inputContainerClasses"
252
+ class="w-full flex items-center"
253
+ v-on-click-outside="onClickOutside"
280
254
  >
281
- <AntTag
282
- v-for="(tag, index) in _modelValue"
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
- {{ options.find((option: SelectOption) => option.value === tag)?.label }}
290
- </AntTag>
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
- <!-- Input -->
294
- <div class="flex items-center w-32 shrink grow">
295
- <AntIcon
296
- :icon="icon"
297
- :size="size === AntTagInputSize.sm ? IconSize.xs : IconSize.sm"
298
- />
299
-
300
- <input
301
- ref="inputRef"
302
- v-model="tagInput"
303
- type="text"
304
- :placeholder="placeholder"
305
- :class="inputClasses"
306
- :disabled="disabled"
307
- :readonly="readonly"
308
- @focus="changeFocus"
309
- @input="filterDropDown"
310
- @keydown.delete="removeLastTag"
311
- @keydown.enter.prevent="checkCreateTag(tagInput)"
312
- @blur="onBlur"
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
- <AntDropDown
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>
@@ -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,6 +46,7 @@ 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
  });
50
52
  const _modelValue = useVModel(props, 'modelValue', emit);
@@ -67,7 +69,7 @@ const inputClasses = computed(() => {
67
69
  };
68
70
 
69
71
  return {
70
- 'block transition-colors relative border-none outline w-full focus:z-10': true,
72
+ 'block transition-colors relative border-none outline w-full focus:z-10 h-full text-black': true,
71
73
  'outline-offset-[-1px] outline-1 focus:outline-offset-[-1px] focus:outline-1': true,
72
74
  'disabled:opacity-50 disabled:cursor-not-allowed': props.disabled,
73
75
  [variants[props.state]]: true,
@@ -90,7 +92,8 @@ const inputClasses = computed(() => {
90
92
  'rounded-none': props.grouped === Grouped.center,
91
93
  'rounded-tl-none rounded-bl-none rounded-tr-md rounded-br-md': props.grouped === Grouped.right,
92
94
  'rounded-md': props.grouped === Grouped.none,
93
- 'invisible': props.skeleton
95
+ 'invisible': props.skeleton,
96
+ 'resize-none': !props.resize
94
97
  };
95
98
  });
96
99
  const iconColor = computed(() => {
@@ -153,9 +156,10 @@ function onBlur(e: FocusEvent) {
153
156
  :limiter-max-value="limiter && max !== undefined ? max : undefined"
154
157
  :limiter-value="limiter ? _modelValue?.length : undefined"
155
158
  :messages="messages"
159
+ :expanded-height="!resize"
156
160
  >
157
161
  <div
158
- class="block relative w-full"
162
+ class="block relative w-full h-full"
159
163
  :class="{...{'-mr-px': grouped !== Grouped.none}, ..._wrapperClass}"
160
164
  >
161
165
  <textarea
@@ -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.xs2, 'w-8': size === Size.sm, 'w-9': size === Size.md, 'w-10': size === Size.lg}"
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,40 @@ 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
+ console.log(props.open);
53
+ if (!props.open) {
54
+ return;
55
+ }
56
+
57
+ emit('update:open', false);
33
58
  });
34
59
 
35
60
  const _modelValue = useVModel(props, 'modelValue', emit);
36
61
  const isOpen = useVModel(props, 'open', emit);
37
62
  const focusedDropDownItem = useVModel(props, 'focused', emit);
38
-
39
63
  const dropdownClasses = computed(() => {
40
64
  const variants: Record<InputState, string> = {
41
65
  [InputState.base]: 'bg-neutral-300 border-neutral-300',
@@ -46,11 +70,9 @@ const dropdownClasses = computed(() => {
46
70
  };
47
71
 
48
72
  return {
49
- 'absolute w-full border flex flex-col gap-px outline-none -mt-px overflow-hidden shadow-md z-40': true,
50
- 'rounded-bl-md rounded-br-md': true,
73
+ 'w-full border flex flex-col gap-px outline-none -mt-px overflow-hidden shadow-md z-[90]': true,
74
+ 'rounded-md': true,
51
75
  [variants[props.state]]: true,
52
- // Size
53
- 'text-sm': props.size === Size.sm || props.size === Size.md
54
76
  };
55
77
  });
56
78
  const dropDownItemClasses = computed(() => {
@@ -66,8 +88,11 @@ const dropDownItemClasses = computed(() => {
66
88
  'select-none text-ellipsis overflow-hidden whitespace-nowrap': true,
67
89
  [variants[props.state]]: true,
68
90
  // Size
69
- 'p-1.5': props.size === Size.sm,
70
- 'p-2': props.size === Size.md,
91
+ 'p-1 text-xs': props.size === Size.xs2,
92
+ 'p-1.5 text-xs': props.size === Size.xs,
93
+ 'p-1.5 text-sm': props.size === Size.sm,
94
+ 'p-2 text-sm': props.size === Size.md,
95
+ 'p-2.5 text-sm': props.size === Size.lg,
71
96
  };
72
97
  });
73
98
 
@@ -86,12 +111,12 @@ watch(isOpen, () => {
86
111
 
87
112
  onMounted(() => {
88
113
  nextTick(() => {
89
- props.inputRef?.addEventListener('keydown', onKeyDownDropDown);
114
+ reference.value?.addEventListener('keydown', onKeyDownDropDown);
90
115
  });
91
116
  });
92
117
 
93
118
  onUnmounted(() => {
94
- props.inputRef?.removeEventListener('keydown', onKeyDownDropDown);
119
+ reference.value?.removeEventListener('keydown', onKeyDownDropDown);
95
120
  });
96
121
 
97
122
  function onKeyDownDropDown(e: KeyboardEvent) {
@@ -100,6 +125,10 @@ function onKeyDownDropDown(e: KeyboardEvent) {
100
125
  isOpen.value = false;
101
126
  }
102
127
 
128
+ if (!isOpen.value) {
129
+ isOpen.value = true
130
+ }
131
+
103
132
  emit('selectElement', focusedDropDownItem.value);
104
133
  }
105
134
 
@@ -108,6 +137,7 @@ function onKeyDownDropDown(e: KeyboardEvent) {
108
137
  }
109
138
 
110
139
  if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
140
+ e.preventDefault()
111
141
  isOpen.value = true;
112
142
 
113
143
  const index = props.options.findIndex(option => option.value === focusedDropDownItem.value);
@@ -121,6 +151,7 @@ function onKeyDownDropDown(e: KeyboardEvent) {
121
151
  }
122
152
 
123
153
  if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
154
+ e.preventDefault()
124
155
  isOpen.value = true;
125
156
 
126
157
  const index = props.options.findIndex(option => option.value === focusedDropDownItem.value);
@@ -138,21 +169,24 @@ function onKeyDownDropDown(e: KeyboardEvent) {
138
169
 
139
170
  function getActiveDropDownItemClasses(option: SelectOption) {
140
171
  const variants: Record<InputState, string> = {
141
- [InputState.base]: 'bg-neutral-50/25',
142
- [InputState.success]: 'bg-success-100/25',
143
- [InputState.info]: 'bg-info-100/25',
144
- [InputState.warning]: 'bg-warning-100/25',
145
- [InputState.danger]: 'bg-danger-100/25',
172
+ [InputState.base]: '!bg-neutral-100',
173
+ [InputState.success]: 'bg-success-200',
174
+ [InputState.info]: 'bg-info-200',
175
+ [InputState.warning]: 'bg-warning-200',
176
+ [InputState.danger]: 'bg-danger-200',
146
177
  };
147
178
 
148
- return option.value === focusedDropDownItem.value ? {[variants[props.state]]: true} : {};
179
+ return option.value === focusedDropDownItem.value ? {'bg-white': false, [variants[props.state]]: true} : {};
149
180
  }
150
181
 
151
182
  function onClickDropDownItem(e: MouseEvent, value: string | number | null) {
152
183
  e.preventDefault();
153
- props.inputRef?.focus();
184
+ reference.value?.focus();
185
+
186
+ if (props.closeOnSelectItem) {
187
+ isOpen.value = false;
188
+ }
154
189
 
155
- isOpen.value = false;
156
190
  emit('selectElement', value);
157
191
  _modelValue.value = value;
158
192
  }
@@ -164,26 +198,37 @@ watch(_modelValue, (val) => {
164
198
 
165
199
  <template>
166
200
  <div
167
- v-if="isOpen"
168
- :class="dropdownClasses"
201
+ ref="reference"
202
+ class="relative"
169
203
  >
170
- <div
171
- v-for="(option, index) in options"
172
- :key="`option-${index}`"
173
- :class="{...dropDownItemClasses, ...getActiveDropDownItemClasses(option)}"
174
- @mousedown="(e) => onClickDropDownItem(e, option.value)"
175
- @mouseover="() => focusedDropDownItem = option.value"
176
- >
177
- {{ option.label }}
178
- </div>
179
-
180
- <div
181
- v-if="options.length === 0"
182
- :class="{...dropDownItemClasses}"
183
- >
184
- <slot name="empty">
185
- No options available
186
- </slot>
187
- </div>
204
+ <slot/>
205
+
206
+ <teleport to="body">
207
+ <div
208
+ v-if="isOpen"
209
+ :class="dropdownClasses"
210
+ ref="floating"
211
+ :style="{width: `${width.width.value}px!important`, ...floatingStyles}"
212
+ >
213
+ <div
214
+ v-for="(option, index) in options"
215
+ :key="`option-${index}`"
216
+ :class="{...dropDownItemClasses, ...getActiveDropDownItemClasses(option)}"
217
+ @mousedown="(e) => onClickDropDownItem(e, option.value)"
218
+ @mouseover="() => focusedDropDownItem = option.value"
219
+ >
220
+ {{ option.label }}
221
+ </div>
222
+
223
+ <div
224
+ v-if="options.length === 0"
225
+ :class="{...dropDownItemClasses}"
226
+ >
227
+ <slot name="empty">
228
+ No options available
229
+ </slot>
230
+ </div>
231
+ </div>
232
+ </teleport>
188
233
  </div>
189
234
  </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
- exports.withValidator = exports.default = exports.Summary = exports.Nullable = exports.IconRight = exports.IconLeft = exports.Docs = void 0;
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: {
@@ -4,8 +4,6 @@ import AntBaseInput from "../AntBaseInput.vue";
4
4
  import AntButton from "../../../buttons/AntButton.vue";
5
5
  import AntIcon from "../../../AntIcon.vue";
6
6
  import { Grouped as _Grouped } from "../../../../enums/Grouped.enum.mjs";
7
- import { isRequiredRule, notBlankRule, useFieldValidator } from "@antify/validate";
8
- import { reactive } from "vue";
9
7
  import { faSearch, faEye } from "@fortawesome/free-solid-svg-icons";
10
8
  import { InputState } from "../../../../enums/index.mjs";
11
9
  import AntFormGroup from "../../../forms/AntFormGroup.vue";
@@ -83,26 +81,6 @@ export const Docs = {
83
81
  placeholder: "Placeholder"
84
82
  }
85
83
  };
86
- export const withValidator = {
87
- render: (args) => ({
88
- components: { AntBaseInput },
89
- setup: () => {
90
- const validator = reactive(useFieldValidator([isRequiredRule, notBlankRule]));
91
- return { args, validator, InputState };
92
- },
93
- template: `
94
- <AntBaseInput
95
- v-model="args.modelValue"
96
- v-bind="args"
97
- :state="args.state ? args.state : (validator.hasErrors() ? InputState.danger : undefined)"
98
- @validate="(val) => validator.validate(val)"
99
- />`
100
- }),
101
- args: {
102
- ...Docs.args,
103
- modelValue: ""
104
- }
105
- };
106
84
  export const Nullable = {
107
85
  render: Docs.render,
108
86
  args: {
@@ -3,4 +3,5 @@ import AntField from '../../forms/AntField.vue';
3
3
  import AntInputDescription from './AntInputDescription.vue';
4
4
  import AntInputLabel from './AntInputLabel.vue';
5
5
  import AntInputLimiter from './AntInputLimiter.vue';
6
- export { AntBaseInput, AntField, AntInputDescription, AntInputLabel, AntInputLimiter };
6
+ import AntSelectMenu from './AntSelectMenu.vue';
7
+ export { AntBaseInput, AntField, AntInputDescription, AntInputLabel, AntInputLimiter, AntSelectMenu };