@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.
@@ -50,7 +50,41 @@ function p(e, t) {
50
50
  }
51
51
  return n;
52
52
  }
53
- var m = {
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
- }, h = e(function({ widget: e, data: h = {}, onDrilldown: g, onSubmit: _ }) {
179
- let v = {
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
- }, y = e.config ? {
187
- ...v,
220
+ }, b = e.config ? {
221
+ ...y,
188
222
  ...e.config
189
- } : v, b = n(() => {
190
- let e = {};
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
- })), A(!1), y.validateOnChange) {
198
- let n = y.fields.find((t) => t.name === e);
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
- w((t) => ({
231
+ E((t) => ({
202
232
  ...t,
203
233
  [e]: r
204
234
  }));
205
235
  }
206
236
  }
207
- }, [y.fields, y.validateOnChange]), M = t((e) => {
208
- if (E((t) => new Set(t).add(e)), y.validateOnBlur) {
209
- let t = y.fields.find((t) => t.name === e);
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(x[e], t);
212
- w((t) => ({
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
- y.fields,
220
- y.validateOnBlur,
221
- x
222
- ]), N = t(async (t) => {
249
+ b.fields,
250
+ b.validateOnBlur,
251
+ C
252
+ ]), F = t(async (t) => {
223
253
  t.preventDefault();
224
- let n = p(x, y.fields);
225
- if (w(n), E(new Set(y.fields.map((e) => e.name))), !Object.values(n).some((e) => e !== null)) {
226
- O(!0);
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
- ...x,
230
- _action: y.submitAction || "form_submit",
259
+ ...C,
260
+ _action: b.submitAction || "form_submit",
231
261
  _widgetId: e.id,
232
262
  _timestamp: (/* @__PURE__ */ new Date()).toISOString()
233
263
  };
234
- _ && await _(t), g && g({
264
+ v && await v(t), _ && _({
235
265
  type: "form_submit",
236
- action: y.submitAction || "form_submit",
266
+ action: b.submitAction || "form_submit",
237
267
  data: t
238
- }), A(!0);
268
+ }), M(!0);
239
269
  } catch {} finally {
240
- O(!1);
270
+ A(!1);
241
271
  }
242
272
  }
243
273
  }, [
244
- x,
245
- y.fields,
246
- y.submitAction,
274
+ C,
275
+ b.fields,
276
+ b.submitAction,
247
277
  e.id,
248
- _,
249
- g
250
- ]), P = t(() => {
251
- S(b), w({}), E(/* @__PURE__ */ new Set()), A(!1);
252
- }, [b]), F = t((e) => {
253
- let t = x[e.name], n = !!(T.has(e.name) && C[e.name]), r = {
254
- ...m.input,
255
- ...n ? m.inputError : {}
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 || D,
294
+ disabled: e.disabled || k,
265
295
  readOnly: e.readonly,
266
296
  rows: e.rows || 4,
267
297
  style: {
268
298
  ...r,
269
- ...m.textarea
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) => j(e.name, t.target.value),
285
- onBlur: () => M(e.name),
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: m.checkbox,
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 || D,
303
- style: m.checkboxInput,
304
- onChange: (t) => j(e.name, t.target.checked),
305
- onBlur: () => M(e.name)
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?.map((n) => /* @__PURE__ */ d("div", {
322
- style: m.checkbox,
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 || D,
330
- style: m.checkboxInput,
331
- onChange: (t) => j(e.name, t.target.value),
332
- onBlur: () => M(e.name)
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 || D,
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) => j(e.name, e.type === "number" ? t.target.valueAsNumber : t.target.value),
363
- onBlur: () => M(e.name)
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
- j,
372
- M
403
+ k,
404
+ N,
405
+ P,
406
+ x
373
407
  ]);
374
- if (y.fields.length === 0) return /* @__PURE__ */ d("div", {
375
- style: m.emptyState,
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 I = y.layout === "grid" ? {
430
+ let R = b.layout === "grid" ? {
397
431
  display: "grid",
398
- gridTemplateColumns: `repeat(${y.columns || 2}, 1fr)`,
432
+ gridTemplateColumns: `repeat(${b.columns || 2}, 1fr)`,
399
433
  gap: "16px"
400
434
  } : {};
401
435
  return /* @__PURE__ */ d("div", {
402
- style: m.container,
436
+ style: h.container,
403
437
  children: [/* @__PURE__ */ d("form", {
404
- onSubmit: N,
438
+ onSubmit: F,
405
439
  style: {
406
- ...m.form,
407
- ...I
440
+ ...h.form,
441
+ ...R
408
442
  },
409
- children: [k && y.successMessage && /* @__PURE__ */ d("div", {
443
+ children: [j && b.successMessage && /* @__PURE__ */ d("div", {
410
444
  style: {
411
- ...m.successMessage,
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
- } }), y.successMessage]
418
- }), y.fields.map((e) => {
419
- if (e.type === "hidden") return F(e);
420
- let t = T.has(e.name) ? C[e.name] : null;
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: m.fieldWrapper,
456
+ style: h.fieldWrapper,
423
457
  children: [
424
458
  e.type !== "checkbox" && /* @__PURE__ */ d("label", {
425
459
  htmlFor: e.name,
426
- style: m.label,
460
+ style: h.label,
427
461
  children: [e.label, e.required && /* @__PURE__ */ u("span", {
428
- style: m.required,
462
+ style: h.required,
429
463
  children: "*"
430
464
  })]
431
465
  }),
432
- F(e),
466
+ L(e),
433
467
  e.helpText && !t && /* @__PURE__ */ u("p", {
434
- style: m.helpText,
468
+ style: h.helpText,
435
469
  children: e.helpText
436
470
  }),
437
471
  t && /* @__PURE__ */ d("p", {
438
- style: m.errorText,
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: m.footer,
449
- children: [y.showReset !== !1 && /* @__PURE__ */ d("button", {
482
+ style: h.footer,
483
+ children: [b.showReset !== !1 && /* @__PURE__ */ d("button", {
450
484
  type: "button",
451
- onClick: P,
452
- disabled: D,
485
+ onClick: I,
486
+ disabled: k,
453
487
  style: {
454
- ...m.button,
455
- ...m.resetButton,
456
- opacity: D ? .6 : 1
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
- } }), y.resetLabel || "Reset"]
495
+ } }), b.resetLabel || "Reset"]
462
496
  }), /* @__PURE__ */ d("button", {
463
497
  type: "submit",
464
- onClick: N,
465
- disabled: D,
498
+ onClick: F,
499
+ disabled: k,
466
500
  style: {
467
- ...m.button,
468
- ...m.submitButton,
469
- opacity: D ? .6 : 1
501
+ ...h.button,
502
+ ...h.submitButton,
503
+ opacity: k ? .6 : 1
470
504
  },
471
- children: [D ? /* @__PURE__ */ u(o, { style: {
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
- } }), y.submitLabel || "Submit"]
512
+ } }), b.submitLabel || "Submit"]
479
513
  })]
480
514
  })]
481
515
  });
482
516
  });
483
517
  //#endregion
484
- export { h as default };
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
- var f = t(function({ to: e, ...t }, n) {
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 { f as AppLink, l as NavigationProvider, d as useAppNavigate, u as useNavigation };
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