df-ae-forms-package 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4243,6 +4243,33 @@ const ComponentSubmissionActions = ({ component }) => {
4243
4243
  return (jsxRuntime.jsx("div", { className: "component-submission-actions", children: jsxRuntime.jsxs("div", { className: "actions-content", children: [hasNotes && (jsxRuntime.jsx("div", { className: "notes-summary-section", children: jsxRuntime.jsxs("div", { className: "notes-full-text", children: [jsxRuntime.jsx("span", { className: "notes-label", children: "Notes:" }), " ", notes] }) })), hasAttachments && (jsxRuntime.jsx("div", { className: "attachments-section", children: jsxRuntime.jsx(SubmissionAttachmentThumbnails, { attachments: attachments }) }))] }) }));
4244
4244
  };
4245
4245
 
4246
+ // Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
4247
+ // Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
4248
+ function ensureStringId$2(id) {
4249
+ if (!id)
4250
+ return '';
4251
+ if (typeof id === 'string') {
4252
+ if (id.includes('[object Object]'))
4253
+ return '';
4254
+ return id;
4255
+ }
4256
+ if (typeof id === 'object' && id !== null) {
4257
+ if (id.$oid)
4258
+ return String(id.$oid);
4259
+ if (id._id)
4260
+ return ensureStringId$2(id._id);
4261
+ try {
4262
+ const str = id.toString();
4263
+ if (str && str !== '[object Object]')
4264
+ return str;
4265
+ return JSON.stringify(id);
4266
+ }
4267
+ catch (e) {
4268
+ return 'id-error';
4269
+ }
4270
+ }
4271
+ return String(id);
4272
+ }
4246
4273
  const DraggableGridComponent = ({ component, selectedComponent, mode, onComponentSelect, onComponentDelete, onComponentEdit, renderFormComponent, isOverlay = false, formData = {}, formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChange, onAttachmentChange, shouldShowComponent }) => {
4247
4274
  const formValue = formData[component.id];
4248
4275
  const isVisible = shouldShowComponent ? shouldShowComponent(component.id) : true;
@@ -4494,7 +4521,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4494
4521
  let entryComponent = entry.components?.[componentIndex];
4495
4522
  if (!entryComponent) {
4496
4523
  // Use entry.id (which is unique) instead of entryIndex to prevent data collisions
4497
- const uniqueId = `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`;
4524
+ const uniqueId = `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`;
4498
4525
  entryComponent = {
4499
4526
  ...templateComponent,
4500
4527
  id: uniqueId,
@@ -4507,7 +4534,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4507
4534
  else {
4508
4535
  entryComponent = {
4509
4536
  ...entryComponent,
4510
- id: entryComponent.id || `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`,
4537
+ id: ensureStringId$2(entryComponent.id) || `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`,
4511
4538
  basic: {
4512
4539
  ...entryComponent.basic,
4513
4540
  showLabel: columnView // Show label in column view
@@ -4631,7 +4658,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4631
4658
  comp.basic?.label === templateComponent.basic?.label);
4632
4659
  }
4633
4660
  if (!entryComponent) {
4634
- const uniqueId = `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`;
4661
+ const uniqueId = `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`;
4635
4662
  entryComponent = {
4636
4663
  ...templateComponent,
4637
4664
  id: uniqueId,
@@ -4644,7 +4671,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4644
4671
  else {
4645
4672
  entryComponent = {
4646
4673
  ...entryComponent,
4647
- id: entryComponent.id || `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`,
4674
+ id: ensureStringId$2(entryComponent.id) || `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`,
4648
4675
  basic: {
4649
4676
  ...entryComponent.basic,
4650
4677
  showLabel: columnView // Show label in column view, hide in grid view
@@ -4712,10 +4739,11 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4712
4739
  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 }) => {
4713
4740
  const [isCollapsed, setIsCollapsed] = React.useState(false);
4714
4741
  const hasInitialized = React.useRef(false);
4742
+ const gridId = ensureStringId$2(id);
4715
4743
  // Get all components in the grid and sanitize them to ensure no data leaks into templates
4716
4744
  let gridComponents = (properties.templateComponents || []).map((comp, index) => ({
4717
4745
  ...comp,
4718
- id: comp.id || `${id}-template-${index}`, // CRITICAL: Ensure template components have stable IDs
4746
+ id: ensureStringId$2(comp.id) || `${gridId}-template-${index}`, // CRITICAL: Ensure template components have stable string IDs
4719
4747
  basic: {
4720
4748
  ...comp.basic,
4721
4749
  // Use an empty string instead of undefined to satisfy component typing
@@ -4729,7 +4757,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4729
4757
  gridComponents = dataEntries[0].components.map((comp, index) => ({
4730
4758
  ...comp,
4731
4759
  // Remove entry suffix for template, use stable ID if missing
4732
- id: comp.id?.replace(/-entry-.*$/, '') || `${id}-template-${index}`,
4760
+ id: ensureStringId$2(comp.id).replace(/-entry-.*$/, '') || `${gridId}-template-${index}`,
4733
4761
  basic: {
4734
4762
  ...comp.basic,
4735
4763
  // Clear any data values while keeping types happy
@@ -4772,7 +4800,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4772
4800
  index: 0,
4773
4801
  components: gridComponents.map((comp, componentIndex) => ({
4774
4802
  ...comp,
4775
- id: `${comp.id}-${newEntryId}-${componentIndex}`,
4803
+ id: `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`,
4776
4804
  basic: {
4777
4805
  ...comp.basic,
4778
4806
  showLabel: false // Hide label in datagrid cells
@@ -4827,8 +4855,10 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4827
4855
  // Update existing component with new template properties while ensuring unique ID and preserving form values
4828
4856
  const updatedComponent = {
4829
4857
  ...templateComp,
4830
- // Preserve existing ID or generate one if missing
4831
- id: existingComponent.id || `${templateComp.id}-${entry.id}-${componentIndex}`,
4858
+ // Preserve existing ID (ensure it's a string) or generate one if missing
4859
+ id: (existingComponent.id && typeof existingComponent.id === 'string')
4860
+ ? existingComponent.id
4861
+ : `${ensureStringId$2(templateComp.id)}-${ensureStringId$2(entry.id)}-${componentIndex}`,
4832
4862
  basic: {
4833
4863
  ...templateComp.basic,
4834
4864
  showLabel: false, // Hide label in datagrid cells
@@ -4842,7 +4872,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4842
4872
  // Create new component based on template
4843
4873
  // Only for NEW components in existing entries (e.g. column added) do we generate a new ID
4844
4874
  const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
4845
- const newId = `${templateComp.id}-${uniqueSuffix}-${componentIndex}`;
4875
+ const newId = `${ensureStringId$2(templateComp.id)}-${uniqueSuffix}-${componentIndex}`;
4846
4876
  const newComponent = {
4847
4877
  ...templateComp,
4848
4878
  id: newId,
@@ -4948,7 +4978,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4948
4978
  id: newEntryId,
4949
4979
  index: properties.entries.length,
4950
4980
  components: gridComponents.map((comp, componentIndex) => {
4951
- const componentId = `${comp.id}-${newEntryId}-${componentIndex}`;
4981
+ const componentId = `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`;
4952
4982
  return {
4953
4983
  ...comp,
4954
4984
  // Use the unique entry ID in the component ID to prevent collisions
@@ -5312,6 +5342,37 @@ const DfFormSection = ({ id, properties, mode = 'edit', formData = {}, onValueCh
5312
5342
 
5313
5343
  // Dynamic imports to avoid circular dependencies
5314
5344
  const DfFormTable$1 = React.lazy(() => Promise.resolve().then(function () { return dfFormTable; }));
5345
+ // Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
5346
+ // This is used globally in this file to prevent [object Object] corruption
5347
+ const ensureStringId$1 = (id) => {
5348
+ if (!id)
5349
+ return '';
5350
+ if (typeof id === 'string') {
5351
+ // If the ID is already corrupted, return empty to trigger regeneration
5352
+ if (id.includes('[object Object]'))
5353
+ return '';
5354
+ return id;
5355
+ }
5356
+ if (typeof id === 'object' && id !== null) {
5357
+ if (id.$oid)
5358
+ return String(id.$oid);
5359
+ if (id._id)
5360
+ return ensureStringId$1(id._id);
5361
+ // Fallback for other object structures that might be IDs
5362
+ try {
5363
+ // If it has a toString that isn't the default, use it
5364
+ const str = id.toString();
5365
+ if (str && str !== '[object Object]')
5366
+ return str;
5367
+ // Otherwise, use a hash or just JSON
5368
+ return JSON.stringify(id);
5369
+ }
5370
+ catch (e) {
5371
+ return 'id-error';
5372
+ }
5373
+ }
5374
+ return String(id);
5375
+ };
5315
5376
  // Normalize a table row from API format (object with numeric keys) into a proper array.
5316
5377
  // The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
5317
5378
  const normalizeTableRow = (row) => {
@@ -5357,16 +5418,17 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5357
5418
  // Recursive function to initialize values from nested components
5358
5419
  const initializeComponentValues = (components, values) => {
5359
5420
  components.forEach(component => {
5360
- if (component.id) {
5421
+ const componentId = ensureStringId$1(component.id);
5422
+ if (componentId) {
5361
5423
  // ALWAYS prioritize existing form state (values param) if it exists
5362
- if (values[component.id] !== undefined) ;
5363
- // Then check initialFormData (if we are merging it) - handled by caller usually, but safe to check
5364
- else if (component.basic && 'value' in component.basic && component.basic.value !== undefined && component.basic.value !== '' && component.basic.value !== null) {
5365
- values[component.id] = component.basic.value;
5424
+ if (values[componentId] !== undefined) ;
5425
+ // Then use captured value in basic.value
5426
+ else if (component.basic && 'value' in component.basic && component.basic.value !== undefined) {
5427
+ values[componentId] = component.basic.value;
5366
5428
  }
5367
- // Then check defaultValue
5368
- else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined && component.basic.defaultValue !== '' && component.basic.defaultValue !== null) {
5369
- values[component.id] = component.basic.defaultValue;
5429
+ // Then use defaultValue
5430
+ else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined) {
5431
+ values[componentId] = component.basic.defaultValue;
5370
5432
  }
5371
5433
  // Only then default to empty
5372
5434
  else {
@@ -5436,12 +5498,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5436
5498
  // Helper to extract notes and attachments recursively
5437
5499
  const extractNotesAndAttachments = (components) => {
5438
5500
  components.forEach(comp => {
5439
- if (comp.id) {
5501
+ const componentId = ensureStringId$1(comp.id);
5502
+ if (componentId) {
5440
5503
  if (comp.basic?.notes || comp.basic?.comments) {
5441
- initialNotes[comp.id] = comp.basic?.notes || comp.basic?.comments;
5504
+ initialNotes[componentId] = comp.basic?.notes || comp.basic?.comments;
5442
5505
  }
5443
5506
  if (comp.basic?.attachments) {
5444
- initialAttachments[comp.id] = comp.basic.attachments;
5507
+ initialAttachments[componentId] = comp.basic.attachments;
5445
5508
  }
5446
5509
  }
5447
5510
  // Recurse
@@ -5463,27 +5526,43 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5463
5526
  };
5464
5527
  // Validate component IDs for uniqueness without mutating original props
5465
5528
  const getValidatedComponents = (components, parentId) => {
5529
+ const parentIdStr = parentId ? ensureStringId$1(parentId) : '';
5466
5530
  return components.map((component, index) => {
5467
5531
  let validatedComponent = { ...component };
5468
- // Ensure component has an ID
5469
- if (!validatedComponent.id || typeof validatedComponent.id !== 'string' || validatedComponent.id.trim() === '') {
5532
+ // Ensure component has a valid string ID
5533
+ let currentId = validatedComponent.id;
5534
+ // CRITICAL: Reject any ID that is not a string, is empty, or contains "[object Object]"
5535
+ let isIdValid = typeof currentId === 'string' &&
5536
+ currentId.trim() !== '' &&
5537
+ !currentId.includes('[object Object]');
5538
+ if (!isIdValid) {
5539
+ // If it's an object ID (but not a corrupted string), convert it to string
5540
+ if (currentId && typeof currentId === 'object') {
5541
+ const convertedId = ensureStringId$1(currentId);
5542
+ if (convertedId && !convertedId.includes('[object Object]')) {
5543
+ validatedComponent.id = convertedId;
5544
+ isIdValid = true;
5545
+ }
5546
+ }
5547
+ }
5548
+ if (!isIdValid) {
5470
5549
  // Determine a base name for the ID
5471
5550
  const name = validatedComponent.name || 'component';
5472
5551
  const label = validatedComponent.basic?.label || '';
5473
5552
  const safeLabel = label.replace(/[^a-zA-Z0-9]/g, '').toLowerCase().substring(0, 10);
5474
5553
  // Generate a stable unique ID if parentId is provided, otherwise fallback to semi-stable
5475
- if (parentId) {
5476
- validatedComponent.id = `${parentId}-${name}-${index}`;
5554
+ if (parentIdStr) {
5555
+ validatedComponent.id = `${parentIdStr}-${name}-${index}`;
5477
5556
  }
5478
5557
  else {
5479
5558
  // For root components, use label if available for stability
5480
5559
  const labelPart = safeLabel ? `-${safeLabel}` : '';
5481
5560
  validatedComponent.id = `${name}${labelPart}-${index}`;
5482
5561
  }
5483
- console.warn(`[DfFormPreview] Assigned missing ID: ${validatedComponent.id}`);
5562
+ console.warn(`[DfFormPreview] Fixed missing/invalid ID: ${validatedComponent.id}`);
5484
5563
  }
5485
5564
  else {
5486
- // Check for duplicates
5565
+ // ID is a valid string, check for duplicates
5487
5566
  if (seenIds.has(validatedComponent.id)) {
5488
5567
  console.error(`[DfFormPreview] Duplicate component ID detected: ${validatedComponent.id}`);
5489
5568
  // Generate a unique ID for duplicate - using index to keep it somewhat stable
@@ -5503,7 +5582,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5503
5582
  return normalizedRow.map((cell, cellIndex) => {
5504
5583
  if (cell && cell.components && Array.isArray(cell.components)) {
5505
5584
  // Stable ID for table cells: tableId-row-X-cell-Y
5506
- const cellContextId = `${validatedComponent.id}-row-${rowIndex}-cell-${cellIndex}`;
5585
+ const cellContextId = `${ensureStringId$1(validatedComponent.id)}-row-${rowIndex}-cell-${cellIndex}`;
5507
5586
  return {
5508
5587
  ...cell,
5509
5588
  components: getValidatedComponents(cell.components, cellContextId)
@@ -5519,9 +5598,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5519
5598
  validatedComponent.entries = validatedComponent.entries.map((entry) => {
5520
5599
  if (entry && entry.components && Array.isArray(entry.components)) {
5521
5600
  // Stable ID for datagrid entries: datagridId-entryId or using entry.id
5601
+ const entryId = entry.id ? ensureStringId$1(entry.id) : `${ensureStringId$1(validatedComponent.id)}-entry-${entry.index}`;
5522
5602
  return {
5523
5603
  ...entry,
5524
- components: getValidatedComponents(entry.components, entry.id || `${validatedComponent.id}-entry-${entry.index}`)
5604
+ id: entryId, // Ensure entry itself has a string ID
5605
+ components: getValidatedComponents(entry.components, entryId)
5525
5606
  };
5526
5607
  }
5527
5608
  return entry;
@@ -6314,13 +6395,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6314
6395
  const componentIdCacheRef = React.useRef(new Map());
6315
6396
  const componentCounterRef = React.useRef(0);
6316
6397
  const renderFormComponent = (component) => {
6317
- // CRITICAL: Ensure component has a valid unique ID
6398
+ // CRITICAL: Ensure component has a valid unique string ID
6318
6399
  // NEVER regenerate IDs - always use existing or cached ID
6319
- let finalComponentId;
6320
- if (component.id && typeof component.id === 'string' && component.id.trim() !== '') {
6321
- // Component already has an ID - use it (most common case)
6322
- finalComponentId = component.id;
6323
- }
6400
+ let finalComponentId = ensureStringId$1(component.id);
6401
+ if (finalComponentId && finalComponentId.trim() !== '') ;
6324
6402
  else {
6325
6403
  // Component is missing an ID - need to generate and cache it
6326
6404
  // Create a stable cache key using component properties that don't change
@@ -6806,6 +6884,32 @@ const DfFormComments = ({ comment = '', onSave, placeholder = 'Enter your reason
6806
6884
  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 }) }) }) })] }));
6807
6885
  };
6808
6886
 
6887
+ // Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
6888
+ const ensureStringId = (id) => {
6889
+ if (!id)
6890
+ return '';
6891
+ if (typeof id === 'string') {
6892
+ if (id.includes('[object Object]'))
6893
+ return '';
6894
+ return id;
6895
+ }
6896
+ if (typeof id === 'object' && id !== null) {
6897
+ if (id.$oid)
6898
+ return String(id.$oid);
6899
+ if (id._id)
6900
+ return ensureStringId(id._id);
6901
+ try {
6902
+ const str = id.toString();
6903
+ if (str && str !== '[object Object]')
6904
+ return str;
6905
+ return JSON.stringify(id);
6906
+ }
6907
+ catch (e) {
6908
+ return 'id-error';
6909
+ }
6910
+ }
6911
+ return String(id);
6912
+ };
6809
6913
  // Normalize a row from the API format (object with numeric keys) into a proper TableCell array.
6810
6914
  // The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
6811
6915
  const normalizeRow = (row) => {
@@ -7000,13 +7104,15 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
7000
7104
  ? cell.components.map((comp, compIndex) => {
7001
7105
  // CRITICAL: Only generate ID if it's missing - never regenerate existing IDs
7002
7106
  // This prevents component remounting and losing input state
7003
- if (comp.id && typeof comp.id === 'string' && comp.id.trim() !== '') {
7004
- // ID already exists - keep it as is
7005
- return comp;
7107
+ const existingId = ensureStringId(comp.id);
7108
+ if (existingId) {
7109
+ // ID already exists and is valid - keep it but ensure it's a string
7110
+ return { ...comp, id: existingId };
7006
7111
  }
7007
7112
  // Generate unique ID that includes table ID, row, cell, and component index
7008
7113
  // This ensures no conflicts with other components
7009
- const uniqueId = `${comp.name || 'component'}-table-${id}-row-${rowIndex}-cell-${cellIndex}-comp-${compIndex}`;
7114
+ const sanitizedTableId = ensureStringId(id);
7115
+ const uniqueId = `${comp.name || 'component'}-table-${sanitizedTableId}-row-${rowIndex}-cell-${cellIndex}-comp-${compIndex}`;
7010
7116
  return {
7011
7117
  ...comp,
7012
7118
  id: uniqueId