@rettangoli/ui 1.0.0-rc13 → 1.0.0-rc15
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-layout.min.js +81 -49
- package/dist/rettangoli-iife-ui.min.js +150 -49
- package/package.json +10 -5
- package/src/common/dimensions.js +85 -0
- package/src/common/responsive.js +72 -0
- package/src/common.js +6 -4
- package/src/components/dropdownMenu/dropdownMenu.schema.yaml +1 -1
- package/src/components/form/form.handlers.js +328 -152
- package/src/components/form/form.methods.js +205 -0
- package/src/components/form/form.schema.yaml +16 -271
- package/src/components/form/form.store.js +535 -95
- package/src/components/form/form.view.yaml +73 -52
- package/src/components/globalUi/globalUi.handlers.js +4 -4
- package/src/components/popoverInput/popoverInput.handlers.js +64 -50
- package/src/components/popoverInput/popoverInput.schema.yaml +3 -1
- package/src/components/popoverInput/popoverInput.store.js +9 -3
- package/src/components/popoverInput/popoverInput.view.yaml +4 -4
- package/src/components/select/select.handlers.js +15 -19
- package/src/components/select/select.schema.yaml +2 -0
- package/src/components/select/select.store.js +8 -6
- package/src/components/select/select.view.yaml +4 -4
- package/src/components/sliderInput/sliderInput.handlers.js +15 -1
- package/src/components/sliderInput/sliderInput.schema.yaml +3 -0
- package/src/components/sliderInput/sliderInput.store.js +2 -1
- package/src/components/sliderInput/sliderInput.view.yaml +2 -2
- package/src/components/tooltip/tooltip.schema.yaml +1 -1
- package/src/deps/createGlobalUI.js +4 -4
- package/src/entry-iife-layout.js +6 -0
- package/src/entry-iife-ui.js +8 -0
- package/src/index.js +8 -0
- package/src/primitives/checkbox.js +295 -0
- package/src/primitives/input-date.js +31 -0
- package/src/primitives/input-datetime.js +31 -0
- package/src/primitives/input-time.js +31 -0
- package/src/primitives/input.js +43 -1
- package/src/primitives/textarea.js +3 -0
- package/src/primitives/view.js +6 -2
|
@@ -16,23 +16,15 @@ refs:
|
|
|
16
16
|
field*:
|
|
17
17
|
eventListeners:
|
|
18
18
|
value-input:
|
|
19
|
-
handler:
|
|
19
|
+
handler: handleValueInput
|
|
20
20
|
value-change:
|
|
21
|
-
handler:
|
|
22
|
-
add-option-click:
|
|
23
|
-
handler: handleSelectAddOption
|
|
21
|
+
handler: handleValueChange
|
|
24
22
|
image*:
|
|
25
23
|
eventListeners:
|
|
26
24
|
click:
|
|
27
25
|
handler: handleImageClick
|
|
28
26
|
contextmenu:
|
|
29
27
|
handler: handleImageClick
|
|
30
|
-
waveform*:
|
|
31
|
-
eventListeners:
|
|
32
|
-
click:
|
|
33
|
-
handler: handleWaveformClick
|
|
34
|
-
contextmenu:
|
|
35
|
-
handler: handleWaveformClick
|
|
36
28
|
template:
|
|
37
29
|
- rtgl-view#formContainer w=f p=md g=lg ${containerAttrString}:
|
|
38
30
|
- rtgl-view g=sm w=f:
|
|
@@ -41,49 +33,78 @@ template:
|
|
|
41
33
|
- $if description:
|
|
42
34
|
- rtgl-text c=mu-fg: ${description}
|
|
43
35
|
- rtgl-view g=lg w=f:
|
|
44
|
-
- $for field, i in
|
|
45
|
-
-
|
|
46
|
-
-
|
|
36
|
+
- $for field, i in flatFields:
|
|
37
|
+
- $if field._isSection:
|
|
38
|
+
- rtgl-view g=md w=f:
|
|
47
39
|
- rtgl-view g=sm:
|
|
48
|
-
-
|
|
49
|
-
- $
|
|
50
|
-
- rtgl-text: ${field.label}
|
|
51
|
-
- $if field.label && field.tooltip:
|
|
52
|
-
- rtgl-svg#tooltipIcon${i} data-field-name=${field.name} svg="info" wh=16 c=mu-fg cur=help ml=xs: null
|
|
40
|
+
- $if field.label:
|
|
41
|
+
- rtgl-text s=md: ${field.label}
|
|
53
42
|
- $if field.description:
|
|
54
43
|
- rtgl-text s=sm c=mu-fg: ${field.description}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
- rtgl-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
44
|
+
- $if !field._isSection:
|
|
45
|
+
- rtgl-view g=md w=f:
|
|
46
|
+
- $if field.label || field.description:
|
|
47
|
+
- rtgl-view g=sm:
|
|
48
|
+
- rtgl-view d=h g=md av=c:
|
|
49
|
+
- $if field.label:
|
|
50
|
+
- rtgl-text: ${field.label}
|
|
51
|
+
- $if field.required:
|
|
52
|
+
- rtgl-text c=fg s=sm: "*"
|
|
53
|
+
- $if field.tooltip:
|
|
54
|
+
- rtgl-svg#tooltipIcon${field._idx} data-field-name=${field.name} svg="info" wh=16 c=mu-fg cur=help ml=xs: null
|
|
55
|
+
- $if field.description:
|
|
56
|
+
- rtgl-text s=sm c=mu-fg: ${field.description}
|
|
57
|
+
- $if field.type == "input-text":
|
|
58
|
+
- rtgl-input#field${field._idx} data-field-name=${field.name} w=f type=${field._inputType} placeholder=${field.placeholder} ?disabled=${field._disabled}: null
|
|
59
|
+
- $if field.type == "input-date":
|
|
60
|
+
- rtgl-input-date#field${field._idx} data-field-name=${field.name} w=f min=${field.min} max=${field.max} placeholder=${field.placeholder} ?disabled=${field._disabled}: null
|
|
61
|
+
- $if field.type == "input-time":
|
|
62
|
+
- rtgl-input-time#field${field._idx} data-field-name=${field.name} w=f min=${field.min} max=${field.max} step=${field.step} placeholder=${field.placeholder} ?disabled=${field._disabled}: null
|
|
63
|
+
- $if field.type == "input-datetime":
|
|
64
|
+
- rtgl-input-datetime#field${field._idx} data-field-name=${field.name} w=f min=${field.min} max=${field.max} step=${field.step} placeholder=${field.placeholder} ?disabled=${field._disabled}: null
|
|
65
|
+
- $if field.type == "input-number":
|
|
66
|
+
- rtgl-input-number#field${field._idx} data-field-name=${field.name} w=f min=${field.min} max=${field.max} step=${field.step} placeholder=${field.placeholder} ?disabled=${field._disabled}: null
|
|
67
|
+
- $if field.type == "input-textarea":
|
|
68
|
+
- rtgl-textarea#field${field._idx} data-field-name=${field.name} w=f rows=${field.rows} placeholder=${field.placeholder} ?disabled=${field._disabled}: null
|
|
69
|
+
- $if field.type == "select":
|
|
70
|
+
- rtgl-select#field${field._idx} data-field-name=${field.name} w=f :options=flatFields[${field._arrIdx}].options ?no-clear=flatFields[${field._arrIdx}].noClear :selectedValue=#{field._selectedValue} :placeholder=#{field.placeholder} ?disabled=${field._disabled}: null
|
|
71
|
+
- $if field.type == "color-picker":
|
|
72
|
+
- rtgl-color-picker#field${field._idx} data-field-name=${field.name} ?disabled=${field._disabled}: null
|
|
73
|
+
- $if field.type == "slider":
|
|
74
|
+
- rtgl-slider#field${field._idx} data-field-name=${field.name} w=f min=${field.min} max=${field.max} step=${field.step} ?disabled=${field._disabled}: null
|
|
75
|
+
- $if field.type == "slider-with-input":
|
|
76
|
+
- rtgl-slider-input#field${field._idx} data-field-name=${field.name} w=f min=${field.min} max=${field.max} step=${field.step} ?disabled=${field._disabled}: null
|
|
77
|
+
- $if field.type == "popover-input":
|
|
78
|
+
- rtgl-popover-input#field${field._idx} data-field-name=${field.name} label="${field.label}" placeholder=${field.placeholder} ?disabled=${field._disabled}: null
|
|
79
|
+
- $if field.type == "checkbox":
|
|
80
|
+
- rtgl-checkbox#field${field._idx} data-field-name=${field.name} label="${field._checkboxText}" ?disabled=${field._disabled}: null
|
|
81
|
+
- $if field.type == "image" && field._imageSrc:
|
|
82
|
+
- rtgl-image#image${field._idx} data-field-name=${field.name} src=${field._imageSrc} w=${field.width} h=${field.height} cur=pointer: null
|
|
83
|
+
- $if field.type == "image" && !field._imageSrc:
|
|
84
|
+
- rtgl-view#image${field._idx} data-field-name=${field.name} w=${field.width} h=${field.height} bc=ac bw=sm ah=c av=c cur=pointer p=md:
|
|
85
|
+
- rtgl-text c=mu-fg ta=c: ${field.placeholderText}
|
|
86
|
+
- $if field.type == "read-only-text":
|
|
87
|
+
- rtgl-text s=sm: ${field.content}
|
|
88
|
+
- $if field.type == "slot":
|
|
89
|
+
- 'slot#fieldSlot${field._idx} name=${field.slot} style="display: contents;"': null
|
|
90
|
+
- $if field._error:
|
|
91
|
+
- rtgl-text s=sm c=de: ${field._error}
|
|
92
|
+
- $if actions.buttons.length > 0:
|
|
93
|
+
- $if actions._layout == "split":
|
|
94
|
+
- rtgl-view d=h w=f g=sm:
|
|
95
|
+
- rtgl-view d=h g=sm:
|
|
96
|
+
- $for button, i in actions._leftButtons:
|
|
97
|
+
- rtgl-button#action${button._globalIdx} data-action-id=${button.id} v=${button.variant} ?disabled=${button._disabled} pre=${button.pre} suf=${button.suf}: ${button.label}
|
|
98
|
+
- rtgl-view d=h g=sm ah=e w=1fg:
|
|
99
|
+
- $for button, i in actions._rightButtons:
|
|
100
|
+
- rtgl-button#action${button._globalIdx} data-action-id=${button.id} v=${button.variant} ?disabled=${button._disabled} pre=${button.pre} suf=${button.suf}: ${button.label}
|
|
101
|
+
- $if actions._layout == "vertical":
|
|
102
|
+
- rtgl-view g=sm w=f:
|
|
103
|
+
- $for button, i in actions._allButtons:
|
|
104
|
+
- rtgl-button#action${button._globalIdx} data-action-id=${button.id} v=${button.variant} w=f ?disabled=${button._disabled} pre=${button.pre} suf=${button.suf}: ${button.label}
|
|
105
|
+
- $if actions._layout == "stretch":
|
|
106
|
+
- rtgl-view d=h g=sm w=f:
|
|
107
|
+
- $for button, i in actions._allButtons:
|
|
108
|
+
- rtgl-view w=1fg:
|
|
109
|
+
- rtgl-button#action${button._globalIdx} data-action-id=${button.id} v=${button.variant} w=f ?disabled=${button._disabled} pre=${button.pre} suf=${button.suf}: ${button.label}
|
|
89
110
|
- rtgl-tooltip ?open=${tooltipState.open} x=${tooltipState.x} y=${tooltipState.y} place="t" content="${tooltipState.content}": null
|
|
@@ -55,7 +55,7 @@ export const handleDropdownItemClick = (deps, payload) => {
|
|
|
55
55
|
* @param {string} [payload.confirmText] - Text for the confirm button (default: "OK")
|
|
56
56
|
* @returns {void}
|
|
57
57
|
*/
|
|
58
|
-
export const
|
|
58
|
+
export const handleShowAlert = (deps, payload) => {
|
|
59
59
|
const { store, render } = deps;
|
|
60
60
|
const options = payload;
|
|
61
61
|
|
|
@@ -69,7 +69,7 @@ export const showAlert = (deps, payload) => {
|
|
|
69
69
|
render();
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
export const
|
|
72
|
+
export const handleShowConfirm = async (deps, payload) => {
|
|
73
73
|
const { store, render, globalUI } = deps;
|
|
74
74
|
const options = payload;
|
|
75
75
|
|
|
@@ -107,7 +107,7 @@ export const showConfirm = async (deps, payload) => {
|
|
|
107
107
|
* @returns {Object} [result.index] - Index of the clicked item
|
|
108
108
|
* @returns {Object} [result.item] - The clicked item object
|
|
109
109
|
*/
|
|
110
|
-
export const
|
|
110
|
+
export const handleShowDropdownMenu = async (deps, payload) => {
|
|
111
111
|
const { store, render, globalUI } = deps;
|
|
112
112
|
const options = payload;
|
|
113
113
|
|
|
@@ -140,7 +140,7 @@ export const showDropdownMenu = async (deps, payload) => {
|
|
|
140
140
|
* @param {Object} deps.globalUI - The globalUI event emitter
|
|
141
141
|
* @returns {void}
|
|
142
142
|
*/
|
|
143
|
-
export const
|
|
143
|
+
export const handleCloseAll = (deps) => {
|
|
144
144
|
const { store, render } = deps;
|
|
145
145
|
|
|
146
146
|
// Close global UI dialogs/dropdowns
|
|
@@ -1,18 +1,46 @@
|
|
|
1
|
+
const normalizePopoverValue = (value) => {
|
|
2
|
+
if (value === undefined || value === null || value === true) {
|
|
3
|
+
return "";
|
|
4
|
+
}
|
|
5
|
+
return String(value);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const commitValue = (deps, value) => {
|
|
9
|
+
const { store, render, dispatchEvent } = deps;
|
|
10
|
+
const nextValue = normalizePopoverValue(value);
|
|
11
|
+
|
|
12
|
+
store.setValue({ value: nextValue });
|
|
13
|
+
store.closePopover({});
|
|
14
|
+
|
|
15
|
+
dispatchEvent(new CustomEvent("value-change", {
|
|
16
|
+
detail: { value: nextValue },
|
|
17
|
+
bubbles: true,
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
render();
|
|
21
|
+
};
|
|
22
|
+
|
|
1
23
|
export const handleBeforeMount = (deps) => {
|
|
2
24
|
const { store, props } = deps;
|
|
3
25
|
|
|
4
26
|
if (props.value !== undefined) {
|
|
5
|
-
|
|
27
|
+
const value = normalizePopoverValue(props.value);
|
|
28
|
+
store.setValue({ value });
|
|
29
|
+
store.setTempValue({ value });
|
|
6
30
|
}
|
|
7
31
|
}
|
|
8
32
|
|
|
9
33
|
export const handleOnUpdate = (deps, payload) => {
|
|
10
34
|
const { oldProps, newProps } = payload;
|
|
11
35
|
const { store, render } = deps;
|
|
36
|
+
const valueChanged = oldProps?.value !== newProps?.value;
|
|
12
37
|
|
|
13
|
-
if (
|
|
14
|
-
const value = newProps?.value
|
|
38
|
+
if (valueChanged) {
|
|
39
|
+
const value = normalizePopoverValue(newProps?.value);
|
|
15
40
|
store.setValue({ value });
|
|
41
|
+
if (!store.getState().isOpen) {
|
|
42
|
+
store.setTempValue({ value });
|
|
43
|
+
}
|
|
16
44
|
}
|
|
17
45
|
|
|
18
46
|
render();
|
|
@@ -20,10 +48,14 @@ export const handleOnUpdate = (deps, payload) => {
|
|
|
20
48
|
|
|
21
49
|
export const handleTextClick = (deps, payload) => {
|
|
22
50
|
const { store, render, refs, props } = deps;
|
|
51
|
+
if (props.disabled) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
23
54
|
const event = payload._event;
|
|
24
55
|
|
|
25
|
-
const value =
|
|
26
|
-
store.
|
|
56
|
+
const value = normalizePopoverValue(props.value);
|
|
57
|
+
store.setValue({ value });
|
|
58
|
+
store.setTempValue({ value });
|
|
27
59
|
|
|
28
60
|
store.openPopover({
|
|
29
61
|
position: {
|
|
@@ -31,16 +63,18 @@ export const handleTextClick = (deps, payload) => {
|
|
|
31
63
|
y: event.currentTarget.getBoundingClientRect().bottom,
|
|
32
64
|
}
|
|
33
65
|
});
|
|
34
|
-
|
|
35
|
-
const { input } = refs;
|
|
36
|
-
input.value = value;
|
|
37
66
|
render();
|
|
38
67
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
68
|
+
setTimeout(() => {
|
|
69
|
+
const { input } = refs;
|
|
70
|
+
if (!input) return;
|
|
71
|
+
input.value = value;
|
|
72
|
+
input.focus();
|
|
73
|
+
const innerInput = input.shadowRoot?.querySelector("input, textarea");
|
|
74
|
+
if (innerInput && typeof innerInput.focus === "function") {
|
|
75
|
+
innerInput.focus();
|
|
76
|
+
}
|
|
77
|
+
}, 50);
|
|
44
78
|
}
|
|
45
79
|
|
|
46
80
|
export const handlePopoverClose = (deps, payload) => {
|
|
@@ -50,54 +84,34 @@ export const handlePopoverClose = (deps, payload) => {
|
|
|
50
84
|
}
|
|
51
85
|
|
|
52
86
|
export const handleInputChange = (deps, payload) => {
|
|
53
|
-
const { store
|
|
87
|
+
const { store } = deps;
|
|
54
88
|
const event = payload._event;
|
|
55
|
-
const value = event.detail.value;
|
|
89
|
+
const value = normalizePopoverValue(event.detail.value);
|
|
56
90
|
|
|
57
91
|
store.setTempValue({ value });
|
|
58
|
-
|
|
59
|
-
dispatchEvent(new CustomEvent('value-input', {
|
|
60
|
-
detail: { value },
|
|
61
|
-
bubbles: true,
|
|
62
|
-
}));
|
|
63
|
-
|
|
64
|
-
render();
|
|
65
92
|
}
|
|
66
93
|
|
|
67
94
|
export const handleSubmitClick = (deps) => {
|
|
68
|
-
const { store,
|
|
69
|
-
const { input } = refs
|
|
70
|
-
const value = input.value;
|
|
71
|
-
|
|
72
|
-
store.setValue({ value });
|
|
73
|
-
store.closePopover({});
|
|
74
|
-
|
|
75
|
-
dispatchEvent(new CustomEvent('value-change', {
|
|
76
|
-
detail: { value },
|
|
77
|
-
bubbles: true,
|
|
78
|
-
}));
|
|
79
|
-
|
|
80
|
-
render();
|
|
95
|
+
const { store, refs } = deps;
|
|
96
|
+
const { input } = refs;
|
|
97
|
+
const value = input ? input.value : store.getState().tempValue;
|
|
98
|
+
commitValue(deps, value);
|
|
81
99
|
}
|
|
82
100
|
|
|
83
101
|
export const handleInputKeydown = (deps, payload) => {
|
|
84
|
-
const { store,
|
|
102
|
+
const { store, refs } = deps;
|
|
85
103
|
const event = payload._event;
|
|
86
104
|
|
|
87
|
-
if (event.key ===
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
store.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}));
|
|
97
|
-
|
|
98
|
-
render();
|
|
99
|
-
} else if (event.key === 'Escape') {
|
|
105
|
+
if (event.key === "Enter") {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
event.stopPropagation();
|
|
108
|
+
const { input } = refs;
|
|
109
|
+
const value = input ? input.value : store.getState().tempValue;
|
|
110
|
+
commitValue(deps, value);
|
|
111
|
+
} else if (event.key === "Escape") {
|
|
112
|
+
event.preventDefault();
|
|
113
|
+
event.stopPropagation();
|
|
100
114
|
store.closePopover({});
|
|
101
|
-
render();
|
|
115
|
+
deps.render();
|
|
102
116
|
}
|
|
103
117
|
}
|
|
@@ -9,15 +9,21 @@ export const createInitialState = () => Object.freeze({
|
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
export const selectViewData = ({ props, state }) => {
|
|
12
|
-
const
|
|
12
|
+
const hasValue = typeof state.value === "string" && state.value.length > 0;
|
|
13
|
+
const value = hasValue ? state.value : "-";
|
|
14
|
+
const placeholder = typeof props.placeholder === "string" ? props.placeholder : "";
|
|
15
|
+
const label = typeof props.label === "string" ? props.label : "";
|
|
16
|
+
const disabled = Boolean(props.disabled);
|
|
13
17
|
|
|
14
18
|
return {
|
|
15
19
|
isOpen: state.isOpen,
|
|
16
20
|
position: state.position,
|
|
17
21
|
value: value,
|
|
22
|
+
valueColor: hasValue ? "fg" : "mu-fg",
|
|
18
23
|
tempValue: state.tempValue,
|
|
19
|
-
placeholder
|
|
20
|
-
label
|
|
24
|
+
placeholder,
|
|
25
|
+
label,
|
|
26
|
+
disabled,
|
|
21
27
|
};
|
|
22
28
|
}
|
|
23
29
|
|
|
@@ -19,10 +19,10 @@ refs:
|
|
|
19
19
|
handler: handleSubmitClick
|
|
20
20
|
template:
|
|
21
21
|
- rtgl-view#textDisplay w=f cur=pointer:
|
|
22
|
-
- rtgl-text: ${value}
|
|
22
|
+
- rtgl-text c=${valueColor}: ${value}
|
|
23
23
|
- rtgl-popover#popover ?open=${isOpen} x=${position.x} y=${position.y}:
|
|
24
|
-
- rtgl-view g=md w=240 slot=content bgc=
|
|
24
|
+
- rtgl-view g=md w=240 slot=content bgc=mu br=md:
|
|
25
25
|
- rtgl-text: ${label}
|
|
26
|
-
- rtgl-input#input w=f placeholder=${placeholder}: null
|
|
26
|
+
- rtgl-input#input w=f placeholder=${placeholder} ?disabled=${disabled}: null
|
|
27
27
|
- rtgl-view w=f ah=e:
|
|
28
|
-
- rtgl-button#submit: Submit
|
|
28
|
+
- rtgl-button#submit ?disabled=${disabled}: Submit
|
|
@@ -17,33 +17,26 @@ export const handleBeforeMount = (deps) => {
|
|
|
17
17
|
export const handleOnUpdate = (deps, payload) => {
|
|
18
18
|
const { oldProps, newProps } = payload;
|
|
19
19
|
const { store, render } = deps;
|
|
20
|
+
let shouldRender = false;
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const selectedValue = newProps?.selectedValue;
|
|
28
|
-
const options = newProps?.options || [];
|
|
29
|
-
|
|
30
|
-
if (selectedValue !== null && selectedValue !== undefined && options) {
|
|
31
|
-
const selectedOption = options.find(opt => deepEqual(opt.value, selectedValue));
|
|
32
|
-
if (selectedOption) {
|
|
33
|
-
store.updateSelectedValue({
|
|
34
|
-
value: selectedOption.value
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
render();
|
|
39
|
-
} else if (oldProps.selectedValue !== newProps.selectedValue) {
|
|
22
|
+
if (!!newProps?.disabled && !oldProps?.disabled) {
|
|
23
|
+
store.closeOptionsPopover({});
|
|
24
|
+
shouldRender = true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (oldProps.selectedValue !== newProps.selectedValue) {
|
|
40
28
|
store.updateSelectedValue({ value: newProps.selectedValue });
|
|
29
|
+
shouldRender = true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (shouldRender) {
|
|
41
33
|
render();
|
|
42
34
|
}
|
|
43
35
|
}
|
|
44
36
|
|
|
45
37
|
export const handleButtonClick = (deps, payload) => {
|
|
46
38
|
const { store, render, refs, props } = deps;
|
|
39
|
+
if (props.disabled) return;
|
|
47
40
|
const event = payload._event;
|
|
48
41
|
event.stopPropagation();
|
|
49
42
|
|
|
@@ -80,6 +73,7 @@ export const handleClickOptionsPopoverOverlay = (deps) => {
|
|
|
80
73
|
|
|
81
74
|
export const handleOptionClick = (deps, payload) => {
|
|
82
75
|
const { render, dispatchEvent, props, store } = deps;
|
|
76
|
+
if (props.disabled) return;
|
|
83
77
|
const event = payload._event;
|
|
84
78
|
event.stopPropagation();
|
|
85
79
|
const id = event.currentTarget.id.slice('option'.length);
|
|
@@ -124,6 +118,7 @@ export const handleOptionMouseLeave = (deps, payload) => {
|
|
|
124
118
|
|
|
125
119
|
export const handleClearClick = (deps, payload) => {
|
|
126
120
|
const { store, render, dispatchEvent, props } = deps;
|
|
121
|
+
if (props.disabled) return;
|
|
127
122
|
const event = payload._event;
|
|
128
123
|
|
|
129
124
|
event.stopPropagation();
|
|
@@ -150,6 +145,7 @@ export const handleClearClick = (deps, payload) => {
|
|
|
150
145
|
}
|
|
151
146
|
|
|
152
147
|
export const handleAddOptionClick = (deps, payload) => {
|
|
148
|
+
if (deps.props.disabled) return;
|
|
153
149
|
const { store, render, dispatchEvent } = deps;
|
|
154
150
|
const { _event: event } = payload;
|
|
155
151
|
event.stopPropagation();
|
|
@@ -14,6 +14,7 @@ const blacklistedProps = [
|
|
|
14
14
|
"options",
|
|
15
15
|
"noClear",
|
|
16
16
|
"addOption",
|
|
17
|
+
"disabled",
|
|
17
18
|
];
|
|
18
19
|
|
|
19
20
|
const stringifyProps = (props = {}) => {
|
|
@@ -37,9 +38,11 @@ export const createInitialState = () => Object.freeze({
|
|
|
37
38
|
export const selectViewData = ({ state, props }) => {
|
|
38
39
|
// Generate container attribute string
|
|
39
40
|
const containerAttrString = stringifyProps(props);
|
|
41
|
+
const isDisabled = !!props.disabled;
|
|
40
42
|
|
|
41
|
-
//
|
|
42
|
-
const
|
|
43
|
+
// Treat selectedValue as a controlled prop when provided by parent.
|
|
44
|
+
const hasControlledValue = Object.prototype.hasOwnProperty.call(props || {}, "selectedValue");
|
|
45
|
+
const currentValue = hasControlledValue ? props.selectedValue : state.selectedValue;
|
|
43
46
|
|
|
44
47
|
// Calculate display label from value
|
|
45
48
|
let displayLabel = props.placeholder || "Select an option";
|
|
@@ -65,6 +68,7 @@ export const selectViewData = ({ state, props }) => {
|
|
|
65
68
|
|
|
66
69
|
return {
|
|
67
70
|
containerAttrString,
|
|
71
|
+
isDisabled,
|
|
68
72
|
isOpen: state.isOpen,
|
|
69
73
|
position: state.position,
|
|
70
74
|
options: optionsWithSelection,
|
|
@@ -72,8 +76,8 @@ export const selectViewData = ({ state, props }) => {
|
|
|
72
76
|
selectedLabel: displayLabel,
|
|
73
77
|
selectedLabelColor: isPlaceholderLabel ? "mu-fg" : "fg",
|
|
74
78
|
hasValue: currentValue !== null && currentValue !== undefined,
|
|
75
|
-
showClear: !props.noClear && (currentValue !== null && currentValue !== undefined),
|
|
76
|
-
showAddOption: !!props.addOption,
|
|
79
|
+
showClear: !isDisabled && !props.noClear && (currentValue !== null && currentValue !== undefined),
|
|
80
|
+
showAddOption: !isDisabled && !!props.addOption,
|
|
77
81
|
addOptionLabel: props.addOption?.label ? `+ ${props.addOption.label}` : "+ Add",
|
|
78
82
|
addOptionBgc: state.hoveredAddOption ? "ac" : "",
|
|
79
83
|
};
|
|
@@ -125,5 +129,3 @@ export const clearSelectedValue = ({ state }) => {
|
|
|
125
129
|
export const setHoveredAddOption = ({ state }, payload = {}) => {
|
|
126
130
|
state.hoveredAddOption = !!payload.isHovered;
|
|
127
131
|
};
|
|
128
|
-
|
|
129
|
-
|
|
@@ -28,9 +28,9 @@ refs:
|
|
|
28
28
|
mouseleave:
|
|
29
29
|
handler: handleAddOptionMouseLeave
|
|
30
30
|
template:
|
|
31
|
-
- rtgl-button#selectButton v=ol ${containerAttrString} data-testid="select-button":
|
|
32
|
-
- rtgl-view d=h av=c w=f:
|
|
33
|
-
- rtgl-text w=1fg c=${selectedLabelColor} ellipsis: ${selectedLabel}
|
|
31
|
+
- rtgl-button#selectButton v=ol ${containerAttrString} ?disabled=${isDisabled} data-testid="select-button":
|
|
32
|
+
- rtgl-view d=h av=c ah=s w=f:
|
|
33
|
+
- rtgl-text w=1fg ta=s c=${selectedLabelColor} ellipsis: ${selectedLabel}
|
|
34
34
|
- $if showClear:
|
|
35
35
|
- rtgl-svg#clearButton ml=md svg=x wh=16 c=mu-fg cur=pointer data-testid="select-clear-button": null
|
|
36
36
|
- rtgl-svg ml=md svg=chevronDown wh=16 c=mu-fg: null
|
|
@@ -38,7 +38,7 @@ template:
|
|
|
38
38
|
- rtgl-view wh=300 g=xs slot=content bgc=mu br=md sv=true:
|
|
39
39
|
- $for option, i in options:
|
|
40
40
|
- rtgl-view#option${i} w=f ph=lg pv=md cur=pointer br=md bgc=${option.bgc} data-testid=${option.testId}:
|
|
41
|
-
- rtgl-text: ${option.label}
|
|
41
|
+
- rtgl-text ta=s: ${option.label}
|
|
42
42
|
- $if showAddOption:
|
|
43
43
|
- rtgl-view w=f bw=xs bc=mu bwt=sm: null
|
|
44
44
|
- rtgl-view#optionAdd w=f ph=lg pv=md cur=pointer br=md bgc=${addOptionBgc} data-testid="select-add-option":
|
|
@@ -6,8 +6,10 @@ export const handleBeforeMount = (deps) => {
|
|
|
6
6
|
export const handleOnUpdate = (deps, payload) => {
|
|
7
7
|
const { oldProps, newProps } = payload;
|
|
8
8
|
const { store, render } = deps;
|
|
9
|
+
const keyChanged = oldProps?.key !== newProps?.key;
|
|
10
|
+
const valueChanged = oldProps?.value !== newProps?.value;
|
|
9
11
|
|
|
10
|
-
if (
|
|
12
|
+
if (keyChanged || valueChanged) {
|
|
11
13
|
const value = newProps?.value ?? 0;
|
|
12
14
|
store.setValue({ value });
|
|
13
15
|
render();
|
|
@@ -18,8 +20,14 @@ export const handleValueChange = (deps, payload) => {
|
|
|
18
20
|
const { store, render, dispatchEvent } = deps;
|
|
19
21
|
const event = payload._event;
|
|
20
22
|
const newValue = Number(event.detail.value);
|
|
23
|
+
const path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
24
|
+
const host = path.find((node) => node?.tagName === "RTGL-SLIDER-INPUT")
|
|
25
|
+
|| event.currentTarget?.getRootNode?.()?.host;
|
|
21
26
|
|
|
22
27
|
store.setValue({ value: newValue });
|
|
28
|
+
if (host && typeof host.setAttribute === "function") {
|
|
29
|
+
host.setAttribute("value", String(newValue));
|
|
30
|
+
}
|
|
23
31
|
|
|
24
32
|
// Re-render to sync slider and input
|
|
25
33
|
render();
|
|
@@ -39,8 +47,14 @@ export const handleValueInput = (deps, payload) => {
|
|
|
39
47
|
const { store, render, dispatchEvent } = deps;
|
|
40
48
|
const event = payload._event;
|
|
41
49
|
const newValue = Number(event.detail.value);
|
|
50
|
+
const path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
51
|
+
const host = path.find((node) => node?.tagName === "RTGL-SLIDER-INPUT")
|
|
52
|
+
|| event.currentTarget?.getRootNode?.()?.host;
|
|
42
53
|
|
|
43
54
|
store.setValue({ value: newValue });
|
|
55
|
+
if (host && typeof host.setAttribute === "function") {
|
|
56
|
+
host.setAttribute("value", String(newValue));
|
|
57
|
+
}
|
|
44
58
|
|
|
45
59
|
// Re-render to sync slider and input
|
|
46
60
|
render();
|
|
@@ -13,6 +13,6 @@ refs:
|
|
|
13
13
|
handler: handleValueInput
|
|
14
14
|
template:
|
|
15
15
|
- rtgl-view d=h av=c g=md w=${w}:
|
|
16
|
-
- rtgl-slider#slider key=${key} w=f type=range min=${min} max=${max} step=${step} value=${value}: null
|
|
16
|
+
- rtgl-slider#slider key=${key} w=f type=range min=${min} max=${max} step=${step} value=${value} ?disabled=${disabled}: null
|
|
17
17
|
- rtgl-view w=84:
|
|
18
|
-
- rtgl-input#input key=${key} w=f
|
|
18
|
+
- rtgl-input-number#input key=${key} w=f min=${min} max=${max} step=${step} value=${value} ?disabled=${disabled}: null
|