df-ae-forms-package 1.1.2 → 1.1.4

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
@@ -1002,20 +1002,15 @@ const DfFormInput = ({ id, properties, validationErrors = {}, formValue = '', in
1002
1002
  touchedFields[id] = true;
1003
1003
  }
1004
1004
  }, [isTouched, id, touchedFields]);
1005
- // Reset touched state and value when switching modes
1005
+ // Reset touched state when switching modes
1006
1006
  useEffect(() => {
1007
+ setIsTouched(false);
1008
+ // Only reset value when explicitly moving to edit mode to show current default
1007
1009
  if (mode === 'edit') {
1008
- setIsTouched(false);
1009
- // Reset value to default value when switching to edit mode
1010
1010
  const defaultValue = properties?.basic?.defaultValue || '';
1011
1011
  setValue(defaultValue);
1012
1012
  }
1013
- else if (mode === 'test') {
1014
- setIsTouched(false);
1015
- // Reset value to empty when switching to test mode for fresh start
1016
- setValue('');
1017
- }
1018
- }, [mode, properties?.basic?.defaultValue]);
1013
+ }, [mode]);
1019
1014
  // Update value when formValue prop changes (but don't override user input)
1020
1015
  // CRITICAL: Only update if formValue is actually for THIS component's ID
1021
1016
  // Use componentIdRef to ensure we're checking against the correct component ID
@@ -4591,7 +4586,11 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4591
4586
  position: 'sticky',
4592
4587
  bottom: 0,
4593
4588
  zIndex: 5
