vueless 0.0.185 → 0.0.187
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/package.json +1 -1
- package/ui.button/configs/default.config.js +1 -1
- package/ui.button-link/configs/default.config.js +2 -2
- package/ui.container-accordion/configs/default.config.js +1 -1
- package/ui.data-table/configs/default.config.js +1 -1
- package/ui.dropdown-badge/configs/default.config.js +1 -1
- package/ui.dropdown-button/configs/default.config.js +1 -1
- package/ui.dropdown-link/configs/default.config.js +1 -1
- package/ui.dropdown-list/composables/usePointer.js +23 -14
- package/ui.dropdown-list/configs/default.config.js +2 -2
- package/ui.dropdown-list/index.vue +29 -30
- package/ui.form-checkbox/configs/default.config.js +1 -1
- package/ui.form-input/configs/default.config.js +3 -3
- package/ui.form-input/index.vue +10 -8
- package/ui.form-input-file/configs/default.config.js +1 -1
- package/ui.form-input-search/configs/default.config.js +2 -2
- package/ui.form-input-search/index.stories.js +3 -2
- package/ui.form-input-search/index.vue +71 -75
- package/ui.form-select/configs/default.config.js +5 -6
- package/ui.form-select/index.stories.js +4 -4
- package/ui.form-select/index.vue +18 -43
- package/ui.form-select/services/select.service.js +22 -20
- package/ui.form-switch/configs/default.config.js +3 -3
- package/ui.form-textarea/configs/default.config.js +2 -2
- package/ui.form-textarea/index.vue +8 -15
- package/ui.loader-rendering/configs/default.config.js +1 -1
- package/ui.loader-top/configs/default.config.js +1 -1
- package/ui.navigation-progress/configs/default.config.js +3 -3
- package/ui.text-notify/configs/default.config.js +3 -3
- package/web-types.json +42 -86
|
@@ -5,14 +5,13 @@
|
|
|
5
5
|
v-model="search"
|
|
6
6
|
:size="size"
|
|
7
7
|
:disabled="disabled"
|
|
8
|
-
:
|
|
8
|
+
:label-align="labelAlign"
|
|
9
9
|
:label="label"
|
|
10
10
|
:error="error"
|
|
11
|
+
:description="description"
|
|
11
12
|
:placeholder="placeholder"
|
|
12
|
-
|
|
13
|
-
:input-mode="search"
|
|
13
|
+
inputmode="search"
|
|
14
14
|
:data-cy="dataCy"
|
|
15
|
-
:label-align="labelAlign"
|
|
16
15
|
v-bind="inputAttrs"
|
|
17
16
|
@keyup.enter="onClickSearch"
|
|
18
17
|
>
|
|
@@ -25,44 +24,44 @@
|
|
|
25
24
|
<!-- @slot Use it to add something before text. -->
|
|
26
25
|
<slot name="right" />
|
|
27
26
|
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
27
|
+
<template v-if="!hasSlotContent($slots['right'])">
|
|
28
|
+
<UIcon
|
|
29
|
+
internal
|
|
30
|
+
interactive
|
|
31
|
+
color="gray"
|
|
32
|
+
:name="config.closeIconName"
|
|
33
|
+
:data-cy="`${dataCy}-close`"
|
|
34
|
+
:size="iconSize"
|
|
35
|
+
v-bind="closeIconAttrs"
|
|
36
|
+
@click="onClickClear"
|
|
37
|
+
/>
|
|
38
|
+
|
|
39
|
+
<UButton
|
|
40
|
+
v-if="searchButtonLabel"
|
|
41
|
+
:label="searchButtonLabel"
|
|
42
|
+
v-bind="buttonAttrs"
|
|
43
|
+
:data-cy="`${dataCy}-right`"
|
|
44
|
+
@click="onClickSearch"
|
|
45
|
+
/>
|
|
46
|
+
|
|
47
|
+
<UIcon
|
|
48
|
+
v-else
|
|
49
|
+
internal
|
|
50
|
+
interactive
|
|
51
|
+
:size="iconSize"
|
|
52
|
+
color="grayscale"
|
|
53
|
+
:name="config.searchIconName"
|
|
54
|
+
:data-cy="`${dataCy}-search`"
|
|
55
|
+
v-bind="searchIconAttrs"
|
|
56
|
+
@click="onClickSearch"
|
|
57
|
+
/>
|
|
58
|
+
</template>
|
|
60
59
|
</template>
|
|
61
60
|
</UInput>
|
|
62
61
|
</template>
|
|
63
62
|
|
|
64
63
|
<script setup>
|
|
65
|
-
import { computed } from "vue";
|
|
64
|
+
import { computed, ref } from "vue";
|
|
66
65
|
|
|
67
66
|
import UIcon from "../ui.image-icon";
|
|
68
67
|
import UInput from "../ui.form-input";
|
|
@@ -78,7 +77,7 @@ defineOptions({ name: "UInputSearch" });
|
|
|
78
77
|
|
|
79
78
|
const props = defineProps({
|
|
80
79
|
/**
|
|
81
|
-
*
|
|
80
|
+
* Search input value.
|
|
82
81
|
*/
|
|
83
82
|
modelValue: {
|
|
84
83
|
type: String,
|
|
@@ -86,7 +85,7 @@ const props = defineProps({
|
|
|
86
85
|
},
|
|
87
86
|
|
|
88
87
|
/**
|
|
89
|
-
*
|
|
88
|
+
* Input size.
|
|
90
89
|
* @values sm, md, lg
|
|
91
90
|
*/
|
|
92
91
|
size: {
|
|
@@ -95,38 +94,30 @@ const props = defineProps({
|
|
|
95
94
|
},
|
|
96
95
|
|
|
97
96
|
/**
|
|
98
|
-
*
|
|
99
|
-
* @ignore
|
|
97
|
+
* Input placeholder.
|
|
100
98
|
*/
|
|
101
|
-
|
|
99
|
+
placeholder: {
|
|
102
100
|
type: String,
|
|
103
|
-
default:
|
|
101
|
+
default: "",
|
|
104
102
|
},
|
|
105
103
|
|
|
106
104
|
/**
|
|
107
|
-
*
|
|
105
|
+
* Label placement.
|
|
106
|
+
* @values top, topInside, topWithDesc, bottom, left, right
|
|
108
107
|
*/
|
|
109
|
-
|
|
110
|
-
type:
|
|
111
|
-
default: UIService.get(defaultConfig, UInputSearch).default.
|
|
108
|
+
labelAlign: {
|
|
109
|
+
type: String,
|
|
110
|
+
default: UIService.get(defaultConfig, UInputSearch).default.labelAlign,
|
|
112
111
|
},
|
|
113
112
|
|
|
114
113
|
/**
|
|
115
|
-
*
|
|
114
|
+
* Input label.
|
|
116
115
|
*/
|
|
117
|
-
|
|
116
|
+
label: {
|
|
118
117
|
type: String,
|
|
119
118
|
default: "",
|
|
120
119
|
},
|
|
121
120
|
|
|
122
|
-
/**
|
|
123
|
-
* Show / hide search button.
|
|
124
|
-
*/
|
|
125
|
-
searchButton: {
|
|
126
|
-
type: Boolean,
|
|
127
|
-
default: UIService.get(defaultConfig, UInputSearch).default.searchButton,
|
|
128
|
-
},
|
|
129
|
-
|
|
130
121
|
/**
|
|
131
122
|
* Input description.
|
|
132
123
|
*/
|
|
@@ -136,40 +127,40 @@ const props = defineProps({
|
|
|
136
127
|
},
|
|
137
128
|
|
|
138
129
|
/**
|
|
139
|
-
*
|
|
140
|
-
* @values top, topInside, topWithDesc, bottom, left, right
|
|
130
|
+
* Error message.
|
|
141
131
|
*/
|
|
142
|
-
|
|
132
|
+
error: {
|
|
143
133
|
type: String,
|
|
144
|
-
default:
|
|
134
|
+
default: "",
|
|
145
135
|
},
|
|
146
136
|
|
|
147
137
|
/**
|
|
148
|
-
*
|
|
138
|
+
* Search button label.
|
|
149
139
|
*/
|
|
150
|
-
|
|
140
|
+
searchButtonLabel: {
|
|
151
141
|
type: String,
|
|
152
142
|
default: "",
|
|
153
143
|
},
|
|
154
144
|
|
|
155
145
|
/**
|
|
156
|
-
*
|
|
146
|
+
* Set input disabled.
|
|
157
147
|
*/
|
|
158
|
-
|
|
159
|
-
type:
|
|
160
|
-
default:
|
|
148
|
+
disabled: {
|
|
149
|
+
type: Boolean,
|
|
150
|
+
default: UIService.get(defaultConfig, UInputSearch).default.disabled,
|
|
161
151
|
},
|
|
162
152
|
|
|
163
153
|
/**
|
|
164
|
-
*
|
|
154
|
+
* Unique element id.
|
|
155
|
+
* @ignore
|
|
165
156
|
*/
|
|
166
|
-
|
|
157
|
+
id: {
|
|
167
158
|
type: String,
|
|
168
|
-
default:
|
|
159
|
+
default: () => getRandomId(),
|
|
169
160
|
},
|
|
170
161
|
|
|
171
162
|
/**
|
|
172
|
-
*
|
|
163
|
+
* Component ui config object.
|
|
173
164
|
*/
|
|
174
165
|
config: {
|
|
175
166
|
type: Object,
|
|
@@ -177,7 +168,7 @@ const props = defineProps({
|
|
|
177
168
|
},
|
|
178
169
|
|
|
179
170
|
/**
|
|
180
|
-
*
|
|
171
|
+
* Data-cy attribute for automated testing.
|
|
181
172
|
*/
|
|
182
173
|
dataCy: {
|
|
183
174
|
type: String,
|
|
@@ -187,12 +178,17 @@ const props = defineProps({
|
|
|
187
178
|
|
|
188
179
|
const emit = defineEmits(["update:modelValue", "clear", "search"]);
|
|
189
180
|
|
|
181
|
+
const localValue = ref("");
|
|
182
|
+
|
|
190
183
|
const { config, inputAttrs, searchIconAttrs, closeIconAttrs, buttonAttrs, hasSlotContent } =
|
|
191
184
|
useAttrs(props);
|
|
192
185
|
|
|
193
186
|
const search = computed({
|
|
194
187
|
get: () => props.modelValue,
|
|
195
|
-
set: (value) =>
|
|
188
|
+
set: (value) => {
|
|
189
|
+
localValue.value = value;
|
|
190
|
+
emit("update:modelValue", value);
|
|
191
|
+
},
|
|
196
192
|
});
|
|
197
193
|
|
|
198
194
|
const iconSize = computed(() => {
|
|
@@ -211,7 +207,7 @@ function onClickClear() {
|
|
|
211
207
|
}
|
|
212
208
|
|
|
213
209
|
function onClickSearch() {
|
|
214
|
-
if (!
|
|
215
|
-
emit("search",
|
|
210
|
+
if (!localValue.value) return;
|
|
211
|
+
emit("search", localValue.value);
|
|
216
212
|
}
|
|
217
213
|
</script>
|
|
@@ -4,7 +4,7 @@ export default /*tw*/ {
|
|
|
4
4
|
base: `
|
|
5
5
|
pb-2 pt-2 flex flex-row-reverse justify-between w-full min-h-full box-border relative
|
|
6
6
|
rounded-lg border border-gray-300 bg-white
|
|
7
|
-
hover:border-gray-400 hover:transition
|
|
7
|
+
hover:border-gray-400 hover:transition hover:focus-within:border-brand-500
|
|
8
8
|
focus-within:border-brand-500 focus-within:ring-4 focus-within:ring-brand-600/[.15] focus-within:outline-none
|
|
9
9
|
`,
|
|
10
10
|
variants: {
|
|
@@ -55,7 +55,7 @@ export default /*tw*/ {
|
|
|
55
55
|
beforeCaretSlot: "",
|
|
56
56
|
afterCaretSlot: "mr-3",
|
|
57
57
|
caretToggle: "mr-3",
|
|
58
|
-
toggleIcon: "transform transition
|
|
58
|
+
toggleIcon: "transform transition duration-300 group-[]/active:rotate-180",
|
|
59
59
|
toggleIconName: "expand_more",
|
|
60
60
|
clearIcon: "",
|
|
61
61
|
clearIconName: "close_small",
|
|
@@ -63,7 +63,7 @@ export default /*tw*/ {
|
|
|
63
63
|
removeItemIconName: "close_small",
|
|
64
64
|
caretRemoveItem: "flex items-center",
|
|
65
65
|
caretClearText: {
|
|
66
|
-
base: "cursor-pointer flex items-center text-sm font-normal text-gray-400 hover:text-gray-500 transition
|
|
66
|
+
base: "cursor-pointer flex items-center text-sm font-normal text-gray-400 hover:text-gray-500 transition",
|
|
67
67
|
compoundVariants: [
|
|
68
68
|
{ size: "sm", class: "text-sm" },
|
|
69
69
|
{ size: "md", class: "text-base" },
|
|
@@ -123,9 +123,8 @@ export default /*tw*/ {
|
|
|
123
123
|
openDirection: "auto",
|
|
124
124
|
labelKey: "label",
|
|
125
125
|
valueKey: "id",
|
|
126
|
-
optionsLimit:
|
|
127
|
-
|
|
128
|
-
optionHeight: 40,
|
|
126
|
+
optionsLimit: 0,
|
|
127
|
+
visibleOptions: 8,
|
|
129
128
|
multiple: false,
|
|
130
129
|
disabled: false,
|
|
131
130
|
searchable: true,
|
|
@@ -222,12 +222,12 @@ Multiple.args = { modelValue: [] };
|
|
|
222
222
|
export const openDirection = OpenDirectionsTemplate.bind({});
|
|
223
223
|
openDirection.args = {};
|
|
224
224
|
|
|
225
|
-
export const
|
|
226
|
-
|
|
225
|
+
export const groupValue = GroupValuesTemplate.bind({});
|
|
226
|
+
groupValue.args = {
|
|
227
227
|
modelValue: "",
|
|
228
228
|
modelValueMultiple: [],
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
groupValueKey: "libs",
|
|
230
|
+
groupLabelKey: "language",
|
|
231
231
|
labelKey: "name",
|
|
232
232
|
valueKey: "name",
|
|
233
233
|
options: [
|
package/ui.form-select/index.vue
CHANGED
|
@@ -117,7 +117,6 @@
|
|
|
117
117
|
:id="id"
|
|
118
118
|
ref="searchInputRef"
|
|
119
119
|
v-model="search"
|
|
120
|
-
:name="name"
|
|
121
120
|
type="text"
|
|
122
121
|
autocomplete="off"
|
|
123
122
|
:spellcheck="false"
|
|
@@ -159,14 +158,13 @@
|
|
|
159
158
|
</div>
|
|
160
159
|
|
|
161
160
|
<UDropdownList
|
|
162
|
-
v-
|
|
161
|
+
v-if="isOpen"
|
|
163
162
|
ref="dropdownListRef"
|
|
164
163
|
v-model="dropdownValue"
|
|
165
164
|
:options="filteredOptions"
|
|
166
165
|
:disabled="disabled"
|
|
167
166
|
:size="size"
|
|
168
|
-
:
|
|
169
|
-
:option-height="optionHeight"
|
|
167
|
+
:visible-options="visibleOptions"
|
|
170
168
|
:value-key="valueKey"
|
|
171
169
|
:label-key="labelKey"
|
|
172
170
|
:add-option="addOption"
|
|
@@ -318,8 +316,7 @@ const props = defineProps({
|
|
|
318
316
|
/**
|
|
319
317
|
* Set a name of the property containing the group label.
|
|
320
318
|
*/
|
|
321
|
-
|
|
322
|
-
groupLabel: {
|
|
319
|
+
groupLabelKey: {
|
|
323
320
|
type: String,
|
|
324
321
|
default: "label",
|
|
325
322
|
},
|
|
@@ -327,17 +324,7 @@ const props = defineProps({
|
|
|
327
324
|
/**
|
|
328
325
|
* Set a name of the property containing the group values.
|
|
329
326
|
*/
|
|
330
|
-
|
|
331
|
-
groupValues: {
|
|
332
|
-
type: String,
|
|
333
|
-
default: "",
|
|
334
|
-
},
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* name attribute to match optional label element.
|
|
338
|
-
*/
|
|
339
|
-
// TODO: what is it?
|
|
340
|
-
name: {
|
|
327
|
+
groupValueKey: {
|
|
341
328
|
type: String,
|
|
342
329
|
default: "",
|
|
343
330
|
},
|
|
@@ -351,18 +338,11 @@ const props = defineProps({
|
|
|
351
338
|
},
|
|
352
339
|
|
|
353
340
|
/**
|
|
354
|
-
*
|
|
341
|
+
* Amount of options you can see without scroll.
|
|
355
342
|
*/
|
|
356
|
-
|
|
357
|
-
maxHeight: {
|
|
358
|
-
type: Number,
|
|
359
|
-
default: UIService.get(defaultConfig, USelect).default.maxHeight,
|
|
360
|
-
},
|
|
361
|
-
|
|
362
|
-
// TODO: there is no desc
|
|
363
|
-
optionHeight: {
|
|
343
|
+
visibleOptions: {
|
|
364
344
|
type: Number,
|
|
365
|
-
default: UIService.get(defaultConfig, USelect).default.
|
|
345
|
+
default: UIService.get(defaultConfig, USelect).default.visibleOptions,
|
|
366
346
|
},
|
|
367
347
|
|
|
368
348
|
/**
|
|
@@ -448,7 +428,6 @@ const { tm } = useLocale();
|
|
|
448
428
|
const isOpen = ref(false);
|
|
449
429
|
const preferredOpenDirection = ref(DIRECTION.bottom);
|
|
450
430
|
const search = ref("");
|
|
451
|
-
const optimizedHeight = ref(props.maxHeight);
|
|
452
431
|
|
|
453
432
|
const dropdownListRef = ref(null);
|
|
454
433
|
const wrapperRef = ref(null);
|
|
@@ -543,17 +522,17 @@ const filteredOptions = computed(() => {
|
|
|
543
522
|
let options = props.multiple
|
|
544
523
|
? SelectService.removeSelectedValues(
|
|
545
524
|
props.options,
|
|
546
|
-
props.
|
|
525
|
+
props.groupValueKey,
|
|
547
526
|
props.valueKey,
|
|
548
527
|
props.modelValue,
|
|
549
528
|
)
|
|
550
529
|
: [...props.options];
|
|
551
530
|
|
|
552
|
-
options = props.
|
|
531
|
+
options = props.groupValueKey
|
|
553
532
|
? filterAndFlat(options, normalizedSearch, props.labelKey)
|
|
554
533
|
: SelectService.filterOptions(options, normalizedSearch, props.labelKey);
|
|
555
534
|
|
|
556
|
-
return options.slice(0, props.optionsLimit);
|
|
535
|
+
return options.slice(0, props.optionsLimit || options.length);
|
|
557
536
|
});
|
|
558
537
|
|
|
559
538
|
const localValue = computed(() => {
|
|
@@ -561,14 +540,14 @@ const localValue = computed(() => {
|
|
|
561
540
|
return SelectService.getCurrentOption(
|
|
562
541
|
props.modelValue,
|
|
563
542
|
props.options,
|
|
564
|
-
props.
|
|
543
|
+
props.groupValueKey,
|
|
565
544
|
props.valueKey,
|
|
566
545
|
);
|
|
567
546
|
}
|
|
568
547
|
|
|
569
548
|
return props.modelValue
|
|
570
549
|
? props.modelValue.map((item) =>
|
|
571
|
-
SelectService.getCurrentOption(item, props.options, props.
|
|
550
|
+
SelectService.getCurrentOption(item, props.options, props.groupValueKey, props.valueKey),
|
|
572
551
|
)
|
|
573
552
|
: [];
|
|
574
553
|
});
|
|
@@ -610,7 +589,6 @@ const onSearchChange = debounce(async function (query) {
|
|
|
610
589
|
|
|
611
590
|
function getOptionLabel(option) {
|
|
612
591
|
if (!option) return "";
|
|
613
|
-
if (option.$isLabel) return option.$groupLabel;
|
|
614
592
|
|
|
615
593
|
return option[props.labelKey] || "";
|
|
616
594
|
}
|
|
@@ -640,11 +618,11 @@ function filterAndFlat(options, search, label) {
|
|
|
640
618
|
options,
|
|
641
619
|
search,
|
|
642
620
|
label,
|
|
643
|
-
props.
|
|
644
|
-
props.
|
|
621
|
+
props.groupValueKey,
|
|
622
|
+
props.groupLabelKey,
|
|
645
623
|
);
|
|
646
624
|
|
|
647
|
-
return SelectService.flattenOptions(filteredGroups, props.
|
|
625
|
+
return SelectService.flattenOptions(filteredGroups, props.groupValueKey, props.groupLabelKey);
|
|
648
626
|
}
|
|
649
627
|
|
|
650
628
|
function toggle() {
|
|
@@ -681,25 +659,22 @@ function activate() {
|
|
|
681
659
|
}
|
|
682
660
|
|
|
683
661
|
function adjustPosition() {
|
|
684
|
-
if (typeof window === "undefined") return;
|
|
662
|
+
if (typeof window === "undefined" || !dropdownListRef.value) return;
|
|
685
663
|
|
|
664
|
+
const dropdownHeight = dropdownListRef.value.wrapperRef.getBoundingClientRect().height;
|
|
686
665
|
const spaceAbove = wrapperRef.value.getBoundingClientRect().top;
|
|
687
666
|
const spaceBelow = window.innerHeight - wrapperRef.value.getBoundingClientRect().bottom;
|
|
688
|
-
const hasEnoughSpaceBelow = spaceBelow >
|
|
667
|
+
const hasEnoughSpaceBelow = spaceBelow > dropdownHeight;
|
|
689
668
|
|
|
690
669
|
if (hasEnoughSpaceBelow || spaceBelow > spaceAbove || props.openDirection === DIRECTION.bottom) {
|
|
691
670
|
preferredOpenDirection.value = DIRECTION.bottom;
|
|
692
|
-
// TODO: magic numbers
|
|
693
|
-
optimizedHeight.value = Math.min(spaceBelow - 40, props.maxHeight);
|
|
694
671
|
} else {
|
|
695
672
|
preferredOpenDirection.value = DIRECTION.top;
|
|
696
|
-
optimizedHeight.value = Math.min(spaceAbove - 40, props.maxHeight);
|
|
697
673
|
}
|
|
698
674
|
}
|
|
699
675
|
|
|
700
676
|
function removeElement(option, shouldClose = true) {
|
|
701
677
|
if (props.disabled) return;
|
|
702
|
-
if (option.$isDisabled) return;
|
|
703
678
|
|
|
704
679
|
if (props.noClear && !props.multiple) {
|
|
705
680
|
deactivate();
|
|
@@ -4,12 +4,15 @@ export default class SelectService {
|
|
|
4
4
|
? options
|
|
5
5
|
.filter((option) => this.interpolateLabel(option, label).includes(search))
|
|
6
6
|
.sort((a, b) => {
|
|
7
|
-
return
|
|
7
|
+
return (
|
|
8
|
+
this.interpolateLabel(a, label).indexOf(search) -
|
|
9
|
+
this.interpolateLabel(b, label).indexOf(search)
|
|
10
|
+
);
|
|
8
11
|
})
|
|
9
12
|
: options;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
|
-
static filterGroups(options, search, label, values,
|
|
15
|
+
static filterGroups(options, search, label, values, groupLabelKey) {
|
|
13
16
|
return options.map((group) => {
|
|
14
17
|
if (!group[values]) {
|
|
15
18
|
// eslint-disable-next-line no-console
|
|
@@ -22,20 +25,17 @@ export default class SelectService {
|
|
|
22
25
|
|
|
23
26
|
return groupOptions.length
|
|
24
27
|
? {
|
|
25
|
-
[
|
|
28
|
+
[groupLabelKey]: group[groupLabelKey],
|
|
26
29
|
[values]: groupOptions,
|
|
27
30
|
}
|
|
28
31
|
: [];
|
|
29
32
|
});
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
static flattenOptions(options, values,
|
|
35
|
+
static flattenOptions(options, values, groupLabelKey) {
|
|
33
36
|
return options.reduce((prev, curr) => {
|
|
34
37
|
if (curr[values] && curr[values].length) {
|
|
35
|
-
prev.push({
|
|
36
|
-
$groupLabel: curr[label],
|
|
37
|
-
$isLabel: true,
|
|
38
|
-
});
|
|
38
|
+
prev.push({ groupLabel: curr[groupLabelKey] });
|
|
39
39
|
|
|
40
40
|
return prev.concat(curr[values]);
|
|
41
41
|
}
|
|
@@ -51,25 +51,27 @@ export default class SelectService {
|
|
|
51
51
|
return !opt;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
static removeEmptyGroups(options,
|
|
54
|
+
static removeEmptyGroups(options, groupValueKey) {
|
|
55
55
|
return options.filter((group) => {
|
|
56
|
-
return Boolean(group[
|
|
56
|
+
return Boolean(group[groupValueKey].filter((item) => !item.isSubGroup).length);
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
static removeSelectedValues(options,
|
|
61
|
-
if (!
|
|
60
|
+
static removeSelectedValues(options, groupValueKey, valueKey, modelValue) {
|
|
61
|
+
if (!groupValueKey) {
|
|
62
62
|
return options.filter((option) => !modelValue.includes(option[valueKey]));
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
const availableValues = options.map((group) => {
|
|
66
66
|
return {
|
|
67
67
|
...group,
|
|
68
|
-
[
|
|
68
|
+
[groupValueKey]: group[groupValueKey].filter(
|
|
69
|
+
(item) => !modelValue.includes(item[valueKey]),
|
|
70
|
+
),
|
|
69
71
|
};
|
|
70
72
|
});
|
|
71
73
|
|
|
72
|
-
return this.removeEmptyGroups(availableValues,
|
|
74
|
+
return this.removeEmptyGroups(availableValues, groupValueKey);
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
static interpolateLabel(option, label) {
|
|
@@ -78,17 +80,17 @@ export default class SelectService {
|
|
|
78
80
|
return label ? option[label] : option;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
static getGroupOption(item, options,
|
|
83
|
+
static getGroupOption(item, options, groupValueKey, valueKey) {
|
|
82
84
|
const groupOptions = options.find((option) =>
|
|
83
|
-
option[
|
|
85
|
+
option[groupValueKey]?.find((value) => value[valueKey] === item),
|
|
84
86
|
);
|
|
85
87
|
|
|
86
|
-
return groupOptions?.[
|
|
88
|
+
return groupOptions?.[groupValueKey].find((value) => value[valueKey] === item);
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
static getCurrentOption(item, options,
|
|
90
|
-
if (
|
|
91
|
-
return this.getGroupOption(item, options,
|
|
91
|
+
static getCurrentOption(item, options, groupValueKey, valueKey) {
|
|
92
|
+
if (groupValueKey) {
|
|
93
|
+
return this.getGroupOption(item, options, groupValueKey, valueKey);
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
const value = item[valueKey] || item;
|
|
@@ -2,7 +2,7 @@ export default /*tw*/ {
|
|
|
2
2
|
label: "flex items-start",
|
|
3
3
|
wrapper: {
|
|
4
4
|
base: `
|
|
5
|
-
transition
|
|
5
|
+
transition duration-300
|
|
6
6
|
flex items-center p-0.5 relative rounded-3xl cursor-pointer
|
|
7
7
|
ring-opacity-10 focus-within:ring-4
|
|
8
8
|
`,
|
|
@@ -28,7 +28,7 @@ export default /*tw*/ {
|
|
|
28
28
|
},
|
|
29
29
|
input: "absolute size-0 opacity-0",
|
|
30
30
|
circle: {
|
|
31
|
-
base: "transition
|
|
31
|
+
base: "transition duration-300 rounded-full bg-white flex items-center justify-center",
|
|
32
32
|
variants: {
|
|
33
33
|
size: {
|
|
34
34
|
sm: "size-4",
|
|
@@ -46,7 +46,7 @@ export default /*tw*/ {
|
|
|
46
46
|
selectedIconName: "check",
|
|
47
47
|
unselectedIconName: "close",
|
|
48
48
|
toggleLabel: {
|
|
49
|
-
base: "absolute text-center text-2xs font-medium uppercase text-white transition
|
|
49
|
+
base: "absolute text-center text-2xs font-medium uppercase text-white transition duration-300",
|
|
50
50
|
compoundVariants: [
|
|
51
51
|
{ toggleLabel: true, checked: true, class: "w-1/2 left-1" },
|
|
52
52
|
{ toggleLabel: true, checked: false, class: "w-1/2 right-1" },
|
|
@@ -4,7 +4,7 @@ export default /*tw*/ {
|
|
|
4
4
|
rightSlot: "flex items-center justify-center h-full w-11 absolute right-0",
|
|
5
5
|
textareaWrapper: {
|
|
6
6
|
base: `
|
|
7
|
-
transition
|
|
7
|
+
transition focus-within:outline-none
|
|
8
8
|
rounded-lg border border-solid border-gray-300 ring-0 cursor-text bg-white pr-4
|
|
9
9
|
hover:border-gray-400 pl-4 hover:focus-within:border-gray-500
|
|
10
10
|
focus-within:border-gray-500 focus-within:ring-4 focus-within:ring-gray-600/[.15]
|
|
@@ -53,7 +53,7 @@ export default /*tw*/ {
|
|
|
53
53
|
defaultVariants: {
|
|
54
54
|
size: "md",
|
|
55
55
|
type: "text",
|
|
56
|
-
|
|
56
|
+
inputmode: "text",
|
|
57
57
|
rows: "2",
|
|
58
58
|
labelAlign: "topInside",
|
|
59
59
|
error: false,
|
|
@@ -27,11 +27,10 @@
|
|
|
27
27
|
v-model="localValue"
|
|
28
28
|
:value="modelValue"
|
|
29
29
|
:placeholder="placeholder"
|
|
30
|
-
:type="type"
|
|
31
30
|
:readonly="readonly"
|
|
32
31
|
:disabled="disabled"
|
|
33
32
|
:rows="rows"
|
|
34
|
-
:inputmode="
|
|
33
|
+
:inputmode="inputmode"
|
|
35
34
|
:data-cy="dataCy"
|
|
36
35
|
v-bind="textareaAttrs"
|
|
37
36
|
@focus="onFocus"
|
|
@@ -129,22 +128,13 @@ const props = defineProps({
|
|
|
129
128
|
default: UIService.get(defaultConfig, UTextarea).default.disabled,
|
|
130
129
|
},
|
|
131
130
|
|
|
132
|
-
/**
|
|
133
|
-
* Set input type.
|
|
134
|
-
* @values text, number, email, tel, password, url
|
|
135
|
-
*/
|
|
136
|
-
type: {
|
|
137
|
-
type: String,
|
|
138
|
-
default: UIService.get(defaultConfig, UTextarea).default.type,
|
|
139
|
-
},
|
|
140
|
-
|
|
141
131
|
/**
|
|
142
132
|
* Set proper keyboard on mobile devices.
|
|
143
|
-
* @values text,
|
|
133
|
+
* @values text, decimal, numeric, tel, email, url, search, none
|
|
144
134
|
*/
|
|
145
|
-
|
|
135
|
+
inputmode: {
|
|
146
136
|
type: String,
|
|
147
|
-
default: UIService.get(defaultConfig, UTextarea).default.
|
|
137
|
+
default: UIService.get(defaultConfig, UTextarea).default.inputmode,
|
|
148
138
|
},
|
|
149
139
|
|
|
150
140
|
/**
|
|
@@ -273,7 +263,10 @@ function setLabelPosition() {
|
|
|
273
263
|
|
|
274
264
|
const leftSlotWidth = leftSlotWrapper.value.getBoundingClientRect().width;
|
|
275
265
|
|
|
276
|
-
labelComponent.value.labelElement
|
|
266
|
+
if (labelComponent.value.labelElement) {
|
|
267
|
+
labelComponent.value.labelElement.style.left = `${leftSlotWidth}px`;
|
|
268
|
+
}
|
|
269
|
+
|
|
277
270
|
textareaWrapper.value.style.paddingLeft = `${leftSlotWidth}px`;
|
|
278
271
|
}
|
|
279
272
|
|