df-ae-forms-package 1.0.89 → 1.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -5301,9 +5301,27 @@ const DfFormSection = ({ id, properties, mode = 'edit', formData = {}, onValueCh
5301
5301
 
5302
5302
  // Dynamic imports to avoid circular dependencies
5303
5303
  const DfFormTable$1 = React.lazy(() => Promise.resolve().then(function () { return dfFormTable; }));
5304
+ // Normalize a table row from API format (object with numeric keys) into a proper array.
5305
+ // The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
5306
+ const normalizeTableRow = (row) => {
5307
+ if (Array.isArray(row))
5308
+ return row;
5309
+ if (row && typeof row === 'object') {
5310
+ const keys = Object.keys(row).filter(k => !isNaN(Number(k))).sort((a, b) => Number(a) - Number(b));
5311
+ if (keys.length > 0)
5312
+ return keys.map(k => row[k]);
5313
+ }
5314
+ return [];
5315
+ };
5304
5316
  const DfFormPreview = ({ formComponents = [], currentDevice = 'desktop', isPreviewMode = false, initialFormData = [], onSubmit, onFormDataChange, formTitle, formDescription, formTemplateId,
5305
5317
  // Add component management props for edit mode
5306
5318
  onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, selectedComponent, workOrderNumber, assetNumber, isStandalone, user, onCreateIssue, onUpdateIssue }) => {
5319
+ // Local copy of formComponents so structure updates (e.g. table cell init) are reflected immediately
5320
+ const [localFormComponents, setLocalFormComponents] = useState(formComponents);
5321
+ // Sync local state when the prop changes from the parent
5322
+ useEffect(() => {
5323
+ setLocalFormComponents(formComponents);
5324
+ }, [formComponents]);
5307
5325
  // Form state
5308
5326
  const [formValues, setFormValues] = useState({});
5309
5327
  const [validationErrors, setValidationErrors] = useState({});
@@ -5324,7 +5342,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5324
5342
  // Initialize form state
5325
5343
  useEffect(() => {
5326
5344
  initializeFormState();
5327
- }, [formComponents, initialFormData]);
5345
+ }, [localFormComponents, initialFormData]);
5328
5346
  // Recursive function to initialize values from nested components
5329
5347
  const initializeComponentValues = (components, values) => {
5330
5348
  components.forEach(component => {
@@ -5353,13 +5371,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5353
5371
  // Handle nested components in table cells
5354
5372
  if (component.cells && Array.isArray(component.cells)) {
5355
5373
  component.cells.forEach((row, _rowIndex) => {
5356
- if (Array.isArray(row)) {
5357
- row.forEach((cell, _cellIndex) => {
5358
- if (cell && cell.components && Array.isArray(cell.components)) {
5359
- initializeComponentValues(cell.components, values);
5360
- }
5361
- });
5362
- }
5374
+ normalizeTableRow(row).forEach((cell, _cellIndex) => {
5375
+ if (cell && cell.components && Array.isArray(cell.components)) {
5376
+ initializeComponentValues(cell.components, values);
5377
+ }
5378
+ });
5363
5379
  });
5364
5380
  }
5365
5381
  // Handle nested components in datagrid entries
@@ -5422,11 +5438,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5422
5438
  extractNotesAndAttachments(comp.children);
5423
5439
  if (comp.cells && Array.isArray(comp.cells))
5424
5440
  comp.cells.forEach((row) => {
5425
- if (Array.isArray(row))
5426
- row.forEach((cell) => {
5427
- if (cell && cell.components)
5428
- extractNotesAndAttachments(cell.components);
5429
- });
5441
+ normalizeTableRow(row).forEach((cell) => {
5442
+ if (cell && cell.components)
5443
+ extractNotesAndAttachments(cell.components);
5444
+ });
5430
5445
  });
5431
5446
  if (comp.entries)
5432
5447
  comp.entries.forEach((entry) => {
@@ -5465,8 +5480,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5465
5480
  }
5466
5481
  if (validatedComponent.cells && Array.isArray(validatedComponent.cells)) {
5467
5482
  validatedComponent.cells = validatedComponent.cells.map((row) => {
5468
- if (Array.isArray(row)) {
5469
- return row.map((cell) => {
5483
+ const normalizedRow = normalizeTableRow(row);
5484
+ if (normalizedRow.length > 0) {
5485
+ return normalizedRow.map((cell) => {
5470
5486
  if (cell && cell.components && Array.isArray(cell.components)) {
5471
5487
  return {
5472
5488
  ...cell,
@@ -5494,11 +5510,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5494
5510
  });
5495
5511
  };
5496
5512
  // Initialize validated components
5497
- let validatedFormComponents = formComponents;
5498
- if (formComponents && formComponents.length > 0) {
5499
- validatedFormComponents = getValidatedComponents(formComponents);
5513
+ let validatedFormComponents = localFormComponents;
5514
+ if (localFormComponents && localFormComponents.length > 0) {
5515
+ validatedFormComponents = getValidatedComponents(localFormComponents);
5500
5516
  // Notifying parent of changed components if they were mutated (IDs added/fixed)
5501
- if (JSON.stringify(validatedFormComponents) !== JSON.stringify(formComponents)) {
5517
+ if (JSON.stringify(validatedFormComponents) !== JSON.stringify(localFormComponents)) {
5502
5518
  onFormDataChange?.(validatedFormComponents);
5503
5519
  }
5504
5520
  }
@@ -5526,7 +5542,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5526
5542
  setComponentAttachments(prev => ({ ...initialAttachments, ...prev }));
5527
5543
  // Conditional logic evaluation disabled temporarily to fix table issues
5528
5544
  // evaluateConditionalLogic()
5529
- }, [initialFormData, formComponents]);
5545
+ }, [initialFormData, localFormComponents]);
5530
5546
  // Conditional logic disabled temporarily - all components are always visible
5531
5547
  const shouldShowComponent = useCallback((_componentId) => {
5532
5548
  return true;
@@ -5539,7 +5555,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5539
5555
  return;
5540
5556
  }
5541
5557
  // CRITICAL: Check if multiple components share this ID (ID collision detection)
5542
- const componentsWithSameId = formComponents.filter(comp => comp.id === change.id);
5558
+ const componentsWithSameId = localFormComponents.filter(comp => comp.id === change.id);
5543
5559
  if (componentsWithSameId.length > 1) {
5544
5560
  console.error(`[DfFormPreview] ID COLLISION DETECTED! Multiple components share ID "${change.id}":`, componentsWithSameId.map(c => ({ id: c.id, name: c.name, label: c.basic?.label })));
5545
5561
  // Don't update - this would cause all components with this ID to get the same value
@@ -5560,7 +5576,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5560
5576
  }
5561
5577
  // Clear raised issues for this component when value changes
5562
5578
  // This ensures that if threshold condition changes, user must raise issue again
5563
- const component = formComponents.find(comp => comp.id === change.id);
5579
+ const component = localFormComponents.find(comp => comp.id === change.id);
5564
5580
  if (component) {
5565
5581
  const threshold = component?.threshold;
5566
5582
  if (threshold && threshold.conditions && threshold.conditions.length > 0) {
@@ -5613,13 +5629,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5613
5629
  if (component.name === 'table' && component.cells) {
5614
5630
  return {
5615
5631
  ...component,
5616
- cells: component.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
5632
+ cells: component.cells.map((row) => normalizeTableRow(row).map((cell) => {
5617
5633
  const updatedCell = { ...cell };
5618
5634
  if (updatedCell.components) {
5619
5635
  updatedCell.components = updateComponentValue(updatedCell.components);
5620
5636
  }
5621
5637
  return updatedCell;
5622
- }) : row)
5638
+ }))
5623
5639
  };
5624
5640
  }
5625
5641
  if (component.name === 'datagrid' && component.entries) {
@@ -5638,7 +5654,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5638
5654
  });
5639
5655
  };
5640
5656
  // Update form components
5641
- const updatedComponents = updateComponentValue(formComponents);
5657
+ const updatedComponents = updateComponentValue(localFormComponents);
5658
+ // CRITICAL: Update local state immediately so structure changes (e.g. table cell init)
5659
+ // are reflected without waiting for Angular parent round-trip
5660
+ setLocalFormComponents(updatedComponents);
5642
5661
  onFormDataChange?.(updatedComponents);
5643
5662
  // Clear validation errors when user starts typing and re-validate
5644
5663
  if (validationErrors[change.id]) {
@@ -5675,7 +5694,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5675
5694
  }
5676
5695
  // Conditional logic evaluation disabled temporarily
5677
5696
  // evaluateConditionalLogic(newFormValues, updatedComponents)
5678
- }, [formComponents, formValues, validationErrors, onFormDataChange]);
5697
+ }, [localFormComponents, formValues, validationErrors, onFormDataChange]);
5679
5698
  // Recursive function to find a component by ID in nested structures
5680
5699
  const findComponentById = useCallback((components, fieldId) => {
5681
5700
  for (const comp of components) {
@@ -5719,7 +5738,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5719
5738
  if (isPreviewMode)
5720
5739
  return;
5721
5740
  // Find component recursively (handles nested components)
5722
- const component = findComponentById(formComponents, fieldId);
5741
+ const component = findComponentById(localFormComponents, fieldId);
5723
5742
  if (!component)
5724
5743
  return;
5725
5744
  // Get current value from form values (real-time input)
@@ -5814,7 +5833,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5814
5833
  ...prev,
5815
5834
  [fieldId]: errorMessage
5816
5835
  }));
5817
- }, [formComponents, isPreviewMode, formValues, findComponentById]);
5836
+ }, [localFormComponents, isPreviewMode, formValues, findComponentById]);
5818
5837
  // Handle form control blur
5819
5838
  const onFormControlBlur = useCallback((fieldId) => {
5820
5839
  setTouchedFields(prev => ({
@@ -5844,11 +5863,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5844
5863
  // useEffect(() => {
5845
5864
  // if (!isPreviewMode && Object.keys(formValues).length > 0) {
5846
5865
  // // Validate all form components when form values change (but not on initial load)
5847
- // formComponents.forEach(component => {
5866
+ // localFormComponents.forEach(component => {
5848
5867
  // validateField(component.id)
5849
5868
  // })
5850
5869
  // }
5851
- // }, [formValues, validateField, isPreviewMode, formComponents])
5870
+ // }, [formValues, validateField, isPreviewMode, localFormComponents])
5852
5871
  // Enhanced form validity check
5853
5872
  const isFormValid = useCallback(() => {
5854
5873
  // Check if there are any validation errors
@@ -5857,7 +5876,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5857
5876
  return false;
5858
5877
  }
5859
5878
  // Check required fields
5860
- return formComponents.every(component => {
5879
+ return localFormComponents.every(component => {
5861
5880
  // Use real-time form values instead of component values
5862
5881
  const currentValue = formValues[component.id] || '';
5863
5882
  // Check if field has a value
@@ -5903,7 +5922,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5903
5922
  }
5904
5923
  return true;
5905
5924
  });
5906
- }, [formComponents, formValues, validationErrors]);
5925
+ }, [localFormComponents, formValues, validationErrors]);
5907
5926
  // Evaluate threshold condition (handles both numeric and string values)
5908
5927
  const evaluateThresholdCondition = useCallback((condition, currentVal) => {
5909
5928
  // Handle array values (for checkbox)
@@ -5957,7 +5976,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5957
5976
  if (isPreviewMode)
5958
5977
  return [];
5959
5978
  const metConditions = [];
5960
- formComponents.forEach(component => {
5979
+ localFormComponents.forEach(component => {
5961
5980
  const condition = component?.condition;
5962
5981
  if (!condition || !condition.conditions || condition.conditions.length === 0) {
5963
5982
  return;
@@ -5983,7 +6002,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5983
6002
  });
5984
6003
  });
5985
6004
  return metConditions;
5986
- }, [formComponents, formValues, isPreviewMode, evaluateThresholdCondition]);
6005
+ }, [localFormComponents, formValues, isPreviewMode, evaluateThresholdCondition]);
5987
6006
  // Validate threshold conditions - check if all met conditions have all mandatory actions completed
5988
6007
  const validateThresholdConditions = useCallback(() => {
5989
6008
  if (isPreviewMode)
@@ -6068,7 +6087,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6068
6087
  let isValid = true;
6069
6088
  setFormSubmitted(true);
6070
6089
  const errors = {};
6071
- formComponents.forEach(component => {
6090
+ localFormComponents.forEach(component => {
6072
6091
  // Use real-time form values instead of component values
6073
6092
  const currentValue = formValues[component.id] || '';
6074
6093
  // Check if field has a value
@@ -6135,13 +6154,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6135
6154
  });
6136
6155
  setValidationErrors(errors);
6137
6156
  return isValid;
6138
- }, [formComponents, isPreviewMode, formValues]);
6157
+ }, [localFormComponents, isPreviewMode, formValues]);
6139
6158
  // Handle form submission
6140
6159
  const handleSubmit = useCallback((status = 'Submitted') => {
6141
6160
  setFormSubmitted(true);
6142
6161
  if (!validateAllFields()) {
6143
6162
  // Focus on the first invalid field
6144
- const firstErrorField = formComponents.find(comp => {
6163
+ const firstErrorField = localFormComponents.find(comp => {
6145
6164
  const currentValue = formValues[comp.id] || '';
6146
6165
  // Check if field has a value
6147
6166
  let hasValue = false;
@@ -6223,13 +6242,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6223
6242
  updatedComponent.children = updateComponentValues(updatedComponent.children);
6224
6243
  }
6225
6244
  if (updatedComponent.name === 'table' && updatedComponent.cells) {
6226
- updatedComponent.cells = updatedComponent.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
6245
+ updatedComponent.cells = updatedComponent.cells.map((row) => normalizeTableRow(row).map((cell) => {
6227
6246
  const updatedCell = { ...cell };
6228
6247
  if (updatedCell.components) {
6229
6248
  updatedCell.components = updateComponentValues(updatedCell.components);
6230
6249
  }
6231
6250
  return updatedCell;
6232
- }) : row);
6251
+ }));
6233
6252
  }
6234
6253
  if (updatedComponent.name === 'datagrid' && updatedComponent.entries) {
6235
6254
  updatedComponent.entries = updatedComponent.entries.map((entry) => {
@@ -6244,12 +6263,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6244
6263
  });
6245
6264
  };
6246
6265
  // Prepare final form data
6247
- const finalFormData = updateComponentValues(formComponents);
6266
+ const finalFormData = updateComponentValues(localFormComponents);
6248
6267
  // Also prepare a clean key-value payload
6249
6268
  const payloadValues = { ...formValues, status };
6250
6269
  // Pass both the updated component tree and the flat values object
6251
6270
  onSubmit?.(finalFormData, payloadValues);
6252
- }, [formComponents, formValues, validateAllFields, onSubmit, componentNotes, componentAttachments]);
6271
+ }, [localFormComponents, formValues, validateAllFields, onSubmit, componentNotes, componentAttachments]);
6253
6272
  // Get preview classes
6254
6273
  const getPreviewClasses = useCallback(() => {
6255
6274
  return {
@@ -6311,7 +6330,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6311
6330
  // Debug: Log if formValue is being shared incorrectly
6312
6331
  if (formValue !== undefined) {
6313
6332
  // Check if this value is being used by multiple components
6314
- const componentsWithSameValue = formComponents.filter(comp => comp.id !== componentId && formValues[comp.id] === formValue);
6333
+ const componentsWithSameValue = localFormComponents.filter(comp => comp.id !== componentId && formValues[comp.id] === formValue);
6315
6334
  if (componentsWithSameValue.length > 0) {
6316
6335
  console.warn(`[DfFormPreview] Component ${componentId} shares form value with other components:`, componentsWithSameValue.map(c => c.id));
6317
6336
  }
@@ -6410,9 +6429,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6410
6429
  return renderFormComponent(field);
6411
6430
  }, onNotesChange: (componentId, notes) => {
6412
6431
  // Handle notes change for table cell components
6413
- const updatedComponents = formComponents.map(comp => {
6432
+ const updatedComponents = localFormComponents.map(comp => {
6414
6433
  if (comp.id === component.id && comp.cells) {
6415
- const updatedCells = comp.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
6434
+ const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
6416
6435
  if (cell.components) {
6417
6436
  const updatedCellComponents = cell.components.map((cellComp) => {
6418
6437
  if (cellComp.id === componentId) {
@@ -6429,7 +6448,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6429
6448
  return { ...cell, components: updatedCellComponents };
6430
6449
  }
6431
6450
  return cell;
6432
- }) : row);
6451
+ }));
6433
6452
  return { ...comp, cells: updatedCells };
6434
6453
  }
6435
6454
  return comp;
@@ -6437,9 +6456,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6437
6456
  onFormDataChange?.(updatedComponents);
6438
6457
  }, onAttachmentChange: (componentId, attachments) => {
6439
6458
  // Handle attachment change for table cell components
6440
- const updatedComponents = formComponents.map(comp => {
6459
+ const updatedComponents = localFormComponents.map(comp => {
6441
6460
  if (comp.id === component.id && comp.cells) {
6442
- const updatedCells = comp.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
6461
+ const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
6443
6462
  if (cell.components) {
6444
6463
  const updatedCellComponents = cell.components.map((cellComp) => {
6445
6464
  if (cellComp.id === componentId) {
@@ -6456,7 +6475,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6456
6475
  return { ...cell, components: updatedCellComponents };
6457
6476
  }
6458
6477
  return cell;
6459
- }) : row);
6478
+ }));
6460
6479
  return { ...comp, cells: updatedCells };
6461
6480
  }
6462
6481
  return comp;
@@ -6467,7 +6486,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6467
6486
  return (jsx(DfFormDataGrid, { ...commonProps, properties: component, formData: formValues, formTemplateId: formTemplateId, mode: commonProps.mode, onThresholdActionCompletion: handleThresholdActionCompletion, onThresholdIssueRaised: handleThresholdIssueRaised, onNotesChange: (componentId, notes) => {
6468
6487
  handleComponentNotesChange(componentId, notes);
6469
6488
  // Handle notes change for datagrid entry components
6470
- const updatedComponents = formComponents.map(comp => {
6489
+ const updatedComponents = localFormComponents.map(comp => {
6471
6490
  if (comp.id === component.id && comp.entries) {
6472
6491
  const updatedEntries = comp.entries.map((entry) => {
6473
6492
  if (entry.components) {
@@ -6495,7 +6514,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6495
6514
  }, onAttachmentChange: (componentId, attachments) => {
6496
6515
  handleComponentAttachmentChange(componentId, attachments);
6497
6516
  // Handle attachment change for datagrid entry components
6498
- const updatedComponents = formComponents.map(comp => {
6517
+ const updatedComponents = localFormComponents.map(comp => {
6499
6518
  if (comp.id === component.id && comp.entries) {
6500
6519
  const updatedEntries = comp.entries.map((entry) => {
6501
6520
  if (entry.components) {
@@ -6523,8 +6542,8 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6523
6542
  }, onValueChange: (change) => {
6524
6543
  // Handle datagrid value changes (entries updates)
6525
6544
  if (change.id === component.id && change.value && typeof change.value === 'object' && 'entries' in change.value) {
6526
- // Update formComponents with new entries structure
6527
- const updatedComponents = formComponents.map(comp => {
6545
+ // Update localFormComponents with new entries structure
6546
+ const updatedComponents = localFormComponents.map(comp => {
6528
6547
  if (comp.id === component.id) {
6529
6548
  return {
6530
6549
  ...comp,
@@ -6562,12 +6581,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6562
6581
  }
6563
6582
  }, onEntryAdd: () => {
6564
6583
  // CRITICAL: Entry has already been added via onValueChange in DfFormDataGrid
6565
- // Get the updated component from formComponents (which should have been updated by onValueChange)
6566
- const currentComponent = formComponents.find(comp => comp.id === component.id);
6584
+ // Get the updated component from localFormComponents (which should have been updated by onValueChange)
6585
+ const currentComponent = localFormComponents.find(comp => comp.id === component.id);
6567
6586
  if (currentComponent && currentComponent.entries) {
6568
6587
  // Entry should already be in the component via onValueChange
6569
- // Just ensure formComponents is in sync (no-op if already synced)
6570
- const updatedComponents = formComponents.map(comp => {
6588
+ // Just ensure localFormComponents is in sync (no-op if already synced)
6589
+ const updatedComponents = localFormComponents.map(comp => {
6571
6590
  if (comp.id === component.id) {
6572
6591
  // Ensure entries are properly structured
6573
6592
  return {
@@ -6584,7 +6603,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6584
6603
  setTimeout(() => {
6585
6604
  const datagridValue = formValues[component.id];
6586
6605
  if (datagridValue && typeof datagridValue === 'object' && 'entries' in datagridValue) {
6587
- const updatedComponents = formComponents.map(comp => {
6606
+ const updatedComponents = localFormComponents.map(comp => {
6588
6607
  if (comp.id === component.id) {
6589
6608
  return {
6590
6609
  ...comp,
@@ -6599,7 +6618,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6599
6618
  }
6600
6619
  }, onEntryRemove: (entryIndex) => {
6601
6620
  // Handle entry remove - update form components
6602
- const updatedComponents = formComponents.map(comp => {
6621
+ const updatedComponents = localFormComponents.map(comp => {
6603
6622
  if (comp.id === component.id && comp.entries) {
6604
6623
  const currentEntries = comp.entries || [];
6605
6624
  const updatedEntries = currentEntries
@@ -6641,7 +6660,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6641
6660
  return (jsx("div", { className: "form-group", children: jsxs("div", { className: "form-group-label", children: ["Unsupported Component: ", component.name] }) }));
6642
6661
  }
6643
6662
  };
6644
- return (jsx("div", { className: "form-preview-container", children: jsx("div", { className: "form-preview-wrapper", children: jsxs("div", { className: `form-preview ${Object.entries(getPreviewClasses()).map(([key, value]) => value ? key : '').join(' ')}`, children: [jsx("div", { className: "form-canvas-header" }), formComponents.length === 0 ? (jsx("div", { className: "empty-state", children: jsx("div", { className: "empty-state-card", children: jsx("div", { className: "empty-state-preview-area", children: jsx("span", { className: "empty-state-placeholder", children: "Add components to see the form preview" }) }) }) })) : (jsxs("form", { className: "form-preview-form", onSubmit: (e) => { e.preventDefault(); handleSubmit(); }, children: [(formTitle || formDescription) && (jsxs("div", { className: "form-header", children: [formTitle && (jsx("h1", { className: "form-title", children: formTitle })), formDescription && (jsx("p", { className: "form-description", children: formDescription }))] })), formComponents.map((component) => {
6663
+ return (jsx("div", { className: "form-preview-container", children: jsx("div", { className: "form-preview-wrapper", children: jsxs("div", { className: `form-preview ${Object.entries(getPreviewClasses()).map(([key, value]) => value ? key : '').join(' ')}`, children: [jsx("div", { className: "form-canvas-header" }), localFormComponents.length === 0 ? (jsx("div", { className: "empty-state", children: jsx("div", { className: "empty-state-card", children: jsx("div", { className: "empty-state-preview-area", children: jsx("span", { className: "empty-state-placeholder", children: "Add components to see the form preview" }) }) }) })) : (jsxs("form", { className: "form-preview-form", onSubmit: (e) => { e.preventDefault(); handleSubmit(); }, children: [(formTitle || formDescription) && (jsxs("div", { className: "form-header", children: [formTitle && (jsx("h1", { className: "form-title", children: formTitle })), formDescription && (jsx("p", { className: "form-description", children: formDescription }))] })), localFormComponents.map((component) => {
6645
6664
  const basic = component.basic;
6646
6665
  const formValue = formValues[component.id];
6647
6666
  const isOptionBased = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');
@@ -6693,7 +6712,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6693
6712
  // Update local state immediately
6694
6713
  setComponentNotes(prev => ({ ...prev, [component.id]: notes }));
6695
6714
  // Handle notes change for regular components - update component.basic.notes
6696
- const updatedComponents = formComponents.map(comp => {
6715
+ const updatedComponents = localFormComponents.map(comp => {
6697
6716
  if (comp.id === component.id) {
6698
6717
  return {
6699
6718
  ...comp,
@@ -6710,7 +6729,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6710
6729
  // Update local state immediately
6711
6730
  setComponentAttachments(prev => ({ ...prev, [component.id]: attachments || [] }));
6712
6731
  // Handle attachment change for regular components - update component.basic.attachments
6713
- const updatedComponents = formComponents.map(comp => {
6732
+ const updatedComponents = localFormComponents.map(comp => {
6714
6733
  if (comp.id === component.id) {
6715
6734
  return {
6716
6735
  ...comp,
@@ -6762,6 +6781,26 @@ const DfFormComments = ({ comment = '', onSave, placeholder = 'Enter your reason
6762
6781
  return (jsxs("div", { className: `df-form-comments ${className}`, children: [jsxs("div", { className: "df-form-comments__header", children: [jsx("h3", { className: "df-form-comments__title", children: "Comments" }), jsx("button", { className: "df-form-comments__toggle", type: "button", onClick: toggleComments, "aria-expanded": isExpanded, "aria-label": "Toggle comments section", disabled: disabled, children: isExpanded ? (jsx("span", { className: "df-form-comments__toggle-icon", children: "\u25BC" })) : (jsx("span", { className: "df-form-comments__toggle-icon", children: "\u25B6" })) })] }), jsx("div", { className: `df-form-comments__content ${isExpanded ? 'df-form-comments__content--expanded' : ''}`, children: jsx("div", { className: "df-form-comments__input-container", children: jsx("div", { className: "df-form-comments__input-line", children: jsx("input", { type: "text", id: "comment-input", className: "df-form-comments__input", value: currentComment, onChange: handleInputChange, onBlur: handleInputBlur, onFocus: handleInputFocus, placeholder: placeholder, disabled: disabled }) }) }) })] }));
6763
6782
  };
6764
6783
 
6784
+ // Normalize a row from the API format (object with numeric keys) into a proper TableCell array.
6785
+ // The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
6786
+ const normalizeRow = (row) => {
6787
+ if (Array.isArray(row))
6788
+ return row;
6789
+ if (row && typeof row === 'object') {
6790
+ // Convert object with numeric keys to array, sorted by key
6791
+ const keys = Object.keys(row).filter(k => !isNaN(Number(k))).sort((a, b) => Number(a) - Number(b));
6792
+ if (keys.length > 0) {
6793
+ return keys.map(k => row[k]);
6794
+ }
6795
+ }
6796
+ return [];
6797
+ };
6798
+ // Normalize the entire cells structure from API format to TableCell[][]
6799
+ const normalizeCells = (cells) => {
6800
+ if (!cells || !Array.isArray(cells))
6801
+ return [];
6802
+ return cells.map(normalizeRow);
6803
+ };
6765
6804
  // Function to ensure table cell components have proper IDs
6766
6805
  const ensureComponentHasId = (component) => {
6767
6806
  if (!component.id) {
@@ -6846,19 +6885,22 @@ const TableCellComponent = ({ cell, mode, onComponentSelect, onComponentDelete,
6846
6885
  };
6847
6886
  const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationErrors = {}, touchedFields = {}, formSubmitted = false, onValueChange, onSelect, isSelected = false, className = '', onTableSelect, onComponentSelect, onComponentDelete, onComponentEdit, selectedComponent, renderFormComponent, formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChange, onAttachmentChange, workOrderNumber, assetNumber, user, onCreateIssue, onUpdateIssue }) => {
6848
6887
  const [isCollapsed, setIsCollapsed] = useState(false); // Always start expanded to show drop zones
6888
+ // CRITICAL: Normalize cells from API format (object with numeric keys) to proper 2D array
6889
+ // The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...]
6890
+ const normalizedCells = useMemo(() => normalizeCells(properties.cells), [properties.cells]);
6849
6891
  // Check if table has any components in any cells
6850
- const hasAnyComponents = properties.cells?.some((row) => Array.isArray(row) && row.some((cell) => cell.components && cell.components.length > 0)) || false;
6892
+ const hasAnyComponents = normalizedCells.some((row) => row.some((cell) => cell.components && cell.components.length > 0)) || false;
6851
6893
  // Initialize and update table cells when rows/columns change
6852
6894
  // Only trigger when cells are truly missing or structure doesn't match rows/columns
6853
6895
  useEffect(() => {
6854
6896
  // Get rows and columns from table properties (where they're actually stored)
6855
6897
  const currentRows = Number(properties.table?.rows || properties.basic?.rows || 3);
6856
6898
  const currentColumns = Number(properties.table?.columns || properties.basic?.columns || 3);
6857
- const currentCells = properties.cells || [];
6899
+ const currentCells = normalizedCells;
6858
6900
  // Check if we need to update the table structure
6859
6901
  const needsUpdate = currentCells.length === 0 ||
6860
6902
  currentCells.length !== currentRows ||
6861
- (currentCells.length > 0 && Array.isArray(currentCells[0]) && currentCells[0].length !== currentColumns);
6903
+ (currentCells.length > 0 && currentCells[0].length !== currentColumns);
6862
6904
  if (needsUpdate) {
6863
6905
  const newCells = [];
6864
6906
  for (let row = 0; row < currentRows; row++) {
@@ -6867,7 +6909,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6867
6909
  const cellId = `cell-${row}-${col}`;
6868
6910
  // Try to preserve existing components if the cell exists
6869
6911
  let existingComponents = [];
6870
- if (Array.isArray(currentCells[row]) && currentCells[row][col]) {
6912
+ if (currentCells[row] && currentCells[row][col]) {
6871
6913
  existingComponents = (currentCells[row][col].components || []).map(ensureComponentHasId);
6872
6914
  }
6873
6915
  rowCells.push({
@@ -6885,7 +6927,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6885
6927
  value: { ...properties, cells: newCells }
6886
6928
  });
6887
6929
  }
6888
- }, [properties.table?.rows, properties.table?.columns, properties.basic?.rows, properties.basic?.columns, properties.cells?.length, id, onValueChange]);
6930
+ }, [properties.table?.rows, properties.table?.columns, properties.basic?.rows, properties.basic?.columns, normalizedCells, id, onValueChange]);
6889
6931
  const handleTableClick = useCallback((event) => {
6890
6932
  event.stopPropagation();
6891
6933
  onSelect?.();
@@ -6902,7 +6944,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6902
6944
  const handleComponentDelete = useCallback((component, event) => {
6903
6945
  event.stopPropagation();
6904
6946
  // Find and remove the component from the table cell
6905
- const updatedCells = properties.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
6947
+ const updatedCells = normalizedCells.map((row) => row.map((cell) => {
6906
6948
  if (cell.components && cell.components.some((comp) => comp.id === component.id)) {
6907
6949
  const filteredComponents = cell.components.filter((comp) => comp.id !== component.id);
6908
6950
  return {
@@ -6911,7 +6953,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6911
6953
  };
6912
6954
  }
6913
6955
  return cell;
6914
- }) : row);
6956
+ }));
6915
6957
  // Update the table with the modified cells
6916
6958
  if (onValueChange) {
6917
6959
  onValueChange({
@@ -6921,13 +6963,13 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6921
6963
  }
6922
6964
  // Don't call parent delete handler for table cell components
6923
6965
  // The parent delete handler is for deleting entire fields, not components within table cells
6924
- }, [onComponentDelete, properties, onValueChange, id]);
6966
+ }, [onComponentDelete, normalizedCells, properties, onValueChange, id]);
6925
6967
  // CRITICAL FIX: Ensure all table cell components have proper IDs with table and cell position
6926
6968
  // Use useMemo to prevent ID regeneration on every render
6927
6969
  const cellsWithIds = useMemo(() => {
6928
- if (!properties.cells)
6970
+ if (normalizedCells.length === 0)
6929
6971
  return [];
6930
- return properties.cells.map((row, rowIndex) => Array.isArray(row) ? row.map((cell, cellIndex) => ({
6972
+ return normalizedCells.map((row, rowIndex) => row.map((cell, cellIndex) => ({
6931
6973
  ...cell,
6932
6974
  components: (cell.components && Array.isArray(cell.components))
6933
6975
  ? cell.components.map((comp, compIndex) => {
@@ -6946,8 +6988,8 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6946
6988
  };
6947
6989
  })
6948
6990
  : []
6949
- })) : []);
6950
- }, [properties.cells, id]); // Only recalculate if cells or table ID changes
6991
+ })));
6992
+ }, [normalizedCells, id]); // Only recalculate if cells or table ID changes
6951
6993
  // CRITICAL FIX: Update the parent component with the cells that have proper IDs
6952
6994
  // Skip this in package to prevent flickering - cells are managed by parent
6953
6995
  // useEffect(() => {