4594
- }, children: jsxs("button", { onClick: () => { console.log('[TableView] Add Entry button clicked (grid view)', 'entries:', dataEntries.length, 'max:', maxEntries); onAddEntry(); }, disabled: dataEntries.length >= maxEntries, style: {
4589
+ }, children: jsxs("button", { onClick: (e) => {
4590
+ e.stopPropagation();
4591
+ console.log('[TableView] Add Entry button clicked (grid view)', 'entries:', dataEntries.length, 'max:', maxEntries);
4592
+ onAddEntry();
4593
+ }, disabled: dataEntries.length >= maxEntries, style: {
4595
4594
  padding: '8px 16px',
4596
4595
  backgroundColor: dataEntries.length >= maxEntries ? '#f3f4f6' : '#10b981',
4597
4596
  color: dataEntries.length >= maxEntries ? '#9ca3af' : '#ffffff',
@@ -4713,7 +4712,11 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4713
4712
  borderRadius: '8px',
4714
4713
  display: 'flex',
4715
4714
  justifyContent: 'center'
4716
- }, children: jsxs("button", { onClick: () => { console.log('[TableView] Add Entry button clicked (list view)', 'entries:', dataEntries.length, 'max:', maxEntries); onAddEntry(); }, disabled: dataEntries.length >= maxEntries, style: {
4715
+ }, children: jsxs("button", { onClick: (e) => {
4716
+ e.stopPropagation();
4717
+ console.log('[TableView] Add Entry button clicked (list view)', 'entries:', dataEntries.length, 'max:', maxEntries);
4718
+ onAddEntry();
4719
+ }, disabled: dataEntries.length >= maxEntries, style: {
4717
4720
  padding: '8px 16px',
4718
4721
  backgroundColor: dataEntries.length >= maxEntries ? '#f3f4f6' : '#10b981',
4719
4722
  color: dataEntries.length >= maxEntries ? '#9ca3af' : '#ffffff',
@@ -4737,7 +4740,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4737
4740
  const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueChange, onSelect, isSelected = false, className = '', onDataGridSelect, onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, selectedComponent, renderFormComponent, onEntryAdd, onEntryRemove, formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChange, onAttachmentChange, shouldShowComponent }) => {
4738
4741
  const [isCollapsed, setIsCollapsed] = useState(false);
4739
4742
  const hasInitialized = useRef(false);
4740
- const gridId = ensureStringId$2(id);
4743
+ const gridId = ensureStringId$2(id) || properties._id || (typeof id === 'string' ? id : 'datagrid-id');
4741
4744
  // Get all components in the grid and sanitize them to ensure no data leaks into templates
4742
4745
  let gridComponents = (properties.templateComponents || []).map((comp, index) => ({
4743
4746
  ...comp,
@@ -4957,24 +4960,25 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4957
4960
  // This allows the form data to be updated for interactive components
4958
4961
  if (onValueChange) {
4959
4962
  onValueChange({
4960
- id: change.id,
4961
- value: change.value
4963
+ ...change
4962
4964
  });
4963
4965
  }
4964
4966
  }
4965
4967
  // In edit/preview modes, don't handle value changes as components are read-only
4966
4968
  }, [mode, onValueChange]);
4967
4969
  const handleAddEntry = useCallback(() => {
4968
- console.log('[DfFormDataGrid] handleAddEntry called');
4969
- console.log('[DfFormDataGrid] gridComponents:', gridComponents.length, gridComponents.map(c => c.id));
4970
- console.log('[DfFormDataGrid] current entries:', properties.entries?.length);
4970
+ console.log('[DfFormDataGrid] handleAddEntry called - Component ID:', id);
4971
+ // Safety check: ensure we have entries array
4972
+ const currentEntries = Array.isArray(properties.entries) ? properties.entries : [];
4973
+ console.log('[DfFormDataGrid] gridComponents:', gridComponents.length);
4974
+ console.log('[DfFormDataGrid] current entries count:', currentEntries.length);
4971
4975
  console.log('[DfFormDataGrid] onValueChange exists:', !!onValueChange);
4972
4976
  // Use timestamp and random string to ensure uniqueness even if entries are deleted
4973
4977
  const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
4974
4978
  const newEntryId = `entry-${uniqueSuffix}`;
4975
4979
  const newEntry = {
4976
4980
  id: newEntryId,
4977
- index: properties.entries.length,
4981
+ index: currentEntries.length,
4978
4982
  components: gridComponents.map((comp, componentIndex) => {
4979
4983
  const componentId = `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`;
4980
4984
  return {
@@ -4983,7 +4987,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4983
4987
  id: componentId,
4984
4988
  basic: {
4985
4989
  ...comp.basic,
4986
- value: '', // Explicitly clear value for new entries
4990
+ value: comp.basic?.defaultValue || '', // Use defaultValue if available, else empty
4987
4991
  showLabel: false // Hide label in datagrid cells
4988
4992
  }
4989
4993
  };
@@ -4991,31 +4995,41 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4991
4995
  styles: {}
4992
4996
  };
4993
4997
  console.log('[DfFormDataGrid] newEntry created:', newEntry.id, 'with', newEntry.components.length, 'components');
4994
- const updatedEntries = [...properties.entries, newEntry];
4998
+ const updatedEntries = [...currentEntries, newEntry];
4995
4999
  console.log('[DfFormDataGrid] updatedEntries count:', updatedEntries.length);
4996
5000
  if (onValueChange) {
4997
- console.log('[DfFormDataGrid] calling onValueChange with updated entries');
5001
+ console.log('[DfFormDataGrid] calling onValueChange with updated datagrid structure - Entries:', updatedEntries.length);
4998
5002
  onValueChange({
4999
- id,
5000
- value: { ...properties, entries: updatedEntries }
5003
+ id: gridId, // Use sanitized gridId
5004
+ value: {
5005
+ ...properties,
5006
+ entries: updatedEntries
5007
+ }
5001
5008
  });
5009
+ // Notify parent if callback provided
5010
+ if (onEntryAdd) {
5011
+ console.log('[DfFormDataGrid] calling onEntryAdd callback');
5012
+ onEntryAdd();
5013
+ }
5002
5014
  }
5003
5015
  else {
5004
- console.log('[DfFormDataGrid] WARNING: onValueChange is not defined!');
5016
+ console.warn('[DfFormDataGrid] Cannot add entry: onValueChange is missing');
5005
5017
  }
5006
- onEntryAdd?.();
5007
- }, [properties, onValueChange, id, onEntryAdd, gridComponents]);
5018
+ }, [onValueChange, properties, gridId, gridComponents, onEntryAdd]);
5008
5019
  const handleRemoveEntry = useCallback((entryIndex) => {
5009
- const updatedEntries = properties.entries
5020
+ // Safety check: ensure we have entries array
5021
+ const currentEntries = Array.isArray(properties.entries) ? properties.entries : [];
5022
+ const updatedEntries = currentEntries
5010
5023
  .filter((_, index) => index !== entryIndex)
5011
5024
  .map((entry, index) => ({ ...entry, index })); // Only update index, preserve unique ID
5012
5025
  if (onValueChange) {
5026
+ console.log('[DfFormDataGrid] Removing entry at index:', entryIndex, 'New count:', updatedEntries.length);
5013
5027
  onValueChange({
5014
- id,
5028
+ id: gridId, // Use sanitized gridId
5015
5029
  value: { ...properties, entries: updatedEntries }
5016
5030
  });
5017
5031
  }
5018
- }, [properties, onValueChange, id, onEntryRemove]);
5032
+ }, [properties.entries, onValueChange, gridId, properties]);
5019
5033
  // Use our own render function to ensure proper onComponentUpdate handling
5020
5034
  const renderComponent = useCallback((field, hideLabel = false) => {
5021
5035
  const formValue = mode === 'test' ? (formData[field.id] || ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '')) : ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '');
@@ -5606,6 +5620,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5606
5620
  return entry;
5607
5621
  });
5608
5622
  }
5623
+ // CRITICAL: Also validate templateComponents for datagrids
5624
+ if (validatedComponent.name === 'datagrid' && validatedComponent.templateComponents && Array.isArray(validatedComponent.templateComponents)) {
5625
+ const datagridId = ensureStringId$1(validatedComponent.id);
5626
+ validatedComponent.templateComponents = getValidatedComponents(validatedComponent.templateComponents, `${datagridId}-template`);
5627
+ }
5609
5628
  return validatedComponent;
5610
5629
  });
5611
5630
  };
