@burdenoff/microfe-bigconsole 2026.805.1 → 2026.805.3

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.
Files changed (150) hide show
  1. package/dist/bigconsole/AdminRoot.js +21 -16
  2. package/dist/bigconsole/AdminRoot.js.map +1 -1
  3. package/dist/bigconsole/BigConsoleRoot.js +44 -39
  4. package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
  5. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +109 -113
  6. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
  7. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +115 -113
  8. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  9. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +71 -62
  10. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  11. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +116 -100
  12. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  13. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +56 -54
  14. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
  15. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +126 -125
  16. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
  17. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +151 -150
  18. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
  19. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +77 -76
  20. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
  21. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +97 -96
  22. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  23. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +172 -191
  24. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  25. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +100 -98
  26. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
  27. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +75 -83
  28. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -1
  29. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +151 -154
  30. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
  31. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +187 -193
  32. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
  33. package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -0
  34. package/dist/bigconsole/components/dashboard/WidgetPalette.js +110 -108
  35. package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
  36. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +102 -103
  37. package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
  38. package/dist/bigconsole/components/datasink/DataSinkCard.js +20 -20
  39. package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
  40. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +36 -41
  41. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
  42. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +38 -37
  43. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
  44. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +113 -117
  45. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
  46. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +182 -197
  47. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  48. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +166 -168
  49. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
  50. package/dist/bigconsole/components/parser/DataSinkSelector.js +87 -86
  51. package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
  52. package/dist/bigconsole/components/parser/ImportParserDialog.js +196 -211
  53. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  54. package/dist/bigconsole/components/parser/ParserSelector.js +130 -128
  55. package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
  56. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +66 -63
  57. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
  58. package/dist/bigconsole/components/preview/AiPreviewPanel.js +95 -91
  59. package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
  60. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +243 -230
  61. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  62. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +149 -145
  63. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
  64. package/dist/bigconsole/components/widgets/PropertiesPanel.js +504 -470
  65. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  66. package/dist/bigconsole/components/widgets/WidgetMenu.js +87 -76
  67. package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
  68. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +44 -47
  69. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
  70. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +143 -142
  71. package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
  72. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +101 -88
  73. package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
  74. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +135 -134
  75. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
  76. package/dist/bigconsole/components/widgets/form/FormWidget.js +167 -159
  77. package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
  78. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +69 -68
  79. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
  80. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +64 -72
  81. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
  82. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +60 -59
  83. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  84. package/dist/bigconsole/components/widgets/list/ListConfig.js +57 -56
  85. package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
  86. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +70 -69
  87. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
  88. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +35 -34
  89. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
  90. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +20 -19
  91. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
  92. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +178 -177
  93. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
  94. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +76 -75
  95. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
  96. package/dist/bigconsole/components/widgets/table/TableConfig.js +183 -168
  97. package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
  98. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +187 -180
  99. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
  100. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +120 -118
  101. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
  102. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +40 -38
  103. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
  104. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +150 -148
  105. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  106. package/dist/bigconsole/pages/DashboardBuilderPage.js +189 -175
  107. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  108. package/dist/bigconsole/pages/DashboardViewPage.js +200 -187
  109. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  110. package/dist/bigconsole/pages/DashboardsPage.js +379 -324
  111. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  112. package/dist/bigconsole/pages/DataParsersPage.js +185 -178
  113. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  114. package/dist/bigconsole/pages/DataSinkBuilderPage.js +195 -170
  115. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  116. package/dist/bigconsole/pages/DataSinkViewPage.js +224 -200
  117. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  118. package/dist/bigconsole/pages/DataSinksPage.js +281 -268
  119. package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
  120. package/dist/bigconsole/pages/DataSourcesPage.js +8 -7
  121. package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
  122. package/dist/bigconsole/pages/InsightsPage.js +238 -208
  123. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  124. package/dist/bigconsole/pages/ParserBuilderPage.js +480 -413
  125. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  126. package/dist/bigconsole/pages/ParserViewPage.js +192 -172
  127. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  128. package/dist/bigconsole/pages/PipelineBuilderPage.js +198 -163
  129. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  130. package/dist/bigconsole/pages/PipelineViewPage.js +138 -133
  131. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  132. package/dist/bigconsole/pages/PipelinesPage.js +162 -136
  133. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  134. package/dist/bigconsole/pages/SettingsPage.js +177 -172
  135. package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
  136. package/dist/bigconsole/pages/WidgetDemoPage.js +121 -83
  137. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  138. package/dist/bigconsole/pages/WorkflowViewPage.js +269 -242
  139. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  140. package/dist/bigconsole/pages/WorkflowsPage.js +153 -138
  141. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  142. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +111 -109
  143. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
  144. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +127 -126
  145. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
  146. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +103 -103
  147. package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
  148. package/dist/constants/permissions.js +83 -0
  149. package/dist/constants/permissions.js.map +1 -0
  150. package/package.json +2 -1
