@rettangoli/ui 0.1.2-rc24 → 0.1.2-rc26
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 +4 -4
- package/dist/rettangoli-iife-ui.min.js +38 -38
- package/package.json +1 -1
- package/src/common.js +19 -0
- package/src/components/form/form.store.js +28 -1
- package/src/components/select/select.handlers.js +3 -2
- package/src/components/select/select.store.js +13 -14
package/package.json
CHANGED
package/src/common.js
CHANGED
|
@@ -180,6 +180,25 @@ function convertObjectToCssString(styleObject, selector = ':host') {
|
|
|
180
180
|
return result;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
// Deep equality helper for comparing values (including objects)
|
|
184
|
+
export const deepEqual = (a, b) => {
|
|
185
|
+
if (a === b) return true;
|
|
186
|
+
if (a == null || b == null) return false;
|
|
187
|
+
if (typeof a !== 'object' || typeof b !== 'object') return false;
|
|
188
|
+
|
|
189
|
+
const keysA = Object.keys(a);
|
|
190
|
+
const keysB = Object.keys(b);
|
|
191
|
+
|
|
192
|
+
if (keysA.length !== keysB.length) return false;
|
|
193
|
+
|
|
194
|
+
for (const key of keysA) {
|
|
195
|
+
if (!keysB.includes(key)) return false;
|
|
196
|
+
if (!deepEqual(a[key], b[key])) return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return true;
|
|
200
|
+
};
|
|
201
|
+
|
|
183
202
|
export {
|
|
184
203
|
css,
|
|
185
204
|
generateCSS,
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
import { parseAndRender } from "jempl";
|
|
2
2
|
|
|
3
|
+
const encode = (input) => {
|
|
4
|
+
function escapeHtml(text) {
|
|
5
|
+
const map = {
|
|
6
|
+
'&': '&',
|
|
7
|
+
'<': '<',
|
|
8
|
+
'>': '>',
|
|
9
|
+
'"': '"',
|
|
10
|
+
"'": '''
|
|
11
|
+
};
|
|
12
|
+
return text.replace(/[&<>"']/g, char => map[char]);
|
|
13
|
+
}
|
|
14
|
+
if (input === undefined || input === null) {
|
|
15
|
+
return ""
|
|
16
|
+
}
|
|
17
|
+
return `"${escapeHtml(String(input))}"`;
|
|
18
|
+
}
|
|
19
|
+
|
|
3
20
|
function pick(obj, keys) {
|
|
4
21
|
return keys.reduce((acc, key) => {
|
|
5
22
|
if (key in obj) acc[key] = obj[key];
|
|
@@ -77,6 +94,7 @@ export const selectForm = ({ state, props }) => {
|
|
|
77
94
|
return form;
|
|
78
95
|
};
|
|
79
96
|
|
|
97
|
+
|
|
80
98
|
export const toViewData = ({ state, props, attrs }) => {
|
|
81
99
|
const containerAttrString = stringifyAttrs(attrs);
|
|
82
100
|
const defaultValues = props.defaultValues || {};
|
|
@@ -85,7 +103,16 @@ export const toViewData = ({ state, props, attrs }) => {
|
|
|
85
103
|
const fields = structuredClone(form.fields || []);
|
|
86
104
|
fields.forEach((field) => {
|
|
87
105
|
// Use formValues from state if available, otherwise fall back to defaultValues from props
|
|
88
|
-
|
|
106
|
+
const defaultValue = get(state.formValues, field.name) ?? get(defaultValues, field.name)
|
|
107
|
+
if (["popover-input", "select", "read-only-text"].includes(field.inputType)) {
|
|
108
|
+
field.defaultValue = defaultValue
|
|
109
|
+
} else {
|
|
110
|
+
field.defaultValue = encode(defaultValue);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (["inputText"].includes(field.inputType)) {
|
|
114
|
+
field.placeholder = encode(field.placeholder)
|
|
115
|
+
}
|
|
89
116
|
|
|
90
117
|
if (field.inputType === "image") {
|
|
91
118
|
const src = field.src;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { deepEqual } from '../../common.js';
|
|
1
2
|
|
|
2
3
|
export const handleBeforeMount = (deps) => {
|
|
3
4
|
const { store, props, render } = deps;
|
|
4
5
|
|
|
5
6
|
if (props.selectedValue !== null && props.selectedValue !== undefined && props.options) {
|
|
6
|
-
const selectedOption = props.options.find(opt => opt.value
|
|
7
|
+
const selectedOption = props.options.find(opt => deepEqual(opt.value, props.selectedValue));
|
|
7
8
|
if (selectedOption) {
|
|
8
9
|
store.updateSelectOption(selectedOption);
|
|
9
10
|
render();
|
|
@@ -25,7 +26,7 @@ export const handleOnUpdate = (changes, deps) => {
|
|
|
25
26
|
const options = newProps?.options || props?.options;
|
|
26
27
|
|
|
27
28
|
if (selectedValue !== null && selectedValue !== undefined && options) {
|
|
28
|
-
const selectedOption = options.find(opt => opt.value
|
|
29
|
+
const selectedOption = options.find(opt => deepEqual(opt.value, selectedValue));
|
|
29
30
|
if (selectedOption) {
|
|
30
31
|
store.updateSelectOption(selectedOption);
|
|
31
32
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { deepEqual } from '../../common.js';
|
|
2
|
+
|
|
1
3
|
export const INITIAL_STATE = Object.freeze({
|
|
2
4
|
isOpen: false,
|
|
3
5
|
position: {
|
|
@@ -5,31 +7,30 @@ export const INITIAL_STATE = Object.freeze({
|
|
|
5
7
|
y: 0,
|
|
6
8
|
},
|
|
7
9
|
selectedValue: null,
|
|
8
|
-
selectedLabel: null,
|
|
9
10
|
});
|
|
10
11
|
|
|
11
12
|
export const toViewData = ({ state, props }) => {
|
|
12
|
-
// Calculate display label
|
|
13
|
-
let displayLabel = props.placeholder || 'Select an option';
|
|
14
|
-
|
|
15
13
|
// Use state's selected value if available, otherwise use props.selectedValue
|
|
16
14
|
const currentValue = state.selectedValue !== null ? state.selectedValue : props.selectedValue;
|
|
17
15
|
|
|
16
|
+
// Calculate display label from value
|
|
17
|
+
let displayLabel = props.placeholder || 'Select an option';
|
|
18
18
|
if (currentValue !== null && currentValue !== undefined && props.options) {
|
|
19
|
-
const selectedOption = props.options.find(opt => opt.value
|
|
19
|
+
const selectedOption = props.options.find(opt => deepEqual(opt.value, currentValue));
|
|
20
20
|
if (selectedOption) {
|
|
21
21
|
displayLabel = selectedOption.label;
|
|
22
22
|
}
|
|
23
|
-
} else if (state.selectedLabel) {
|
|
24
|
-
displayLabel = state.selectedLabel;
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
// Map options to include isSelected flag and computed background color
|
|
28
|
-
const optionsWithSelection = (props.options || []).map(option =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
const optionsWithSelection = (props.options || []).map(option => {
|
|
27
|
+
const isSelected = deepEqual(option.value, currentValue);
|
|
28
|
+
return {
|
|
29
|
+
...option,
|
|
30
|
+
isSelected,
|
|
31
|
+
bgc: isSelected ? 'mu' : ''
|
|
32
|
+
};
|
|
33
|
+
});
|
|
33
34
|
|
|
34
35
|
return {
|
|
35
36
|
isOpen: state.isOpen,
|
|
@@ -57,13 +58,11 @@ export const closeOptionsPopover = (state) => {
|
|
|
57
58
|
|
|
58
59
|
export const updateSelectOption = (state, option) => {
|
|
59
60
|
state.selectedValue = option.value;
|
|
60
|
-
state.selectedLabel = option.label;
|
|
61
61
|
state.isOpen = false;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
export const resetSelection = (state) => {
|
|
65
65
|
state.selectedValue = undefined;
|
|
66
|
-
state.selectedLabel = undefined;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
|