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.esm.js
CHANGED
|
@@ -4241,6 +4241,33 @@ const ComponentSubmissionActions = ({ component }) => {
|
|
|
4241
4241
|
return (jsx("div", { className: "component-submission-actions", children: jsxs("div", { className: "actions-content", children: [hasNotes && (jsx("div", { className: "notes-summary-section", children: jsxs("div", { className: "notes-full-text", children: [jsx("span", { className: "notes-label", children: "Notes:" }), " ", notes] }) })), hasAttachments && (jsx("div", { className: "attachments-section", children: jsx(SubmissionAttachmentThumbnails, { attachments: attachments }) }))] }) }));
|
|
4242
4242
|
};
|
|
4243
4243
|
|
|
4244
|
+
// Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
|
|
4245
|
+
// Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
|
|
4246
|
+
function ensureStringId$2(id) {
|
|
4247
|
+
if (!id)
|
|
4248
|
+
return '';
|
|
4249
|
+
if (typeof id === 'string') {
|
|
4250
|
+
if (id.includes('[object Object]'))
|
|
4251
|
+
return '';
|
|
4252
|
+
return id;
|
|
4253
|
+
}
|
|
4254
|
+
if (typeof id === 'object' && id !== null) {
|
|
4255
|
+
if (id.$oid)
|
|
4256
|
+
return String(id.$oid);
|
|
4257
|
+
if (id._id)
|
|
4258
|
+
return ensureStringId$2(id._id);
|
|
4259
|
+
try {
|
|
4260
|
+
const str = id.toString();
|
|
4261
|
+
if (str && str !== '[object Object]')
|
|
4262
|
+
return str;
|
|
4263
|
+
return JSON.stringify(id);
|
|
4264
|
+
}
|
|
4265
|
+
catch (e) {
|
|
4266
|
+
return 'id-error';
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
return String(id);
|
|
4270
|
+
}
|
|
4244
4271
|
const DraggableGridComponent = ({ component, selectedComponent, mode, onComponentSelect, onComponentDelete, onComponentEdit, renderFormComponent, isOverlay = false, formData = {}, formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChange, onAttachmentChange, shouldShowComponent }) => {
|
|
4245
4272
|
const formValue = formData[component.id];
|
|
4246
4273
|
const isVisible = shouldShowComponent ? shouldShowComponent(component.id) : true;
|
|
@@ -4492,7 +4519,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4492
4519
|
let entryComponent = entry.components?.[componentIndex];
|
|
4493
4520
|
if (!entryComponent) {
|
|
4494
4521
|
// Use entry.id (which is unique) instead of entryIndex to prevent data collisions
|
|
4495
|
-
const uniqueId = `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`;
|
|
4522
|
+
const uniqueId = `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`;
|
|
4496
4523
|
entryComponent = {
|
|
4497
4524
|
...templateComponent,
|
|
4498
4525
|
id: uniqueId,
|
|
@@ -4505,7 +4532,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4505
4532
|
else {
|
|
4506
4533
|
entryComponent = {
|
|
4507
4534
|
...entryComponent,
|
|
4508
|
-
id: entryComponent.id || `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`,
|
|
4535
|
+
id: ensureStringId$2(entryComponent.id) || `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`,
|
|
4509
4536
|
basic: {
|
|
4510
4537
|
...entryComponent.basic,
|
|
4511
4538
|
showLabel: columnView // Show label in column view
|
|
@@ -4629,7 +4656,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4629
4656
|
comp.basic?.label === templateComponent.basic?.label);
|
|
4630
4657
|
}
|
|
4631
4658
|
if (!entryComponent) {
|
|
4632
|
-
const uniqueId = `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`;
|
|
4659
|
+
const uniqueId = `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`;
|
|
4633
4660
|
entryComponent = {
|
|
4634
4661
|
...templateComponent,
|
|
4635
4662
|
id: uniqueId,
|
|
@@ -4642,7 +4669,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4642
4669
|
else {
|
|
4643
4670
|
entryComponent = {
|
|
4644
4671
|
...entryComponent,
|
|
4645
|
-
id: entryComponent.id || `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`,
|
|
4672
|
+
id: ensureStringId$2(entryComponent.id) || `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`,
|
|
4646
4673
|
basic: {
|
|
4647
4674
|
...entryComponent.basic,
|
|
4648
4675
|
showLabel: columnView // Show label in column view, hide in grid view
|
|
@@ -4710,10 +4737,11 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4710
4737
|
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 }) => {
|
|
4711
4738
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
|
4712
4739
|
const hasInitialized = useRef(false);
|
|
4740
|
+
const gridId = ensureStringId$2(id);
|
|
4713
4741
|
// Get all components in the grid and sanitize them to ensure no data leaks into templates
|
|
4714
4742
|
let gridComponents = (properties.templateComponents || []).map((comp, index) => ({
|
|
4715
4743
|
...comp,
|
|
4716
|
-
id: comp.id || `${
|
|
4744
|
+
id: ensureStringId$2(comp.id) || `${gridId}-template-${index}`, // CRITICAL: Ensure template components have stable string IDs
|
|
4717
4745
|
basic: {
|
|
4718
4746
|
...comp.basic,
|
|
4719
4747
|
// Use an empty string instead of undefined to satisfy component typing
|
|
@@ -4727,7 +4755,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4727
4755
|
gridComponents = dataEntries[0].components.map((comp, index) => ({
|
|
4728
4756
|
...comp,
|
|
4729
4757
|
// Remove entry suffix for template, use stable ID if missing
|
|
4730
|
-
id: comp.id
|
|
4758
|
+
id: ensureStringId$2(comp.id).replace(/-entry-.*$/, '') || `${gridId}-template-${index}`,
|
|
4731
4759
|
basic: {
|
|
4732
4760
|
...comp.basic,
|
|
4733
4761
|
// Clear any data values while keeping types happy
|
|
@@ -4770,7 +4798,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4770
4798
|
index: 0,
|
|
4771
4799
|
components: gridComponents.map((comp, componentIndex) => ({
|
|
4772
4800
|
...comp,
|
|
4773
|
-
id: `${comp.id}-${newEntryId}-${componentIndex}`,
|
|
4801
|
+
id: `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`,
|
|
4774
4802
|
basic: {
|
|
4775
4803
|
...comp.basic,
|
|
4776
4804
|
showLabel: false // Hide label in datagrid cells
|
|
@@ -4825,8 +4853,10 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4825
4853
|
// Update existing component with new template properties while ensuring unique ID and preserving form values
|
|
4826
4854
|
const updatedComponent = {
|
|
4827
4855
|
...templateComp,
|
|
4828
|
-
// Preserve existing ID or generate one if missing
|
|
4829
|
-
id: existingComponent.id
|
|
4856
|
+
// Preserve existing ID (ensure it's a string) or generate one if missing
|
|
4857
|
+
id: (existingComponent.id && typeof existingComponent.id === 'string')
|
|
4858
|
+
? existingComponent.id
|
|
4859
|
+
: `${ensureStringId$2(templateComp.id)}-${ensureStringId$2(entry.id)}-${componentIndex}`,
|
|
4830
4860
|
basic: {
|
|
4831
4861
|
...templateComp.basic,
|
|
4832
4862
|
showLabel: false, // Hide label in datagrid cells
|
|
@@ -4840,7 +4870,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4840
4870
|
// Create new component based on template
|
|
4841
4871
|
// Only for NEW components in existing entries (e.g. column added) do we generate a new ID
|
|
4842
4872
|
const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
|
|
4843
|
-
const newId = `${templateComp.id}-${uniqueSuffix}-${componentIndex}`;
|
|
4873
|
+
const newId = `${ensureStringId$2(templateComp.id)}-${uniqueSuffix}-${componentIndex}`;
|
|
4844
4874
|
const newComponent = {
|
|
4845
4875
|
...templateComp,
|
|
4846
4876
|
id: newId,
|
|
@@ -4946,7 +4976,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4946
4976
|
id: newEntryId,
|
|
4947
4977
|
index: properties.entries.length,
|
|
4948
4978
|
components: gridComponents.map((comp, componentIndex) => {
|
|
4949
|
-
const componentId = `${comp.id}-${newEntryId}-${componentIndex}`;
|
|
4979
|
+
const componentId = `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`;
|
|
4950
4980
|
return {
|
|
4951
4981
|
...comp,
|
|
4952
4982
|
// Use the unique entry ID in the component ID to prevent collisions
|
|
@@ -5310,6 +5340,37 @@ const DfFormSection = ({ id, properties, mode = 'edit', formData = {}, onValueCh
|
|
|
5310
5340
|
|
|
5311
5341
|
// Dynamic imports to avoid circular dependencies
|
|
5312
5342
|
const DfFormTable$1 = React.lazy(() => Promise.resolve().then(function () { return dfFormTable; }));
|
|
5343
|
+
// Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
|
|
5344
|
+
// This is used globally in this file to prevent [object Object] corruption
|
|
5345
|
+
const ensureStringId$1 = (id) => {
|
|
5346
|
+
if (!id)
|
|
5347
|
+
return '';
|
|
5348
|
+
if (typeof id === 'string') {
|
|
5349
|
+
// If the ID is already corrupted, return empty to trigger regeneration
|
|
5350
|
+
if (id.includes('[object Object]'))
|
|
5351
|
+
return '';
|
|
5352
|
+
return id;
|
|
5353
|
+
}
|
|
5354
|
+
if (typeof id === 'object' && id !== null) {
|
|
5355
|
+
if (id.$oid)
|
|
5356
|
+
return String(id.$oid);
|
|
5357
|
+
if (id._id)
|
|
5358
|
+
return ensureStringId$1(id._id);
|
|
5359
|
+
// Fallback for other object structures that might be IDs
|
|
5360
|
+
try {
|
|
5361
|
+
// If it has a toString that isn't the default, use it
|
|
5362
|
+
const str = id.toString();
|
|
5363
|
+
if (str && str !== '[object Object]')
|
|
5364
|
+
return str;
|
|
5365
|
+
// Otherwise, use a hash or just JSON
|
|
5366
|
+
return JSON.stringify(id);
|
|
5367
|
+
}
|
|
5368
|
+
catch (e) {
|
|
5369
|
+
return 'id-error';
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5372
|
+
return String(id);
|
|
5373
|
+
};
|
|
5313
5374
|
// Normalize a table row from API format (object with numeric keys) into a proper array.
|
|
5314
5375
|
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
|
|
5315
5376
|
const normalizeTableRow = (row) => {
|
|
@@ -5355,16 +5416,17 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5355
5416
|
// Recursive function to initialize values from nested components
|
|
5356
5417
|
const initializeComponentValues = (components, values) => {
|
|
5357
5418
|
components.forEach(component => {
|
|
5358
|
-
|
|
5419
|
+
const componentId = ensureStringId$1(component.id);
|
|
5420
|
+
if (componentId) {
|
|
5359
5421
|
// ALWAYS prioritize existing form state (values param) if it exists
|
|
5360
|
-
if (values[
|
|
5361
|
-
// Then
|
|
5362
|
-
else if (component.basic && 'value' in component.basic && component.basic.value !== undefined
|
|
5363
|
-
values[
|
|
5422
|
+
if (values[componentId] !== undefined) ;
|
|
5423
|
+
// Then use captured value in basic.value
|
|
5424
|
+
else if (component.basic && 'value' in component.basic && component.basic.value !== undefined) {
|
|
5425
|
+
values[componentId] = component.basic.value;
|
|
5364
5426
|
}
|
|
5365
|
-
// Then
|
|
5366
|
-
else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined
|
|
5367
|
-
values[
|
|
5427
|
+
// Then use defaultValue
|
|
5428
|
+
else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined) {
|
|
5429
|
+
values[componentId] = component.basic.defaultValue;
|
|
5368
5430
|
}
|
|
5369
5431
|
// Only then default to empty
|
|
5370
5432
|
else {
|
|
@@ -5434,12 +5496,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5434
5496
|
// Helper to extract notes and attachments recursively
|
|
5435
5497
|
const extractNotesAndAttachments = (components) => {
|
|
5436
5498
|
components.forEach(comp => {
|
|
5437
|
-
|
|
5499
|
+
const componentId = ensureStringId$1(comp.id);
|
|
5500
|
+
if (componentId) {
|
|
5438
5501
|
if (comp.basic?.notes || comp.basic?.comments) {
|
|
5439
|
-
initialNotes[
|
|
5502
|
+
initialNotes[componentId] = comp.basic?.notes || comp.basic?.comments;
|
|
5440
5503
|
}
|
|
5441
5504
|
if (comp.basic?.attachments) {
|
|
5442
|
-
initialAttachments[
|
|
5505
|
+
initialAttachments[componentId] = comp.basic.attachments;
|
|
5443
5506
|
}
|
|
5444
5507
|
}
|
|
5445
5508
|
// Recurse
|
|
@@ -5461,27 +5524,43 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5461
5524
|
};
|
|
5462
5525
|
// Validate component IDs for uniqueness without mutating original props
|
|
5463
5526
|
const getValidatedComponents = (components, parentId) => {
|
|
5527
|
+
const parentIdStr = parentId ? ensureStringId$1(parentId) : '';
|
|
5464
5528
|
return components.map((component, index) => {
|
|
5465
5529
|
let validatedComponent = { ...component };
|
|
5466
|
-
// Ensure component has
|
|
5467
|
-
|
|
5530
|
+
// Ensure component has a valid string ID
|
|
5531
|
+
let currentId = validatedComponent.id;
|
|
5532
|
+
// CRITICAL: Reject any ID that is not a string, is empty, or contains "[object Object]"
|
|
5533
|
+
let isIdValid = typeof currentId === 'string' &&
|
|
5534
|
+
currentId.trim() !== '' &&
|
|
5535
|
+
!currentId.includes('[object Object]');
|
|
5536
|
+
if (!isIdValid) {
|
|
5537
|
+
// If it's an object ID (but not a corrupted string), convert it to string
|
|
5538
|
+
if (currentId && typeof currentId === 'object') {
|
|
5539
|
+
const convertedId = ensureStringId$1(currentId);
|
|
5540
|
+
if (convertedId && !convertedId.includes('[object Object]')) {
|
|
5541
|
+
validatedComponent.id = convertedId;
|
|
5542
|
+
isIdValid = true;
|
|
5543
|
+
}
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5546
|
+
if (!isIdValid) {
|
|
5468
5547
|
// Determine a base name for the ID
|
|
5469
5548
|
const name = validatedComponent.name || 'component';
|
|
5470
5549
|
const label = validatedComponent.basic?.label || '';
|
|
5471
5550
|
const safeLabel = label.replace(/[^a-zA-Z0-9]/g, '').toLowerCase().substring(0, 10);
|
|
5472
5551
|
// Generate a stable unique ID if parentId is provided, otherwise fallback to semi-stable
|
|
5473
|
-
if (
|
|
5474
|
-
validatedComponent.id = `${
|
|
5552
|
+
if (parentIdStr) {
|
|
5553
|
+
validatedComponent.id = `${parentIdStr}-${name}-${index}`;
|
|
5475
5554
|
}
|
|
5476
5555
|
else {
|
|
5477
5556
|
// For root components, use label if available for stability
|
|
5478
5557
|
const labelPart = safeLabel ? `-${safeLabel}` : '';
|
|
5479
5558
|
validatedComponent.id = `${name}${labelPart}-${index}`;
|
|
5480
5559
|
}
|
|
5481
|
-
console.warn(`[DfFormPreview]
|
|
5560
|
+
console.warn(`[DfFormPreview] Fixed missing/invalid ID: ${validatedComponent.id}`);
|
|
5482
5561
|
}
|
|
5483
5562
|
else {
|
|
5484
|
-
//
|
|
5563
|
+
// ID is a valid string, check for duplicates
|
|
5485
5564
|
if (seenIds.has(validatedComponent.id)) {
|
|
5486
5565
|
console.error(`[DfFormPreview] Duplicate component ID detected: ${validatedComponent.id}`);
|
|
5487
5566
|
// Generate a unique ID for duplicate - using index to keep it somewhat stable
|
|
@@ -5501,7 +5580,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5501
5580
|
return normalizedRow.map((cell, cellIndex) => {
|
|
5502
5581
|
if (cell && cell.components && Array.isArray(cell.components)) {
|
|
5503
5582
|
// Stable ID for table cells: tableId-row-X-cell-Y
|
|
5504
|
-
const cellContextId = `${validatedComponent.id}-row-${rowIndex}-cell-${cellIndex}`;
|
|
5583
|
+
const cellContextId = `${ensureStringId$1(validatedComponent.id)}-row-${rowIndex}-cell-${cellIndex}`;
|
|
5505
5584
|
return {
|
|
5506
5585
|
...cell,
|
|
5507
5586
|
components: getValidatedComponents(cell.components, cellContextId)
|
|
@@ -5517,9 +5596,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5517
5596
|
validatedComponent.entries = validatedComponent.entries.map((entry) => {
|
|
5518
5597
|
if (entry && entry.components && Array.isArray(entry.components)) {
|
|
5519
5598
|
// Stable ID for datagrid entries: datagridId-entryId or using entry.id
|
|
5599
|
+
const entryId = entry.id ? ensureStringId$1(entry.id) : `${ensureStringId$1(validatedComponent.id)}-entry-${entry.index}`;
|
|
5520
5600
|
return {
|
|
5521
5601
|
...entry,
|
|
5522
|
-
|
|
5602
|
+
id: entryId, // Ensure entry itself has a string ID
|
|
5603
|
+
components: getValidatedComponents(entry.components, entryId)
|
|
5523
5604
|
};
|
|
5524
5605
|
}
|
|
5525
5606
|
return entry;
|
|
@@ -6312,13 +6393,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6312
6393
|
const componentIdCacheRef = useRef(new Map());
|
|
6313
6394
|
const componentCounterRef = useRef(0);
|
|
6314
6395
|
const renderFormComponent = (component) => {
|
|
6315
|
-
// CRITICAL: Ensure component has a valid unique ID
|
|
6396
|
+
// CRITICAL: Ensure component has a valid unique string ID
|
|
6316
6397
|
// NEVER regenerate IDs - always use existing or cached ID
|
|
6317
|
-
let finalComponentId;
|
|
6318
|
-
if (
|
|
6319
|
-
// Component already has an ID - use it (most common case)
|
|
6320
|
-
finalComponentId = component.id;
|
|
6321
|
-
}
|
|
6398
|
+
let finalComponentId = ensureStringId$1(component.id);
|
|
6399
|
+
if (finalComponentId && finalComponentId.trim() !== '') ;
|
|
6322
6400
|
else {
|
|
6323
6401
|
// Component is missing an ID - need to generate and cache it
|
|
6324
6402
|
// Create a stable cache key using component properties that don't change
|
|
@@ -6804,6 +6882,32 @@ const DfFormComments = ({ comment = '', onSave, placeholder = 'Enter your reason
|
|
|
6804
6882
|
return (jsxs("div", { className: `df-form-comments ${className}`, children: [jsxs("div", { className: "df-form-comments__header", children: [jsx("h3", { className: "df-form-comments__title", children: "Comments" }), jsx("button", { className: "df-form-comments__toggle", type: "button", onClick: toggleComments, "aria-expanded": isExpanded, "aria-label": "Toggle comments section", disabled: disabled, children: isExpanded ? (jsx("span", { className: "df-form-comments__toggle-icon", children: "\u25BC" })) : (jsx("span", { className: "df-form-comments__toggle-icon", children: "\u25B6" })) })] }), jsx("div", { className: `df-form-comments__content ${isExpanded ? 'df-form-comments__content--expanded' : ''}`, children: jsx("div", { className: "df-form-comments__input-container", children: jsx("div", { className: "df-form-comments__input-line", children: jsx("input", { type: "text", id: "comment-input", className: "df-form-comments__input", value: currentComment, onChange: handleInputChange, onBlur: handleInputBlur, onFocus: handleInputFocus, placeholder: placeholder, disabled: disabled }) }) }) })] }));
|
|
6805
6883
|
};
|
|
6806
6884
|
|
|
6885
|
+
// Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
|
|
6886
|
+
const ensureStringId = (id) => {
|
|
6887
|
+
if (!id)
|
|
6888
|
+
return '';
|
|
6889
|
+
if (typeof id === 'string') {
|
|
6890
|
+
if (id.includes('[object Object]'))
|
|
6891
|
+
return '';
|
|
6892
|
+
return id;
|
|
6893
|
+
}
|
|
6894
|
+
if (typeof id === 'object' && id !== null) {
|
|
6895
|
+
if (id.$oid)
|
|
6896
|
+
return String(id.$oid);
|
|
6897
|
+
if (id._id)
|
|
6898
|
+
return ensureStringId(id._id);
|
|
6899
|
+
try {
|
|
6900
|
+
const str = id.toString();
|
|
6901
|
+
if (str && str !== '[object Object]')
|
|
6902
|
+
return str;
|
|
6903
|
+
return JSON.stringify(id);
|
|
6904
|
+
}
|
|
6905
|
+
catch (e) {
|
|
6906
|
+
return 'id-error';
|
|
6907
|
+
}
|
|
6908
|
+
}
|
|
6909
|
+
return String(id);
|
|
6910
|
+
};
|
|
6807
6911
|
// Normalize a row from the API format (object with numeric keys) into a proper TableCell array.
|
|
6808
6912
|
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
|
|
6809
6913
|
const normalizeRow = (row) => {
|
|
@@ -6998,13 +7102,15 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
6998
7102
|
? cell.components.map((comp, compIndex) => {
|
|
6999
7103
|
// CRITICAL: Only generate ID if it's missing - never regenerate existing IDs
|
|
7000
7104
|
// This prevents component remounting and losing input state
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7105
|
+
const existingId = ensureStringId(comp.id);
|
|
7106
|
+
if (existingId) {
|
|
7107
|
+
// ID already exists and is valid - keep it but ensure it's a string
|
|
7108
|
+
return { ...comp, id: existingId };
|
|
7004
7109
|
}
|
|
7005
7110
|
// Generate unique ID that includes table ID, row, cell, and component index
|
|
7006
7111
|
// This ensures no conflicts with other components
|
|
7007
|
-
const
|
|
7112
|
+
const sanitizedTableId = ensureStringId(id);
|
|
7113
|
+
const uniqueId = `${comp.name || 'component'}-table-${sanitizedTableId}-row-${rowIndex}-cell-${cellIndex}-comp-${compIndex}`;
|
|
7008
7114
|
return {
|
|
7009
7115
|
...comp,
|
|
7010
7116
|
id: uniqueId
|