@@ -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// 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
+ {"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 { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\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\n/** Translator function shape from useI18n().t, threaded into module-level validators. */\ntype TFunc = (\n key: string,\n fallbackOrParams?: string | Record<string, string | number>,\n params?: Record<string, string | number>\n) => string;\n\nfunction validateField(value: unknown, field: FormField, t: TFunc): 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 t('bigconsole.widget.form.validation.required', '{{label}} is required', { label: field.label ?? '' });\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 t('bigconsole.widget.form.validation.email', 'Please enter a valid email address');\n }\n }\n\n if (field.type === 'url') {\n try {\n new URL(strValue);\n } catch {\n return t('bigconsole.widget.form.validation.url', 'Please enter a valid URL');\n }\n }\n\n if (field.type === 'number') {\n if (isNaN(Number(value))) {\n return t('bigconsole.widget.form.validation.number', 'Please enter a valid number');\n }\n if (field.min !== undefined && Number(value) < Number(field.min)) {\n return t('bigconsole.widget.form.validation.min', 'Value must be at least {{min}}', {\n min: field.min ?? '',\n });\n }\n if (field.max !== undefined && Number(value) > Number(field.max)) {\n return t('bigconsole.widget.form.validation.max', 'Value must be at most {{max}}', {\n max: field.max ?? '',\n });\n }\n }\n\n return null;\n}\n\nfunction validateForm(values: Record<string, unknown>, fields: FormField[], t: TFunc): FieldErrors {\n const errors: FieldErrors = {};\n for (const field of fields) {\n const error = validateField(values[field.name], field, t);\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 { t } = useI18n();\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, t);\n setErrors((prev) => ({ ...prev, [fieldName]: error }));\n }\n }\n },\n [config.fields, config.validateOnChange, t]\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, t);\n setErrors((prev) => ({ ...prev, [fieldName]: error }));\n }\n }\n },\n [config.fields, config.validateOnBlur, values, t]\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, t);\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, t]\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=\"\">\n {field.placeholder ||\n t('bigconsole.widget.form.selectPlaceholder', 'Select {{label}}...', { label: field.label ?? '' })}\n </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, t]\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' }}>{t('bigconsole.widget.form.configureTitle', 'Configure Form Fields')}</p>\n <p style={{ fontSize: '12px', marginTop: '4px' }}>\n {t('bigconsole.widget.form.configureHint', 'Add fields in widget settings to create your form')}\n </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 || t('bigconsole.widget.form.reset', '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 || t('bigconsole.widget.form.submit', 'Submit')}\n </button>\n </div>\n </div>\n );\n});\n\nexport default FormWidget;\n"],"mappings":"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"}
@@ -1,104 +1,105 @@
1
1
  import { memo as e, useCallback as t } from "react";
