vueless 0.0.592 → 0.0.594
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/composables/useUI.ts +17 -15
- package/package.json +1 -1
- package/types.ts +2 -0
- package/ui.button/storybook/stories.ts +3 -1
- package/ui.button-link/storybook/stories.ts +3 -1
- package/ui.button-toggle/storybook/stories.ts +3 -1
- package/ui.button-toggle-item/storybook/stories.ts +3 -1
- package/ui.container-accordion/storybook/stories.ts +3 -1
- package/ui.container-card/storybook/stories.ts +3 -1
- package/ui.container-col/storybook/stories.ts +1 -1
- package/ui.container-divider/storybook/stories.ts +3 -1
- package/ui.container-group/storybook/stories.ts +1 -1
- package/ui.container-groups/storybook/stories.ts +1 -1
- package/ui.container-modal/storybook/stories.ts +1 -1
- package/ui.container-modal-confirm/storybook/stories.ts +1 -1
- package/ui.container-page/storybook/stories.ts +3 -1
- package/ui.container-row/storybook/stories.ts +3 -1
- package/ui.data-list/storybook/stories.ts +3 -1
- package/ui.data-table/storybook/stories.ts +3 -1
- package/ui.dropdown-badge/storybook/stories.ts +1 -1
- package/ui.dropdown-button/storybook/stories.ts +1 -1
- package/ui.dropdown-link/storybook/stories.ts +1 -1
- package/ui.dropdown-list/storybook/stories.ts +1 -1
- package/ui.dropdown-list/types.ts +1 -1
- package/ui.form-calendar/storybook/stories.ts +1 -1
- package/ui.form-checkbox/storybook/stories.ts +3 -1
- package/ui.form-checkbox-group/storybook/stories.ts +3 -1
- package/ui.form-checkbox-multi-state/storybook/stories.ts +3 -1
- package/ui.form-color-picker/storybook/stories.ts +3 -1
- package/ui.form-date-picker/UDatePicker.vue +1 -1
- package/ui.form-date-picker/storybook/stories.ts +1 -1
- package/ui.form-date-picker-range/storybook/stories.ts +3 -1
- package/ui.form-input/storybook/stories.ts +3 -1
- package/ui.form-input-file/storybook/stories.ts +3 -1
- package/ui.form-input-money/storybook/stories.ts +3 -1
- package/ui.form-input-number/storybook/stories.ts +3 -1
- package/ui.form-input-rating/storybook/stories.ts +3 -1
- package/ui.form-input-search/storybook/stories.ts +3 -1
- package/ui.form-label/ULabel.vue +1 -1
- package/ui.form-label/storybook/stories.ts +3 -1
- package/ui.form-radio/storybook/stories.ts +3 -1
- package/ui.form-radio-group/storybook/stories.ts +3 -1
- package/ui.form-select/USelect.vue +535 -682
- package/ui.form-select/{config.js → config.ts} +2 -1
- package/ui.form-select/{constants.js → constants.ts} +0 -5
- package/ui.form-select/storybook/Docs.mdx +2 -2
- package/ui.form-select/storybook/{stories.js → stories.ts} +23 -13
- package/ui.form-select/types.ts +134 -0
- package/ui.form-select/utilSelect.ts +122 -0
- package/ui.form-switch/storybook/stories.ts +3 -1
- package/ui.form-textarea/storybook/stories.ts +3 -1
- package/ui.image-avatar/storybook/stories.ts +3 -1
- package/ui.image-icon/storybook/stories.ts +3 -1
- package/ui.loader/storybook/stories.ts +3 -1
- package/ui.loader-overlay/storybook/stories.ts +1 -1
- package/ui.loader-progress/storybook/stories.ts +3 -1
- package/ui.navigation-progress/storybook/stories.ts +3 -1
- package/ui.navigation-tab/storybook/stories.ts +3 -1
- package/ui.navigation-tabs/storybook/stories.ts +3 -1
- package/ui.other-dot/storybook/stories.ts +3 -1
- package/ui.text-alert/storybook/stories.ts +3 -1
- package/ui.text-badge/storybook/stories.ts +3 -1
- package/ui.text-block/storybook/stories.ts +3 -1
- package/ui.text-empty/storybook/stories.ts +3 -1
- package/ui.text-file/storybook/stories.ts +3 -1
- package/ui.text-files/storybook/stories.ts +3 -1
- package/ui.text-header/storybook/stories.ts +3 -1
- package/ui.text-money/storybook/stories.ts +3 -1
- package/ui.text-notify/storybook/stories.ts +1 -1
- package/utils/storybook.ts +3 -5
- package/web-types.json +77 -35
- package/ui.form-select/utilSelect.js +0 -100
|
@@ -138,8 +138,9 @@ export default /*tw*/ {
|
|
|
138
138
|
size: "md",
|
|
139
139
|
labelAlign: "topInside",
|
|
140
140
|
openDirection: "auto",
|
|
141
|
-
labelKey: "label",
|
|
142
141
|
valueKey: "id",
|
|
142
|
+
labelKey: "label",
|
|
143
|
+
groupLabelKey: "label",
|
|
143
144
|
optionsLimit: 0,
|
|
144
145
|
visibleOptions: 8,
|
|
145
146
|
multiple: false,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
|
|
2
2
|
import { getSource } from "../../utils/storybook.ts";
|
|
3
3
|
|
|
4
|
-
import * as stories from "./stories.
|
|
5
|
-
import defaultConfig from "../config.
|
|
4
|
+
import * as stories from "./stories.ts";
|
|
5
|
+
import defaultConfig from "../config.ts?raw"
|
|
6
6
|
|
|
7
7
|
<Meta of={stories} />
|
|
8
8
|
<Title of={stories} />
|
|
@@ -11,6 +11,20 @@ import UBadge from "../../ui.text-badge/UBadge.vue";
|
|
|
11
11
|
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
12
12
|
import ULink from "../../ui.button-link/ULink.vue";
|
|
13
13
|
|
|
14
|
+
import type { Meta, StoryFn } from "@storybook/vue3";
|
|
15
|
+
import type { Props } from "../types.ts";
|
|
16
|
+
|
|
17
|
+
interface USelectArgs extends Props {
|
|
18
|
+
slotTemplate?: string;
|
|
19
|
+
enum: "size" | "openDirection";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface SelectOption {
|
|
23
|
+
id: string | number;
|
|
24
|
+
label: string;
|
|
25
|
+
badge?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
export default {
|
|
15
29
|
id: "3080",
|
|
16
30
|
title: "Form Inputs & Controls / Select",
|
|
@@ -31,18 +45,18 @@ export default {
|
|
|
31
45
|
},
|
|
32
46
|
parameters: {
|
|
33
47
|
docs: {
|
|
48
|
+
...getDocsDescription(USelect.__name),
|
|
34
49
|
story: {
|
|
35
50
|
height: "280px",
|
|
36
51
|
},
|
|
37
52
|
},
|
|
38
|
-
...getDocsDescription(USelect.__name),
|
|
39
53
|
},
|
|
40
|
-
};
|
|
54
|
+
} as Meta;
|
|
41
55
|
|
|
42
|
-
const DefaultTemplate = (args) => ({
|
|
56
|
+
const DefaultTemplate: StoryFn<USelectArgs> = (args: USelectArgs) => ({
|
|
43
57
|
components: { USelect, UIcon, UBadge, ULink },
|
|
44
58
|
setup() {
|
|
45
|
-
function getSelectedBadge(options, currentValue) {
|
|
59
|
+
function getSelectedBadge(options: SelectOption[], currentValue: string | number) {
|
|
46
60
|
return options?.find((option) => option.id === currentValue);
|
|
47
61
|
}
|
|
48
62
|
|
|
@@ -52,17 +66,17 @@ const DefaultTemplate = (args) => ({
|
|
|
52
66
|
},
|
|
53
67
|
template: `
|
|
54
68
|
<USelect v-bind="args" v-model="args.modelValue">
|
|
55
|
-
${args.slotTemplate || getSlotsFragment()}
|
|
69
|
+
${args.slotTemplate || getSlotsFragment("")}
|
|
56
70
|
</USelect>
|
|
57
71
|
`,
|
|
58
72
|
});
|
|
59
73
|
|
|
60
|
-
const EnumVariantTemplate = (args, { argTypes }) => ({
|
|
74
|
+
const EnumVariantTemplate: StoryFn<USelectArgs> = (args: USelectArgs, { argTypes }) => ({
|
|
61
75
|
components: { USelect, URow },
|
|
62
76
|
setup() {
|
|
63
77
|
return {
|
|
64
78
|
args,
|
|
65
|
-
options: argTypes[args.enum]
|
|
79
|
+
options: argTypes?.[args.enum]?.options,
|
|
66
80
|
};
|
|
67
81
|
},
|
|
68
82
|
template: `
|
|
@@ -79,7 +93,7 @@ const EnumVariantTemplate = (args, { argTypes }) => ({
|
|
|
79
93
|
`,
|
|
80
94
|
});
|
|
81
95
|
|
|
82
|
-
const GroupValuesTemplate = (args) => ({
|
|
96
|
+
const GroupValuesTemplate: StoryFn<USelectArgs> = (args: USelectArgs) => ({
|
|
83
97
|
components: { USelect },
|
|
84
98
|
setup() {
|
|
85
99
|
return {
|
|
@@ -121,7 +135,6 @@ OpenDirection.args = { enum: "openDirection" };
|
|
|
121
135
|
export const GroupValue = GroupValuesTemplate.bind({});
|
|
122
136
|
GroupValue.args = {
|
|
123
137
|
modelValue: "",
|
|
124
|
-
modelValueMultiple: [],
|
|
125
138
|
groupValueKey: "libs",
|
|
126
139
|
groupLabelKey: "language",
|
|
127
140
|
labelKey: "name",
|
|
@@ -162,9 +175,6 @@ Description.args = { description: "some description text" };
|
|
|
162
175
|
export const OptionsLimit2 = DefaultTemplate.bind({});
|
|
163
176
|
OptionsLimit2.args = { optionsLimit: 2 };
|
|
164
177
|
|
|
165
|
-
export const NoClear = DefaultTemplate.bind({});
|
|
166
|
-
NoClear.args = { noClear: true };
|
|
167
|
-
|
|
168
178
|
export const AddOption = DefaultTemplate.bind({});
|
|
169
179
|
AddOption.args = { addOption: true };
|
|
170
180
|
|
|
@@ -179,7 +189,7 @@ OptionIsHidden.args = {
|
|
|
179
189
|
};
|
|
180
190
|
|
|
181
191
|
export const Sizes = EnumVariantTemplate.bind({});
|
|
182
|
-
Sizes.args = { enum: "size", multiple: true,
|
|
192
|
+
Sizes.args = { enum: "size", multiple: true, modelValue: [] };
|
|
183
193
|
|
|
184
194
|
export const SlotToggle = DefaultTemplate.bind({});
|
|
185
195
|
SlotToggle.args = {
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import defaultConfig from "./config.ts";
|
|
2
|
+
|
|
3
|
+
import type { Option } from "../ui.dropdown-list/types.ts";
|
|
4
|
+
import type { ComponentConfig } from "../types.ts";
|
|
5
|
+
|
|
6
|
+
export type Config = typeof defaultConfig;
|
|
7
|
+
export type IconSize = "xs" | "sm" | "md";
|
|
8
|
+
|
|
9
|
+
export interface Props {
|
|
10
|
+
/**
|
|
11
|
+
* Select value.
|
|
12
|
+
*/
|
|
13
|
+
modelValue?: string | number | (string | number)[];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Select options.
|
|
17
|
+
*/
|
|
18
|
+
options?: Option[];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Select label.
|
|
22
|
+
*/
|
|
23
|
+
label?: string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Label placement.
|
|
27
|
+
*/
|
|
28
|
+
labelAlign?: "top" | "topInside" | "topWithDesc" | "left" | "right";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Select placeholder.
|
|
32
|
+
*/
|
|
33
|
+
placeholder?: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Select description.
|
|
37
|
+
*/
|
|
38
|
+
description?: string;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Select error message.
|
|
42
|
+
*/
|
|
43
|
+
error?: string;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Select size.
|
|
47
|
+
*/
|
|
48
|
+
size?: "sm" | "md" | "lg";
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Left icon name.
|
|
52
|
+
*/
|
|
53
|
+
leftIcon?: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Right icon name.
|
|
57
|
+
*/
|
|
58
|
+
rightIcon?: string;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Select open direction.
|
|
62
|
+
*/
|
|
63
|
+
openDirection?: "auto" | "top" | "bottom";
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Label key in the item object of options.
|
|
67
|
+
*/
|
|
68
|
+
labelKey?: string;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Value key in the item object of options.
|
|
72
|
+
*/
|
|
73
|
+
valueKey?: string;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Set a name of the property containing the group label.
|
|
77
|
+
*/
|
|
78
|
+
groupLabelKey?: string;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Set a name of the property containing the group values.
|
|
82
|
+
*/
|
|
83
|
+
groupValueKey?: string;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Number of options displayed in the dropdown.
|
|
87
|
+
*/
|
|
88
|
+
optionsLimit?: number;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Number of options you can see without a scroll.
|
|
92
|
+
*/
|
|
93
|
+
visibleOptions?: number;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Allow clearing selected value.
|
|
97
|
+
*/
|
|
98
|
+
clearable?: boolean;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Allows multiple selection.
|
|
102
|
+
*/
|
|
103
|
+
multiple?: boolean;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Allows to search value in a list.
|
|
107
|
+
*/
|
|
108
|
+
searchable?: boolean;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Disable the select.
|
|
112
|
+
*/
|
|
113
|
+
disabled?: boolean;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Show "Add new option" button in the list.
|
|
117
|
+
*/
|
|
118
|
+
addOption?: boolean;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Unique element id.
|
|
122
|
+
*/
|
|
123
|
+
id?: string;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Component config object.
|
|
127
|
+
*/
|
|
128
|
+
config?: ComponentConfig<Config>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Data-test attribute for automated testing.
|
|
132
|
+
*/
|
|
133
|
+
dataTest?: string;
|
|
134
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { Option } from "../ui.dropdown-list/types.ts";
|
|
2
|
+
|
|
3
|
+
export function filterOptions(options: Option[], search: string, labelKey: string) {
|
|
4
|
+
if (!search) return options;
|
|
5
|
+
|
|
6
|
+
return options
|
|
7
|
+
.filter((option) => {
|
|
8
|
+
return interpolateLabel(option, labelKey).toLowerCase().includes(search.toLowerCase());
|
|
9
|
+
})
|
|
10
|
+
.sort((a, b) => {
|
|
11
|
+
const aOptionIndex = interpolateLabel(a, labelKey).indexOf(search);
|
|
12
|
+
const bOptionIndex = interpolateLabel(b, labelKey).indexOf(search);
|
|
13
|
+
|
|
14
|
+
return aOptionIndex - bOptionIndex;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function filterGroups(
|
|
19
|
+
options: Option[],
|
|
20
|
+
search: string,
|
|
21
|
+
label: string,
|
|
22
|
+
groupValueKey: string,
|
|
23
|
+
groupLabelKey: string,
|
|
24
|
+
): Option[] {
|
|
25
|
+
return options
|
|
26
|
+
.map((option) => {
|
|
27
|
+
const group = option[groupValueKey];
|
|
28
|
+
|
|
29
|
+
if (Array.isArray(group)) {
|
|
30
|
+
return {
|
|
31
|
+
[groupLabelKey]: option[groupLabelKey],
|
|
32
|
+
[groupValueKey]: filterOptions(group, search, label),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
.reduce((accumulator: Option[], group) => {
|
|
37
|
+
if (!group) return accumulator;
|
|
38
|
+
|
|
39
|
+
const groupValues = group[groupValueKey];
|
|
40
|
+
|
|
41
|
+
if (Array.isArray(groupValues) && groupValues.length) {
|
|
42
|
+
accumulator.push({ groupLabel: String(group[groupLabelKey] || "") });
|
|
43
|
+
|
|
44
|
+
return accumulator.concat(groupValues);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return accumulator;
|
|
48
|
+
}, []);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function removeSelectedValues(
|
|
52
|
+
options: Option[],
|
|
53
|
+
selectedValues: (string | number)[],
|
|
54
|
+
valueKey: string,
|
|
55
|
+
groupValueKey?: string,
|
|
56
|
+
): Option[] {
|
|
57
|
+
if (!groupValueKey) {
|
|
58
|
+
return options.filter((option) => {
|
|
59
|
+
const value = option[valueKey];
|
|
60
|
+
|
|
61
|
+
return typeof value === "string" || typeof value === "number"
|
|
62
|
+
? !selectedValues.includes(value)
|
|
63
|
+
: false;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return options
|
|
68
|
+
.map((option) => {
|
|
69
|
+
if (!Array.isArray(option[groupValueKey])) return;
|
|
70
|
+
|
|
71
|
+
const filteredGroup = option[groupValueKey].filter((item) => {
|
|
72
|
+
const value = item[valueKey];
|
|
73
|
+
|
|
74
|
+
return typeof value === "string" || typeof value === "number"
|
|
75
|
+
? !selectedValues.includes(value) && !item.isSubGroup
|
|
76
|
+
: false;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return filteredGroup.length ? { ...option, [groupValueKey]: filteredGroup } : null;
|
|
80
|
+
})
|
|
81
|
+
.filter((option): option is Option => !!option);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function getCurrentOption(
|
|
85
|
+
options: Option[],
|
|
86
|
+
selectedValue: string | number | Option,
|
|
87
|
+
valueKey: string,
|
|
88
|
+
groupValueKey?: string,
|
|
89
|
+
) {
|
|
90
|
+
const value = typeof selectedValue === "object" ? selectedValue?.[valueKey] : selectedValue;
|
|
91
|
+
|
|
92
|
+
const currentOption = groupValueKey
|
|
93
|
+
? getGroupOption(options, selectedValue, valueKey, groupValueKey)
|
|
94
|
+
: options.find((option) => option[valueKey] === value);
|
|
95
|
+
|
|
96
|
+
return currentOption || ({} as Option);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function getGroupOption(
|
|
100
|
+
options: Option[],
|
|
101
|
+
selectedValue: string | number | Option,
|
|
102
|
+
valueKey: string,
|
|
103
|
+
groupValueKey: string,
|
|
104
|
+
) {
|
|
105
|
+
const group = options.find((option) => {
|
|
106
|
+
return Array.isArray(option[groupValueKey])
|
|
107
|
+
? option[groupValueKey].find((value) => value[valueKey] === selectedValue)
|
|
108
|
+
: false;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const groupValues = group?.[groupValueKey] || [];
|
|
112
|
+
|
|
113
|
+
return Array.isArray(groupValues)
|
|
114
|
+
? groupValues.find((value) => value[valueKey] === selectedValue)
|
|
115
|
+
: undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function interpolateLabel(option: Option, label: string) {
|
|
119
|
+
const interpolatedLabel = label ? option[label] : option;
|
|
120
|
+
|
|
121
|
+
return interpolatedLabel !== "object" ? String(interpolatedLabel) : "";
|
|
122
|
+
}
|
package/utils/storybook.ts
CHANGED
|
@@ -65,13 +65,11 @@ export function getSlotNames(componentName: string | undefined) {
|
|
|
65
65
|
* Create story param config to show component description with a link on GitHub.
|
|
66
66
|
*/
|
|
67
67
|
export function getDocsDescription(componentName: string | undefined) {
|
|
68
|
-
if (!componentName) return;
|
|
68
|
+
if (!componentName) return {};
|
|
69
69
|
|
|
70
70
|
return {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
component: `The \`${componentName}\` component. | [View on GitHub](https://github.com/vuelessjs/vueless/tree/main/src/${COMPONENTS[componentName as ComponentNames]})`,
|
|
74
|
-
},
|
|
71
|
+
description: {
|
|
72
|
+
component: `The \`${componentName}\` component. | [View on GitHub](https://github.com/vuelessjs/vueless/tree/main/src/${COMPONENTS[componentName as ComponentNames]})`,
|
|
75
73
|
},
|
|
76
74
|
};
|
|
77
75
|
}
|