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.esm.js +146 -40
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +146 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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 || `${
|
|
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
|
|
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
|
|
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
|
-
|
|
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[
|
|
5363
|
-
// Then
|
|
5364
|
-
else if (component.basic && 'value' in component.basic && component.basic.value !== undefined
|
|
5365
|
-
values[
|
|
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
|
|
5368
|
-
else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined
|
|
5369
|
-
values[
|
|
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
|
-
|
|
5501
|
+
const componentId = ensureStringId$1(comp.id);
|
|
5502
|
+
if (componentId) {
|
|
5440
5503
|
if (comp.basic?.notes || comp.basic?.comments) {
|
|
5441
|
-
initialNotes[
|
|
5504
|
+
initialNotes[componentId] = comp.basic?.notes || comp.basic?.comments;
|
|
5442
5505
|
}
|
|
5443
5506
|
if (comp.basic?.attachments) {
|
|
5444
|
-
initialAttachments[
|
|
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
|
|
5469
|
-
|
|
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 (
|
|
5476
|
-
validatedComponent.id = `${
|
|
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]
|
|
5562
|
+
console.warn(`[DfFormPreview] Fixed missing/invalid ID: ${validatedComponent.id}`);
|
|
5484
5563
|
}
|
|
5485
5564
|
else {
|
|
5486
|
-
//
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
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
|
|
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
|