@@ -5613,8 +5632,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5613
5632
  let validatedFormComponents = localFormComponents;
5614
5633
  if (localFormComponents && localFormComponents.length > 0) {
5615
5634
  validatedFormComponents = getValidatedComponents(localFormComponents);
5616
- // Notifying parent of changed components if they were mutated (IDs added/fixed)
5635
+ // Synchronize local state if components were mutated (IDs added/fixed)
5617
5636
  if (JSON.stringify(validatedFormComponents) !== JSON.stringify(localFormComponents)) {
5637
+ console.log('[DfFormPreview] Synchronizing local components after ID validation');
5638
+ setLocalFormComponents(validatedFormComponents);
5618
5639
  onFormDataChange?.(validatedFormComponents);
5619
5640
  }
5620
5641
  }
@@ -5655,9 +5676,35 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5655
5676
  return;
5656
5677
  }
5657
5678
  // CRITICAL: Check if multiple components share this ID (ID collision detection)
5658
- const componentsWithSameId = localFormComponents.filter(comp => comp.id === change.id);
5679
+ // Use recursive search for accurate detection across all levels
5680
+ const checkIdCollision = (components, targetId) => {
5681
+ let matches = [];
5682
+ components.forEach(comp => {
5683
+ if (ensureStringId$1(comp.id) === targetId)
5684
+ matches.push(comp);
5685
+ if (comp.name === 'section' && comp.children) {
5686
+ matches = [...matches, ...checkIdCollision(comp.children, targetId)];
5687
+ }
5688
+ if (comp.name === 'table' && comp.cells) {
5689
+ comp.cells.forEach((row) => {
5690
+ normalizeTableRow(row).forEach((cell) => {
5691
+ if (cell.components)
5692
+ matches = [...matches, ...checkIdCollision(cell.components, targetId)];
5693
+ });
5694
+ });
5695
+ }
5696
+ if (comp.name === 'datagrid' && comp.entries) {
5697
+ comp.entries.forEach((entry) => {
5698
+ if (entry.components)
5699
+ matches = [...matches, ...checkIdCollision(entry.components, targetId)];
5700
+ });
5701
+ }
5702
+ });
5703
+ return matches;
5704
+ };
5705
+ const componentsWithSameId = checkIdCollision(localFormComponents, change.id);
5659
5706
  if (componentsWithSameId.length > 1) {
5660
- 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 })));
5707
+ console.error(`[DfFormPreview] ID COLLISION DETECTED! Multiple components share ID "${change.id}":`, componentsWithSameId.map(c => ({ id: ensureStringId$1(c.id), name: c.name, label: c.basic?.label })));
5661
5708
  // Don't update - this would cause all components with this ID to get the same value
5662
5709
  return;
5663
5710
  }
@@ -5676,7 +5723,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5676
5723
  }
5677
5724
  // Clear raised issues for this component when value changes
5678
5725
  // This ensures that if threshold condition changes, user must raise issue again
