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.js CHANGED
@@ -5303,9 +5303,27 @@ const DfFormSection = ({ id, properties, mode = 'edit', formData = {}, onValueCh
5303
5303
 
5304
5304
  // Dynamic imports to avoid circular dependencies
5305
5305
  const DfFormTable$1 = React.lazy(() => Promise.resolve().then(function () { return dfFormTable; }));
5306
+ // Normalize a table row from API format (object with numeric keys) into a proper array.
5307
+ // The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
5308
+ const normalizeTableRow = (row) => {
5309
+ if (Array.isArray(row))
5310
+ return row;
5311
+ if (row && typeof row === 'object') {
5312
+ const keys = Object.keys(row).filter(k => !isNaN(Number(k))).sort((a, b) => Number(a) - Number(b));
5313
+ if (keys.length > 0)
5314
+ return keys.map(k => row[k]);
5315
+ }
5316
+ return [];
5317
+ };
5306
5318
  const DfFormPreview = ({ formComponents = [], currentDevice = 'desktop', isPreviewMode = false, initialFormData = [], onSubmit, onFormDataChange, formTitle, formDescription, formTemplateId,
5307
5319
  // Add component management props for edit mode
5308
5320
  onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, selectedComponent, workOrderNumber, assetNumber, isStandalone, user, onCreateIssue, onUpdateIssue }) => {
5321
+ // Local copy of formComponents so structure updates (e.g. table cell init) are reflected immediately
5322
+ const [localFormComponents, setLocalFormComponents] = React.useState(formComponents);
5323
+ // Sync local state when the prop changes from the parent
5324
+ React.useEffect(() => {
5325
+ setLocalFormComponents(formComponents);
5326
+ }, [formComponents]);
5309
5327
  // Form state
5310
5328
  const [formValues, setFormValues] = React.useState({});
5311
5329
  const [validationErrors, setValidationErrors] = React.useState({});
@@ -5326,7 +5344,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5326
5344
  // Initialize form state
5327
5345
  React.useEffect(() => {
5328
5346
  initializeFormState();
5329
- }, [formComponents, initialFormData]);
5347
+ }, [localFormComponents, initialFormData]);
5330
5348
  // Recursive function to initialize values from nested components
5331
5349
  const initializeComponentValues = (components, values) => {
5332
5350
  components.forEach(component => {
@@ -5355,13 +5373,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5355
5373
  // Handle nested components in table cells
5356
5374
  if (component.cells && Array.isArray(component.cells)) {
5357
5375
  component.cells.forEach((row, _rowIndex) => {
5358
- if (Array.isArray(row)) {
5359
- row.forEach((cell, _cellIndex) => {
5360
- if (cell && cell.components && Array.isArray(cell.components)) {
5361
- initializeComponentValues(cell.components, values);
5362
- }
5363
- });
5364
- }
5376
+ normalizeTableRow(row).forEach((cell, _cellIndex) => {
5377
+ if (cell && cell.components && Array.isArray(cell.components)) {
5378
+ initializeComponentValues(cell.components, values);
5379
+ }
5380
+ });
5365
5381
  });
5366
5382
  }
5367
5383
  // Handle nested components in datagrid entries
@@ -5424,11 +5440,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5424
5440
  extractNotesAndAttachments(comp.children);
5425
5441
  if (comp.cells && Array.isArray(comp.cells))
5426
5442
  comp.cells.forEach((row) => {
5427
- if (Array.isArray(row))
5428
- row.forEach((cell) => {
5429
- if (cell && cell.components)
5430
- extractNotesAndAttachments(cell.components);
5431
- });
5443
+ normalizeTableRow(row).forEach((cell) => {
5444
+ if (cell && cell.components)
5445
+ extractNotesAndAttachments(cell.components);
5446
+ });
5432
5447
  });
5433
5448
  if (comp.entries)
5434
5449
  comp.entries.forEach((entry) => {
@@ -5467,8 +5482,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5467
5482
  }
5468
5483
  if (validatedComponent.cells && Array.isArray(validatedComponent.cells)) {
5469
5484
  validatedComponent.cells = validatedComponent.cells.map((row) => {
5470
- if (Array.isArray(row)) {
5471
- return row.map((cell) => {
5485
+ const normalizedRow = normalizeTableRow(row);
5486
+ if (normalizedRow.length > 0) {
5487
+ return normalizedRow.map((cell) => {
5472
5488
  if (cell && cell.components && Array.isArray(cell.components)) {
5473
5489
  return {
5474
5490
  ...cell,
@@ -5496,11 +5512,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5496
5512
  });
5497
5513
  };
5498
5514
  // Initialize validated components
5499
- let validatedFormComponents = formComponents;
5500
- if (formComponents && formComponents.length > 0) {
5501
- validatedFormComponents = getValidatedComponents(formComponents);
5515
+ let validatedFormComponents = localFormComponents;
5516
+ if (localFormComponents && localFormComponents.length > 0) {
5517
+ validatedFormComponents = getValidatedComponents(localFormComponents);
5502
5518
  // Notifying parent of changed components if they were mutated (IDs added/fixed)
5503
- if (JSON.stringify(validatedFormComponents) !== JSON.stringify(formComponents)) {
5519
+ if (JSON.stringify(validatedFormComponents) !== JSON.stringify(localFormComponents)) {
5504
5520
  onFormDataChange?.(validatedFormComponents);
5505
5521
  }
5506
5522
  }
@@ -5528,7 +5544,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5528
5544
  setComponentAttachments(prev => ({ ...initialAttachments, ...prev }));
5529
5545
  // Conditional logic evaluation disabled temporarily to fix table issues
5530
5546
  // evaluateConditionalLogic()
5531
- }, [initialFormData, formComponents]);
5547
+ }, [initialFormData, localFormComponents]);
5532
5548
  // Conditional logic disabled temporarily - all components are always visible
5533
5549
  const shouldShowComponent = React.useCallback((_componentId) => {
5534
5550
  return true;
@@ -5541,7 +5557,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5541
5557
  return;
5542
5558
  }
5543
5559
  // CRITICAL: Check if multiple components share this ID (ID collision detection)
5544
- const componentsWithSameId = formComponents.filter(comp => comp.id === change.id);
5560
+ const componentsWithSameId = localFormComponents.filter(comp => comp.id === change.id);
5545
5561
  if (componentsWithSameId.length > 1) {
5546
5562
  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 })));
5547
5563
  // Don't update - this would cause all components with this ID to get the same value
@@ -5562,7 +5578,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5562
5578
  }
5563
5579
  // Clear raised issues for this component when value changes
5564
5580
  // This ensures that if threshold condition changes, user must raise issue again
5565
- const component = formComponents.find(comp => comp.id === change.id);
5581
+ const component = localFormComponents.find(comp => comp.id === change.id);
5566
5582
  if (component) {
5567
5583
  const threshold = component?.threshold;
5568
5584
  if (threshold && threshold.conditions && threshold.conditions.length > 0) {
@@ -5615,13 +5631,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5615
5631
  if (component.name === 'table' && component.cells) {
5616
5632
  return {
5617
5633
  ...component,
5618
- cells: component.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
5634
+ cells: component.cells.map((row) => normalizeTableRow(row).map((cell) => {
5619
5635
  const updatedCell = { ...cell };
5620
5636
  if (updatedCell.components) {
5621
5637
  updatedCell.components = updateComponentValue(updatedCell.components);
5622
5638
  }
5623
5639
  return updatedCell;
5624
- }) : row)
5640
+ }))
5625
5641
  };
5626
5642
  }
5627
5643
  if (component.name === 'datagrid' && component.entries) {
@@ -5640,7 +5656,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5640
5656
  });
5641
5657
  };
5642
5658
  // Update form components
5643
- const updatedComponents = updateComponentValue(formComponents);
5659
+ const updatedComponents = updateComponentValue(localFormComponents);
5660
+ // CRITICAL: Update local state immediately so structure changes (e.g. table cell init)
5661
+ // are reflected without waiting for Angular parent round-trip
5662
+ setLocalFormComponents(updatedComponents);
5644
5663
  onFormDataChange?.(updatedComponents);
5645
5664
  // Clear validation errors when user starts typing and re-validate
5646
5665
  if (validationErrors[change.id]) {
@@ -5677,7 +5696,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5677
5696
  }
5678
5697
  // Conditional logic evaluation disabled temporarily
5679
5698
  // evaluateConditionalLogic(newFormValues, updatedComponents)
5680
- }, [formComponents, formValues, validationErrors, onFormDataChange]);
5699
+ }, [localFormComponents, formValues, validationErrors, onFormDataChange]);
5681
5700
  // Recursive function to find a component by ID in nested structures
5682
5701
  const findComponentById = React.useCallback((components, fieldId) => {
5683
5702
  for (const comp of components) {
@@ -5721,7 +5740,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5721
5740
  if (isPreviewMode)
5722
5741
  return;
5723
5742
  // Find component recursively (handles nested components)
5724
- const component = findComponentById(formComponents, fieldId);
5743
+ const component = findComponentById(localFormComponents, fieldId);
5725
5744
  if (!component)
5726
5745
  return;
5727
5746
  // Get current value from form values (real-time input)
@@ -5816,7 +5835,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5816
5835
  ...prev,
5817
5836
  [fieldId]: errorMessage
5818
5837
  }));
5819
- }, [formComponents, isPreviewMode, formValues, findComponentById]);
5838
+ }, [localFormComponents, isPreviewMode, formValues, findComponentById]);
5820
5839
  // Handle form control blur
