vueless 0.0.184 → 0.0.186
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/index.vue +0 -9
- package/ui.dropdown-badge/index.vue +1 -1
- package/ui.dropdown-button/index.vue +1 -1
- package/ui.dropdown-link/index.vue +1 -1
- package/ui.dropdown-list/composables/usePointer.js +23 -14
- package/ui.dropdown-list/configs/default.config.js +1 -1
- package/ui.dropdown-list/index.vue +29 -30
- package/ui.form-checkbox/composables/attrs.composable.js +8 -8
- package/ui.form-checkbox/index.vue +20 -8
- package/ui.form-checkbox-group/index.stories.js +142 -7
- package/ui.form-checkbox-group/index.vue +4 -2
- package/ui.form-radio/configs/default.config.js +5 -1
- package/ui.form-radio/index.vue +35 -10
- package/ui.form-radio-group/Docs.mdx +1 -0
- package/ui.form-radio-group/configs/default.config.js +1 -0
- package/ui.form-radio-group/index.stories.js +141 -11
- package/ui.form-radio-group/index.vue +2 -1
- package/ui.form-select/configs/default.config.js +2 -3
- 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.text-alert/configs/default.config.js +1 -1
- package/web-types.json +18 -40
package/package.json
CHANGED
package/ui.button/index.vue
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
:disabled="disabled"
|
|
7
7
|
:data-cy="dataCy"
|
|
8
8
|
v-bind="buttonAttrs"
|
|
9
|
-
@click="onClick"
|
|
10
9
|
>
|
|
11
10
|
<template v-if="loading">
|
|
12
11
|
<!-- Label is needed to prevent changing button height -->
|
|
@@ -180,8 +179,6 @@ const props = defineProps({
|
|
|
180
179
|
},
|
|
181
180
|
});
|
|
182
181
|
|
|
183
|
-
const emit = defineEmits(["click"]);
|
|
184
|
-
|
|
185
182
|
const { buttonAttrs, loaderAttrs, textAttrs } = useAttrs(props);
|
|
186
183
|
|
|
187
184
|
const buttonRef = ref(null);
|
|
@@ -204,10 +201,4 @@ const loaderSize = computed(() => {
|
|
|
204
201
|
const componentColor = computed(() => {
|
|
205
202
|
return props.variant === "primary" ? "white" : props.color;
|
|
206
203
|
});
|
|
207
|
-
|
|
208
|
-
function onClick(event) {
|
|
209
|
-
if (props.disabled) return;
|
|
210
|
-
|
|
211
|
-
emit("click", event);
|
|
212
|
-
}
|
|
213
204
|
</script>
|
|
@@ -189,7 +189,7 @@ const props = defineProps({
|
|
|
189
189
|
|
|
190
190
|
const emit = defineEmits(["select"]);
|
|
191
191
|
|
|
192
|
-
provide("hideDropdownOptions",
|
|
192
|
+
provide("hideDropdownOptions", hideOptions);
|
|
193
193
|
|
|
194
194
|
const isShownOptions = ref(false);
|
|
195
195
|
const selectedItem = ref("");
|
|
@@ -224,7 +224,7 @@ const props = defineProps({
|
|
|
224
224
|
|
|
225
225
|
const emit = defineEmits(["select"]);
|
|
226
226
|
|
|
227
|
-
provide("hideDropdownOptions",
|
|
227
|
+
provide("hideDropdownOptions", hideOptions);
|
|
228
228
|
|
|
229
229
|
const isShownOptions = ref(false);
|
|
230
230
|
const selectedItem = ref("");
|
|
@@ -210,7 +210,7 @@ const props = defineProps({
|
|
|
210
210
|
|
|
211
211
|
const emit = defineEmits(["select"]);
|
|
212
212
|
|
|
213
|
-
provide("hideDropdownOptions",
|
|
213
|
+
provide("hideDropdownOptions", hideOptions);
|
|
214
214
|
|
|
215
215
|
const isShownOptions = ref(false);
|
|
216
216
|
const selectedItem = ref("");
|
|
@@ -1,17 +1,32 @@
|
|
|
1
|
-
import { ref, computed } from "vue";
|
|
1
|
+
import { ref, computed, toValue } from "vue";
|
|
2
2
|
|
|
3
|
-
export default function usePointer(options,
|
|
3
|
+
export default function usePointer(options, optionElements, listWrapperElement) {
|
|
4
4
|
const pointer = ref(null);
|
|
5
5
|
const pointerDirty = ref(false);
|
|
6
6
|
|
|
7
|
+
const activeElementHeight = computed(() => {
|
|
8
|
+
const isGroupLabel = toValue(optionElements).at(pointer.value).dataset.groupLabel;
|
|
9
|
+
const groupIndex = 2;
|
|
10
|
+
|
|
11
|
+
if (isGroupLabel) {
|
|
12
|
+
return toValue(optionElements)
|
|
13
|
+
.at(pointer.value - groupIndex)
|
|
14
|
+
.getBoundingClientRect().height;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return toValue(optionElements).at(pointer.value).getBoundingClientRect().height;
|
|
18
|
+
});
|
|
19
|
+
|
|
7
20
|
const pointerPosition = computed(() => {
|
|
8
|
-
return pointer.value *
|
|
21
|
+
return pointer.value * activeElementHeight.value || 0;
|
|
9
22
|
});
|
|
10
23
|
|
|
11
24
|
function scrollWrapperToElement() {
|
|
12
|
-
const visibleElements =
|
|
25
|
+
const visibleElements =
|
|
26
|
+
listWrapperElement.value.getBoundingClientRect().height / activeElementHeight.value;
|
|
13
27
|
const currentElement = visibleElements - 1;
|
|
14
|
-
const currentPointerPosition =
|
|
28
|
+
const currentPointerPosition =
|
|
29
|
+
pointerPosition.value - currentElement * activeElementHeight.value;
|
|
15
30
|
|
|
16
31
|
if (listWrapperElement.value.scrollTop <= currentPointerPosition) {
|
|
17
32
|
listWrapperElement.value.scrollTop = currentPointerPosition;
|
|
@@ -22,10 +37,7 @@ export default function usePointer(options, optionHeight, listWrapperElement) {
|
|
|
22
37
|
if (pointer.value < options.length - 1) {
|
|
23
38
|
pointer.value++;
|
|
24
39
|
|
|
25
|
-
const isGroup =
|
|
26
|
-
options[pointer.value].$isLabel ||
|
|
27
|
-
options[pointer.value].isSubGroup ||
|
|
28
|
-
options[pointer.value].$groupLabel;
|
|
40
|
+
const isGroup = options[pointer.value].isSubGroup || options[pointer.value].groupLabel;
|
|
29
41
|
|
|
30
42
|
if (listWrapperElement) scrollWrapperToElement();
|
|
31
43
|
|
|
@@ -41,10 +53,7 @@ export default function usePointer(options, optionHeight, listWrapperElement) {
|
|
|
41
53
|
if (pointer.value > 0) {
|
|
42
54
|
pointer.value--;
|
|
43
55
|
|
|
44
|
-
const isGroup =
|
|
45
|
-
options[pointer.value].$isLabel ||
|
|
46
|
-
options[pointer.value].isSubGroup ||
|
|
47
|
-
options[pointer.value].$groupLabel;
|
|
56
|
+
const isGroup = options[pointer.value].isSubGroup || options[pointer.value].groupLabel;
|
|
48
57
|
|
|
49
58
|
if (listWrapperElement && listWrapperElement.value.scrollTop >= pointerPosition.value) {
|
|
50
59
|
listWrapperElement.value.scrollTop = pointerPosition.value;
|
|
@@ -54,7 +63,7 @@ export default function usePointer(options, optionHeight, listWrapperElement) {
|
|
|
54
63
|
pointerBackward();
|
|
55
64
|
}
|
|
56
65
|
} else {
|
|
57
|
-
if (options[pointer.value] && options[0]
|
|
66
|
+
if (options[pointer.value] && options[0].groupLabel) {
|
|
58
67
|
pointerForward();
|
|
59
68
|
}
|
|
60
69
|
}
|
|
@@ -13,15 +13,14 @@
|
|
|
13
13
|
v-for="(option, index) of options"
|
|
14
14
|
:id="`${id}-${index}`"
|
|
15
15
|
:key="index"
|
|
16
|
-
:role="!(option && (option.$isLabel || option.$isDisabled)) ? 'option' : null"
|
|
17
16
|
v-bind="optionItemAttrs"
|
|
17
|
+
ref="optionsRef"
|
|
18
|
+
:role="!(option && option.groupLabel) ? 'option' : null"
|
|
19
|
+
:data-group-label="Boolean(option.groupLabel)"
|
|
18
20
|
>
|
|
19
21
|
<!-- option title -->
|
|
20
22
|
<span
|
|
21
|
-
v-if="
|
|
22
|
-
!(option && (option.$isLabel || option.$isDisabled || option.isSubGroup)) &&
|
|
23
|
-
!option.isHidden
|
|
24
|
-
"
|
|
23
|
+
v-if="!(option && (option.groupLabel || option.isSubGroup)) && !option.isHidden"
|
|
25
24
|
v-bind="optionAttrs(optionHighlight(index, option))"
|
|
26
25
|
@click.stop="select(option)"
|
|
27
26
|
@mouseenter.self="pointerSet(index)"
|
|
@@ -42,14 +41,8 @@
|
|
|
42
41
|
</span>
|
|
43
42
|
|
|
44
43
|
<!-- group title -->
|
|
45
|
-
<div
|
|
46
|
-
v-if="
|
|
47
|
-
option &&
|
|
48
|
-
(option.$isLabel || option.$isDisabled || option.isSubGroup) &&
|
|
49
|
-
!option.isHidden
|
|
50
|
-
"
|
|
51
|
-
>
|
|
52
|
-
<div v-if="option.$groupLabel" v-bind="groupLabelAttrs" v-text="option.$groupLabel" />
|
|
44
|
+
<div v-if="option && (option.groupLabel || option.isSubGroup) && !option.isHidden">
|
|
45
|
+
<div v-if="option.groupLabel" v-bind="groupLabelAttrs" v-text="option.groupLabel" />
|
|
53
46
|
|
|
54
47
|
<div
|
|
55
48
|
v-else-if="option.isSubGroup"
|
|
@@ -180,19 +173,11 @@ const props = defineProps({
|
|
|
180
173
|
},
|
|
181
174
|
|
|
182
175
|
/**
|
|
183
|
-
*
|
|
176
|
+
* Amount of options you can see without scroll.
|
|
184
177
|
*/
|
|
185
|
-
|
|
178
|
+
visibleOptions: {
|
|
186
179
|
type: Number,
|
|
187
|
-
default: UIService.get(defaultConfig, UDropdownList).default.
|
|
188
|
-
},
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* List option height in pixels.
|
|
192
|
-
*/
|
|
193
|
-
optionHeight: {
|
|
194
|
-
type: Number,
|
|
195
|
-
default: UIService.get(defaultConfig, UDropdownList).default.optionHeight,
|
|
180
|
+
default: UIService.get(defaultConfig, UDropdownList).default.visibleOptions,
|
|
196
181
|
},
|
|
197
182
|
|
|
198
183
|
/**
|
|
@@ -216,9 +201,10 @@ const props = defineProps({
|
|
|
216
201
|
const emit = defineEmits(["update:modelValue", "addOption"]);
|
|
217
202
|
|
|
218
203
|
const wrapperRef = ref(null);
|
|
204
|
+
const optionsRef = ref([]);
|
|
219
205
|
|
|
220
206
|
const { pointer, pointerDirty, pointerSet, pointerBackward, pointerForward, pointerReset } =
|
|
221
|
-
usePointer(props.options,
|
|
207
|
+
usePointer(props.options, optionsRef, wrapperRef);
|
|
222
208
|
|
|
223
209
|
const {
|
|
224
210
|
config,
|
|
@@ -240,7 +226,15 @@ const {
|
|
|
240
226
|
|
|
241
227
|
const { tm } = useLocale();
|
|
242
228
|
|
|
243
|
-
defineExpose({
|
|
229
|
+
defineExpose({
|
|
230
|
+
pointerSet,
|
|
231
|
+
pointerBackward,
|
|
232
|
+
pointerForward,
|
|
233
|
+
pointerReset,
|
|
234
|
+
addPointerElement,
|
|
235
|
+
optionsRef,
|
|
236
|
+
wrapperRef,
|
|
237
|
+
});
|
|
244
238
|
|
|
245
239
|
const i18nGlobal = tm(UDropdownList);
|
|
246
240
|
const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config.i18n));
|
|
@@ -249,16 +243,21 @@ const addOptionKeyCombination = computed(() => {
|
|
|
249
243
|
return isMac ? "(⌘ + Enter)" : "(Ctrl + Enter)";
|
|
250
244
|
});
|
|
251
245
|
|
|
252
|
-
const wrapperHeight = computed(() =>
|
|
253
|
-
|
|
254
|
-
)
|
|
246
|
+
const wrapperHeight = computed(() => {
|
|
247
|
+
const maxHeight = optionsRef.value
|
|
248
|
+
.slice(0, props.visibleOptions)
|
|
249
|
+
.map((el) => el.getBoundingClientRect().height)
|
|
250
|
+
.reduce((acc, cur) => acc + cur, 0);
|
|
251
|
+
|
|
252
|
+
return props.visibleOptions === undefined ? "auto" : `${maxHeight}px`;
|
|
253
|
+
});
|
|
255
254
|
|
|
256
255
|
function onClickAddOption() {
|
|
257
256
|
emit("addOption");
|
|
258
257
|
}
|
|
259
258
|
|
|
260
259
|
function select(option, key) {
|
|
261
|
-
if (props.disabled || option
|
|
260
|
+
if (props.disabled || option.groupLabel) {
|
|
262
261
|
return;
|
|
263
262
|
}
|
|
264
263
|
|
|
@@ -4,7 +4,7 @@ import { cva } from "../../service.ui";
|
|
|
4
4
|
|
|
5
5
|
import defaultConfig from "../configs/default.config";
|
|
6
6
|
|
|
7
|
-
export function useAttrs(props) {
|
|
7
|
+
export function useAttrs(props, { checkboxColor, checkboxSize }) {
|
|
8
8
|
const { config, getAttrs, getColor, setColor } = useUI(defaultConfig, () => props.config);
|
|
9
9
|
const { checkbox, iconWrapper } = config.value;
|
|
10
10
|
|
|
@@ -23,22 +23,22 @@ export function useAttrs(props) {
|
|
|
23
23
|
const checkboxClasses = computed(() =>
|
|
24
24
|
setColor(
|
|
25
25
|
cvaCheckbox({
|
|
26
|
-
size:
|
|
26
|
+
size: checkboxSize.value,
|
|
27
27
|
label: Boolean(props.label),
|
|
28
|
-
color: getColor(
|
|
29
|
-
disabled: props.
|
|
28
|
+
color: getColor(checkboxColor.value),
|
|
29
|
+
disabled: props.disabled,
|
|
30
30
|
}),
|
|
31
|
-
|
|
31
|
+
checkboxColor.value,
|
|
32
32
|
),
|
|
33
33
|
);
|
|
34
34
|
|
|
35
35
|
const iconWrapperClasses = computed(() =>
|
|
36
36
|
setColor(
|
|
37
37
|
cvaIconWrapper({
|
|
38
|
-
size:
|
|
39
|
-
color: getColor(
|
|
38
|
+
size: checkboxSize.value,
|
|
39
|
+
color: getColor(checkboxColor.value),
|
|
40
40
|
}),
|
|
41
|
-
|
|
41
|
+
checkboxColor.value,
|
|
42
42
|
),
|
|
43
43
|
);
|
|
44
44
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<ULabel
|
|
3
3
|
:for="id"
|
|
4
|
-
:size="
|
|
4
|
+
:size="checkboxSize"
|
|
5
5
|
:label="label"
|
|
6
6
|
:description="description"
|
|
7
7
|
:align="labelAlign"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
</template>
|
|
40
40
|
|
|
41
41
|
<script setup>
|
|
42
|
-
import { inject, ref, onMounted, computed } from "vue";
|
|
42
|
+
import { inject, ref, onMounted, computed, watchEffect } from "vue";
|
|
43
43
|
import { isEqual } from "lodash-es";
|
|
44
44
|
|
|
45
45
|
import UIcon from "../ui.image-icon";
|
|
@@ -54,9 +54,11 @@ import { useAttrs } from "./composables/attrs.composable";
|
|
|
54
54
|
/* Should be a string for correct web-types gen */
|
|
55
55
|
defineOptions({ name: "UCheckbox", inheritAttrs: false });
|
|
56
56
|
|
|
57
|
-
const
|
|
58
|
-
const
|
|
57
|
+
const getCheckboxGroupName = inject("getCheckboxGroupName", null);
|
|
58
|
+
const getCheckboxGroupCheckedItems = inject("getCheckboxGroupCheckedItems", null);
|
|
59
59
|
const setCheckboxGroupCheckedItems = inject("setCheckboxGroupCheckedItems", null);
|
|
60
|
+
const getCheckboxGroupColor = inject("getCheckboxGroupColor", null);
|
|
61
|
+
const getCheckboxSize = inject("getCheckboxSize", null);
|
|
60
62
|
|
|
61
63
|
const props = defineProps({
|
|
62
64
|
/**
|
|
@@ -187,8 +189,13 @@ const props = defineProps({
|
|
|
187
189
|
const emit = defineEmits(["update:modelValue", "input"]);
|
|
188
190
|
|
|
189
191
|
const checkboxName = ref("");
|
|
192
|
+
const checkboxSize = ref(props.size);
|
|
193
|
+
const checkboxColor = ref(props.color);
|
|
190
194
|
|
|
191
|
-
const { config, checkboxAttrs, iconWrapperCellAttrs, labelAttrs, iconAttrs } = useAttrs(props
|
|
195
|
+
const { config, checkboxAttrs, iconWrapperCellAttrs, labelAttrs, iconAttrs } = useAttrs(props, {
|
|
196
|
+
checkboxColor,
|
|
197
|
+
checkboxSize,
|
|
198
|
+
});
|
|
192
199
|
|
|
193
200
|
const iconSize = computed(() => {
|
|
194
201
|
const sizes = {
|
|
@@ -203,7 +210,7 @@ const iconSize = computed(() => {
|
|
|
203
210
|
});
|
|
204
211
|
|
|
205
212
|
const isBinary = computed(() => !Array.isArray(props.modelValue));
|
|
206
|
-
const isCheckboxInGroup = computed(() => Boolean(
|
|
213
|
+
const isCheckboxInGroup = computed(() => Boolean(getCheckboxGroupName()));
|
|
207
214
|
|
|
208
215
|
const isChecked = computed(() => {
|
|
209
216
|
return isBinary.value && !isCheckboxInGroup.value
|
|
@@ -216,13 +223,18 @@ const checkboxValue = computed(() => {
|
|
|
216
223
|
});
|
|
217
224
|
|
|
218
225
|
const currentValue = computed(() => {
|
|
219
|
-
return isCheckboxInGroup.value ?
|
|
226
|
+
return isCheckboxInGroup.value ? getCheckboxGroupCheckedItems() : props.modelValue;
|
|
220
227
|
});
|
|
221
228
|
|
|
222
229
|
onMounted(() => {
|
|
223
|
-
checkboxName.value = isCheckboxInGroup.value ?
|
|
230
|
+
checkboxName.value = isCheckboxInGroup.value ? getCheckboxGroupName() : props.name;
|
|
224
231
|
});
|
|
225
232
|
|
|
233
|
+
watchEffect(
|
|
234
|
+
() => (checkboxColor.value = getCheckboxGroupColor ? getCheckboxGroupColor() : props.color),
|
|
235
|
+
);
|
|
236
|
+
watchEffect(() => (checkboxSize.value = getCheckboxSize ? getCheckboxSize() : props.size));
|
|
237
|
+
|
|
226
238
|
function onChange() {
|
|
227
239
|
let newModelValue;
|
|
228
240
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { getArgTypes } from "../service.storybook";
|
|
2
2
|
|
|
3
3
|
import UCheckboxGroup from "../ui.form-checkbox-group";
|
|
4
|
+
import UCheckbox from "../ui.form-checkbox";
|
|
5
|
+
import UAlert from "../ui.text-alert";
|
|
6
|
+
import URow from "../ui.container-row";
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* The `UCheckboxGroup` component. | [View on GitHub](https://github.com/vuelessjs/vueless/tree/main/src/ui.form-checkbox-group)
|
|
@@ -16,7 +19,7 @@ export default {
|
|
|
16
19
|
{ label: "checkbox 2", description: "some description 2", value: "2" },
|
|
17
20
|
{ label: "checkbox 3", description: "some description 3", value: "3" },
|
|
18
21
|
],
|
|
19
|
-
value: ["
|
|
22
|
+
value: ["One"],
|
|
20
23
|
},
|
|
21
24
|
argTypes: {
|
|
22
25
|
...getArgTypes(UCheckboxGroup.name),
|
|
@@ -24,25 +27,157 @@ export default {
|
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
const DefaultTemplate = (args) => ({
|
|
27
|
-
components: { UCheckboxGroup },
|
|
30
|
+
components: { UCheckboxGroup, UCheckbox, UAlert, URow },
|
|
28
31
|
setup() {
|
|
29
32
|
return { args };
|
|
30
33
|
},
|
|
31
34
|
data() {
|
|
32
35
|
return {
|
|
33
|
-
|
|
36
|
+
value: args.value,
|
|
34
37
|
};
|
|
35
38
|
},
|
|
36
39
|
template: `
|
|
37
|
-
<
|
|
40
|
+
<URow class="!flex-col">
|
|
41
|
+
<UCheckboxGroup v-bind="args" v-model="value">
|
|
42
|
+
<template v-for="(radio, index) in args.options" :key="index">
|
|
43
|
+
<UCheckbox
|
|
44
|
+
v-bind="radio"
|
|
45
|
+
>
|
|
46
|
+
</UCheckbox>
|
|
47
|
+
</template>
|
|
48
|
+
</UCheckboxGroup>
|
|
49
|
+
|
|
50
|
+
<URow>
|
|
51
|
+
<UAlert color="red" v-if=args.isDefaultStory>
|
|
52
|
+
<b>NOTE:</b> <p>UCheckboxGroup component have to have unique name attribute</p>
|
|
53
|
+
</UAlert>
|
|
54
|
+
<UAlert color="blue">
|
|
55
|
+
<p>Selected value: {{ value }}</p>
|
|
56
|
+
</UAlert>
|
|
57
|
+
</URow>
|
|
58
|
+
</URow>
|
|
59
|
+
`,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const OptionsTemplate = (args) => ({
|
|
63
|
+
components: { UCheckboxGroup, UCheckbox, UAlert, URow },
|
|
64
|
+
setup() {
|
|
65
|
+
return { args };
|
|
66
|
+
},
|
|
67
|
+
data() {
|
|
68
|
+
return {
|
|
69
|
+
value: args.value,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
template: `
|
|
73
|
+
<URow class="!flex-col">
|
|
74
|
+
<UCheckboxGroup v-bind="args" v-model="value" :options="args.options" />
|
|
75
|
+
|
|
76
|
+
<URow>
|
|
77
|
+
<UAlert color="blue">
|
|
78
|
+
<p>Selected value: {{ value }}</p>
|
|
79
|
+
</UAlert>
|
|
80
|
+
</URow>
|
|
81
|
+
</URow>
|
|
38
82
|
`,
|
|
39
83
|
});
|
|
40
84
|
|
|
41
85
|
export const Default = DefaultTemplate.bind({});
|
|
42
|
-
Default.args = {
|
|
86
|
+
Default.args = {
|
|
87
|
+
name: "Default",
|
|
88
|
+
isDefaultStory: true,
|
|
89
|
+
options: [
|
|
90
|
+
{ name: "Default", label: "String", description: "some description 1", value: "One" },
|
|
91
|
+
{ name: "Default", label: "Boolean", description: "some description 2", value: false },
|
|
92
|
+
{
|
|
93
|
+
name: "Default",
|
|
94
|
+
label: "Object",
|
|
95
|
+
description: "some description 3",
|
|
96
|
+
value: { key: "value" },
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "Default",
|
|
100
|
+
label: "Object",
|
|
101
|
+
description: "some description 4",
|
|
102
|
+
value: ["Array", 1],
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const Options = OptionsTemplate.bind({});
|
|
108
|
+
Options.args = {
|
|
109
|
+
name: "Options",
|
|
110
|
+
options: [
|
|
111
|
+
{ name: "Options", label: "Boolean", value: false },
|
|
112
|
+
{ name: "Options", label: "String", value: "One" },
|
|
113
|
+
{ name: "Options", label: "Number", value: 3 },
|
|
114
|
+
{ name: "Options", label: "Object", value: { key: "value" } },
|
|
115
|
+
{ name: "Options", label: "Array", value: ["Array", 1] },
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const ColorsTemplate = (args, { argTypes } = {}) => ({
|
|
120
|
+
components: { UCheckboxGroup, URow },
|
|
121
|
+
setup() {
|
|
122
|
+
return { args };
|
|
123
|
+
},
|
|
124
|
+
data() {
|
|
125
|
+
return {
|
|
126
|
+
value: args.value,
|
|
127
|
+
colors: argTypes.color.options,
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
template: `
|
|
131
|
+
<URow class="!flex-col">
|
|
132
|
+
<UCheckboxGroup
|
|
133
|
+
v-bind="args"
|
|
134
|
+
v-for="color in colors"
|
|
135
|
+
:key="color"
|
|
136
|
+
:label="color"
|
|
137
|
+
:color="color"
|
|
138
|
+
:options="args.options"
|
|
139
|
+
name="color"
|
|
140
|
+
v-model="value"
|
|
141
|
+
/>
|
|
142
|
+
</URow>
|
|
143
|
+
`,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const SizesTemplate = (args, { argTypes } = {}) => ({
|
|
147
|
+
components: { UCheckboxGroup, URow },
|
|
148
|
+
setup() {
|
|
149
|
+
return { args };
|
|
150
|
+
},
|
|
151
|
+
data() {
|
|
152
|
+
return {
|
|
153
|
+
value: args.value,
|
|
154
|
+
sizes: argTypes.size.options,
|
|
155
|
+
};
|
|
156
|
+
},
|
|
157
|
+
template: `
|
|
158
|
+
<URow class="!flex-col">
|
|
159
|
+
<UCheckboxGroup
|
|
160
|
+
v-bind="args"
|
|
161
|
+
v-for="size in sizes"
|
|
162
|
+
:key="size"
|
|
163
|
+
:label="size"
|
|
164
|
+
:size="size"
|
|
165
|
+
:options="args.options"
|
|
166
|
+
name="size"
|
|
167
|
+
v-model="value"
|
|
168
|
+
/>
|
|
169
|
+
</URow>
|
|
170
|
+
`,
|
|
171
|
+
});
|
|
43
172
|
|
|
44
173
|
export const disabled = DefaultTemplate.bind({});
|
|
45
|
-
disabled.args = { disabled: true };
|
|
174
|
+
disabled.args = { name: "Disabled", disabled: true };
|
|
46
175
|
|
|
47
176
|
export const error = DefaultTemplate.bind({});
|
|
48
|
-
error.args = { error: "some error" };
|
|
177
|
+
error.args = { name: "Error", error: "some error" };
|
|
178
|
+
|
|
179
|
+
export const Colors = ColorsTemplate.bind({});
|
|
180
|
+
Colors.args = { name: "Colors" };
|
|
181
|
+
|
|
182
|
+
export const Sizes = SizesTemplate.bind({});
|
|
183
|
+
Sizes.args = { name: "Sizes" };
|
|
@@ -144,8 +144,10 @@ const checkedItems = ref([]);
|
|
|
144
144
|
const { labelAttrs, checkboxAttrs, listAttrs } = useAttrs(props);
|
|
145
145
|
|
|
146
146
|
provide("setCheckboxGroupCheckedItems", (value) => (checkedItems.value = value));
|
|
147
|
-
provide("
|
|
148
|
-
provide("
|
|
147
|
+
provide("getCheckboxGroupCheckedItems", () => checkedItems.value);
|
|
148
|
+
provide("getCheckboxGroupName", () => props.name);
|
|
149
|
+
provide("getCheckboxGroupColor", () => props.color);
|
|
150
|
+
provide("getCheckboxSize", () => props.size);
|
|
149
151
|
|
|
150
152
|
watch(() => checkedItems.value.length, onChangeCheckedItems);
|
|
151
153
|
watch(() => props.modelValue.length, onModelValueChange, { immediate: true });
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export default /*tw*/ {
|
|
2
|
-
label:
|
|
2
|
+
label: {
|
|
3
|
+
wrapper: "inline-flex",
|
|
4
|
+
label: "cursor-pointer",
|
|
5
|
+
},
|
|
3
6
|
radio: {
|
|
4
7
|
base: `
|
|
8
|
+
cursor-pointer
|
|
5
9
|
transition duration-100 ease-in-out
|
|
6
10
|
border border-solid border-{color}-300 text-{color}-500
|
|
7
11
|
hover:border-{color}-400
|
package/ui.form-radio/index.vue
CHANGED
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
:disabled="disabled"
|
|
16
16
|
:name="radioName"
|
|
17
17
|
:value="radioValue"
|
|
18
|
-
:checked="checked"
|
|
18
|
+
:checked="checked || isChecked"
|
|
19
19
|
:data-cy="dataCy"
|
|
20
20
|
v-bind="radioAttrs"
|
|
21
|
-
@
|
|
21
|
+
@change="onChange"
|
|
22
22
|
/>
|
|
23
23
|
|
|
24
24
|
<slot />
|
|
@@ -42,7 +42,21 @@ import { URadio } from "./constants";
|
|
|
42
42
|
/* Should be a string for correct web-types gen */
|
|
43
43
|
defineOptions({ name: "URadio", inheritAttrs: false });
|
|
44
44
|
|
|
45
|
+
const setRadioGroupSelectedItem = inject("setRadioGroupSelectedItem", null);
|
|
46
|
+
const getRadioGroupName = inject("getRadioGroupName", null);
|
|
47
|
+
const getRadioGroupColor = inject("getRadioGroupColor", null);
|
|
48
|
+
const getRadioGroupSize = inject("getRadioGroupSize", null);
|
|
49
|
+
const getRadioGroupSelectedItem = inject("getRadioGroupSelectedItem", null);
|
|
50
|
+
|
|
45
51
|
const props = defineProps({
|
|
52
|
+
/**
|
|
53
|
+
* Native value attribute.
|
|
54
|
+
*/
|
|
55
|
+
modelValue: {
|
|
56
|
+
type: [Boolean, String, Number, Array, Object],
|
|
57
|
+
default: null,
|
|
58
|
+
},
|
|
59
|
+
|
|
46
60
|
/**
|
|
47
61
|
* Native value attribute.
|
|
48
62
|
*/
|
|
@@ -146,15 +160,21 @@ const props = defineProps({
|
|
|
146
160
|
|
|
147
161
|
const emit = defineEmits(["update:modelValue"]);
|
|
148
162
|
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
const getRadioGroupColor = inject("getRadioGroupColor", null);
|
|
152
|
-
const getRadioGroupSize = inject("getRadioGroupSize", null);
|
|
153
|
-
|
|
154
|
-
const radioName = ref("");
|
|
163
|
+
const localValue = ref("");
|
|
164
|
+
const radioName = ref(null);
|
|
155
165
|
const radioColor = ref(getRadioGroupColor ? getRadioGroupColor() : props.color);
|
|
156
166
|
const radioSize = ref(getRadioGroupSize ? getRadioGroupSize() : props.size);
|
|
157
167
|
|
|
168
|
+
const isChecked = computed(() => {
|
|
169
|
+
const currentValue = props.modelValue ?? localValue.value;
|
|
170
|
+
|
|
171
|
+
if (typeof currentValue !== "object") {
|
|
172
|
+
return currentValue === props.value;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return JSON.stringify(currentValue) === JSON.stringify(props.value);
|
|
176
|
+
});
|
|
177
|
+
|
|
158
178
|
const { radioAttrs, labelAttrs } = useAttrs(props, { radioColor, radioSize });
|
|
159
179
|
|
|
160
180
|
const radioValue = computed(() => {
|
|
@@ -162,13 +182,18 @@ const radioValue = computed(() => {
|
|
|
162
182
|
});
|
|
163
183
|
|
|
164
184
|
onMounted(() => {
|
|
165
|
-
radioName.value = props.name || getRadioGroupName;
|
|
185
|
+
radioName.value = props.name || getRadioGroupName();
|
|
166
186
|
});
|
|
167
187
|
|
|
168
188
|
watchEffect(() => (radioColor.value = getRadioGroupColor ? getRadioGroupColor() : props.color));
|
|
169
189
|
watchEffect(() => (radioSize.value = getRadioGroupSize ? getRadioGroupSize() : props.size));
|
|
190
|
+
watchEffect(() => {
|
|
191
|
+
localValue.value = getRadioGroupSelectedItem ? getRadioGroupSelectedItem() : null;
|
|
192
|
+
|
|
193
|
+
emit("update:modelValue", props.value);
|
|
194
|
+
});
|
|
170
195
|
|
|
171
|
-
function
|
|
196
|
+
function onChange(event) {
|
|
172
197
|
setRadioGroupSelectedItem && setRadioGroupSelectedItem(props.value);
|
|
173
198
|
|
|
174
199
|
emit("update:modelValue", event.target.value);
|
|
@@ -2,6 +2,8 @@ import { getArgTypes } from "../service.storybook";
|
|
|
2
2
|
|
|
3
3
|
import URadioGroup from "../ui.form-radio-group";
|
|
4
4
|
import URadio from "../ui.form-radio";
|
|
5
|
+
import UAlert from "../ui.text-alert";
|
|
6
|
+
import URow from "../ui.container-row";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* The `URadioGroup` component. | [View on GitHub](https://github.com/vuelessjs/vueless/tree/main/src/ui.form-radio-group)
|
|
@@ -10,9 +12,16 @@ export default {
|
|
|
10
12
|
id: "3160",
|
|
11
13
|
title: "Form Inputs & Controls / Radio Group",
|
|
12
14
|
component: URadioGroup,
|
|
15
|
+
parameters: {
|
|
16
|
+
docs: {
|
|
17
|
+
description: {
|
|
18
|
+
story: "Another description on the story, overriding the comments",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
13
22
|
args: {
|
|
14
23
|
label: "Label",
|
|
15
|
-
value: "
|
|
24
|
+
value: "One",
|
|
16
25
|
radios: [
|
|
17
26
|
{ name: "radio", label: "Radio 1", value: "1" },
|
|
18
27
|
{ name: "radio", label: "Radio 2", value: "2" },
|
|
@@ -25,21 +34,142 @@ export default {
|
|
|
25
34
|
};
|
|
26
35
|
|
|
27
36
|
const DefaultTemplate = (args) => ({
|
|
28
|
-
components: { URadioGroup, URadio },
|
|
37
|
+
components: { URadioGroup, URadio, UAlert, URow },
|
|
38
|
+
setup() {
|
|
39
|
+
return { args };
|
|
40
|
+
},
|
|
41
|
+
data() {
|
|
42
|
+
return {
|
|
43
|
+
value: args.value,
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
template: `
|
|
47
|
+
<URow class="!flex-col">
|
|
48
|
+
<URadioGroup v-bind="args" v-model="value">
|
|
49
|
+
<template v-for="(radio,index) in args.radios" :key="index">
|
|
50
|
+
<URadio
|
|
51
|
+
v-bind="radio"
|
|
52
|
+
>
|
|
53
|
+
</URadio>
|
|
54
|
+
</template>
|
|
55
|
+
</URadioGroup>
|
|
56
|
+
|
|
57
|
+
<URow>
|
|
58
|
+
<UAlert color="red" v-if=args.isDefaultStory>
|
|
59
|
+
<b>NOTE:</b> <p>URadioGroup component have to have unique name attribute</p>
|
|
60
|
+
</UAlert>
|
|
61
|
+
<UAlert color="blue">
|
|
62
|
+
<p>Selected value: {{ value }}</p>
|
|
63
|
+
</UAlert>
|
|
64
|
+
</URow>
|
|
65
|
+
</URow>
|
|
66
|
+
`,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const OptionsTemplate = (args) => ({
|
|
70
|
+
components: { URadioGroup, URadio, UAlert, URow },
|
|
71
|
+
setup() {
|
|
72
|
+
return { args };
|
|
73
|
+
},
|
|
74
|
+
data() {
|
|
75
|
+
return {
|
|
76
|
+
value: args.value,
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
template: `
|
|
80
|
+
<URow class="!flex-col">
|
|
81
|
+
<URadioGroup v-bind="args" v-model="value" :options="args.radios" />
|
|
82
|
+
|
|
83
|
+
<URow>
|
|
84
|
+
<UAlert color="blue">
|
|
85
|
+
<p>Selected value: {{ value }}</p>
|
|
86
|
+
</UAlert>
|
|
87
|
+
</URow>
|
|
88
|
+
</URow>
|
|
89
|
+
`,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const ColorsTemplate = (args, { argTypes } = {}) => ({
|
|
93
|
+
components: { URadioGroup, URow },
|
|
94
|
+
setup() {
|
|
95
|
+
return { args };
|
|
96
|
+
},
|
|
97
|
+
data() {
|
|
98
|
+
return {
|
|
99
|
+
value: args.value,
|
|
100
|
+
colors: argTypes.color.options,
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
template: `
|
|
104
|
+
<URow class="!flex-col">
|
|
105
|
+
<URadioGroup
|
|
106
|
+
v-bind="args"
|
|
107
|
+
v-for="color in colors"
|
|
108
|
+
:key="color"
|
|
109
|
+
:label="color"
|
|
110
|
+
:color="color"
|
|
111
|
+
:options="args.radios"
|
|
112
|
+
name="color"
|
|
113
|
+
v-model="value"
|
|
114
|
+
/>
|
|
115
|
+
</URow>
|
|
116
|
+
`,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const SizesTemplate = (args, { argTypes } = {}) => ({
|
|
120
|
+
components: { URadioGroup, URow },
|
|
29
121
|
setup() {
|
|
30
122
|
return { args };
|
|
31
123
|
},
|
|
124
|
+
data() {
|
|
125
|
+
return {
|
|
126
|
+
value: args.value,
|
|
127
|
+
sizes: argTypes.size.options,
|
|
128
|
+
};
|
|
129
|
+
},
|
|
32
130
|
template: `
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
131
|
+
<URow class="!flex-col">
|
|
132
|
+
<URadioGroup
|
|
133
|
+
v-bind="args"
|
|
134
|
+
v-for="size in sizes"
|
|
135
|
+
:key="size"
|
|
136
|
+
:label="size"
|
|
137
|
+
:size="size"
|
|
138
|
+
:options="args.radios"
|
|
139
|
+
name="size"
|
|
140
|
+
v-model="value"
|
|
141
|
+
/>
|
|
142
|
+
</URow>
|
|
41
143
|
`,
|
|
42
144
|
});
|
|
43
145
|
|
|
44
146
|
export const Default = DefaultTemplate.bind({});
|
|
45
|
-
Default.args = {
|
|
147
|
+
Default.args = {
|
|
148
|
+
name: "Default",
|
|
149
|
+
isDefaultStory: true,
|
|
150
|
+
radios: [
|
|
151
|
+
{ name: "slotValues", label: "Boolean", value: false },
|
|
152
|
+
{ name: "slotValues", label: "String", value: "One" },
|
|
153
|
+
{ name: "slotValues", label: "Number", value: 3 },
|
|
154
|
+
{ name: "slotValues", label: "Object", value: { key: "value" } },
|
|
155
|
+
{ name: "slotValues", label: "Array", value: ["Array", 1] },
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export const Options = OptionsTemplate.bind({});
|
|
160
|
+
Options.args = {
|
|
161
|
+
name: "Options",
|
|
162
|
+
radios: [
|
|
163
|
+
{ name: "radioValues", label: "Boolean", value: false },
|
|
164
|
+
{ name: "radioValues", label: "String", value: "One" },
|
|
165
|
+
{ name: "radioValues", label: "Number", value: 3 },
|
|
166
|
+
{ name: "radioValues", label: "Object", value: { key: "value" } },
|
|
167
|
+
{ name: "radioValues", label: "Array", value: ["Array", 1] },
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export const Colors = ColorsTemplate.bind({});
|
|
172
|
+
Colors.args = { name: "Colors" };
|
|
173
|
+
|
|
174
|
+
export const Sizes = SizesTemplate.bind({});
|
|
175
|
+
Sizes.args = { name: "Sizes" };
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<URadio
|
|
15
15
|
v-for="(option, index) in options"
|
|
16
16
|
:key="option.value"
|
|
17
|
-
:model-value="
|
|
17
|
+
:model-value="selectedItem"
|
|
18
18
|
:value="option.value"
|
|
19
19
|
:label="option.label"
|
|
20
20
|
:description="option.description"
|
|
@@ -143,6 +143,7 @@ const selectedItem = computed({
|
|
|
143
143
|
});
|
|
144
144
|
|
|
145
145
|
provide("setRadioGroupSelectedItem", (value) => (selectedItem.value = value));
|
|
146
|
+
provide("getRadioGroupSelectedItem", () => selectedItem.value);
|
|
146
147
|
provide("getRadioGroupName", () => props.name);
|
|
147
148
|
provide("getRadioGroupColor", () => props.color);
|
|
148
149
|
provide("getRadioGroupSize", () => props.size);
|
|
@@ -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;
|
|
@@ -17,7 +17,7 @@ export default /*tw*/ {
|
|
|
17
17
|
base: `
|
|
18
18
|
flex gap-2 items-baseline
|
|
19
19
|
font-normal leading-normal
|
|
20
|
-
[&_b]:font-bold [&_i]:italic [&_p]:font-normal
|
|
20
|
+
[&_b]:font-bold [&_b]:font-bold [&_i]:italic [&_em]:italic [&_p]:font-normal
|
|
21
21
|
[&_a:not([class])]:underline [&_a:not([class])]:underline-offset-4
|
|
22
22
|
[&_a:not([class]):hover]:no-underline [&_a:not([class])]:font-bold
|
|
23
23
|
[&_ul]:font-normal [&_ol]:font-normal
|
package/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"framework": "vue",
|
|
3
3
|
"name": "vueless",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.186",
|
|
5
5
|
"contributions": {
|
|
6
6
|
"html": {
|
|
7
7
|
"description-markup": "markdown",
|
|
@@ -826,11 +826,6 @@
|
|
|
826
826
|
"default": "\"\""
|
|
827
827
|
}
|
|
828
828
|
],
|
|
829
|
-
"events": [
|
|
830
|
-
{
|
|
831
|
-
"name": "click"
|
|
832
|
-
}
|
|
833
|
-
],
|
|
834
829
|
"slots": [
|
|
835
830
|
{
|
|
836
831
|
"name": "left",
|
|
@@ -2853,22 +2848,13 @@
|
|
|
2853
2848
|
"default": "md"
|
|
2854
2849
|
},
|
|
2855
2850
|
{
|
|
2856
|
-
"name": "
|
|
2857
|
-
"description": "
|
|
2851
|
+
"name": "visibleOptions",
|
|
2852
|
+
"description": "Amount of options you can see without scroll.",
|
|
2858
2853
|
"value": {
|
|
2859
2854
|
"kind": "expression",
|
|
2860
2855
|
"type": "number"
|
|
2861
2856
|
}
|
|
2862
2857
|
},
|
|
2863
|
-
{
|
|
2864
|
-
"name": "optionHeight",
|
|
2865
|
-
"description": "List option height in pixels.",
|
|
2866
|
-
"value": {
|
|
2867
|
-
"kind": "expression",
|
|
2868
|
-
"type": "number"
|
|
2869
|
-
},
|
|
2870
|
-
"default": "40"
|
|
2871
|
-
},
|
|
2872
2858
|
{
|
|
2873
2859
|
"name": "id",
|
|
2874
2860
|
"description": "@ignore: Generates unique element id.",
|
|
@@ -5796,6 +5782,15 @@
|
|
|
5796
5782
|
"name": "URadio",
|
|
5797
5783
|
"description": "",
|
|
5798
5784
|
"attributes": [
|
|
5785
|
+
{
|
|
5786
|
+
"name": "modelValue",
|
|
5787
|
+
"description": "Native value attribute.",
|
|
5788
|
+
"value": {
|
|
5789
|
+
"kind": "expression",
|
|
5790
|
+
"type": "boolean|string|number|array|object"
|
|
5791
|
+
},
|
|
5792
|
+
"default": "null"
|
|
5793
|
+
},
|
|
5799
5794
|
{
|
|
5800
5795
|
"name": "value",
|
|
5801
5796
|
"description": "Native value attribute.",
|
|
@@ -6207,7 +6202,7 @@
|
|
|
6207
6202
|
"default": "id"
|
|
6208
6203
|
},
|
|
6209
6204
|
{
|
|
6210
|
-
"name": "
|
|
6205
|
+
"name": "groupLabelKey",
|
|
6211
6206
|
"description": "Set a name of the property containing the group label.",
|
|
6212
6207
|
"value": {
|
|
6213
6208
|
"kind": "expression",
|
|
@@ -6216,7 +6211,7 @@
|
|
|
6216
6211
|
"default": "\"label\""
|
|
6217
6212
|
},
|
|
6218
6213
|
{
|
|
6219
|
-
"name": "
|
|
6214
|
+
"name": "groupValueKey",
|
|
6220
6215
|
"description": "Set a name of the property containing the group values.",
|
|
6221
6216
|
"value": {
|
|
6222
6217
|
"kind": "expression",
|
|
@@ -6224,15 +6219,6 @@
|
|
|
6224
6219
|
},
|
|
6225
6220
|
"default": "\"\""
|
|
6226
6221
|
},
|
|
6227
|
-
{
|
|
6228
|
-
"name": "name",
|
|
6229
|
-
"description": "name attribute to match optional label element.",
|
|
6230
|
-
"value": {
|
|
6231
|
-
"kind": "expression",
|
|
6232
|
-
"type": "string"
|
|
6233
|
-
},
|
|
6234
|
-
"default": "\"\""
|
|
6235
|
-
},
|
|
6236
6222
|
{
|
|
6237
6223
|
"name": "optionsLimit",
|
|
6238
6224
|
"description": "Number of options displayed in the dropdown.",
|
|
@@ -6240,24 +6226,16 @@
|
|
|
6240
6226
|
"kind": "expression",
|
|
6241
6227
|
"type": "number"
|
|
6242
6228
|
},
|
|
6243
|
-
"default": "
|
|
6244
|
-
},
|
|
6245
|
-
{
|
|
6246
|
-
"name": "maxHeight",
|
|
6247
|
-
"description": "Sets maxHeight style value of the dropdown",
|
|
6248
|
-
"value": {
|
|
6249
|
-
"kind": "expression",
|
|
6250
|
-
"type": "number"
|
|
6251
|
-
},
|
|
6252
|
-
"default": "300"
|
|
6229
|
+
"default": "0"
|
|
6253
6230
|
},
|
|
6254
6231
|
{
|
|
6255
|
-
"name": "
|
|
6232
|
+
"name": "visibleOptions",
|
|
6233
|
+
"description": "Amount of options you can see without scroll.",
|
|
6256
6234
|
"value": {
|
|
6257
6235
|
"kind": "expression",
|
|
6258
6236
|
"type": "number"
|
|
6259
6237
|
},
|
|
6260
|
-
"default": "
|
|
6238
|
+
"default": "8"
|
|
6261
6239
|
},
|
|
6262
6240
|
{
|
|
6263
6241
|
"name": "noClear",
|