@rettangoli/ui 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/rettangoli-iife-ui.min.js +38 -38
- package/package.json +1 -1
- package/src/components/dropdownMenu/dropdownMenu.handlers.js +13 -1
- package/src/components/dropdownMenu/dropdownMenu.schema.yaml +2 -1
- package/src/components/dropdownMenu/dropdownMenu.store.js +14 -3
- package/src/components/dropdownMenu/dropdownMenu.view.yaml +1 -1
- package/src/components/select/select.handlers.js +17 -2
- package/src/components/select/select.schema.yaml +6 -0
- package/src/components/select/select.store.js +47 -3
- package/src/components/select/select.view.yaml +17 -11
package/package.json
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
|
|
2
|
+
const getItemType = (item = {}) => {
|
|
3
|
+
if (item.type === 'section' || item.type === 'label') {
|
|
4
|
+
return 'section';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
if (item.type === 'separator') {
|
|
8
|
+
return 'separator';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return 'item';
|
|
12
|
+
};
|
|
13
|
+
|
|
2
14
|
export const handleClosePopover = (deps, payload) => {
|
|
3
15
|
const { dispatchEvent } = deps;
|
|
4
16
|
dispatchEvent(new CustomEvent('close'));
|
|
@@ -9,7 +21,7 @@ export const handleClickMenuItem = (deps, payload) => {
|
|
|
9
21
|
const event = payload._event;
|
|
10
22
|
const index = Number(event.currentTarget.dataset.index ?? event.currentTarget.id.slice('option'.length));
|
|
11
23
|
const item = props.items[index];
|
|
12
|
-
const itemType = item
|
|
24
|
+
const itemType = getItemType(item);
|
|
13
25
|
|
|
14
26
|
if (!item || itemType !== 'item' || item.disabled) {
|
|
15
27
|
event.preventDefault();
|
|
@@ -3,12 +3,23 @@ export const createInitialState = () => Object.freeze({
|
|
|
3
3
|
});
|
|
4
4
|
|
|
5
5
|
const escapeAttrValue = (value) => `${value}`.replace(/"/g, '"');
|
|
6
|
+
const getItemType = (item = {}) => {
|
|
7
|
+
if (item.type === 'section' || item.type === 'label') {
|
|
8
|
+
return 'section';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (item.type === 'separator') {
|
|
12
|
+
return 'separator';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return 'item';
|
|
16
|
+
};
|
|
6
17
|
|
|
7
18
|
const normalizeItems = (items) => {
|
|
8
19
|
return items.map((item, index) => {
|
|
9
|
-
const type = item
|
|
20
|
+
const type = getItemType(item);
|
|
10
21
|
const isSeparator = type === 'separator';
|
|
11
|
-
const
|
|
22
|
+
const isSection = type === 'section';
|
|
12
23
|
const isItem = type === 'item';
|
|
13
24
|
const isDisabled = !!item.disabled;
|
|
14
25
|
const isInteractive = isItem && !isDisabled;
|
|
@@ -34,7 +45,7 @@ const normalizeItems = (items) => {
|
|
|
34
45
|
index,
|
|
35
46
|
type,
|
|
36
47
|
isSeparator,
|
|
37
|
-
|
|
48
|
+
isSection,
|
|
38
49
|
isItem,
|
|
39
50
|
isDisabled,
|
|
40
51
|
isInteractive,
|
|
@@ -20,7 +20,7 @@ styles:
|
|
|
20
20
|
template:
|
|
21
21
|
- rtgl-popover#popover ?open=${open} x=${x} y=${y} place=${place} content-w=${w} content-h=${h} content-sv=true content-g=xs content-pv=sm:
|
|
22
22
|
- $for item, i in items:
|
|
23
|
-
- $if item.
|
|
23
|
+
- $if item.isSection:
|
|
24
24
|
- rtgl-view w=f p=md:
|
|
25
25
|
- rtgl-text s=xs c=mu-fg: ${item.label}
|
|
26
26
|
$elif item.isItem && item.isDisabled:
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { deepEqual } from '../../common.js';
|
|
2
2
|
|
|
3
|
+
const getOptionType = (option = {}) => {
|
|
4
|
+
if (option.type === 'section') {
|
|
5
|
+
return 'section';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (option.type === 'separator') {
|
|
9
|
+
return 'separator';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return 'item';
|
|
13
|
+
};
|
|
14
|
+
|
|
3
15
|
export const handleBeforeMount = (deps) => {
|
|
4
16
|
const { store, props, render } = deps;
|
|
5
17
|
|
|
6
18
|
if (props.selectedValue !== null && props.selectedValue !== undefined && props.options) {
|
|
7
|
-
const selectedOption = props.options.find(opt => deepEqual(opt.value, props.selectedValue));
|
|
19
|
+
const selectedOption = props.options.find((opt) => getOptionType(opt) === 'item' && deepEqual(opt.value, props.selectedValue));
|
|
8
20
|
if (selectedOption) {
|
|
9
21
|
store.updateSelectedValue({
|
|
10
22
|
value: selectedOption?.value
|
|
@@ -48,7 +60,7 @@ export const handleButtonClick = (deps, payload) => {
|
|
|
48
60
|
const currentValue = storeSelectedValue !== null ? storeSelectedValue : props.selectedValue;
|
|
49
61
|
let selectedIndex = null;
|
|
50
62
|
if (currentValue !== null && currentValue !== undefined && props.options) {
|
|
51
|
-
selectedIndex = props.options.findIndex(opt => deepEqual(opt.value, currentValue));
|
|
63
|
+
selectedIndex = props.options.findIndex((opt) => getOptionType(opt) === 'item' && deepEqual(opt.value, currentValue));
|
|
52
64
|
if (selectedIndex === -1) selectedIndex = null;
|
|
53
65
|
}
|
|
54
66
|
|
|
@@ -87,6 +99,9 @@ export const handleOptionClick = (deps, payload) => {
|
|
|
87
99
|
const index = Number(id);
|
|
88
100
|
|
|
89
101
|
const option = props.options[id];
|
|
102
|
+
if (getOptionType(option) !== 'item') {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
90
105
|
|
|
91
106
|
// Update internal state
|
|
92
107
|
store.updateSelectedValue({ value: option?.value });
|
|
@@ -25,6 +25,18 @@ const stringifyProps = (props = {}) => {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const hasOwnProp = (object, key) => Object.prototype.hasOwnProperty.call(object || {}, key);
|
|
28
|
+
const getOptionType = (option = {}) => {
|
|
29
|
+
if (option.type === 'section') {
|
|
30
|
+
return 'section';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (option.type === 'separator') {
|
|
34
|
+
return 'separator';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return 'item';
|
|
38
|
+
};
|
|
39
|
+
const isSelectableOption = (option = {}) => getOptionType(option) === 'item';
|
|
28
40
|
|
|
29
41
|
const getOptionIcon = (option = {}) => {
|
|
30
42
|
return typeof option.icon === 'string' && option.icon.length > 0 ? option.icon : '';
|
|
@@ -43,6 +55,33 @@ const getOptionSuffixText = (option = {}) => {
|
|
|
43
55
|
};
|
|
44
56
|
|
|
45
57
|
const normalizeOption = (option = {}, index, currentValue, hoveredOptionId, hasIconColumn) => {
|
|
58
|
+
const type = getOptionType(option);
|
|
59
|
+
const isSection = type === 'section';
|
|
60
|
+
const isSeparator = type === 'separator';
|
|
61
|
+
const isItem = type === 'item';
|
|
62
|
+
|
|
63
|
+
if (isSection) {
|
|
64
|
+
return {
|
|
65
|
+
...option,
|
|
66
|
+
index,
|
|
67
|
+
type,
|
|
68
|
+
isSection,
|
|
69
|
+
isSeparator,
|
|
70
|
+
isItem,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (isSeparator) {
|
|
75
|
+
return {
|
|
76
|
+
...option,
|
|
77
|
+
index,
|
|
78
|
+
type,
|
|
79
|
+
isSection,
|
|
80
|
+
isSeparator,
|
|
81
|
+
isItem,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
46
85
|
const isSelected = deepEqual(option.value, currentValue);
|
|
47
86
|
const isHovered = hoveredOptionId === index;
|
|
48
87
|
const icon = getOptionIcon(option);
|
|
@@ -50,6 +89,11 @@ const normalizeOption = (option = {}, index, currentValue, hoveredOptionId, hasI
|
|
|
50
89
|
|
|
51
90
|
return {
|
|
52
91
|
...option,
|
|
92
|
+
index,
|
|
93
|
+
type,
|
|
94
|
+
isSection,
|
|
95
|
+
isSeparator,
|
|
96
|
+
isItem,
|
|
53
97
|
isSelected,
|
|
54
98
|
bgc: isHovered ? 'ac' : (isSelected ? 'mu' : ''),
|
|
55
99
|
hasIconSlot: hasIconColumn,
|
|
@@ -88,17 +132,17 @@ export const selectViewData = ({ state, props }) => {
|
|
|
88
132
|
let isPlaceholderLabel = true;
|
|
89
133
|
|
|
90
134
|
const options = props.options || [];
|
|
91
|
-
const selectedOption = options.find((opt) => deepEqual(opt.value, currentValue));
|
|
135
|
+
const selectedOption = options.find((opt) => isSelectableOption(opt) && deepEqual(opt.value, currentValue));
|
|
92
136
|
if (selectedOption) {
|
|
93
137
|
displayLabel = selectedOption.label;
|
|
94
138
|
isPlaceholderLabel = false;
|
|
95
139
|
}
|
|
96
140
|
|
|
97
|
-
const hasIconColumn = options.some((option) => hasOwnProp(option, 'icon'));
|
|
141
|
+
const hasIconColumn = options.some((option) => isSelectableOption(option) && hasOwnProp(option, 'icon'));
|
|
98
142
|
const optionsWithSelection = options.map((option, index) => {
|
|
99
143
|
return normalizeOption(option, index, currentValue, state.hoveredOptionId, hasIconColumn);
|
|
100
144
|
});
|
|
101
|
-
const selectedOptionView = optionsWithSelection.find((option) => option.isSelected);
|
|
145
|
+
const selectedOptionView = optionsWithSelection.find((option) => option.isItem && option.isSelected);
|
|
102
146
|
|
|
103
147
|
return {
|
|
104
148
|
containerAttrString,
|
|
@@ -48,17 +48,23 @@ template:
|
|
|
48
48
|
- rtgl-svg svg=chevronDown wh=16 c=mu-fg: null
|
|
49
49
|
- rtgl-popover#popover ?open=${isOpen} x=${position.x} y=${position.y} place=rs content-wh=300 content-g=xs content-sv=true content-pv=sm:
|
|
50
50
|
- $for option, i in options:
|
|
51
|
-
-
|
|
52
|
-
- rtgl-view
|
|
53
|
-
- rtgl-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
- $if option.isSection:
|
|
52
|
+
- rtgl-view w=f p=md:
|
|
53
|
+
- rtgl-text s=xs c=mu-fg: ${option.label}
|
|
54
|
+
$elif option.isItem:
|
|
55
|
+
- rtgl-view#option${option.index} w=f ph=lg pv=md cur=pointer bgc=${option.bgc} data-testid=${option.testId}:
|
|
56
|
+
- rtgl-view d=h av=c w=f g=md:
|
|
57
|
+
- rtgl-view d=h av=c g=md w=1fg:
|
|
58
|
+
- $if option.hasIconSlot:
|
|
59
|
+
- $if option.hasIcon:
|
|
60
|
+
- rtgl-svg wh=16 svg=${option.icon} c=${option.iconColor}: null
|
|
61
|
+
$else:
|
|
62
|
+
- div class=icon-placeholder aria-hidden="true": null
|
|
63
|
+
- rtgl-text s=sm c=${option.c} w=1fg ellipsis: ${option.label}
|
|
64
|
+
- $if option.hasSuffixText:
|
|
65
|
+
- rtgl-text s=xs c=${option.suffixTextColor} ta=e: ${option.suffixText}
|
|
66
|
+
$elif option.isSeparator:
|
|
67
|
+
- rtgl-view w=f h=1 bgc=mu mv=sm: null
|
|
62
68
|
- $if showAddOption:
|
|
63
69
|
- rtgl-view w=f bw=xs bc=mu bwt=sm: null
|
|
64
70
|
- rtgl-view#optionAdd w=f ph=lg pv=md cur=pointer bgc=${addOptionBgc} data-testid="select-add-option":
|