5679
- const component = localFormComponents.find(comp => comp.id === change.id);
5726
+ const component = findComponentById(localFormComponents, change.id);
5680
5727
  if (component) {
5681
5728
  const threshold = component?.threshold;
5682
5729
  if (threshold && threshold.conditions && threshold.conditions.length > 0) {
@@ -5692,7 +5739,8 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5692
5739
  // Recursive function to update component values
5693
5740
  const updateComponentValue = (components) => {
5694
5741
  return components.map(component => {
5695
- if (component.id === change.id) {
5742
+ const componentId = ensureStringId$1(component.id);
5743
+ if (componentId === change.id) {
5696
5744
  // CRITICAL: Handle table/datagrid structure updates (cells, entries, etc.)
5697
5745
  // When a table sends onValueChange with cells data, update the whole component structure
5698
5746
  if (change.value && typeof change.value === 'object' && 'cells' in change.value) {
@@ -5708,13 +5756,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5708
5756
  ...change.value
5709
5757
  };
5710
5758
  }
5711
- if ('defaultValue' in component.basic) {
5759
+ if ('value' in component.basic || 'defaultValue' in component.basic) {
5712
5760
  return {
5713
5761
  ...component,
5714
5762
  basic: {
5715
5763
  ...component.basic,
5716
- value: change.value ?? component.basic.defaultValue,
5717
- defaultValue: change.value
5764
+ value: change.value
5718
5765
  }
5719
5766
  };
5720
5767
  }
@@ -6526,12 +6573,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6526
6573
  return renderFormComponent(field);
6527
6574
  }, onNotesChange: (componentId, notes) => {
6528
6575
  // Handle notes change for table cell components
6576
+ const targetTableId = ensureStringId$1(component.id);
6529
6577
  const updatedComponents = localFormComponents.map(comp => {
6530
- if (comp.id === component.id && comp.cells) {
6578
+ if (ensureStringId$1(comp.id) === targetTableId && comp.cells) {
6531
6579
  const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
6532
6580
  if (cell.components) {
6533
6581
  const updatedCellComponents = cell.components.map((cellComp) => {
6534
- if (cellComp.id === componentId) {
6582
+ if (ensureStringId$1(cellComp.id) === componentId) {
6535
6583
  return {
6536
6584
  ...cellComp,
6537
6585
  basic: {
@@ -6553,12 +6601,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6553
6601
  onFormDataChange?.(updatedComponents);
6554
6602
  }, onAttachmentChange: (componentId, attachments) => {
6555
6603
  // Handle attachment change for table cell components
6604
+ const targetTableId = ensureStringId$1(component.id);
6556
6605
  const updatedComponents = localFormComponents.map(comp => {
6557
- if (comp.id === component.id && comp.cells) {
6606
+ if (ensureStringId$1(comp.id) === targetTableId && comp.cells) {
6558
6607
  const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
6559
6608
  if (cell.components) {
6560
6609
  const updatedCellComponents = cell.components.map((cellComp) => {
6561
- if (cellComp.id === componentId) {
6610
+ if (ensureStringId$1(cellComp.id) === componentId) {
6562
6611
  return {
6563
6612
  ...cellComp,
6564
6613
  basic: {
@@ -6583,12 +6632,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6583
6632
  return (jsx(DfFormDataGrid, { ...commonProps, properties: component, formData: formValues, formTemplateId: formTemplateId, mode: commonProps.mode, onThresholdActionCompletion: handleThresholdActionCompletion, onThresholdIssueRaised: handleThresholdIssueRaised, onNotesChange: (componentId, notes) => {
6584
6633
  handleComponentNotesChange(componentId, notes);
6585
6634
  // Handle notes change for datagrid entry components
6635
+ const targetGridId = ensureStringId$1(component.id);
6586
6636
  const updatedComponents = localFormComponents.map(comp => {
6587
- if (comp.id === component.id && comp.entries) {
6637
+ if (ensureStringId$1(comp.id) === targetGridId && comp.entries) {
6588
6638
  const updatedEntries = comp.entries.map((entry) => {
6589
6639
  if (entry.components) {
6590
6640
  const updatedEntryComponents = entry.components.map((entryComp) => {
6591
- if (entryComp.id === componentId) {
6641
+ if (ensureStringId$1(entryComp.id) === componentId) {
6592
6642
  return {
6593
6643
  ...entryComp,
6594
6644
  basic: {
@@ -6611,12 +6661,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6611
6661
  }, onAttachmentChange: (componentId, attachments) => {
6612
6662
  handleComponentAttachmentChange(componentId, attachments);
6613
6663
  // Handle attachment change for datagrid entry components
6664
+ const targetGridId = ensureStringId$1(component.id);
6614
6665
  const updatedComponents = localFormComponents.map(comp => {
6615
- if (comp.id === component.id && comp.entries) {
6666
+ if (ensureStringId$1(comp.id) === targetGridId && comp.entries) {
6616
6667
  const updatedEntries = comp.entries.map((entry) => {
6617
6668
  if (entry.components) {
6618
6669
  const updatedEntryComponents = entry.components.map((entryComp) => {
6619
- if (entryComp.id === componentId) {
6670
+ if (ensureStringId$1(entryComp.id) === componentId) {
6620
6671
  return {
6621
6672
  ...entryComp,
6622
6673
  basic: {
@@ -6637,13 +6688,16 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6637
6688
  });
6638
6689
  onFormDataChange?.(updatedComponents);
6639
6690
  }, onValueChange: (change) => {
6640
- console.log('[DfFormPreview] datagrid onValueChange received:', change.id, 'hasEntries:', change.value && typeof change.value === 'object' && 'entries' in change.value);
6691
+ const changeId = ensureStringId$1(change.id);
6692
+ const componentId = ensureStringId$1(component.id);
6693
+ console.log(`[DfFormPreview] datagrid onValueChange - Target: ${changeId}, Component: ${componentId}`);
6641
6694
  // Handle datagrid value changes (entries updates)
6642
- if (change.id === component.id && change.value && typeof change.value === 'object' && 'entries' in change.value) {
6695
+ if (changeId === componentId && change.value && typeof change.value === 'object' && 'entries' in change.value) {
6643
6696
  console.log('[DfFormPreview] datagrid entries update - entries count:', change.value.entries?.length);
6644
6697
  // Update localFormComponents with new entries structure
6645
6698
  const updatedComponents = localFormComponents.map(comp => {
6646
- if (comp.id === component.id) {
6699
+ const currentCompId = ensureStringId$1(comp.id);
6700
+ if (currentCompId === componentId) {
6647
6701
  return {
6648
6702
  ...comp,
6649
6703
  ...change.value
@@ -6654,26 +6708,37 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6654
6708
  // CRITICAL: Update local state immediately so new entries render without Angular round-trip
6655
6709
  setLocalFormComponents(updatedComponents);
6656
6710
  onFormDataChange?.(updatedComponents);
6657
- // Also update formValues for nested components
6711
+ // Also update formValues for nested components to prevent undefined values
6658
6712
  if (change.value.entries && Array.isArray(change.value.entries)) {
6713
+ const newValues = { ...formValues };
6714
+ let valuesChanged = false;
6659
6715
  change.value.entries.forEach((entry) => {
6660
6716
  if (entry.components && Array.isArray(entry.components)) {
6661
6717
  entry.components.forEach((nestedComp) => {
6662
- const nestedValue = formValues[nestedComp.id];
6663
- if (nestedValue !== undefined) ;
6664
- else {
6665
- // Initialize with defaultValue if available
6718
+ const nestedId = ensureStringId$1(nestedComp.id);
6719
+ if (!nestedId)
6720
+ return;
6721
+ if (newValues[nestedId] === undefined) {
6722
+ // Initialize with defaultValue if available, otherwise empty string/array
6666
6723
  const defaultValue = nestedComp.basic?.defaultValue;
6667
6724
  if (defaultValue !== undefined) {
6668
- setFormValues(prev => ({
6669
- ...prev,
6670
- [nestedComp.id]: defaultValue
6671
- }));
6725
+ newValues[nestedId] = defaultValue;
6726
+ }
6727
+ else if (nestedComp.name === 'checkbox' || nestedComp.name === 'select') {
6728
+ newValues[nestedId] = [];
6672
6729
  }
6730
+ else {
6731
+ newValues[nestedId] = '';
6732
+ }
6733
+ valuesChanged = true;
6673
6734
  }
6674
6735
  });
6675
6736
  }
6676
6737
  });
6738
+ if (valuesChanged) {
6739
+ console.log('[DfFormPreview] Initializing form values for new datagrid entries');
6740
+ setFormValues(newValues);
6741
+ }
6677
6742
  }
6678
6743
  }
6679
6744
  else {