2
- import { jsx as n, jsxs as r } from "react/jsx-runtime";
2
+ import { useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
3
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
3
4
  //#region src/bigconsole/components/widgets/gauge/GaugeConfig.tsx
4
- var i = e(function({ config: e, onChange: i }) {
5
- let a = t((t, n) => {
6
- i({
5
+ var a = e(function({ config: e, onChange: a }) {
6
+ let { t: o } = n(), s = t((t, n) => {
7
+ a({
7
8
  ...e,
8
9
  [t]: n
9
10
  });
10
- }, [e, i]);
11
- return /* @__PURE__ */ r("div", {
11
+ }, [e, a]);
12
+ return /* @__PURE__ */ i("div", {
12
13
  className: "space-y-4",
13
14
  children: [
14
- /* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("label", {
15
+ /* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("label", {
15
16
  className: "block text-sm font-medium text-text-primary mb-1",
16
- children: "Gauge Type"
17
- }), /* @__PURE__ */ r("select", {
17
+ children: o("bigconsole.widget.config.gauge.gaugeType", "Gauge Type")
18
+ }), /* @__PURE__ */ i("select", {
18
19
  value: e.variant || "circular",
19
- onChange: (e) => a("variant", e.target.value),
20
+ onChange: (e) => s("variant", e.target.value),
20
21
  className: "\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n ",
21
- children: [/* @__PURE__ */ n("option", {
22
+ children: [/* @__PURE__ */ r("option", {
22
23
  value: "circular",
23
- children: "Circular"
24
- }), /* @__PURE__ */ n("option", {
24
+ children: o("bigconsole.widget.config.gauge.variant.circular", "Circular")
25
+ }), /* @__PURE__ */ r("option", {
25
26
  value: "linear",
26
- children: "Linear"
27
+ children: o("bigconsole.widget.config.gauge.variant.linear", "Linear")
27
28
  })]
28
29
  })] }),
29
- /* @__PURE__ */ r("div", {
30
+ /* @__PURE__ */ i("div", {
30
31
  className: "grid grid-cols-2 gap-3",
31
- children: [/* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("label", {
32
+ children: [/* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("label", {
32
33
  className: "block text-sm font-medium text-text-primary mb-1",
33
- children: "Minimum"
34
- }), /* @__PURE__ */ n("input", {
34
+ children: o("bigconsole.widget.config.gauge.minimum", "Minimum")
35
+ }), /* @__PURE__ */ r("input", {
35
36
  type: "number",
36
37
  value: e.min ?? 0,
37
- onChange: (e) => a("min", Number(e.target.value)),
38
+ onChange: (e) => s("min", Number(e.target.value)),
38
39
  className: "\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n "
39
- })] }), /* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("label", {
40
+ })] }), /* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("label", {
40
41
  className: "block text-sm font-medium text-text-primary mb-1",
41
- children: "Maximum"
42
- }), /* @__PURE__ */ n("input", {
42
+ children: o("bigconsole.widget.config.gauge.maximum", "Maximum")
43
+ }), /* @__PURE__ */ r("input", {
43
44
  type: "number",
44
45
  value: e.max ?? 100,
45
- onChange: (e) => a("max", Number(e.target.value)),
46
+ onChange: (e) => s("max", Number(e.target.value)),
46
47
  className: "\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n "
47
48
  })] })]
48
49
  }),
49
- /* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("label", {
50
+ /* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("label", {
50
51
  className: "block text-sm font-medium text-text-primary mb-1",
51
- children: "Unit Label"
52
- }), /* @__PURE__ */ n("input", {
52
+ children: o("bigconsole.widget.config.gauge.unitLabel", "Unit Label")
53
+ }), /* @__PURE__ */ r("input", {
53
54
  type: "text",
54
55
  value: e.unit || "",
55
- onChange: (e) => a("unit", e.target.value),
56
- placeholder: "e.g., %, ms, users",
56
+ onChange: (e) => s("unit", e.target.value),
57
+ placeholder: o("bigconsole.widget.config.gauge.unitPlaceholder", "e.g., %, ms, users"),
57
58
  className: "\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n "
58
59
  })] }),
59
- /* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("label", {
60
+ /* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("label", {
60
61
  className: "block text-sm font-medium text-text-primary mb-1",
61
- children: "Value Format"
62
- }), /* @__PURE__ */ r("select", {
62
+ children: o("bigconsole.widget.config.gauge.valueFormat", "Value Format")
63
+ }), /* @__PURE__ */ i("select", {
63
64
  value: e.format || "number",
64
- onChange: (e) => a("format", e.target.value),
65
+ onChange: (e) => s("format", e.target.value),
65
66
  className: "\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n ",
66
67
  children: [
67
- /* @__PURE__ */ n("option", {
68
+ /* @__PURE__ */ r("option", {
68
69
  value: "number",
69
- children: "Number"
70
+ children: o("bigconsole.widget.config.gauge.format.number", "Number")
70
71
  }),
71
- /* @__PURE__ */ n("option", {
72
+ /* @__PURE__ */ r("option", {
72
73
  value: "percentage",
73
- children: "Percentage"
74
+ children: o("bigconsole.widget.config.gauge.format.percentage", "Percentage")
74
75
  }),
75
- /* @__PURE__ */ n("option", {
76
+ /* @__PURE__ */ r("option", {
76
77
  value: "currency",
77
- children: "Currency"
78
+ children: o("bigconsole.widget.config.gauge.format.currency", "Currency")
78
79
  })
79
80
  ]
80
81
  })] }),
81
- /* @__PURE__ */ r("div", { children: [
82
- /* @__PURE__ */ n("label", {
82
+ /* @__PURE__ */ i("div", { children: [
83
+ /* @__PURE__ */ r("label", {
83
84
  className: "block text-sm font-medium text-text-primary mb-2",
84
- children: "Color Thresholds"
85
+ children: o("bigconsole.widget.config.gauge.colorThresholds", "Color Thresholds")
85
86
  }),
86
- /* @__PURE__ */ n("p", {
87
+ /* @__PURE__ */ r("p", {
87
88
  className: "text-xs text-text-secondary mb-3",
88
- children: "Define color zones based on value ranges. Values up to each threshold will use that color."
89
+ children: o("bigconsole.widget.config.gauge.colorThresholdsHelp", "Define color zones based on value ranges. Values up to each threshold will use that color.")
89
90
  }),
90
- /* @__PURE__ */ r("div", {
91
+ /* @__PURE__ */ i("div", {
91
92
  className: "space-y-2",
92
93
  children: [
93
- /* @__PURE__ */ r("div", {
94
+ /* @__PURE__ */ i("div", {
94
95
  className: "flex items-center gap-2",
95
96
  children: [
96
- /* @__PURE__ */ n("div", { className: "w-4 h-4 rounded bg-status-error-bg" }),
97
- /* @__PURE__ */ n("span", {
97
+ /* @__PURE__ */ r("div", { className: "w-4 h-4 rounded bg-status-error-bg" }),
98
+ /* @__PURE__ */ r("span", {
98
99
  className: "text-sm text-text-primary flex-1",
99
- children: "Danger (Red)"
100
+ children: o("bigconsole.widget.config.gauge.threshold.danger", "Danger (Red)")
100
101
  }),
101
- /* @__PURE__ */ n("input", {
102
+ /* @__PURE__ */ r("input", {
102
103
  type: "number",
103
104
  value: e.thresholds?.[0]?.value ?? 33,
104
105
  onChange: (t) => {
@@ -106,21 +107,21 @@ var i = e(function({ config: e, onChange: i }) {
106
107
  n[0] = {
107
108
  value: Number(t.target.value),
108
109
  color: "error"
109
- }, a("thresholds", n);
110
+ }, s("thresholds", n);
110
111
  },
111
112
  className: "\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n "
112
113
  })
113
114
  ]
114
115
  }),
115
- /* @__PURE__ */ r("div", {
116
+ /* @__PURE__ */ i("div", {
116
117
  className: "flex items-center gap-2",
117
118
  children: [
118
- /* @__PURE__ */ n("div", { className: "w-4 h-4 rounded bg-status-warning-bg" }),
119
- /* @__PURE__ */ n("span", {
119
+ /* @__PURE__ */ r("div", { className: "w-4 h-4 rounded bg-status-warning-bg" }),
120
+ /* @__PURE__ */ r("span", {
120
121
  className: "text-sm text-text-primary flex-1",
121
- children: "Warning (Yellow)"
122
+ children: o("bigconsole.widget.config.gauge.threshold.warning", "Warning (Yellow)")
122
123
  }),
123
- /* @__PURE__ */ n("input", {
124
+ /* @__PURE__ */ r("input", {
124
125
  type: "number",
125
126
  value: e.thresholds?.[1]?.value ?? 66,
126
127
  onChange: (t) => {
@@ -128,21 +129,21 @@ var i = e(function({ config: e, onChange: i }) {
128
129
  n[1] = {
129
130
  value: Number(t.target.value),
130
131
  color: "warning"
131
- }, a("thresholds", n);
132
+ }, s("thresholds", n);
132
133
  },
133
134
  className: "\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n "
134
135
  })
135
136
  ]
136
137
  }),
137
- /* @__PURE__ */ r("div", {
138
+ /* @__PURE__ */ i("div", {
138
139
  className: "flex items-center gap-2",
139
140
  children: [
140
- /* @__PURE__ */ n("div", { className: "w-4 h-4 rounded bg-status-success-bg" }),
141
- /* @__PURE__ */ n("span", {
141
+ /* @__PURE__ */ r("div", { className: "w-4 h-4 rounded bg-status-success-bg" }),
142
+ /* @__PURE__ */ r("span", {
142
143
  className: "text-sm text-text-primary flex-1",
143
- children: "Good (Green)"
144
+ children: o("bigconsole.widget.config.gauge.threshold.good", "Good (Green)")
144
145
  }),
145
- /* @__PURE__ */ n("input", {
146
+ /* @__PURE__ */ r("input", {
146
147
  type: "number",
147
148
  value: e.thresholds?.[2]?.value ?? 100,
148
149
  onChange: (t) => {
@@ -150,7 +151,7 @@ var i = e(function({ config: e, onChange: i }) {
150
151
  n[2] = {
151
152
  value: Number(t.target.value),
152
153
  color: "success"
153
- }, a("thresholds", n);
154
+ }, s("thresholds", n);
154
155
  },
155
156
  className: "\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n "
156
157
  })
@@ -159,22 +160,22 @@ var i = e(function({ config: e, onChange: i }) {
159
160
  ]
160
161
  })
161
162
  ] }),
162
- e.variant === "linear" && /* @__PURE__ */ r("label", {
163
+ e.variant === "linear" && /* @__PURE__ */ i("label", {
163
164
  className: "flex items-center gap-3",
164
- children: [/* @__PURE__ */ n("input", {
165
+ children: [/* @__PURE__ */ r("input", {
165
166
  type: "checkbox",
166
167
  checked: e.showZones === !0,
167
- onChange: (e) => a("showZones", e.target.checked),
168
+ onChange: (e) => s("showZones", e.target.checked),
168
169
  className: "\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n "
169
- }), /* @__PURE__ */ n("span", {
170
+ }), /* @__PURE__ */ r("span", {
170
171
  className: "text-sm text-text-primary",
171
- children: "Show color zones in background"
172
+ children: o("bigconsole.widget.config.gauge.showZones", "Show color zones in background")
172
173
  })]
173
174
  })
174
175
  ]
175
176
  });
176
177
  });
177
178
  //#endregion
178
- export { i as default };
179
+ export { a as default };
179
180
 
180
181
  //# sourceMappingURL=GaugeConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GaugeConfig.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/gauge/GaugeConfig.tsx"],"sourcesContent":["/**\n * GaugeConfig Component\n *\n * Configuration panel for Gauge widgets.\n */\n\nimport { type FC, memo, useCallback } from 'react';\nimport type { GaugeConfig as ConfigType } from '../../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface GaugeConfigProps {\n /** Current configuration */\n config: ConfigType;\n /** Callback when config changes */\n onChange: (config: ConfigType) => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const GaugeConfig: FC<GaugeConfigProps> = memo(function GaugeConfig({ config, onChange }) {\n const handleChange = useCallback(\n <K extends keyof ConfigType>(key: K, value: ConfigType[K]) => {\n onChange({ ...config, [key]: value });\n },\n [config, onChange]\n );\n\n return (\n <div className=\"space-y-4\">\n {/* Variant */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Gauge Type</label>\n <select\n value={config.variant || 'circular'}\n onChange={(e) => handleChange('variant', e.target.value as ConfigType['variant'])}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n >\n <option value=\"circular\">Circular</option>\n <option value=\"linear\">Linear</option>\n </select>\n </div>\n\n {/* Min/Max Range */}\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Minimum</label>\n <input\n type=\"number\"\n value={config.min ?? 0}\n onChange={(e) => handleChange('min', Number(e.target.value))}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Maximum</label>\n <input\n type=\"number\"\n value={config.max ?? 100}\n onChange={(e) => handleChange('max', Number(e.target.value))}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n </div>\n\n {/* Unit */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Unit Label</label>\n <input\n type=\"text\"\n value={config.unit || ''}\n onChange={(e) => handleChange('unit', e.target.value)}\n placeholder=\"e.g., %, ms, users\"\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n\n {/* Format */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Value Format</label>\n <select\n value={config.format || 'number'}\n onChange={(e) => handleChange('format', e.target.value as ConfigType['format'])}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n >\n <option value=\"number\">Number</option>\n <option value=\"percentage\">Percentage</option>\n <option value=\"currency\">Currency</option>\n </select>\n </div>\n\n {/* Thresholds Section */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Color Thresholds</label>\n <p className=\"text-xs text-text-secondary mb-3\">\n Define color zones based on value ranges. Values up to each threshold will use that color.\n </p>\n\n <div className=\"space-y-2\">\n {/* Red zone */}\n <div className=\"flex items-center gap-2\">\n <div className=\"w-4 h-4 rounded bg-status-error-bg\" />\n <span className=\"text-sm text-text-primary flex-1\">Danger (Red)</span>\n <input\n type=\"number\"\n value={config.thresholds?.[0]?.value ?? 33}\n onChange={(e) => {\n const thresholds = [...(config.thresholds || [])];\n thresholds[0] = {\n value: Number(e.target.value),\n color: 'error',\n };\n handleChange('thresholds', thresholds);\n }}\n className=\"\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n\n {/* Yellow zone */}\n <div className=\"flex items-center gap-2\">\n <div className=\"w-4 h-4 rounded bg-status-warning-bg\" />\n <span className=\"text-sm text-text-primary flex-1\">Warning (Yellow)</span>\n <input\n type=\"number\"\n value={config.thresholds?.[1]?.value ?? 66}\n onChange={(e) => {\n const thresholds = [...(config.thresholds || [])];\n thresholds[1] = {\n value: Number(e.target.value),\n color: 'warning',\n };\n handleChange('thresholds', thresholds);\n }}\n className=\"\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n\n {/* Green zone */}\n <div className=\"flex items-center gap-2\">\n <div className=\"w-4 h-4 rounded bg-status-success-bg\" />\n <span className=\"text-sm text-text-primary flex-1\">Good (Green)</span>\n <input\n type=\"number\"\n value={config.thresholds?.[2]?.value ?? 100}\n onChange={(e) => {\n const thresholds = [...(config.thresholds || [])];\n thresholds[2] = {\n value: Number(e.target.value),\n color: 'success',\n };\n handleChange('thresholds', thresholds);\n }}\n className=\"\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n </div>\n </div>\n\n {/* Show zones (for linear gauge) */}\n {config.variant === 'linear' && (\n <label className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={config.showZones === true}\n onChange={(e) => handleChange('showZones', e.target.checked)}\n className=\"\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n \"\n />\n <span className=\"text-sm text-text-primary\">Show color zones in background</span>\n </label>\n )}\n </div>\n );\n});\n\nexport default GaugeConfig;\n"],"mappings":"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"}
1
+ {"version":3,"file":"GaugeConfig.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/gauge/GaugeConfig.tsx"],"sourcesContent":["/**\n * GaugeConfig Component\n *\n * Configuration panel for Gauge widgets.\n */\n\nimport { type FC, memo, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type { GaugeConfig as ConfigType } from '../../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface GaugeConfigProps {\n /** Current configuration */\n config: ConfigType;\n /** Callback when config changes */\n onChange: (config: ConfigType) => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const GaugeConfig: FC<GaugeConfigProps> = memo(function GaugeConfig({ config, onChange }) {\n const { t } = useI18n();\n const handleChange = useCallback(\n <K extends keyof ConfigType>(key: K, value: ConfigType[K]) => {\n onChange({ ...config, [key]: value });\n },\n [config, onChange]\n );\n\n return (\n <div className=\"space-y-4\">\n {/* Variant */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.gauge.gaugeType', 'Gauge Type')}\n </label>\n <select\n value={config.variant || 'circular'}\n onChange={(e) => handleChange('variant', e.target.value as ConfigType['variant'])}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n >\n <option value=\"circular\">{t('bigconsole.widget.config.gauge.variant.circular', 'Circular')}</option>\n <option value=\"linear\">{t('bigconsole.widget.config.gauge.variant.linear', 'Linear')}</option>\n </select>\n </div>\n\n {/* Min/Max Range */}\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.gauge.minimum', 'Minimum')}\n </label>\n <input\n type=\"number\"\n value={config.min ?? 0}\n onChange={(e) => handleChange('min', Number(e.target.value))}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.gauge.maximum', 'Maximum')}\n </label>\n <input\n type=\"number\"\n value={config.max ?? 100}\n onChange={(e) => handleChange('max', Number(e.target.value))}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n </div>\n\n {/* Unit */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.gauge.unitLabel', 'Unit Label')}\n </label>\n <input\n type=\"text\"\n value={config.unit || ''}\n onChange={(e) => handleChange('unit', e.target.value)}\n placeholder={t('bigconsole.widget.config.gauge.unitPlaceholder', 'e.g., %, ms, users')}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n\n {/* Format */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.gauge.valueFormat', 'Value Format')}\n </label>\n <select\n value={config.format || 'number'}\n onChange={(e) => handleChange('format', e.target.value as ConfigType['format'])}\n className=\"\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n >\n <option value=\"number\">{t('bigconsole.widget.config.gauge.format.number', 'Number')}</option>\n <option value=\"percentage\">{t('bigconsole.widget.config.gauge.format.percentage', 'Percentage')}</option>\n <option value=\"currency\">{t('bigconsole.widget.config.gauge.format.currency', 'Currency')}</option>\n </select>\n </div>\n\n {/* Thresholds Section */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n {t('bigconsole.widget.config.gauge.colorThresholds', 'Color Thresholds')}\n </label>\n <p className=\"text-xs text-text-secondary mb-3\">\n {t(\n 'bigconsole.widget.config.gauge.colorThresholdsHelp',\n 'Define color zones based on value ranges. Values up to each threshold will use that color.'\n )}\n </p>\n\n <div className=\"space-y-2\">\n {/* Red zone */}\n <div className=\"flex items-center gap-2\">\n <div className=\"w-4 h-4 rounded bg-status-error-bg\" />\n <span className=\"text-sm text-text-primary flex-1\">\n {t('bigconsole.widget.config.gauge.threshold.danger', 'Danger (Red)')}\n </span>\n <input\n type=\"number\"\n value={config.thresholds?.[0]?.value ?? 33}\n onChange={(e) => {\n const thresholds = [...(config.thresholds || [])];\n thresholds[0] = {\n value: Number(e.target.value),\n color: 'error',\n };\n handleChange('thresholds', thresholds);\n }}\n className=\"\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n\n {/* Yellow zone */}\n <div className=\"flex items-center gap-2\">\n <div className=\"w-4 h-4 rounded bg-status-warning-bg\" />\n <span className=\"text-sm text-text-primary flex-1\">\n {t('bigconsole.widget.config.gauge.threshold.warning', 'Warning (Yellow)')}\n </span>\n <input\n type=\"number\"\n value={config.thresholds?.[1]?.value ?? 66}\n onChange={(e) => {\n const thresholds = [...(config.thresholds || [])];\n thresholds[1] = {\n value: Number(e.target.value),\n color: 'warning',\n };\n handleChange('thresholds', thresholds);\n }}\n className=\"\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n\n {/* Green zone */}\n <div className=\"flex items-center gap-2\">\n <div className=\"w-4 h-4 rounded bg-status-success-bg\" />\n <span className=\"text-sm text-text-primary flex-1\">\n {t('bigconsole.widget.config.gauge.threshold.good', 'Good (Green)')}\n </span>\n <input\n type=\"number\"\n value={config.thresholds?.[2]?.value ?? 100}\n onChange={(e) => {\n const thresholds = [...(config.thresholds || [])];\n thresholds[2] = {\n value: Number(e.target.value),\n color: 'success',\n };\n handleChange('thresholds', thresholds);\n }}\n className=\"\n w-20 px-2 py-1\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n \"\n />\n </div>\n </div>\n </div>\n\n {/* Show zones (for linear gauge) */}\n {config.variant === 'linear' && (\n <label className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={config.showZones === true}\n onChange={(e) => handleChange('showZones', e.target.checked)}\n className=\"\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n \"\n />\n <span className=\"text-sm text-text-primary\">\n {t('bigconsole.widget.config.gauge.showZones', 'Show color zones in background')}\n </span>\n </label>\n )}\n </div>\n );\n});\n\nexport default GaugeConfig;\n"],"mappings":"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"}