@rettangoli/ui 1.0.0-rc8 → 1.0.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-layout.min.js +74 -42
- package/dist/rettangoli-iife-ui.min.js +161 -60
- package/dist/themes/base.css +4 -4
- package/dist/themes/theme-catppuccin.css +1 -1
- package/dist/themes/theme-rtgl-mono.css +1 -1
- package/dist/themes/theme-rtgl-slate.css +1 -1
- package/package.json +11 -7
- 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 +542 -97
- 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 +8 -2
- package/src/themes/base.css +4 -4
- package/src/themes/theme-catppuccin.css +1 -1
- package/src/themes/theme-rtgl-mono.css +1 -1
- package/src/themes/theme-rtgl-slate.css +1 -1
|
@@ -1,194 +1,405 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
get,
|
|
3
|
+
set,
|
|
4
|
+
selectForm,
|
|
5
|
+
selectFormValues,
|
|
6
|
+
collectAllDataFields,
|
|
7
|
+
getDefaultValue,
|
|
8
|
+
pruneHiddenValues,
|
|
9
|
+
validateField,
|
|
10
|
+
validateForm,
|
|
11
|
+
} from "./form.store.js";
|
|
5
12
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
13
|
+
const syncInteractiveFieldAttribute = ({ field, target, value }) => {
|
|
14
|
+
if (!field || !target) return;
|
|
15
|
+
if (!["slider-with-input", "popover-input"].includes(field.type)) return;
|
|
9
16
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
if (value === undefined || value === null) {
|
|
18
|
+
target.removeAttribute("value");
|
|
19
|
+
} else {
|
|
20
|
+
target.setAttribute("value", String(value));
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const updateFieldAttributes = ({
|
|
25
|
+
form,
|
|
26
|
+
formValues = {},
|
|
27
|
+
refs,
|
|
28
|
+
formDisabled = false,
|
|
29
|
+
}) => {
|
|
30
|
+
const fields = form.fields || [];
|
|
31
|
+
let idx = 0;
|
|
32
|
+
|
|
33
|
+
const walk = (fieldList) => {
|
|
34
|
+
for (const field of fieldList) {
|
|
35
|
+
if (field.type === "section") {
|
|
36
|
+
idx++;
|
|
37
|
+
if (Array.isArray(field.fields)) {
|
|
38
|
+
walk(field.fields);
|
|
39
|
+
}
|
|
40
|
+
continue;
|
|
16
41
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
42
|
+
|
|
43
|
+
const ref = refs[`field${idx}`];
|
|
44
|
+
idx++;
|
|
45
|
+
|
|
46
|
+
if (!ref) continue;
|
|
47
|
+
|
|
48
|
+
const disabled = formDisabled || !!field.disabled;
|
|
49
|
+
|
|
50
|
+
if (["input-text", "input-date", "input-time", "input-datetime", "input-number", "input-textarea", "color-picker", "slider", "slider-with-input", "popover-input"].includes(field.type)) {
|
|
51
|
+
const value = get(formValues, field.name);
|
|
52
|
+
if (value === undefined || value === null) {
|
|
53
|
+
ref.removeAttribute("value");
|
|
23
54
|
} else {
|
|
24
|
-
ref.setAttribute(
|
|
55
|
+
ref.setAttribute("value", String(value));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (field.type === "slider-with-input" && ref.store?.setValue) {
|
|
59
|
+
const normalized = Number(value ?? 0);
|
|
60
|
+
ref.store.setValue({ value: Number.isFinite(normalized) ? normalized : 0 });
|
|
61
|
+
if (typeof ref.render === "function") {
|
|
62
|
+
ref.render();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (field.type === "popover-input" && ref.store?.setValue) {
|
|
67
|
+
ref.store.setValue({ value: value === undefined || value === null ? "" : String(value) });
|
|
68
|
+
if (typeof ref.render === "function") {
|
|
69
|
+
ref.render();
|
|
70
|
+
}
|
|
25
71
|
}
|
|
26
72
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
73
|
+
|
|
74
|
+
if (field.type === "checkbox") {
|
|
75
|
+
const value = get(formValues, field.name);
|
|
76
|
+
if (value) {
|
|
77
|
+
ref.setAttribute("checked", "");
|
|
78
|
+
} else {
|
|
79
|
+
ref.removeAttribute("checked");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (["input-text", "input-date", "input-time", "input-datetime", "input-number", "input-textarea", "popover-input"].includes(field.type) && field.placeholder) {
|
|
84
|
+
const current = ref.getAttribute("placeholder");
|
|
85
|
+
if (current !== field.placeholder) {
|
|
86
|
+
if (field.placeholder === undefined || field.placeholder === null) {
|
|
87
|
+
ref.removeAttribute("placeholder");
|
|
88
|
+
} else {
|
|
89
|
+
ref.setAttribute("placeholder", field.placeholder);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (disabled) {
|
|
95
|
+
ref.setAttribute("disabled", "");
|
|
96
|
+
} else {
|
|
97
|
+
ref.removeAttribute("disabled");
|
|
40
98
|
}
|
|
41
99
|
}
|
|
42
|
-
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
walk(fields);
|
|
43
103
|
};
|
|
44
104
|
|
|
105
|
+
const initFormValues = (store, props) => {
|
|
106
|
+
const defaultValues = props?.defaultValues || {};
|
|
107
|
+
const seededValues = {};
|
|
108
|
+
Object.keys(defaultValues).forEach((path) => {
|
|
109
|
+
set(seededValues, path, defaultValues[path]);
|
|
110
|
+
});
|
|
111
|
+
const form = selectForm({ state: { formValues: seededValues }, props });
|
|
112
|
+
const dataFields = collectAllDataFields(form.fields || []);
|
|
113
|
+
const initial = {};
|
|
114
|
+
|
|
115
|
+
for (const field of dataFields) {
|
|
116
|
+
const defaultVal = get(defaultValues, field.name);
|
|
117
|
+
if (defaultVal !== undefined) {
|
|
118
|
+
set(initial, field.name, defaultVal);
|
|
119
|
+
} else {
|
|
120
|
+
set(initial, field.name, getDefaultValue(field));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
store.resetFormValues({ defaultValues: initial });
|
|
125
|
+
};
|
|
45
126
|
|
|
46
127
|
export const handleBeforeMount = (deps) => {
|
|
47
128
|
const { store, props } = deps;
|
|
48
|
-
store
|
|
129
|
+
initFormValues(store, props);
|
|
49
130
|
};
|
|
50
131
|
|
|
51
132
|
export const handleAfterMount = (deps) => {
|
|
52
133
|
const { props, refs, render } = deps;
|
|
53
|
-
const
|
|
54
|
-
|
|
134
|
+
const state = deps.store.getState();
|
|
135
|
+
const form = selectForm({ state, props });
|
|
136
|
+
updateFieldAttributes({
|
|
137
|
+
form,
|
|
138
|
+
formValues: state.formValues,
|
|
139
|
+
refs,
|
|
140
|
+
formDisabled: !!props?.disabled,
|
|
141
|
+
});
|
|
55
142
|
render();
|
|
56
|
-
|
|
57
|
-
// Auto-focus first input field if autofocus attribute is set
|
|
58
|
-
if (props?.autofocus) {
|
|
59
|
-
setTimeout(() => {
|
|
60
|
-
autoFocusFirstInput(refs);
|
|
61
|
-
}, 50);
|
|
62
|
-
}
|
|
63
143
|
};
|
|
64
144
|
|
|
65
145
|
export const handleOnUpdate = (deps, payload) => {
|
|
66
|
-
const {
|
|
146
|
+
const { newProps } = payload;
|
|
67
147
|
const { store, render, refs } = deps;
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
148
|
+
const formDisabled = !!newProps?.disabled;
|
|
149
|
+
|
|
150
|
+
const state = store.getState();
|
|
151
|
+
pruneHiddenValues({ state, props: newProps });
|
|
152
|
+
const form = selectForm({ state, props: newProps });
|
|
153
|
+
updateFieldAttributes({
|
|
154
|
+
form,
|
|
155
|
+
formValues: state.formValues,
|
|
156
|
+
refs,
|
|
157
|
+
formDisabled,
|
|
158
|
+
});
|
|
159
|
+
render();
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export const handleValueInput = (deps, payload) => {
|
|
163
|
+
const { store, dispatchEvent, render, props } = deps;
|
|
164
|
+
const event = payload._event;
|
|
165
|
+
const name = event.currentTarget.dataset.fieldName;
|
|
166
|
+
if (!name || !event.detail || !Object.prototype.hasOwnProperty.call(event.detail, "value")) {
|
|
73
167
|
return;
|
|
74
168
|
}
|
|
169
|
+
|
|
170
|
+
const value = event.detail.value;
|
|
171
|
+
store.setFormFieldValue({ name, value });
|
|
172
|
+
|
|
173
|
+
const state = store.getState();
|
|
174
|
+
pruneHiddenValues({ state, props });
|
|
175
|
+
const form = selectForm({ state, props });
|
|
176
|
+
const dataFields = collectAllDataFields(form.fields || []);
|
|
177
|
+
const field = dataFields.find((f) => f.name === name);
|
|
178
|
+
|
|
179
|
+
syncInteractiveFieldAttribute({
|
|
180
|
+
field,
|
|
181
|
+
target: event.currentTarget,
|
|
182
|
+
value,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Reactive validation
|
|
186
|
+
if (state.reactiveMode) {
|
|
187
|
+
if (field) {
|
|
188
|
+
const error = validateField(field, value);
|
|
189
|
+
if (error) {
|
|
190
|
+
store.setErrors({ errors: { ...state.errors, [name]: error } });
|
|
191
|
+
} else {
|
|
192
|
+
store.clearFieldError({ name });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Keep conditional fields and jempl-rendered content in sync while typing.
|
|
75
198
|
render();
|
|
76
|
-
};
|
|
77
199
|
|
|
78
|
-
const dispatchFormChange = (name, fieldValue, formValues, dispatchEvent) => {
|
|
79
200
|
dispatchEvent(
|
|
80
|
-
new CustomEvent("form-
|
|
201
|
+
new CustomEvent("form-input", {
|
|
202
|
+
bubbles: true,
|
|
81
203
|
detail: {
|
|
82
204
|
name,
|
|
83
|
-
|
|
84
|
-
|
|
205
|
+
value,
|
|
206
|
+
values: selectFormValues({ state: store.getState(), props }),
|
|
85
207
|
},
|
|
86
208
|
}),
|
|
87
209
|
);
|
|
88
210
|
};
|
|
89
211
|
|
|
90
|
-
export const
|
|
91
|
-
const { store, dispatchEvent } = deps;
|
|
212
|
+
export const handleValueChange = (deps, payload) => {
|
|
213
|
+
const { store, dispatchEvent, render, props } = deps;
|
|
92
214
|
const event = payload._event;
|
|
93
|
-
const
|
|
215
|
+
const name = event.currentTarget.dataset.fieldName;
|
|
216
|
+
if (!name || !event.detail || !Object.prototype.hasOwnProperty.call(event.detail, "value")) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const value = event.detail.value;
|
|
221
|
+
store.setFormFieldValue({ name, value });
|
|
222
|
+
|
|
223
|
+
const state = store.getState();
|
|
224
|
+
pruneHiddenValues({ state, props });
|
|
225
|
+
const form = selectForm({ state, props });
|
|
226
|
+
const dataFields = collectAllDataFields(form.fields || []);
|
|
227
|
+
const field = dataFields.find((f) => f.name === name);
|
|
228
|
+
|
|
229
|
+
syncInteractiveFieldAttribute({
|
|
230
|
+
field,
|
|
231
|
+
target: event.currentTarget,
|
|
232
|
+
value,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Reactive validation
|
|
236
|
+
if (state.reactiveMode) {
|
|
237
|
+
if (field) {
|
|
238
|
+
const error = validateField(field, value);
|
|
239
|
+
if (error) {
|
|
240
|
+
store.setErrors({ errors: { ...state.errors, [name]: error } });
|
|
241
|
+
} else {
|
|
242
|
+
store.clearFieldError({ name });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Re-render on committed changes so controlled child components stay synchronized.
|
|
248
|
+
render();
|
|
249
|
+
|
|
94
250
|
dispatchEvent(
|
|
95
|
-
new CustomEvent("
|
|
251
|
+
new CustomEvent("form-change", {
|
|
252
|
+
bubbles: true,
|
|
96
253
|
detail: {
|
|
97
|
-
|
|
98
|
-
|
|
254
|
+
name,
|
|
255
|
+
value,
|
|
256
|
+
values: selectFormValues({ state: store.getState(), props }),
|
|
99
257
|
},
|
|
100
258
|
}),
|
|
101
259
|
);
|
|
102
260
|
};
|
|
103
261
|
|
|
104
|
-
export const
|
|
105
|
-
const { store, dispatchEvent } = deps;
|
|
262
|
+
export const handleActionClick = (deps, payload) => {
|
|
263
|
+
const { store, dispatchEvent, render, props } = deps;
|
|
106
264
|
const event = payload._event;
|
|
107
|
-
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
265
|
+
const actionId = event.currentTarget.dataset.actionId;
|
|
266
|
+
if (!actionId) return;
|
|
267
|
+
|
|
268
|
+
const state = store.getState();
|
|
269
|
+
const form = selectForm({ state, props });
|
|
270
|
+
const actions = form.actions || {};
|
|
271
|
+
const buttons = actions.buttons || [];
|
|
272
|
+
const button = buttons.find((b) => b.id === actionId);
|
|
273
|
+
|
|
274
|
+
const values = selectFormValues({ state, props });
|
|
275
|
+
|
|
276
|
+
if (button && button.validate) {
|
|
277
|
+
const dataFields = collectAllDataFields(form.fields || []);
|
|
278
|
+
const { valid, errors } = validateForm(dataFields, state.formValues);
|
|
279
|
+
store.setErrors({ errors });
|
|
280
|
+
if (!valid) {
|
|
281
|
+
store.setReactiveMode();
|
|
282
|
+
}
|
|
283
|
+
render();
|
|
284
|
+
|
|
285
|
+
dispatchEvent(
|
|
286
|
+
new CustomEvent("form-action", {
|
|
287
|
+
bubbles: true,
|
|
288
|
+
detail: {
|
|
289
|
+
actionId,
|
|
290
|
+
values,
|
|
291
|
+
valid,
|
|
292
|
+
errors,
|
|
293
|
+
},
|
|
294
|
+
}),
|
|
295
|
+
);
|
|
296
|
+
} else {
|
|
297
|
+
dispatchEvent(
|
|
298
|
+
new CustomEvent("form-action", {
|
|
299
|
+
bubbles: true,
|
|
300
|
+
detail: {
|
|
301
|
+
actionId,
|
|
302
|
+
values,
|
|
303
|
+
},
|
|
304
|
+
}),
|
|
119
305
|
);
|
|
120
306
|
}
|
|
121
307
|
};
|
|
122
308
|
|
|
123
|
-
|
|
124
309
|
export const handleImageClick = (deps, payload) => {
|
|
125
310
|
const event = payload._event;
|
|
126
311
|
if (event.type === "contextmenu") {
|
|
127
312
|
event.preventDefault();
|
|
128
313
|
}
|
|
129
|
-
const { dispatchEvent } = deps;
|
|
130
|
-
const name = event.currentTarget.dataset.fieldName
|
|
314
|
+
const { store, dispatchEvent, props } = deps;
|
|
315
|
+
const name = event.currentTarget.dataset.fieldName;
|
|
316
|
+
|
|
131
317
|
dispatchEvent(
|
|
132
|
-
new CustomEvent("
|
|
318
|
+
new CustomEvent("form-field-event", {
|
|
319
|
+
bubbles: true,
|
|
133
320
|
detail: {
|
|
134
|
-
name
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
trigger: event.type,
|
|
321
|
+
name,
|
|
322
|
+
event: event.type,
|
|
323
|
+
values: selectFormValues({ state: store.getState(), props }),
|
|
138
324
|
},
|
|
139
325
|
}),
|
|
140
326
|
);
|
|
141
327
|
};
|
|
142
328
|
|
|
143
|
-
export const
|
|
329
|
+
export const handleKeyDown = (deps, payload) => {
|
|
330
|
+
const { store, dispatchEvent, render, props } = deps;
|
|
144
331
|
const event = payload._event;
|
|
145
|
-
|
|
332
|
+
|
|
333
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
334
|
+
const target = event.target;
|
|
335
|
+
if (target.tagName === "TEXTAREA" || target.tagName === "RTGL-TEXTAREA") {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
146
339
|
event.preventDefault();
|
|
147
|
-
}
|
|
148
|
-
const { dispatchEvent } = deps;
|
|
149
|
-
const name = event.currentTarget.dataset.fieldName || event.currentTarget.id.slice("waveform".length);
|
|
150
|
-
dispatchEvent(
|
|
151
|
-
new CustomEvent("extra-event", {
|
|
152
|
-
detail: {
|
|
153
|
-
name: name,
|
|
154
|
-
x: event.clientX,
|
|
155
|
-
y: event.clientY,
|
|
156
|
-
trigger: event.type,
|
|
157
|
-
},
|
|
158
|
-
}),
|
|
159
|
-
);
|
|
160
|
-
};
|
|
161
340
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
})
|
|
174
|
-
|
|
341
|
+
const state = store.getState();
|
|
342
|
+
const form = selectForm({ state, props });
|
|
343
|
+
const actions = form.actions || {};
|
|
344
|
+
const buttons = actions.buttons || [];
|
|
345
|
+
|
|
346
|
+
// Find the first button with validate: true, or the first button
|
|
347
|
+
const validateButton = buttons.find((b) => b.validate);
|
|
348
|
+
const targetButton = validateButton || buttons[0];
|
|
349
|
+
|
|
350
|
+
if (!targetButton) return;
|
|
351
|
+
|
|
352
|
+
const values = selectFormValues({ state, props });
|
|
353
|
+
|
|
354
|
+
if (targetButton.validate) {
|
|
355
|
+
const dataFields = collectAllDataFields(form.fields || []);
|
|
356
|
+
const { valid, errors } = validateForm(dataFields, state.formValues);
|
|
357
|
+
store.setErrors({ errors });
|
|
358
|
+
if (!valid) {
|
|
359
|
+
store.setReactiveMode();
|
|
360
|
+
}
|
|
361
|
+
render();
|
|
362
|
+
|
|
363
|
+
dispatchEvent(
|
|
364
|
+
new CustomEvent("form-action", {
|
|
365
|
+
bubbles: true,
|
|
366
|
+
detail: {
|
|
367
|
+
actionId: targetButton.id,
|
|
368
|
+
values,
|
|
369
|
+
valid,
|
|
370
|
+
errors,
|
|
371
|
+
},
|
|
372
|
+
}),
|
|
373
|
+
);
|
|
374
|
+
} else {
|
|
375
|
+
dispatchEvent(
|
|
376
|
+
new CustomEvent("form-action", {
|
|
377
|
+
bubbles: true,
|
|
378
|
+
detail: {
|
|
379
|
+
actionId: targetButton.id,
|
|
380
|
+
values,
|
|
381
|
+
},
|
|
382
|
+
}),
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
175
386
|
};
|
|
176
387
|
|
|
177
388
|
export const handleTooltipMouseEnter = (deps, payload) => {
|
|
178
389
|
const { store, render, props } = deps;
|
|
179
390
|
const event = payload._event;
|
|
180
|
-
const fieldName = event.currentTarget.dataset.fieldName
|
|
391
|
+
const fieldName = event.currentTarget.dataset.fieldName;
|
|
181
392
|
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
const field =
|
|
393
|
+
const form = selectForm({ state: store.getState(), props });
|
|
394
|
+
const allFields = collectAllDataFields(form.fields || []);
|
|
395
|
+
const field = allFields.find((f) => f.name === fieldName);
|
|
185
396
|
|
|
186
397
|
if (field && field.tooltip) {
|
|
187
398
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
188
399
|
store.showTooltip({
|
|
189
400
|
x: rect.left + rect.width / 2,
|
|
190
401
|
y: rect.top - 8,
|
|
191
|
-
content: field.tooltip.content
|
|
402
|
+
content: typeof field.tooltip === "string" ? field.tooltip : field.tooltip.content || "",
|
|
192
403
|
});
|
|
193
404
|
render();
|
|
194
405
|
}
|
|
@@ -199,38 +410,3 @@ export const handleTooltipMouseLeave = (deps) => {
|
|
|
199
410
|
store.hideTooltip({});
|
|
200
411
|
render();
|
|
201
412
|
};
|
|
202
|
-
|
|
203
|
-
export const handleKeyDown = (deps, payload) => {
|
|
204
|
-
const { store, dispatchEvent, props } = deps;
|
|
205
|
-
const event = payload._event;
|
|
206
|
-
|
|
207
|
-
// Handle Enter key to submit form
|
|
208
|
-
if (event.key === 'Enter' && !event.shiftKey) {
|
|
209
|
-
const target = event.target;
|
|
210
|
-
// Don't submit if we're in a textarea (native or custom component)
|
|
211
|
-
if (target.tagName === 'TEXTAREA' || target.tagName === 'RTGL-TEXTAREA') {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
event.preventDefault();
|
|
216
|
-
|
|
217
|
-
// Dispatch action-click event for the first button
|
|
218
|
-
const form = props.form || {};
|
|
219
|
-
const actions = form.actions || {};
|
|
220
|
-
const buttons = actions.buttons || [];
|
|
221
|
-
|
|
222
|
-
if (buttons.length > 0) {
|
|
223
|
-
const firstButtonId = buttons[0].id;
|
|
224
|
-
const formValues = store.selectFormValues();
|
|
225
|
-
|
|
226
|
-
dispatchEvent(
|
|
227
|
-
new CustomEvent("action-click", {
|
|
228
|
-
detail: {
|
|
229
|
-
actionId: firstButtonId,
|
|
230
|
-
formValues: formValues,
|
|
231
|
-
},
|
|
232
|
-
}),
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
};
|