@burdenoff/microfe-bigconsole 2026.803.4 → 2026.804.2
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/bigconsole/components/datasink/ImportDataGuideDialog.js +66 -0
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -0
- package/dist/bigconsole/components/parser/DataSinkSelector.js +129 -106
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +183 -144
- package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetWrapper.js +3 -1
- package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
- package/dist/bigconsole/components/widgets/form/FormWidget.js +155 -121
- package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/form/index.js +2 -2
- package/dist/bigconsole/components/widgets/index.js +2 -0
- package/dist/bigconsole/contexts/NavigationContext.js +6 -2
- package/dist/bigconsole/contexts/NavigationContext.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +136 -101
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -50,7 +50,41 @@ function p(e, t) {
|
|
|
50
50
|
}
|
|
51
51
|
return n;
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
function m(e, t) {
|
|
54
|
+
let n = {}, r = {};
|
|
55
|
+
if (!e || typeof e != "object" || Array.isArray(e)) {
|
|
56
|
+
for (let e of t) n[e.name] = e.defaultValue ?? (e.type === "checkbox" ? !1 : "");
|
|
57
|
+
return {
|
|
58
|
+
values: n,
|
|
59
|
+
fieldOptions: r
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
let i = e.values && typeof e.values == "object" && !Array.isArray(e.values) ? e.values : void 0, a = e.options && typeof e.options == "object" && !Array.isArray(e.options) ? e.options : void 0;
|
|
63
|
+
for (let o of t) {
|
|
64
|
+
let t = i?.[o.name] ?? e[o.name] ?? o.defaultValue;
|
|
65
|
+
if (o.type === "checkbox" && t === void 0 && (t = !1), n[o.name] = t ?? "", o.type === "select" || o.type === "radio") {
|
|
66
|
+
let t = a?.[o.name] ?? e[`${o.name}Options`];
|
|
67
|
+
Array.isArray(t) && (r[o.name] = t.map((e) => {
|
|
68
|
+
if (e && typeof e == "object") {
|
|
69
|
+
let t = e, n = {
|
|
70
|
+
value: String(t.value ?? t.id ?? t.key ?? ""),
|
|
71
|
+
label: String(t.label ?? t.name ?? t.text ?? t.value ?? t.id ?? t.key ?? "")
|
|
72
|
+
};
|
|
73
|
+
return t.disabled === !0 && (n.disabled = !0), n;
|
|
74
|
+
}
|
|
75
|
+
return typeof e == "string" || typeof e == "number" ? {
|
|
76
|
+
value: String(e),
|
|
77
|
+
label: String(e)
|
|
78
|
+
} : null;
|
|
79
|
+
}).filter((e) => e !== null));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
values: n,
|
|
84
|
+
fieldOptions: r
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
var h = {
|
|
54
88
|
container: {
|
|
55
89
|
display: "flex",
|
|
56
90
|
flexDirection: "column",
|
|
@@ -175,84 +209,80 @@ var m = {
|
|
|
175
209
|
color: "var(--color-text-muted)",
|
|
176
210
|
textAlign: "center"
|
|
177
211
|
}
|
|
178
|
-
},
|
|
179
|
-
let
|
|
212
|
+
}, g = e(function({ widget: e, data: g = {}, onDrilldown: _, onSubmit: v }) {
|
|
213
|
+
let y = {
|
|
180
214
|
fields: [],
|
|
181
215
|
layout: "vertical",
|
|
182
216
|
submitLabel: "Submit",
|
|
183
217
|
showReset: !0,
|
|
184
218
|
validateOnBlur: !0,
|
|
185
219
|
validateOnChange: !1
|
|
186
|
-
},
|
|
187
|
-
...
|
|
220
|
+
}, b = e.config ? {
|
|
221
|
+
...y,
|
|
188
222
|
...e.config
|
|
189
|
-
} :
|
|
190
|
-
|
|
191
|
-
for (let t of y.fields) e[t.name] = h[t.name] ?? t.defaultValue ?? (t.type === "checkbox" ? !1 : "");
|
|
192
|
-
return e;
|
|
193
|
-
}, [y.fields, h]), [x, S] = r(b), [C, w] = r({}), [T, E] = r(/* @__PURE__ */ new Set()), [D, O] = r(!1), [k, A] = r(!1), j = t((e, t) => {
|
|
194
|
-
if (S((n) => ({
|
|
223
|
+
} : y, x = n(() => m(g, b.fields), [g, b.fields]), S = n(() => x.values, [x.values]), [C, w] = r(S), [T, E] = r({}), [D, O] = r(/* @__PURE__ */ new Set()), [k, A] = r(!1), [j, M] = r(!1), N = t((e, t) => {
|
|
224
|
+
if (w((n) => ({
|
|
195
225
|
...n,
|
|
196
226
|
[e]: t
|
|
197
|
-
})),
|
|
198
|
-
let n =
|
|
227
|
+
})), M(!1), b.validateOnChange) {
|
|
228
|
+
let n = b.fields.find((t) => t.name === e);
|
|
199
229
|
if (n) {
|
|
200
230
|
let r = f(t, n);
|
|
201
|
-
|
|
231
|
+
E((t) => ({
|
|
202
232
|
...t,
|
|
203
233
|
[e]: r
|
|
204
234
|
}));
|
|
205
235
|
}
|
|
206
236
|
}
|
|
207
|
-
}, [
|
|
208
|
-
if (
|
|
209
|
-
let t =
|
|
237
|
+
}, [b.fields, b.validateOnChange]), P = t((e) => {
|
|
238
|
+
if (O((t) => new Set(t).add(e)), b.validateOnBlur) {
|
|
239
|
+
let t = b.fields.find((t) => t.name === e);
|
|
210
240
|
if (t) {
|
|
211
|
-
let n = f(
|
|
212
|
-
|
|
241
|
+
let n = f(C[e], t);
|
|
242
|
+
E((t) => ({
|
|
213
243
|
...t,
|
|
214
244
|
[e]: n
|
|
215
245
|
}));
|
|
216
246
|
}
|
|
217
247
|
}
|
|
218
248
|
}, [
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
]),
|
|
249
|
+
b.fields,
|
|
250
|
+
b.validateOnBlur,
|
|
251
|
+
C
|
|
252
|
+
]), F = t(async (t) => {
|
|
223
253
|
t.preventDefault();
|
|
224
|
-
let n = p(
|
|
225
|
-
if (
|
|
226
|
-
|
|
254
|
+
let n = p(C, b.fields);
|
|
255
|
+
if (E(n), O(new Set(b.fields.map((e) => e.name))), !Object.values(n).some((e) => e !== null)) {
|
|
256
|
+
A(!0);
|
|
227
257
|
try {
|
|
228
258
|
let t = {
|
|
229
|
-
...
|
|
230
|
-
_action:
|
|
259
|
+
...C,
|
|
260
|
+
_action: b.submitAction || "form_submit",
|
|
231
261
|
_widgetId: e.id,
|
|
232
262
|
_timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
233
263
|
};
|
|
234
|
-
|
|
264
|
+
v && await v(t), _ && _({
|
|
235
265
|
type: "form_submit",
|
|
236
|
-
action:
|
|
266
|
+
action: b.submitAction || "form_submit",
|
|
237
267
|
data: t
|
|
238
|
-
}),
|
|
268
|
+
}), M(!0);
|
|
239
269
|
} catch {} finally {
|
|
240
|
-
|
|
270
|
+
A(!1);
|
|
241
271
|
}
|
|
242
272
|
}
|
|
243
273
|
}, [
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
274
|
+
C,
|
|
275
|
+
b.fields,
|
|
276
|
+
b.submitAction,
|
|
247
277
|
e.id,
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
]),
|
|
251
|
-
S
|
|
252
|
-
}, [
|
|
253
|
-
let t =
|
|
254
|
-
...
|
|
255
|
-
...n ?
|
|
278
|
+
v,
|
|
279
|
+
_
|
|
280
|
+
]), I = t(() => {
|
|
281
|
+
w(S), E({}), O(/* @__PURE__ */ new Set()), M(!1);
|
|
282
|
+
}, [S]), L = t((e) => {
|
|
283
|
+
let t = C[e.name], n = !!(D.has(e.name) && T[e.name]), r = {
|
|
284
|
+
...h.input,
|
|
285
|
+
...n ? h.inputError : {}
|
|
256
286
|
};
|
|
257
287
|
switch (e.type) {
|
|
258
288
|
case "textarea": return /* @__PURE__ */ u("textarea", {
|
|
@@ -261,48 +291,51 @@ var m = {
|
|
|
261
291
|
value: String(t ?? ""),
|
|
262
292
|
placeholder: e.placeholder,
|
|
263
293
|
required: e.required,
|
|
264
|
-
disabled: e.disabled ||
|
|
294
|
+
disabled: e.disabled || k,
|
|
265
295
|
readOnly: e.readonly,
|
|
266
296
|
rows: e.rows || 4,
|
|
267
297
|
style: {
|
|
268
298
|
...r,
|
|
269
|
-
...
|
|
270
|
-
},
|
|
271
|
-
onChange: (t) => j(e.name, t.target.value),
|
|
272
|
-
onBlur: () => M(e.name)
|
|
273
|
-
});
|
|
274
|
-
case "select": return /* @__PURE__ */ d("select", {
|
|
275
|
-
id: e.name,
|
|
276
|
-
name: e.name,
|
|
277
|
-
value: String(t ?? ""),
|
|
278
|
-
required: e.required,
|
|
279
|
-
disabled: e.disabled || D,
|
|
280
|
-
style: {
|
|
281
|
-
...r,
|
|
282
|
-
...m.select
|
|
299
|
+
...h.textarea
|
|
283
300
|
},
|
|
284
|
-
onChange: (t) =>
|
|
285
|
-
onBlur: () =>
|
|
286
|
-
children: [/* @__PURE__ */ u("option", {
|
|
287
|
-
value: "",
|
|
288
|
-
children: e.placeholder || `Select ${e.label}...`
|
|
289
|
-
}), e.options?.map((e) => /* @__PURE__ */ u("option", {
|
|
290
|
-
value: e.value,
|
|
291
|
-
disabled: e.disabled,
|
|
292
|
-
children: e.label
|
|
293
|
-
}, e.value))]
|
|
301
|
+
onChange: (t) => N(e.name, t.target.value),
|
|
302
|
+
onBlur: () => P(e.name)
|
|
294
303
|
});
|
|
304
|
+
case "select": {
|
|
305
|
+
let n = x.fieldOptions[e.name] ?? e.options ?? [];
|
|
306
|
+
return /* @__PURE__ */ d("select", {
|
|
307
|
+
id: e.name,
|
|
308
|
+
name: e.name,
|
|
309
|
+
value: String(t ?? ""),
|
|
310
|
+
required: e.required,
|
|
311
|
+
disabled: e.disabled || k,
|
|
312
|
+
style: {
|
|
313
|
+
...r,
|
|
314
|
+
...h.select
|
|
315
|
+
},
|
|
316
|
+
onChange: (t) => N(e.name, t.target.value),
|
|
317
|
+
onBlur: () => P(e.name),
|
|
318
|
+
children: [/* @__PURE__ */ u("option", {
|
|
319
|
+
value: "",
|
|
320
|
+
children: e.placeholder || `Select ${e.label}...`
|
|
321
|
+
}), n.map((e) => /* @__PURE__ */ u("option", {
|
|
322
|
+
value: e.value,
|
|
323
|
+
disabled: e.disabled,
|
|
324
|
+
children: e.label
|
|
325
|
+
}, e.value))]
|
|
326
|
+
});
|
|
327
|
+
}
|
|
295
328
|
case "checkbox": return /* @__PURE__ */ d("div", {
|
|
296
|
-
style:
|
|
329
|
+
style: h.checkbox,
|
|
297
330
|
children: [/* @__PURE__ */ u("input", {
|
|
298
331
|
type: "checkbox",
|
|
299
332
|
id: e.name,
|
|
300
333
|
name: e.name,
|
|
301
334
|
checked: !!t,
|
|
302
|
-
disabled: e.disabled ||
|
|
303
|
-
style:
|
|
304
|
-
onChange: (t) =>
|
|
305
|
-
onBlur: () =>
|
|
335
|
+
disabled: e.disabled || k,
|
|
336
|
+
style: h.checkboxInput,
|
|
337
|
+
onChange: (t) => N(e.name, t.target.checked),
|
|
338
|
+
onBlur: () => P(e.name)
|
|
306
339
|
}), /* @__PURE__ */ u("label", {
|
|
307
340
|
htmlFor: e.name,
|
|
308
341
|
style: {
|
|
@@ -318,18 +351,18 @@ var m = {
|
|
|
318
351
|
flexDirection: "column",
|
|
319
352
|
gap: "8px"
|
|
320
353
|
},
|
|
321
|
-
children: e.options
|
|
322
|
-
style:
|
|
354
|
+
children: (x.fieldOptions[e.name] ?? e.options ?? []).map((n) => /* @__PURE__ */ d("div", {
|
|
355
|
+
style: h.checkbox,
|
|
323
356
|
children: [/* @__PURE__ */ u("input", {
|
|
324
357
|
type: "radio",
|
|
325
358
|
id: `${e.name}-${n.value}`,
|
|
326
359
|
name: e.name,
|
|
327
360
|
value: n.value,
|
|
328
361
|
checked: t === n.value,
|
|
329
|
-
disabled: e.disabled || n.disabled ||
|
|
330
|
-
style:
|
|
331
|
-
onChange: (t) =>
|
|
332
|
-
onBlur: () =>
|
|
362
|
+
disabled: e.disabled || n.disabled || k,
|
|
363
|
+
style: h.checkboxInput,
|
|
364
|
+
onChange: (t) => N(e.name, t.target.value),
|
|
365
|
+
onBlur: () => P(e.name)
|
|
333
366
|
}), /* @__PURE__ */ u("label", {
|
|
334
367
|
htmlFor: `${e.name}-${n.value}`,
|
|
335
368
|
style: {
|
|
@@ -352,27 +385,28 @@ var m = {
|
|
|
352
385
|
value: String(t ?? ""),
|
|
353
386
|
placeholder: e.placeholder,
|
|
354
387
|
required: e.required,
|
|
355
|
-
disabled: e.disabled ||
|
|
388
|
+
disabled: e.disabled || k,
|
|
356
389
|
readOnly: e.readonly,
|
|
357
390
|
min: e.min,
|
|
358
391
|
max: e.max,
|
|
359
392
|
step: e.step,
|
|
360
393
|
pattern: e.pattern,
|
|
361
394
|
style: r,
|
|
362
|
-
onChange: (t) =>
|
|
363
|
-
onBlur: () =>
|
|
395
|
+
onChange: (t) => N(e.name, e.type === "number" ? t.target.valueAsNumber : t.target.value),
|
|
396
|
+
onBlur: () => P(e.name)
|
|
364
397
|
});
|
|
365
398
|
}
|
|
366
399
|
}, [
|
|
367
|
-
x,
|
|
368
400
|
C,
|
|
369
401
|
T,
|
|
370
402
|
D,
|
|
371
|
-
|
|
372
|
-
|
|
403
|
+
k,
|
|
404
|
+
N,
|
|
405
|
+
P,
|
|
406
|
+
x
|
|
373
407
|
]);
|
|
374
|
-
if (
|
|
375
|
-
style:
|
|
408
|
+
if (b.fields.length === 0) return /* @__PURE__ */ d("div", {
|
|
409
|
+
style: h.emptyState,
|
|
376
410
|
children: [
|
|
377
411
|
/* @__PURE__ */ u(l, { style: {
|
|
378
412
|
width: "48px",
|
|
@@ -393,49 +427,49 @@ var m = {
|
|
|
393
427
|
})
|
|
394
428
|
]
|
|
395
429
|
});
|
|
396
|
-
let
|
|
430
|
+
let R = b.layout === "grid" ? {
|
|
397
431
|
display: "grid",
|
|
398
|
-
gridTemplateColumns: `repeat(${
|
|
432
|
+
gridTemplateColumns: `repeat(${b.columns || 2}, 1fr)`,
|
|
399
433
|
gap: "16px"
|
|
400
434
|
} : {};
|
|
401
435
|
return /* @__PURE__ */ d("div", {
|
|
402
|
-
style:
|
|
436
|
+
style: h.container,
|
|
403
437
|
children: [/* @__PURE__ */ d("form", {
|
|
404
|
-
onSubmit:
|
|
438
|
+
onSubmit: F,
|
|
405
439
|
style: {
|
|
406
|
-
...
|
|
407
|
-
...
|
|
440
|
+
...h.form,
|
|
441
|
+
...R
|
|
408
442
|
},
|
|
409
|
-
children: [
|
|
443
|
+
children: [j && b.successMessage && /* @__PURE__ */ d("div", {
|
|
410
444
|
style: {
|
|
411
|
-
...
|
|
445
|
+
...h.successMessage,
|
|
412
446
|
gridColumn: "1 / -1"
|
|
413
447
|
},
|
|
414
448
|
children: [/* @__PURE__ */ u(a, { style: {
|
|
415
449
|
width: "18px",
|
|
416
450
|
height: "18px"
|
|
417
|
-
} }),
|
|
418
|
-
}),
|
|
419
|
-
if (e.type === "hidden") return
|
|
420
|
-
let t =
|
|
451
|
+
} }), b.successMessage]
|
|
452
|
+
}), b.fields.map((e) => {
|
|
453
|
+
if (e.type === "hidden") return L(e);
|
|
454
|
+
let t = D.has(e.name) ? T[e.name] : null;
|
|
421
455
|
return /* @__PURE__ */ d("div", {
|
|
422
|
-
style:
|
|
456
|
+
style: h.fieldWrapper,
|
|
423
457
|
children: [
|
|
424
458
|
e.type !== "checkbox" && /* @__PURE__ */ d("label", {
|
|
425
459
|
htmlFor: e.name,
|
|
426
|
-
style:
|
|
460
|
+
style: h.label,
|
|
427
461
|
children: [e.label, e.required && /* @__PURE__ */ u("span", {
|
|
428
|
-
style:
|
|
462
|
+
style: h.required,
|
|
429
463
|
children: "*"
|
|
430
464
|
})]
|
|
431
465
|
}),
|
|
432
|
-
|
|
466
|
+
L(e),
|
|
433
467
|
e.helpText && !t && /* @__PURE__ */ u("p", {
|
|
434
|
-
style:
|
|
468
|
+
style: h.helpText,
|
|
435
469
|
children: e.helpText
|
|
436
470
|
}),
|
|
437
471
|
t && /* @__PURE__ */ d("p", {
|
|
438
|
-
style:
|
|
472
|
+
style: h.errorText,
|
|
439
473
|
children: [/* @__PURE__ */ u(i, { style: {
|
|
440
474
|
width: "14px",
|
|
441
475
|
height: "14px"
|
|
@@ -445,42 +479,42 @@ var m = {
|
|
|
445
479
|
}, e.name);
|
|
446
480
|
})]
|
|
447
481
|
}), /* @__PURE__ */ d("div", {
|
|
448
|
-
style:
|
|
449
|
-
children: [
|
|
482
|
+
style: h.footer,
|
|
483
|
+
children: [b.showReset !== !1 && /* @__PURE__ */ d("button", {
|
|
450
484
|
type: "button",
|
|
451
|
-
onClick:
|
|
452
|
-
disabled:
|
|
485
|
+
onClick: I,
|
|
486
|
+
disabled: k,
|
|
453
487
|
style: {
|
|
454
|
-
...
|
|
455
|
-
...
|
|
456
|
-
opacity:
|
|
488
|
+
...h.button,
|
|
489
|
+
...h.resetButton,
|
|
490
|
+
opacity: k ? .6 : 1
|
|
457
491
|
},
|
|
458
492
|
children: [/* @__PURE__ */ u(s, { style: {
|
|
459
493
|
width: "16px",
|
|
460
494
|
height: "16px"
|
|
461
|
-
} }),
|
|
495
|
+
} }), b.resetLabel || "Reset"]
|
|
462
496
|
}), /* @__PURE__ */ d("button", {
|
|
463
497
|
type: "submit",
|
|
464
|
-
onClick:
|
|
465
|
-
disabled:
|
|
498
|
+
onClick: F,
|
|
499
|
+
disabled: k,
|
|
466
500
|
style: {
|
|
467
|
-
...
|
|
468
|
-
...
|
|
469
|
-
opacity:
|
|
501
|
+
...h.button,
|
|
502
|
+
...h.submitButton,
|
|
503
|
+
opacity: k ? .6 : 1
|
|
470
504
|
},
|
|
471
|
-
children: [
|
|
505
|
+
children: [k ? /* @__PURE__ */ u(o, { style: {
|
|
472
506
|
width: "16px",
|
|
473
507
|
height: "16px",
|
|
474
508
|
animation: "spin 1s linear infinite"
|
|
475
509
|
} }) : /* @__PURE__ */ u(c, { style: {
|
|
476
510
|
width: "16px",
|
|
477
511
|
height: "16px"
|
|
478
|
-
} }),
|
|
512
|
+
} }), b.submitLabel || "Submit"]
|
|
479
513
|
})]
|
|
480
514
|
})]
|
|
481
515
|
});
|
|
482
516
|
});
|
|
483
517
|
//#endregion
|
|
484
|
-
export {
|
|
518
|
+
export { g as default, m as normalizeFormData };
|
|
485
519
|
|
|
486
520
|
//# sourceMappingURL=FormWidget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormWidget.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/form/FormWidget.tsx"],"sourcesContent":["/**\n * FormWidget Component\n *\n * Interactive form widget for data input with validation and submit actions.\n * v2.0 spec compliant widget type.\n */\n\nimport { type FC, memo, useState, useCallback, useMemo } from 'react';\nimport type {\n Widget,\n FormConfig as FormConfigType,\n FormFieldConfig,\n FormFieldType as FormFieldTypeAlias,\n FormFieldOption,\n FormValidationRule,\n} from '../../../types';\nimport { AlertCircle, CheckCircle, Send, RotateCcw, Settings, Loader2 } from 'lucide-react';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n// Re-export types from main types file\nexport type FieldType = FormFieldTypeAlias;\nexport type FormField = FormFieldConfig;\nexport type SelectOption = FormFieldOption;\nexport type ValidationRule = FormValidationRule;\nexport type FormConfig = FormConfigType;\n\nexport interface FormWidgetProps {\n widget: Widget;\n data?: Record<string, unknown>;\n /** Whether the widget is in edit mode */\n isEditMode?: boolean;\n /** Whether the widget is selected */\n isSelected?: boolean;\n /** Whether data is loading */\n isLoading?: boolean;\n /** Error message if any */\n error?: string | null;\n /** Callback when widget is clicked */\n onClick?: () => void;\n onDrilldown?: (selectedData: Record<string, unknown>) => void;\n onSubmit?: (formData: Record<string, unknown>) => void;\n}\n\ninterface FieldErrors {\n [fieldName: string]: string | null;\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\nfunction validateField(value: unknown, field: FormField): string | null {\n const strValue = String(value ?? '');\n const isEmpty = value === null || value === undefined || strValue.trim() === '';\n\n // Check required\n if (field.required && isEmpty) {\n return `${field.label} is required`;\n }\n\n // Skip other validations if empty and not required\n if (isEmpty) return null;\n\n // Apply validation rules\n if (field.validation) {\n for (const rule of field.validation) {\n switch (rule.type) {\n case 'required':\n if (isEmpty) return rule.message;\n break;\n case 'minLength':\n if (strValue.length < Number(rule.value)) return rule.message;\n break;\n case 'maxLength':\n if (strValue.length > Number(rule.value)) return rule.message;\n break;\n case 'min':\n if (Number(value) < Number(rule.value)) return rule.message;\n break;\n case 'max':\n if (Number(value) > Number(rule.value)) return rule.message;\n break;\n case 'pattern':\n if (rule.value && !new RegExp(String(rule.value)).test(strValue)) {\n return rule.message;\n }\n break;\n case 'email':\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(strValue)) {\n return rule.message;\n }\n break;\n }\n }\n }\n\n // Type-specific validation\n if (field.type === 'email' && !field.validation?.some((r) => r.type === 'email')) {\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(strValue)) {\n return 'Please enter a valid email address';\n }\n }\n\n if (field.type === 'url') {\n try {\n new URL(strValue);\n } catch {\n return 'Please enter a valid URL';\n }\n }\n\n if (field.type === 'number') {\n if (isNaN(Number(value))) {\n return 'Please enter a valid number';\n }\n if (field.min !== undefined && Number(value) < Number(field.min)) {\n return `Value must be at least ${field.min}`;\n }\n if (field.max !== undefined && Number(value) > Number(field.max)) {\n return `Value must be at most ${field.max}`;\n }\n }\n\n return null;\n}\n\nfunction validateForm(values: Record<string, unknown>, fields: FormField[]): FieldErrors {\n const errors: FieldErrors = {};\n for (const field of fields) {\n const error = validateField(values[field.name], field);\n if (error) {\n errors[field.name] = error;\n }\n }\n return errors;\n}\n\n// ============================================================================\n// Styles\n// ============================================================================\n\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n height: '100%',\n overflow: 'hidden',\n },\n form: {\n flex: 1,\n overflow: 'auto',\n padding: '16px',\n },\n fieldWrapper: {\n marginBottom: '16px',\n },\n label: {\n display: 'block',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--color-text-primary)',\n marginBottom: '6px',\n },\n required: {\n color: 'var(--color-status-error-text)',\n marginLeft: '2px',\n },\n input: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n backgroundColor: 'var(--color-bg-surface)',\n transition: 'border-color 0.15s, box-shadow 0.15s',\n outline: 'none',\n },\n inputError: {\n borderColor: 'var(--color-status-error-border)',\n },\n inputFocus: {\n borderColor: 'var(--color-border-focus)',\n boxShadow: 'var(--shadow-focus)',\n },\n textarea: {\n resize: 'vertical' as const,\n minHeight: '80px',\n },\n select: {\n appearance: 'none' as const,\n backgroundImage: `url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e\")`,\n backgroundPosition: 'right 8px center',\n backgroundRepeat: 'no-repeat',\n backgroundSize: '20px',\n paddingRight: '36px',\n },\n checkbox: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n checkboxInput: {\n width: '16px',\n height: '16px',\n cursor: 'pointer',\n },\n helpText: {\n fontSize: '12px',\n color: 'var(--color-text-muted)',\n marginTop: '4px',\n },\n errorText: {\n fontSize: '12px',\n color: 'var(--color-status-error-text)',\n marginTop: '4px',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n },\n footer: {\n display: 'flex',\n justifyContent: 'flex-end',\n gap: '12px',\n padding: '12px 16px',\n borderTop: '1px solid var(--color-border-subtle)',\n backgroundColor: 'var(--color-bg-subtle)',\n },\n button: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n borderRadius: '6px',\n cursor: 'pointer',\n transition: 'all 0.15s',\n border: 'none',\n },\n submitButton: {\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-text-inverse)',\n },\n resetButton: {\n backgroundColor: 'var(--color-bg-surface)',\n color: 'var(--color-text-primary)',\n border: '1px solid var(--color-border-default)',\n },\n successMessage: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '12px 16px',\n backgroundColor: 'var(--color-status-success-bgSubtle)',\n border: '1px solid var(--color-status-success-border)',\n borderRadius: '6px',\n marginBottom: '16px',\n color: 'var(--color-status-success-text)',\n fontSize: '14px',\n },\n emptyState: {\n display: 'flex',\n flexDirection: 'column' as const,\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n padding: '32px',\n color: 'var(--color-text-muted)',\n textAlign: 'center' as const,\n },\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const FormWidget: FC<FormWidgetProps> = memo(function FormWidget({ widget, data = {}, onDrilldown, onSubmit }) {\n const defaultConfig: FormConfig = {\n fields: [],\n layout: 'vertical',\n submitLabel: 'Submit',\n showReset: true,\n validateOnBlur: true,\n validateOnChange: false,\n };\n const config: FormConfig = widget.config\n ? { ...defaultConfig, ...(widget.config as Partial<FormConfig>) }\n : defaultConfig;\n\n // Initialize form values from default values or data\n const initialValues = useMemo(() => {\n const values: Record<string, unknown> = {};\n for (const field of config.fields) {\n values[field.name] = data[field.name] ?? field.defaultValue ?? (field.type === 'checkbox' ? false : '');\n }\n return values;\n }, [config.fields, data]);\n\n const [values, setValues] = useState<Record<string, unknown>>(initialValues);\n const [errors, setErrors] = useState<FieldErrors>({});\n const [touched, setTouched] = useState<Set<string>>(new Set());\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [submitSuccess, setSubmitSuccess] = useState(false);\n\n // Handle field change\n const handleChange = useCallback(\n (fieldName: string, value: unknown) => {\n setValues((prev) => ({ ...prev, [fieldName]: value }));\n setSubmitSuccess(false);\n\n if (config.validateOnChange) {\n const field = config.fields.find((f) => f.name === fieldName);\n if (field) {\n const error = validateField(value, field);\n setErrors((prev) => ({ ...prev, [fieldName]: error }));\n }\n }\n },\n [config.fields, config.validateOnChange]\n );\n\n // Handle field blur\n const handleBlur = useCallback(\n (fieldName: string) => {\n setTouched((prev) => new Set(prev).add(fieldName));\n\n if (config.validateOnBlur) {\n const field = config.fields.find((f) => f.name === fieldName);\n if (field) {\n const error = validateField(values[fieldName], field);\n setErrors((prev) => ({ ...prev, [fieldName]: error }));\n }\n }\n },\n [config.fields, config.validateOnBlur, values]\n );\n\n // Handle form submit\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n // Validate all fields\n const allErrors = validateForm(values, config.fields);\n setErrors(allErrors);\n setTouched(new Set(config.fields.map((f) => f.name)));\n\n // Check if there are errors\n const hasErrors = Object.values(allErrors).some((e) => e !== null);\n if (hasErrors) {\n return;\n }\n\n setIsSubmitting(true);\n\n try {\n // Emit form submit event via onDrilldown or onSubmit\n const formData = {\n ...values,\n _action: config.submitAction || 'form_submit',\n _widgetId: widget.id,\n _timestamp: new Date().toISOString(),\n };\n\n if (onSubmit) {\n await onSubmit(formData);\n }\n\n if (onDrilldown) {\n onDrilldown({\n type: 'form_submit',\n action: config.submitAction || 'form_submit',\n data: formData,\n });\n }\n\n setSubmitSuccess(true);\n } catch (error) {\n } finally {\n setIsSubmitting(false);\n }\n },\n [values, config.fields, config.submitAction, widget.id, onSubmit, onDrilldown]\n );\n\n // Handle form reset\n const handleReset = useCallback(() => {\n setValues(initialValues);\n setErrors({});\n setTouched(new Set());\n setSubmitSuccess(false);\n }, [initialValues]);\n\n // Render a field\n const renderField = useCallback(\n (field: FormField) => {\n const value = values[field.name];\n const error = touched.has(field.name) ? errors[field.name] : null;\n const hasError = Boolean(error);\n\n const inputStyle = {\n ...styles.input,\n ...(hasError ? styles.inputError : {}),\n };\n\n switch (field.type) {\n case 'textarea':\n return (\n <textarea\n id={field.name}\n name={field.name}\n value={String(value ?? '')}\n placeholder={field.placeholder}\n required={field.required}\n disabled={field.disabled || isSubmitting}\n readOnly={field.readonly}\n rows={field.rows || 4}\n style={{ ...inputStyle, ...styles.textarea }}\n onChange={(e) => handleChange(field.name, e.target.value)}\n onBlur={() => handleBlur(field.name)}\n />\n );\n\n case 'select':\n return (\n <select\n id={field.name}\n name={field.name}\n value={String(value ?? '')}\n required={field.required}\n disabled={field.disabled || isSubmitting}\n style={{ ...inputStyle, ...styles.select }}\n onChange={(e) => handleChange(field.name, e.target.value)}\n onBlur={() => handleBlur(field.name)}\n >\n <option value=\"\">{field.placeholder || `Select ${field.label}...`}</option>\n {field.options?.map((opt) => (\n <option key={opt.value} value={opt.value} disabled={opt.disabled}>\n {opt.label}\n </option>\n ))}\n </select>\n );\n\n case 'checkbox':\n return (\n <div style={styles.checkbox}>\n <input\n type=\"checkbox\"\n id={field.name}\n name={field.name}\n checked={Boolean(value)}\n disabled={field.disabled || isSubmitting}\n style={styles.checkboxInput}\n onChange={(e) => handleChange(field.name, e.target.checked)}\n onBlur={() => handleBlur(field.name)}\n />\n <label htmlFor={field.name} style={{ fontSize: '14px', cursor: 'pointer' }}>\n {field.label}\n </label>\n </div>\n );\n\n case 'radio':\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n {field.options?.map((opt) => (\n <div key={opt.value} style={styles.checkbox}>\n <input\n type=\"radio\"\n id={`${field.name}-${opt.value}`}\n name={field.name}\n value={opt.value}\n checked={value === opt.value}\n disabled={field.disabled || opt.disabled || isSubmitting}\n style={styles.checkboxInput}\n onChange={(e) => handleChange(field.name, e.target.value)}\n onBlur={() => handleBlur(field.name)}\n />\n <label htmlFor={`${field.name}-${opt.value}`} style={{ fontSize: '14px', cursor: 'pointer' }}>\n {opt.label}\n </label>\n </div>\n ))}\n </div>\n );\n\n case 'hidden':\n return <input type=\"hidden\" name={field.name} value={String(value ?? '')} />;\n\n default:\n return (\n <input\n type={field.type}\n id={field.name}\n name={field.name}\n value={String(value ?? '')}\n placeholder={field.placeholder}\n required={field.required}\n disabled={field.disabled || isSubmitting}\n readOnly={field.readonly}\n min={field.min}\n max={field.max}\n step={field.step}\n pattern={field.pattern}\n style={inputStyle}\n onChange={(e) =>\n handleChange(field.name, field.type === 'number' ? e.target.valueAsNumber : e.target.value)\n }\n onBlur={() => handleBlur(field.name)}\n />\n );\n }\n },\n [values, errors, touched, isSubmitting, handleChange, handleBlur]\n );\n\n // Empty state\n if (config.fields.length === 0) {\n return (\n <div style={styles.emptyState}>\n <Settings style={{ width: '48px', height: '48px', marginBottom: '16px', opacity: 0.5 }} />\n <p style={{ fontSize: '14px' }}>Configure Form Fields</p>\n <p style={{ fontSize: '12px', marginTop: '4px' }}>Add fields in widget settings to create your form</p>\n </div>\n );\n }\n\n // Grid layout styles\n const gridStyle =\n config.layout === 'grid'\n ? {\n display: 'grid',\n gridTemplateColumns: `repeat(${config.columns || 2}, 1fr)`,\n gap: '16px',\n }\n : {};\n\n return (\n <div style={styles.container}>\n <form onSubmit={handleSubmit} style={{ ...styles.form, ...gridStyle }}>\n {/* Success message */}\n {submitSuccess && config.successMessage && (\n <div style={{ ...styles.successMessage, gridColumn: '1 / -1' }}>\n <CheckCircle style={{ width: '18px', height: '18px' }} />\n {config.successMessage}\n </div>\n )}\n\n {/* Form fields */}\n {config.fields.map((field) => {\n if (field.type === 'hidden') {\n return renderField(field);\n }\n\n const error = touched.has(field.name) ? errors[field.name] : null;\n\n return (\n <div key={field.name} style={styles.fieldWrapper}>\n {field.type !== 'checkbox' && (\n <label htmlFor={field.name} style={styles.label}>\n {field.label}\n {field.required && <span style={styles.required}>*</span>}\n </label>\n )}\n\n {renderField(field)}\n\n {field.helpText && !error && <p style={styles.helpText}>{field.helpText}</p>}\n\n {error && (\n <p style={styles.errorText}>\n <AlertCircle style={{ width: '14px', height: '14px' }} />\n {error}\n </p>\n )}\n </div>\n );\n })}\n </form>\n\n {/* Footer with buttons */}\n <div style={styles.footer}>\n {config.showReset !== false && (\n <button\n type=\"button\"\n onClick={handleReset}\n disabled={isSubmitting}\n style={{\n ...styles.button,\n ...styles.resetButton,\n opacity: isSubmitting ? 0.6 : 1,\n }}\n >\n <RotateCcw style={{ width: '16px', height: '16px' }} />\n {config.resetLabel || 'Reset'}\n </button>\n )}\n\n <button\n type=\"submit\"\n onClick={handleSubmit}\n disabled={isSubmitting}\n style={{\n ...styles.button,\n ...styles.submitButton,\n opacity: isSubmitting ? 0.6 : 1,\n }}\n >\n {isSubmitting ? (\n <Loader2 style={{ width: '16px', height: '16px', animation: 'spin 1s linear infinite' }} />\n ) : (\n <Send style={{ width: '16px', height: '16px' }} />\n )}\n {config.submitLabel || 'Submit'}\n </button>\n </div>\n </div>\n );\n});\n\nexport default FormWidget;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormWidget.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/form/FormWidget.tsx"],"sourcesContent":["/**\n * FormWidget Component\n *\n * Interactive form widget for data input with validation and submit actions.\n * v2.0 spec compliant widget type.\n */\n\nimport { type FC, memo, useState, useCallback, useMemo } from 'react';\nimport type {\n Widget,\n FormConfig as FormConfigType,\n FormFieldConfig,\n FormFieldType as FormFieldTypeAlias,\n FormFieldOption,\n FormValidationRule,\n} from '../../../types';\nimport { AlertCircle, CheckCircle, Send, RotateCcw, Settings, Loader2 } from 'lucide-react';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n// Re-export types from main types file\nexport type FieldType = FormFieldTypeAlias;\nexport type FormField = FormFieldConfig;\nexport type SelectOption = FormFieldOption;\nexport type ValidationRule = FormValidationRule;\nexport type FormConfig = FormConfigType;\n\nexport interface FormWidgetProps {\n widget: Widget;\n data?: Record<string, unknown>;\n /** Whether the widget is in edit mode */\n isEditMode?: boolean;\n /** Whether the widget is selected */\n isSelected?: boolean;\n /** Whether data is loading */\n isLoading?: boolean;\n /** Error message if any */\n error?: string | null;\n /** Callback when widget is clicked */\n onClick?: () => void;\n onDrilldown?: (selectedData: Record<string, unknown>) => void;\n onSubmit?: (formData: Record<string, unknown>) => void;\n}\n\ninterface FieldErrors {\n [fieldName: string]: string | null;\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\nfunction validateField(value: unknown, field: FormField): string | null {\n const strValue = String(value ?? '');\n const isEmpty = value === null || value === undefined || strValue.trim() === '';\n\n // Check required\n if (field.required && isEmpty) {\n return `${field.label} is required`;\n }\n\n // Skip other validations if empty and not required\n if (isEmpty) return null;\n\n // Apply validation rules\n if (field.validation) {\n for (const rule of field.validation) {\n switch (rule.type) {\n case 'required':\n if (isEmpty) return rule.message;\n break;\n case 'minLength':\n if (strValue.length < Number(rule.value)) return rule.message;\n break;\n case 'maxLength':\n if (strValue.length > Number(rule.value)) return rule.message;\n break;\n case 'min':\n if (Number(value) < Number(rule.value)) return rule.message;\n break;\n case 'max':\n if (Number(value) > Number(rule.value)) return rule.message;\n break;\n case 'pattern':\n if (rule.value && !new RegExp(String(rule.value)).test(strValue)) {\n return rule.message;\n }\n break;\n case 'email':\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(strValue)) {\n return rule.message;\n }\n break;\n }\n }\n }\n\n // Type-specific validation\n if (field.type === 'email' && !field.validation?.some((r) => r.type === 'email')) {\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(strValue)) {\n return 'Please enter a valid email address';\n }\n }\n\n if (field.type === 'url') {\n try {\n new URL(strValue);\n } catch {\n return 'Please enter a valid URL';\n }\n }\n\n if (field.type === 'number') {\n if (isNaN(Number(value))) {\n return 'Please enter a valid number';\n }\n if (field.min !== undefined && Number(value) < Number(field.min)) {\n return `Value must be at least ${field.min}`;\n }\n if (field.max !== undefined && Number(value) > Number(field.max)) {\n return `Value must be at most ${field.max}`;\n }\n }\n\n return null;\n}\n\nfunction validateForm(values: Record<string, unknown>, fields: FormField[]): FieldErrors {\n const errors: FieldErrors = {};\n for (const field of fields) {\n const error = validateField(values[field.name], field);\n if (error) {\n errors[field.name] = error;\n }\n }\n return errors;\n}\n\n// ============================================================================\n// Data normalisation (DataSink -> Parser -> Widget)\n// ============================================================================\n\nexport interface NormalizedFormData {\n /** Resolved initial values keyed by field name. */\n values: Record<string, unknown>;\n /** Dynamic options keyed by field name (select / radio only). */\n fieldOptions: Record<string, FormFieldOption[]>;\n}\n\n/**\n * Normalise parser output into the shape the FormWidget expects.\n *\n * The parser can emit one of three shapes:\n * 1. `{ values: { fieldName: value }, options: { fieldName: [...] } }` — explicit\n * envelope. Values populate field defaults; options replace select/radio options.\n * 2. `{ fieldName: value, ... }` — flat object. Each key is treated as a field value.\n * 3. `{ questions: [...] }` or `{ fields: [...] }` — not consumed by the renderer;\n * the widget config owns the field schema. Values are extracted when the keys match.\n *\n * Config-defined `defaultValue` is the final fallback for any missing value.\n */\nexport function normalizeFormData(data: Record<string, unknown> | undefined, fields: FormField[]): NormalizedFormData {\n const values: Record<string, unknown> = {};\n const fieldOptions: Record<string, FormFieldOption[]> = {};\n\n if (!data || typeof data !== 'object' || Array.isArray(data)) {\n for (const field of fields) {\n values[field.name] = field.defaultValue ?? (field.type === 'checkbox' ? false : '');\n }\n return { values, fieldOptions };\n }\n\n const explicitValues =\n data.values && typeof data.values === 'object' && !Array.isArray(data.values)\n ? (data.values as Record<string, unknown>)\n : undefined;\n\n const explicitOptions =\n data.options && typeof data.options === 'object' && !Array.isArray(data.options)\n ? (data.options as Record<string, unknown>)\n : undefined;\n\n for (const field of fields) {\n // Resolve value: explicit envelope > flat data key > config default\n let value: unknown = explicitValues?.[field.name] ?? data[field.name] ?? field.defaultValue;\n\n // Normalise checkbox default to boolean\n if (field.type === 'checkbox' && value === undefined) {\n value = false;\n }\n values[field.name] = value ?? '';\n\n // Resolve dynamic options for select / radio\n if (field.type === 'select' || field.type === 'radio') {\n const rawOptions = explicitOptions?.[field.name] ?? data[`${field.name}Options`];\n if (Array.isArray(rawOptions)) {\n fieldOptions[field.name] = rawOptions\n .map((opt) => {\n if (opt && typeof opt === 'object') {\n const o = opt as Record<string, unknown>;\n const normalized: FormFieldOption = {\n value: String(o.value ?? o.id ?? o.key ?? ''),\n label: String(o.label ?? o.name ?? o.text ?? o.value ?? o.id ?? o.key ?? ''),\n };\n if (o.disabled === true) {\n normalized.disabled = true;\n }\n return normalized;\n }\n if (typeof opt === 'string' || typeof opt === 'number') {\n return { value: String(opt), label: String(opt) };\n }\n return null;\n })\n .filter((opt): opt is FormFieldOption => opt !== null);\n }\n }\n }\n\n return { values, fieldOptions };\n}\n\n// ============================================================================\n// Styles\n// ============================================================================\n\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n height: '100%',\n overflow: 'hidden',\n },\n form: {\n flex: 1,\n overflow: 'auto',\n padding: '16px',\n },\n fieldWrapper: {\n marginBottom: '16px',\n },\n label: {\n display: 'block',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--color-text-primary)',\n marginBottom: '6px',\n },\n required: {\n color: 'var(--color-status-error-text)',\n marginLeft: '2px',\n },\n input: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n backgroundColor: 'var(--color-bg-surface)',\n transition: 'border-color 0.15s, box-shadow 0.15s',\n outline: 'none',\n },\n inputError: {\n borderColor: 'var(--color-status-error-border)',\n },\n inputFocus: {\n borderColor: 'var(--color-border-focus)',\n boxShadow: 'var(--shadow-focus)',\n },\n textarea: {\n resize: 'vertical' as const,\n minHeight: '80px',\n },\n select: {\n appearance: 'none' as const,\n backgroundImage: `url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e\")`,\n backgroundPosition: 'right 8px center',\n backgroundRepeat: 'no-repeat',\n backgroundSize: '20px',\n paddingRight: '36px',\n },\n checkbox: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n checkboxInput: {\n width: '16px',\n height: '16px',\n cursor: 'pointer',\n },\n helpText: {\n fontSize: '12px',\n color: 'var(--color-text-muted)',\n marginTop: '4px',\n },\n errorText: {\n fontSize: '12px',\n color: 'var(--color-status-error-text)',\n marginTop: '4px',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n },\n footer: {\n display: 'flex',\n justifyContent: 'flex-end',\n gap: '12px',\n padding: '12px 16px',\n borderTop: '1px solid var(--color-border-subtle)',\n backgroundColor: 'var(--color-bg-subtle)',\n },\n button: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n borderRadius: '6px',\n cursor: 'pointer',\n transition: 'all 0.15s',\n border: 'none',\n },\n submitButton: {\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-text-inverse)',\n },\n resetButton: {\n backgroundColor: 'var(--color-bg-surface)',\n color: 'var(--color-text-primary)',\n border: '1px solid var(--color-border-default)',\n },\n successMessage: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '12px 16px',\n backgroundColor: 'var(--color-status-success-bgSubtle)',\n border: '1px solid var(--color-status-success-border)',\n borderRadius: '6px',\n marginBottom: '16px',\n color: 'var(--color-status-success-text)',\n fontSize: '14px',\n },\n emptyState: {\n display: 'flex',\n flexDirection: 'column' as const,\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n padding: '32px',\n color: 'var(--color-text-muted)',\n textAlign: 'center' as const,\n },\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const FormWidget: FC<FormWidgetProps> = memo(function FormWidget({ widget, data = {}, onDrilldown, onSubmit }) {\n const defaultConfig: FormConfig = {\n fields: [],\n layout: 'vertical',\n submitLabel: 'Submit',\n showReset: true,\n validateOnBlur: true,\n validateOnChange: false,\n };\n const config: FormConfig = widget.config\n ? { ...defaultConfig, ...(widget.config as Partial<FormConfig>) }\n : defaultConfig;\n\n // Resolve parser-driven values and dynamic options for data-driven fields\n const normalized = useMemo(() => normalizeFormData(data, config.fields), [data, config.fields]);\n\n // Initialize form values from normalised parser output or config defaults\n const initialValues = useMemo(() => {\n return normalized.values;\n }, [normalized.values]);\n\n const [values, setValues] = useState<Record<string, unknown>>(initialValues);\n const [errors, setErrors] = useState<FieldErrors>({});\n const [touched, setTouched] = useState<Set<string>>(new Set());\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [submitSuccess, setSubmitSuccess] = useState(false);\n\n // Handle field change\n const handleChange = useCallback(\n (fieldName: string, value: unknown) => {\n setValues((prev) => ({ ...prev, [fieldName]: value }));\n setSubmitSuccess(false);\n\n if (config.validateOnChange) {\n const field = config.fields.find((f) => f.name === fieldName);\n if (field) {\n const error = validateField(value, field);\n setErrors((prev) => ({ ...prev, [fieldName]: error }));\n }\n }\n },\n [config.fields, config.validateOnChange]\n );\n\n // Handle field blur\n const handleBlur = useCallback(\n (fieldName: string) => {\n setTouched((prev) => new Set(prev).add(fieldName));\n\n if (config.validateOnBlur) {\n const field = config.fields.find((f) => f.name === fieldName);\n if (field) {\n const error = validateField(values[fieldName], field);\n setErrors((prev) => ({ ...prev, [fieldName]: error }));\n }\n }\n },\n [config.fields, config.validateOnBlur, values]\n );\n\n // Handle form submit\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n // Validate all fields\n const allErrors = validateForm(values, config.fields);\n setErrors(allErrors);\n setTouched(new Set(config.fields.map((f) => f.name)));\n\n // Check if there are errors\n const hasErrors = Object.values(allErrors).some((e) => e !== null);\n if (hasErrors) {\n return;\n }\n\n setIsSubmitting(true);\n\n try {\n // Emit form submit event via onDrilldown or onSubmit\n const formData = {\n ...values,\n _action: config.submitAction || 'form_submit',\n _widgetId: widget.id,\n _timestamp: new Date().toISOString(),\n };\n\n if (onSubmit) {\n await onSubmit(formData);\n }\n\n if (onDrilldown) {\n onDrilldown({\n type: 'form_submit',\n action: config.submitAction || 'form_submit',\n data: formData,\n });\n }\n\n setSubmitSuccess(true);\n } catch (error) {\n } finally {\n setIsSubmitting(false);\n }\n },\n [values, config.fields, config.submitAction, widget.id, onSubmit, onDrilldown]\n );\n\n // Handle form reset\n const handleReset = useCallback(() => {\n setValues(initialValues);\n setErrors({});\n setTouched(new Set());\n setSubmitSuccess(false);\n }, [initialValues]);\n\n // Render a field\n const renderField = useCallback(\n (field: FormField) => {\n const value = values[field.name];\n const error = touched.has(field.name) ? errors[field.name] : null;\n const hasError = Boolean(error);\n\n const inputStyle = {\n ...styles.input,\n ...(hasError ? styles.inputError : {}),\n };\n\n switch (field.type) {\n case 'textarea':\n return (\n <textarea\n id={field.name}\n name={field.name}\n value={String(value ?? '')}\n placeholder={field.placeholder}\n required={field.required}\n disabled={field.disabled || isSubmitting}\n readOnly={field.readonly}\n rows={field.rows || 4}\n style={{ ...inputStyle, ...styles.textarea }}\n onChange={(e) => handleChange(field.name, e.target.value)}\n onBlur={() => handleBlur(field.name)}\n />\n );\n\n case 'select': {\n const selectOptions = normalized.fieldOptions[field.name] ?? field.options ?? [];\n return (\n <select\n id={field.name}\n name={field.name}\n value={String(value ?? '')}\n required={field.required}\n disabled={field.disabled || isSubmitting}\n style={{ ...inputStyle, ...styles.select }}\n onChange={(e) => handleChange(field.name, e.target.value)}\n onBlur={() => handleBlur(field.name)}\n >\n <option value=\"\">{field.placeholder || `Select ${field.label}...`}</option>\n {selectOptions.map((opt) => (\n <option key={opt.value} value={opt.value} disabled={opt.disabled}>\n {opt.label}\n </option>\n ))}\n </select>\n );\n }\n\n case 'checkbox':\n return (\n <div style={styles.checkbox}>\n <input\n type=\"checkbox\"\n id={field.name}\n name={field.name}\n checked={Boolean(value)}\n disabled={field.disabled || isSubmitting}\n style={styles.checkboxInput}\n onChange={(e) => handleChange(field.name, e.target.checked)}\n onBlur={() => handleBlur(field.name)}\n />\n <label htmlFor={field.name} style={{ fontSize: '14px', cursor: 'pointer' }}>\n {field.label}\n </label>\n </div>\n );\n\n case 'radio': {\n const radioOptions = normalized.fieldOptions[field.name] ?? field.options ?? [];\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n {radioOptions.map((opt) => (\n <div key={opt.value} style={styles.checkbox}>\n <input\n type=\"radio\"\n id={`${field.name}-${opt.value}`}\n name={field.name}\n value={opt.value}\n checked={value === opt.value}\n disabled={field.disabled || opt.disabled || isSubmitting}\n style={styles.checkboxInput}\n onChange={(e) => handleChange(field.name, e.target.value)}\n onBlur={() => handleBlur(field.name)}\n />\n <label htmlFor={`${field.name}-${opt.value}`} style={{ fontSize: '14px', cursor: 'pointer' }}>\n {opt.label}\n </label>\n </div>\n ))}\n </div>\n );\n }\n\n case 'hidden':\n return <input type=\"hidden\" name={field.name} value={String(value ?? '')} />;\n\n default:\n return (\n <input\n type={field.type}\n id={field.name}\n name={field.name}\n value={String(value ?? '')}\n placeholder={field.placeholder}\n required={field.required}\n disabled={field.disabled || isSubmitting}\n readOnly={field.readonly}\n min={field.min}\n max={field.max}\n step={field.step}\n pattern={field.pattern}\n style={inputStyle}\n onChange={(e) =>\n handleChange(field.name, field.type === 'number' ? e.target.valueAsNumber : e.target.value)\n }\n onBlur={() => handleBlur(field.name)}\n />\n );\n }\n },\n [values, errors, touched, isSubmitting, handleChange, handleBlur, normalized]\n );\n\n // Empty state\n if (config.fields.length === 0) {\n return (\n <div style={styles.emptyState}>\n <Settings style={{ width: '48px', height: '48px', marginBottom: '16px', opacity: 0.5 }} />\n <p style={{ fontSize: '14px' }}>Configure Form Fields</p>\n <p style={{ fontSize: '12px', marginTop: '4px' }}>Add fields in widget settings to create your form</p>\n </div>\n );\n }\n\n // Grid layout styles\n const gridStyle =\n config.layout === 'grid'\n ? {\n display: 'grid',\n gridTemplateColumns: `repeat(${config.columns || 2}, 1fr)`,\n gap: '16px',\n }\n : {};\n\n return (\n <div style={styles.container}>\n <form onSubmit={handleSubmit} style={{ ...styles.form, ...gridStyle }}>\n {/* Success message */}\n {submitSuccess && config.successMessage && (\n <div style={{ ...styles.successMessage, gridColumn: '1 / -1' }}>\n <CheckCircle style={{ width: '18px', height: '18px' }} />\n {config.successMessage}\n </div>\n )}\n\n {/* Form fields */}\n {config.fields.map((field) => {\n if (field.type === 'hidden') {\n return renderField(field);\n }\n\n const error = touched.has(field.name) ? errors[field.name] : null;\n\n return (\n <div key={field.name} style={styles.fieldWrapper}>\n {field.type !== 'checkbox' && (\n <label htmlFor={field.name} style={styles.label}>\n {field.label}\n {field.required && <span style={styles.required}>*</span>}\n </label>\n )}\n\n {renderField(field)}\n\n {field.helpText && !error && <p style={styles.helpText}>{field.helpText}</p>}\n\n {error && (\n <p style={styles.errorText}>\n <AlertCircle style={{ width: '14px', height: '14px' }} />\n {error}\n </p>\n )}\n </div>\n );\n })}\n </form>\n\n {/* Footer with buttons */}\n <div style={styles.footer}>\n {config.showReset !== false && (\n <button\n type=\"button\"\n onClick={handleReset}\n disabled={isSubmitting}\n style={{\n ...styles.button,\n ...styles.resetButton,\n opacity: isSubmitting ? 0.6 : 1,\n }}\n >\n <RotateCcw style={{ width: '16px', height: '16px' }} />\n {config.resetLabel || 'Reset'}\n </button>\n )}\n\n <button\n type=\"submit\"\n onClick={handleSubmit}\n disabled={isSubmitting}\n style={{\n ...styles.button,\n ...styles.submitButton,\n opacity: isSubmitting ? 0.6 : 1,\n }}\n >\n {isSubmitting ? (\n <Loader2 style={{ width: '16px', height: '16px', animation: 'spin 1s linear infinite' }} />\n ) : (\n <Send style={{ width: '16px', height: '16px' }} />\n )}\n {config.submitLabel || 'Submit'}\n </button>\n </div>\n </div>\n );\n});\n\nexport default FormWidget;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from "./FormWidget.js";
|
|
2
|
-
export { e as FormWidget, e as default };
|
|
1
|
+
import e, { normalizeFormData as t } from "./FormWidget.js";
|
|
2
|
+
export { e as FormWidget, e as default, t as normalizeFormData };
|
|
@@ -16,6 +16,8 @@ import "./chart/ChartWidget.js";
|
|
|
16
16
|
import "./chart/index.js";
|
|
17
17
|
import "./custom/CustomWidget.js";
|
|
18
18
|
import "./custom/index.js";
|
|
19
|
+
import "./form/FormWidget.js";
|
|
20
|
+
import "./form/index.js";
|
|
19
21
|
import "./gauge/GaugeWidget.js";
|
|
20
22
|
import "./gauge/index.js";
|
|
21
23
|
import "./heatmap/HeatmapWidget.js";
|
|
@@ -29,7 +29,11 @@ function d() {
|
|
|
29
29
|
let { navigate: e } = u();
|
|
30
30
|
return e;
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
function f() {
|
|
33
|
+
let { buildPath: e } = u();
|
|
34
|
+
return e;
|
|
35
|
+
}
|
|
36
|
+
var p = t(function({ to: e, ...t }, n) {
|
|
33
37
|
let { buildPath: r } = u();
|
|
34
38
|
return /* @__PURE__ */ s(a, {
|
|
35
39
|
ref: n,
|
|
@@ -38,6 +42,6 @@ var f = t(function({ to: e, ...t }, n) {
|
|
|
38
42
|
});
|
|
39
43
|
});
|
|
40
44
|
//#endregion
|
|
41
|
-
export {
|
|
45
|
+
export { p as AppLink, l as NavigationProvider, d as useAppNavigate, f as useBuildPath, u as useNavigation };
|
|
42
46
|
|
|
43
47
|
//# sourceMappingURL=NavigationContext.js.map
|