5821
5840
  const onFormControlBlur = React.useCallback((fieldId) => {
5822
5841
  setTouchedFields(prev => ({
@@ -5846,11 +5865,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5846
5865
  // useEffect(() => {
5847
5866
  // if (!isPreviewMode && Object.keys(formValues).length > 0) {
5848
5867
  // // Validate all form components when form values change (but not on initial load)
5849
- // formComponents.forEach(component => {
5868
+ // localFormComponents.forEach(component => {
5850
5869
  // validateField(component.id)
5851
5870
  // })
5852
5871
  // }
5853
- // }, [formValues, validateField, isPreviewMode, formComponents])
5872
+ // }, [formValues, validateField, isPreviewMode, localFormComponents])
5854
5873
  // Enhanced form validity check
5855
5874
  const isFormValid = React.useCallback(() => {
5856
5875
  // Check if there are any validation errors
@@ -5859,7 +5878,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5859
5878
  return false;
5860
5879
  }
5861
5880
  // Check required fields
5862
- return formComponents.every(component => {
5881
+ return localFormComponents.every(component => {
5863
5882
  // Use real-time form values instead of component values
5864
5883
  const currentValue = formValues[component.id] || '';
5865
5884
  // Check if field has a value
@@ -5905,7 +5924,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5905
5924
  }
5906
5925
  return true;
5907
5926
  });
5908
- }, [formComponents, formValues, validationErrors]);
5927
+ }, [localFormComponents, formValues, validationErrors]);
5909
5928
  // Evaluate threshold condition (handles both numeric and string values)
5910
5929
  const evaluateThresholdCondition = React.useCallback((condition, currentVal) => {
5911
5930
  // Handle array values (for checkbox)
@@ -5959,7 +5978,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5959
5978
  if (isPreviewMode)
5960
5979
  return [];
5961
5980
  const metConditions = [];
5962
- formComponents.forEach(component => {
5981
+ localFormComponents.forEach(component => {
5963
5982
  const condition = component?.condition;
5964
5983
  if (!condition || !condition.conditions || condition.conditions.length === 0) {
5965
5984
  return;
@@ -5985,7 +6004,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5985
6004
  });
5986
6005
  });
5987
6006
  return metConditions;
5988
- }, [formComponents, formValues, isPreviewMode, evaluateThresholdCondition]);
6007
+ }, [localFormComponents, formValues, isPreviewMode, evaluateThresholdCondition]);
5989
6008
  // Validate threshold conditions - check if all met conditions have all mandatory actions completed
5990
6009
  const validateThresholdConditions = React.useCallback(() => {
5991
6010
  if (isPreviewMode)
@@ -6070,7 +6089,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6070
6089
  let isValid = true;
6071
6090
  setFormSubmitted(true);
6072
6091
  const errors = {};
6073
- formComponents.forEach(component => {
6092
+ localFormComponents.forEach(component => {
6074
6093
  // Use real-time form values instead of component values
6075
6094
  const currentValue = formValues[component.id] || '';
6076
6095
  // Check if field has a value
@@ -6137,13 +6156,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6137
6156
  });
6138
6157
  setValidationErrors(errors);
6139
6158
  return isValid;
6140
- }, [formComponents, isPreviewMode, formValues]);
6159
+ }, [localFormComponents, isPreviewMode, formValues]);
6141
6160
  // Handle form submission
6142
6161
  const handleSubmit = React.useCallback((status = 'Submitted') => {
6143
6162
  setFormSubmitted(true);
6144
6163
  if (!validateAllFields()) {
6145
6164
  // Focus on the first invalid field
6146
- const firstErrorField = formComponents.find(comp => {
6165
+ const firstErrorField = localFormComponents.find(comp => {
6147
6166
  const currentValue = formValues[comp.id] || '';
6148
6167
  // Check if field has a value
6149
6168
  let hasValue = false;
@@ -6225,13 +6244,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6225
6244
  updatedComponent.children = updateComponentValues(updatedComponent.children);
6226
6245
  }
6227
6246
  if (updatedComponent.name === 'table' && updatedComponent.cells) {
6228
- updatedComponent.cells = updatedComponent.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
6247
+ updatedComponent.cells = updatedComponent.cells.map((row) => normalizeTableRow(row).map((cell) => {
6229
6248
  const updatedCell = { ...cell };
6230
6249
  if (updatedCell.components) {
6231
6250
  updatedCell.components = updateComponentValues(updatedCell.components);
6232
6251
  }
6233
6252
  return updatedCell;
6234
- }) : row);
6253
+ }));
6235
6254
  }
6236
6255
  if (updatedComponent.name === 'datagrid' && updatedComponent.entries) {
6237
6256
  updatedComponent.entries = updatedComponent.entries.map((entry) => {
@@ -6246,12 +6265,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6246
6265
  });
6247
6266
  };
6248
6267
  // Prepare final form data
6249
- const finalFormData = updateComponentValues(formComponents);
6268
+ const finalFormData = updateComponentValues(localFormComponents);
6250
6269
  // Also prepare a clean key-value payload
6251
6270
  const payloadValues = { ...formValues, status };
6252
6271
  // Pass both the updated component tree and the flat values object
6253
6272
  onSubmit?.(finalFormData, payloadValues);
6254
- }, [formComponents, formValues, validateAllFields, onSubmit, componentNotes, componentAttachments]);
6273
+ }, [localFormComponents, formValues, validateAllFields, onSubmit, componentNotes, componentAttachments]);
6255
6274
  // Get preview classes
6256
6275
  const getPreviewClasses = React.useCallback(() => {
6257
6276
  return {
@@ -6313,7 +6332,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6313
6332
  // Debug: Log if formValue is being shared incorrectly
6314
6333
  if (formValue !== undefined) {
6315
6334
  // Check if this value is being used by multiple components
6316
- const componentsWithSameValue = formComponents.filter(comp => comp.id !== componentId && formValues[comp.id] === formValue);
6335
+ const componentsWithSameValue = localFormComponents.filter(comp => comp.id !== componentId && formValues[comp.id] === formValue);
6317
6336
  if (componentsWithSameValue.length > 0) {
6318
6337
  console.warn(`[DfFormPreview] Component ${componentId} shares form value with other components:`, componentsWithSameValue.map(c => c.id));
6319
6338
  }
@@ -6412,9 +6431,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6412
6431
  return renderFormComponent(field);
6413
6432
  }, onNotesChange: (componentId, notes) => {
6414
6433
  // Handle notes change for table cell components
6415
- const updatedComponents = formComponents.map(comp => {
6434
+ const updatedComponents = localFormComponents.map(comp => {
6416
6435
  if (comp.id === component.id && comp.cells) {
6417
- const updatedCells = comp.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
6436
+ const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
6418
6437
  if (cell.components) {
6419
6438
  const updatedCellComponents = cell.components.map((cellComp) => {
6420
6439
  if (cellComp.id === componentId) {
@@ -6431,7 +6450,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6431
6450
  return { ...cell, components: updatedCellComponents };
6432
6451
  }
6433
6452
  return cell;
6434
- }) : row);
6453
+ }));
6435
6454
  return { ...comp, cells: updatedCells };
6436
6455
  }
6437
6456
  return comp;
@@ -6439,9 +6458,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6439
6458
  onFormDataChange?.(updatedComponents);
6440
6459
  }, onAttachmentChange: (componentId, attachments) => {
6441
6460
  // Handle attachment change for table cell components
6442
- const updatedComponents = formComponents.map(comp => {
6461
+ const updatedComponents = localFormComponents.map(comp => {
6443
6462
  if (comp.id === component.id && comp.cells) {
6444
- const updatedCells = comp.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
6463
+ const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
6445
6464
  if (cell.components) {
6446
6465
  const updatedCellComponents = cell.components.map((cellComp) => {
6447
6466
  if (cellComp.id === componentId) {
@@ -6458,7 +6477,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6458
6477
  return { ...cell, components: updatedCellComponents };
6459
6478
  }
6460
6479
  return cell;
6461
- }) : row);
6480
+ }));
6462
6481
  return { ...comp, cells: updatedCells };
6463
6482
  }
6464
6483
  return comp;
@@ -6469,7 +6488,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6469
6488
  return (jsxRuntime.jsx(DfFormDataGrid, { ...commonProps, properties: component, formData: formValues, formTemplateId: formTemplateId, mode: commonProps.mode, onThresholdActionCompletion: handleThresholdActionCompletion, onThresholdIssueRaised: handleThresholdIssueRaised, onNotesChange: (componentId, notes) => {
6470
6489
  handleComponentNotesChange(componentId, notes);
6471
6490
  // Handle notes change for datagrid entry components
6472
- const updatedComponents = formComponents.map(comp => {
6491
+ const updatedComponents = localFormComponents.map(comp => {
6473
6492
  if (comp.id === component.id && comp.entries) {
6474
6493
  const updatedEntries = comp.entries.map((entry) => {
6475
6494
  if (entry.components) {
@@ -6497,7 +6516,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6497
6516
  }, onAttachmentChange: (componentId, attachments) => {
6498
6517
  handleComponentAttachmentChange(componentId, attachments);
6499
6518
  // Handle attachment change for datagrid entry components
6500
- const updatedComponents = formComponents.map(comp => {
6519
+ const updatedComponents = localFormComponents.map(comp => {
6501
6520
  if (comp.id === component.id && comp.entries) {
6502
6521
  const updatedEntries = comp.entries.map((entry) => {
6503
6522
  if (entry.components) {
@@ -6525,8 +6544,8 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6525
6544
  }, onValueChange: (change) => {
6526
6545
  // Handle datagrid value changes (entries updates)
6527
6546
  if (change.id === component.id && change.value && typeof change.value === 'object' && 'entries' in change.value) {
6528
- // Update formComponents with new entries structure
6529
- const updatedComponents = formComponents.map(comp => {
6547
+ // Update localFormComponents with new entries structure
6548
+ const updatedComponents = localFormComponents.map(comp => {
6530
6549
  if (comp.id === component.id) {
6531
6550
  return {
6532
6551
  ...comp,
@@ -6564,12 +6583,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6564
6583
  }
6565
6584
  }, onEntryAdd: () => {
6566
6585
  // CRITICAL: Entry has already been added via onValueChange in DfFormDataGrid
6567
- // Get the updated component from formComponents (which should have been updated by onValueChange)
6568
- const currentComponent = formComponents.find(comp => comp.id === component.id);
6586
+ // Get the updated component from localFormComponents (which should have been updated by onValueChange)
6587
+ const currentComponent = localFormComponents.find(comp => comp.id === component.id);
6569
6588
  if (currentComponent && currentComponent.entries) {
6570
6589
  // Entry should already be in the component via onValueChange
6571
- // Just ensure formComponents is in sync (no-op if already synced)
6572
- const updatedComponents = formComponents.map(comp => {
6590
+ // Just ensure localFormComponents is in sync (no-op if already synced)
6591
+ const updatedComponents = localFormComponents.map(comp => {
6573
6592
  if (comp.id === component.id) {
6574
6593
  // Ensure entries are properly structured
6575
6594
  return {
@@ -6586,7 +6605,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6586
6605
  setTimeout(() => {
6587
6606
  const datagridValue = formValues[component.id];
6588
6607
  if (datagridValue && typeof datagridValue === 'object' && 'entries' in datagridValue) {
6589
- const updatedComponents = formComponents.map(comp => {
6608
+ const updatedComponents = localFormComponents.map(comp => {
6590
6609
  if (comp.id === component.id) {
6591
6610
  return {
6592
6611
  ...comp,
@@ -6601,7 +6620,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6601
6620
  }
6602
6621
  }, onEntryRemove: (entryIndex) => {
6603
6622
  // Handle entry remove - update form components
6604
- const updatedComponents = formComponents.map(comp => {
6623
+ const updatedComponents = localFormComponents.map(comp => {
6605
6624
  if (comp.id === component.id && comp.entries) {
6606
6625
  const currentEntries = comp.entries || [];
6607
6626
  const updatedEntries = currentEntries
@@ -6643,7 +6662,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6643
6662
  return (jsxRuntime.jsx("div", { className: "form-group", children: jsxRuntime.jsxs("div", { className: "form-group-label", children: ["Unsupported Component: ", component.name] }) }));
6644
6663
  }
6645
6664
  };
6646
- return (jsxRuntime.jsx("div", { className: "form-preview-container", children: jsxRuntime.jsx("div", { className: "form-preview-wrapper", children: jsxRuntime.jsxs("div", { className: `form-preview ${Object.entries(getPreviewClasses()).map(([key, value]) => value ? key : '').join(' ')}`, children: [jsxRuntime.jsx("div", { className: "form-canvas-header" }), formComponents.length === 0 ? (jsxRuntime.jsx("div", { className: "empty-state", children: jsxRuntime.jsx("div", { className: "empty-state-card", children: jsxRuntime.jsx("div", { className: "empty-state-preview-area", children: jsxRuntime.jsx("span", { className: "empty-state-placeholder", children: "Add components to see the form preview" }) }) }) })) : (jsxRuntime.jsxs("form", { className: "form-preview-form", onSubmit: (e) => { e.preventDefault(); handleSubmit(); }, children: [(formTitle || formDescription) && (jsxRuntime.jsxs("div", { className: "form-header", children: [formTitle && (jsxRuntime.jsx("h1", { className: "form-title", children: formTitle })), formDescription && (jsxRuntime.jsx("p", { className: "form-description", children: formDescription }))] })), formComponents.map((component) => {
6665
+ return (jsxRuntime.jsx("div", { className: "form-preview-container", children: jsxRuntime.jsx("div", { className: "form-preview-wrapper", children: jsxRuntime.jsxs("div", { className: `form-preview ${Object.entries(getPreviewClasses()).map(([key, value]) => value ? key : '').join(' ')}`, children: [jsxRuntime.jsx("div", { className: "form-canvas-header" }), localFormComponents.length === 0 ? (jsxRuntime.jsx("div", { className: "empty-state", children: jsxRuntime.jsx("div", { className: "empty-state-card", children: jsxRuntime.jsx("div", { className: "empty-state-preview-area", children: jsxRuntime.jsx("span", { className: "empty-state-placeholder", children: "Add components to see the form preview" }) }) }) })) : (jsxRuntime.jsxs("form", { className: "form-preview-form", onSubmit: (e) => { e.preventDefault(); handleSubmit(); }, children: [(formTitle || formDescription) && (jsxRuntime.jsxs("div", { className: "form-header", children: [formTitle && (jsxRuntime.jsx("h1", { className: "form-title", children: formTitle })), formDescription && (jsxRuntime.jsx("p", { className: "form-description", children: formDescription }))] })), localFormComponents.map((component) => {
6647
6666
  const basic = component.basic;
6648
6667
  const formValue = formValues[component.id];
6649
6668
  const isOptionBased = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');
@@ -6695,7 +6714,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6695
6714
  // Update local state immediately
6696
6715
  setComponentNotes(prev => ({ ...prev, [component.id]: notes }));
6697
6716
  // Handle notes change for regular components - update component.basic.notes
6698
- const updatedComponents = formComponents.map(comp => {
6717
+ const updatedComponents = localFormComponents.map(comp => {
6699
6718
  if (comp.id === component.id) {
6700
6719
  return {
6701
6720
  ...comp,
@@ -6712,7 +6731,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6712
6731
  // Update local state immediately
6713
6732
  setComponentAttachments(prev => ({ ...prev, [component.id]: attachments || [] }));
6714
6733
  // Handle attachment change for regular components - update component.basic.attachments
6715
- const updatedComponents = formComponents.map(comp => {
6734
+ const updatedComponents = localFormComponents.map(comp => {
6716
6735
  if (comp.id === component.id) {
6717
6736
  return {
6718
6737
  ...comp,
@@ -6764,6 +6783,26 @@ const DfFormComments = ({ comment = '', onSave, placeholder = 'Enter your reason
6764
6783
  return (jsxRuntime.jsxs("div", { className: `df-form-comments ${className}`, children: [jsxRuntime.jsxs("div", { className: "df-form-comments__header", children: [jsxRuntime.jsx("h3", { className: "df-form-comments__title", children: "Comments" }), jsxRuntime.jsx("button", { className: "df-form-comments__toggle", type: "button", onClick: toggleComments, "aria-expanded": isExpanded, "aria-label": "Toggle comments section", disabled: disabled, children: isExpanded ? (jsxRuntime.jsx("span", { className: "df-form-comments__toggle-icon", children: "\u25BC" })) : (jsxRuntime.jsx("span", { className: "df-form-comments__toggle-icon", children: "\u25B6" })) })] }), jsxRuntime.jsx("div", { className: `df-form-comments__content ${isExpanded ? 'df-form-comments__content--expanded' : ''}`, children: jsxRuntime.jsx("div", { className: "df-form-comments__input-container", children: jsxRuntime.jsx("div", { className: "df-form-comments__input-line", children: jsxRuntime.jsx("input", { type: "text", id: "comment-input", className: "df-form-comments__input", value: currentComment, onChange: handleInputChange, onBlur: handleInputBlur, onFocus: handleInputFocus, placeholder: placeholder, disabled: disabled }) }) }) })] }));
6765
6784
  };
6766
6785
 
6786
+ // Normalize a row from the API format (object with numeric keys) into a proper TableCell array.
6787
+ // The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
6788
+ const normalizeRow = (row) => {
6789
+ if (Array.isArray(row))
6790
+ return row;
6791
+ if (row && typeof row === 'object') {
6792
+ // Convert object with numeric keys to array, sorted by key
6793
+ const keys = Object.keys(row).filter(k => !isNaN(Number(k))).sort((a, b) => Number(a) - Number(b));
6794
+ if (keys.length > 0) {
6795
+ return keys.map(k => row[k]);
6796
+ }
6797
+ }
6798
+ return [];
6799
+ };
6800
+ // Normalize the entire cells structure from API format to TableCell[][]
6801
+ const normalizeCells = (cells) => {
6802
+ if (!cells || !Array.isArray(cells))
6803
+ return [];
6804
+ return cells.map(normalizeRow);
6805
+ };
6767
6806
  // Function to ensure table cell components have proper IDs
6768
6807
  const ensureComponentHasId = (component) => {
6769
6808
  if (!component.id) {
@@ -6848,19 +6887,22 @@ const TableCellComponent = ({ cell, mode, onComponentSelect, onComponentDelete,
6848
6887
  };
6849
6888
  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 }) => {
6850
6889
  const [isCollapsed, setIsCollapsed] = React.useState(false); // Always start expanded to show drop zones
6890
+ // CRITICAL: Normalize cells from API format (object with numeric keys) to proper 2D array
6891
+ // The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...]
6892
+ const normalizedCells = React.useMemo(() => normalizeCells(properties.cells), [properties.cells]);
6851
6893
  // Check if table has any components in any cells
6852
- const hasAnyComponents = properties.cells?.some((row) => Array.isArray(row) && row.some((cell) => cell.components && cell.components.length > 0)) || false;
6894
+ const hasAnyComponents = normalizedCells.some((row) => row.some((cell) => cell.components && cell.components.length > 0)) || false;
6853
6895
  // Initialize and update table cells when rows/columns change
6854
6896
  // Only trigger when cells are truly missing or structure doesn't match rows/columns
6855
6897
  React.useEffect(() => {
6856
6898
  // Get rows and columns from table properties (where they're actually stored)
6857
6899
  const currentRows = Number(properties.table?.rows || properties.basic?.rows || 3);
6858
6900
  const currentColumns = Number(properties.table?.columns || properties.basic?.columns || 3);
6859
- const currentCells = properties.cells || [];
6901
+ const currentCells = normalizedCells;
6860
6902
  // Check if we need to update the table structure
6861
6903
  const needsUpdate = currentCells.length === 0 ||
6862
6904
  currentCells.length !== currentRows ||
6863
- (currentCells.length > 0 && Array.isArray(currentCells[0]) && currentCells[0].length !== currentColumns);
6905
+ (currentCells.length > 0 && currentCells[0].length !== currentColumns);
6864
6906
  if (needsUpdate) {
6865
6907
  const newCells = [];
6866
6908
  for (let row = 0; row < currentRows; row++) {
@@ -6869,7 +6911,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6869
6911
  const cellId = `cell-${row}-${col}`;
6870
6912
  // Try to preserve existing components if the cell exists
6871
6913
  let existingComponents = [];
6872
- if (Array.isArray(currentCells[row]) && currentCells[row][col]) {
6914
+ if (currentCells[row] && currentCells[row][col]) {
6873
6915
  existingComponents = (currentCells[row][col].components || []).map(ensureComponentHasId);
6874
6916
  }
6875
6917
  rowCells.push({
@@ -6887,7 +6929,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6887
6929
  value: { ...properties, cells: newCells }
6888
6930
  });
6889
6931
  }
6890
- }, [properties.table?.rows, properties.table?.columns, properties.basic?.rows, properties.basic?.columns, properties.cells?.length, id, onValueChange]);
6932
+ }, [properties.table?.rows, properties.table?.columns, properties.basic?.rows, properties.basic?.columns, normalizedCells, id, onValueChange]);
6891
6933
  const handleTableClick = React.useCallback((event) => {
6892
6934
  event.stopPropagation();
6893
6935
  onSelect?.();
@@ -6904,7 +6946,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6904
6946
  const handleComponentDelete = React.useCallback((component, event) => {
6905
6947
  event.stopPropagation();
6906
6948
  // Find and remove the component from the table cell
6907
- const updatedCells = properties.cells.map((row) => Array.isArray(row) ? row.map((cell) => {
6949
+ const updatedCells = normalizedCells.map((row) => row.map((cell) => {
6908
6950
  if (cell.components && cell.components.some((comp) => comp.id === component.id)) {
6909
6951
  const filteredComponents = cell.components.filter((comp) => comp.id !== component.id);
6910
6952
  return {
@@ -6913,7 +6955,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6913
6955
  };
6914
6956
  }
6915
6957
  return cell;
6916
- }) : row);
6958
+ }));
6917
6959
  // Update the table with the modified cells
6918
6960
  if (onValueChange) {
6919
6961
  onValueChange({
@@ -6923,13 +6965,13 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6923
6965
  }
6924
6966
  // Don't call parent delete handler for table cell components
6925
6967
  // The parent delete handler is for deleting entire fields, not components within table cells
6926
- }, [onComponentDelete, properties, onValueChange, id]);
6968
+ }, [onComponentDelete, normalizedCells, properties, onValueChange, id]);
6927
6969
  // CRITICAL FIX: Ensure all table cell components have proper IDs with table and cell position
6928
6970
  // Use useMemo to prevent ID regeneration on every render
6929
6971
  const cellsWithIds = React.useMemo(() => {
6930
- if (!properties.cells)
6972
+ if (normalizedCells.length === 0)
6931
6973
  return [];
6932
- return properties.cells.map((row, rowIndex) => Array.isArray(row) ? row.map((cell, cellIndex) => ({
6974
+ return normalizedCells.map((row, rowIndex) => row.map((cell, cellIndex) => ({
6933
6975
  ...cell,
6934
6976
  components: (cell.components && Array.isArray(cell.components))
6935
6977
  ? cell.components.map((comp, compIndex) => {
@@ -6948,8 +6990,8 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
6948
6990
  };
6949
6991
  })
6950
6992
  : []
6951
- })) : []);
6952
- }, [properties.cells, id]); // Only recalculate if cells or table ID changes
6993
+ })));
6994
+ }, [normalizedCells, id]); // Only recalculate if cells or table ID changes
6953
6995
  // CRITICAL FIX: Update the parent component with the cells that have proper IDs
6954
6996
  // Skip this in package to prevent flickering - cells are managed by parent
6955
6997
  // useEffect(() => {