df-ae-forms-package 1.0.99 → 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 +167 -52
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +167 -52
- 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}-${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
|
|
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}-${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
|
|
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,9 +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
|
-
let gridComponents = (properties.templateComponents || []).map(comp => ({
|
|
4742
|
+
let gridComponents = (properties.templateComponents || []).map((comp, index) => ({
|
|
4715
4743
|
...comp,
|
|
4744
|
+
id: ensureStringId$2(comp.id) || `${gridId}-template-${index}`, // CRITICAL: Ensure template components have stable string IDs
|
|
4716
4745
|
basic: {
|
|
4717
4746
|
...comp.basic,
|
|
4718
4747
|
// Use an empty string instead of undefined to satisfy component typing
|
|
@@ -4723,9 +4752,10 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4723
4752
|
const dataEntries = properties.entries || [];
|
|
4724
4753
|
// Fallback: If no template components but we have entries, extract template from first entry
|
|
4725
4754
|
if (gridComponents.length === 0 && dataEntries.length > 0 && dataEntries[0].components) {
|
|
4726
|
-
gridComponents = dataEntries[0].components.map((comp) => ({
|
|
4755
|
+
gridComponents = dataEntries[0].components.map((comp, index) => ({
|
|
4727
4756
|
...comp,
|
|
4728
|
-
|
|
4757
|
+
// Remove entry suffix for template, use stable ID if missing
|
|
4758
|
+
id: ensureStringId$2(comp.id).replace(/-entry-.*$/, '') || `${gridId}-template-${index}`,
|
|
4729
4759
|
basic: {
|
|
4730
4760
|
...comp.basic,
|
|
4731
4761
|
// Clear any data values while keeping types happy
|
|
@@ -4768,7 +4798,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4768
4798
|
index: 0,
|
|
4769
4799
|
components: gridComponents.map((comp, componentIndex) => ({
|
|
4770
4800
|
...comp,
|
|
4771
|
-
id: `${comp.id}-${newEntryId}-${componentIndex}`,
|
|
4801
|
+
id: `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`,
|
|
4772
4802
|
basic: {
|
|
4773
4803
|
...comp.basic,
|
|
4774
4804
|
showLabel: false // Hide label in datagrid cells
|
|
@@ -4793,12 +4823,9 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4793
4823
|
// Check if entry is missing any template components or if existing components need updates
|
|
4794
4824
|
return gridComponents.some((templateComp, componentIndex) => {
|
|
4795
4825
|
const existingComponent = entry.components?.[componentIndex];
|
|
4796
|
-
if (!existingComponent) {
|
|
4797
|
-
return true; // Missing component at this index
|
|
4826
|
+
if (!existingComponent || !existingComponent.id) {
|
|
4827
|
+
return true; // Missing component or missing ID at this index
|
|
4798
4828
|
}
|
|
4799
|
-
// We don't check for ID matches here anymore
|
|
4800
|
-
// const expectedId = `${templateComp.id}-entry-${entry.index}-${componentIndex}`
|
|
4801
|
-
// const hasProperId = existingComponent.id === expectedId
|
|
4802
4829
|
// Check if existing component needs to be updated with new template properties
|
|
4803
4830
|
// Compare key properties that should be synced
|
|
4804
4831
|
const needsPropertyUpdate = JSON.stringify(existingComponent.basic?.options) !== JSON.stringify(templateComp.basic?.options) ||
|
|
@@ -4806,7 +4833,6 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4806
4833
|
existingComponent.basic?.defaultValue !== templateComp.basic?.defaultValue ||
|
|
4807
4834
|
existingComponent.basic?.label !== templateComp.basic?.label ||
|
|
4808
4835
|
existingComponent.validation?.required !== templateComp.validation?.required;
|
|
4809
|
-
// We do not check for ID mismatch anymore as we want to preserve unique IDs
|
|
4810
4836
|
return needsPropertyUpdate;
|
|
4811
4837
|
});
|
|
4812
4838
|
});
|
|
@@ -4827,7 +4853,10 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4827
4853
|
// Update existing component with new template properties while ensuring unique ID and preserving form values
|
|
4828
4854
|
const updatedComponent = {
|
|
4829
4855
|
...templateComp,
|
|
4830
|
-
|
|
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}`,
|
|
4831
4860
|
basic: {
|
|
4832
4861
|
...templateComp.basic,
|
|
4833
4862
|
showLabel: false, // Hide label in datagrid cells
|
|
@@ -4841,7 +4870,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4841
4870
|
// Create new component based on template
|
|
4842
4871
|
// Only for NEW components in existing entries (e.g. column added) do we generate a new ID
|
|
4843
4872
|
const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
|
|
4844
|
-
const newId = `${templateComp.id}-${uniqueSuffix}-${componentIndex}`;
|
|
4873
|
+
const newId = `${ensureStringId$2(templateComp.id)}-${uniqueSuffix}-${componentIndex}`;
|
|
4845
4874
|
const newComponent = {
|
|
4846
4875
|
...templateComp,
|
|
4847
4876
|
id: newId,
|
|
@@ -4947,7 +4976,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4947
4976
|
id: newEntryId,
|
|
4948
4977
|
index: properties.entries.length,
|
|
4949
4978
|
components: gridComponents.map((comp, componentIndex) => {
|
|
4950
|
-
const componentId = `${comp.id}-${newEntryId}-${componentIndex}`;
|
|
4979
|
+
const componentId = `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`;
|
|
4951
4980
|
return {
|
|
4952
4981
|
...comp,
|
|
4953
4982
|
// Use the unique entry ID in the component ID to prevent collisions
|
|
@@ -5311,6 +5340,37 @@ const DfFormSection = ({ id, properties, mode = 'edit', formData = {}, onValueCh
|
|
|
5311
5340
|
|
|
5312
5341
|
// Dynamic imports to avoid circular dependencies
|
|
5313
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
|
+
};
|
|
5314
5374
|
// Normalize a table row from API format (object with numeric keys) into a proper array.
|
|
5315
5375
|
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
|
|
5316
5376
|
const normalizeTableRow = (row) => {
|
|
@@ -5356,16 +5416,17 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5356
5416
|
// Recursive function to initialize values from nested components
|
|
5357
5417
|
const initializeComponentValues = (components, values) => {
|
|
5358
5418
|
components.forEach(component => {
|
|
5359
|
-
|
|
5419
|
+
const componentId = ensureStringId$1(component.id);
|
|
5420
|
+
if (componentId) {
|
|
5360
5421
|
// ALWAYS prioritize existing form state (values param) if it exists
|
|
5361
|
-
if (values[
|
|
5362
|
-
// Then
|
|
5363
|
-
else if (component.basic && 'value' in component.basic && component.basic.value !== undefined
|
|
5364
|
-
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;
|
|
5365
5426
|
}
|
|
5366
|
-
// Then
|
|
5367
|
-
else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined
|
|
5368
|
-
values[
|
|
5427
|
+
// Then use defaultValue
|
|
5428
|
+
else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined) {
|
|
5429
|
+
values[componentId] = component.basic.defaultValue;
|
|
5369
5430
|
}
|
|
5370
5431
|
// Only then default to empty
|
|
5371
5432
|
else {
|
|
@@ -5435,12 +5496,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5435
5496
|
// Helper to extract notes and attachments recursively
|
|
5436
5497
|
const extractNotesAndAttachments = (components) => {
|
|
5437
5498
|
components.forEach(comp => {
|
|
5438
|
-
|
|
5499
|
+
const componentId = ensureStringId$1(comp.id);
|
|
5500
|
+
if (componentId) {
|
|
5439
5501
|
if (comp.basic?.notes || comp.basic?.comments) {
|
|
5440
|
-
initialNotes[
|
|
5502
|
+
initialNotes[componentId] = comp.basic?.notes || comp.basic?.comments;
|
|
5441
5503
|
}
|
|
5442
5504
|
if (comp.basic?.attachments) {
|
|
5443
|
-
initialAttachments[
|
|
5505
|
+
initialAttachments[componentId] = comp.basic.attachments;
|
|
5444
5506
|
}
|
|
5445
5507
|
}
|
|
5446
5508
|
// Recurse
|
|
@@ -5461,42 +5523,67 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5461
5523
|
});
|
|
5462
5524
|
};
|
|
5463
5525
|
// Validate component IDs for uniqueness without mutating original props
|
|
5464
|
-
const getValidatedComponents = (components) => {
|
|
5526
|
+
const getValidatedComponents = (components, parentId) => {
|
|
5527
|
+
const parentIdStr = parentId ? ensureStringId$1(parentId) : '';
|
|
5465
5528
|
return components.map((component, index) => {
|
|
5466
5529
|
let validatedComponent = { ...component };
|
|
5467
|
-
// Ensure component has
|
|
5468
|
-
|
|
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) {
|
|
5469
5547
|
// Determine a base name for the ID
|
|
5470
5548
|
const name = validatedComponent.name || 'component';
|
|
5471
5549
|
const label = validatedComponent.basic?.label || '';
|
|
5472
5550
|
const safeLabel = label.replace(/[^a-zA-Z0-9]/g, '').toLowerCase().substring(0, 10);
|
|
5473
|
-
// Generate a unique ID
|
|
5474
|
-
|
|
5475
|
-
|
|
5551
|
+
// Generate a stable unique ID if parentId is provided, otherwise fallback to semi-stable
|
|
5552
|
+
if (parentIdStr) {
|
|
5553
|
+
validatedComponent.id = `${parentIdStr}-${name}-${index}`;
|
|
5554
|
+
}
|
|
5555
|
+
else {
|
|
5556
|
+
// For root components, use label if available for stability
|
|
5557
|
+
const labelPart = safeLabel ? `-${safeLabel}` : '';
|
|
5558
|
+
validatedComponent.id = `${name}${labelPart}-${index}`;
|
|
5559
|
+
}
|
|
5560
|
+
console.warn(`[DfFormPreview] Fixed missing/invalid ID: ${validatedComponent.id}`);
|
|
5476
5561
|
}
|
|
5477
5562
|
else {
|
|
5478
|
-
//
|
|
5563
|
+
// ID is a valid string, check for duplicates
|
|
5479
5564
|
if (seenIds.has(validatedComponent.id)) {
|
|
5480
5565
|
console.error(`[DfFormPreview] Duplicate component ID detected: ${validatedComponent.id}`);
|
|
5481
|
-
// Generate a unique ID for duplicate
|
|
5482
|
-
validatedComponent.id = `${validatedComponent.id}-
|
|
5566
|
+
// Generate a unique ID for duplicate - using index to keep it somewhat stable
|
|
5567
|
+
validatedComponent.id = `${validatedComponent.id}-dup-${index}`;
|
|
5483
5568
|
console.warn(`[DfFormPreview] Generated new unique ID: ${validatedComponent.id}`);
|
|
5484
5569
|
}
|
|
5485
5570
|
}
|
|
5486
5571
|
seenIds.add(validatedComponent.id);
|
|
5487
5572
|
// Recursively validate nested components
|
|
5488
5573
|
if (validatedComponent.children && Array.isArray(validatedComponent.children)) {
|
|
5489
|
-
validatedComponent.children = getValidatedComponents(validatedComponent.children);
|
|
5574
|
+
validatedComponent.children = getValidatedComponents(validatedComponent.children, validatedComponent.id);
|
|
5490
5575
|
}
|
|
5491
5576
|
if (validatedComponent.cells && Array.isArray(validatedComponent.cells)) {
|
|
5492
|
-
validatedComponent.cells = validatedComponent.cells.map((row) => {
|
|
5577
|
+
validatedComponent.cells = validatedComponent.cells.map((row, rowIndex) => {
|
|
5493
5578
|
const normalizedRow = normalizeTableRow(row);
|
|
5494
5579
|
if (normalizedRow.length > 0) {
|
|
5495
|
-
return normalizedRow.map((cell) => {
|
|
5580
|
+
return normalizedRow.map((cell, cellIndex) => {
|
|
5496
5581
|
if (cell && cell.components && Array.isArray(cell.components)) {
|
|
5582
|
+
// Stable ID for table cells: tableId-row-X-cell-Y
|
|
5583
|
+
const cellContextId = `${ensureStringId$1(validatedComponent.id)}-row-${rowIndex}-cell-${cellIndex}`;
|
|
5497
5584
|
return {
|
|
5498
5585
|
...cell,
|
|
5499
|
-
components: getValidatedComponents(cell.components)
|
|
5586
|
+
components: getValidatedComponents(cell.components, cellContextId)
|
|
5500
5587
|
};
|
|
5501
5588
|
}
|
|
5502
5589
|
return cell;
|
|
@@ -5508,9 +5595,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5508
5595
|
if (validatedComponent.entries && Array.isArray(validatedComponent.entries)) {
|
|
5509
5596
|
validatedComponent.entries = validatedComponent.entries.map((entry) => {
|
|
5510
5597
|
if (entry && entry.components && Array.isArray(entry.components)) {
|
|
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}`;
|
|
5511
5600
|
return {
|
|
5512
5601
|
...entry,
|
|
5513
|
-
|
|
5602
|
+
id: entryId, // Ensure entry itself has a string ID
|
|
5603
|
+
components: getValidatedComponents(entry.components, entryId)
|
|
5514
5604
|
};
|
|
5515
5605
|
}
|
|
5516
5606
|
return entry;
|
|
@@ -6303,13 +6393,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6303
6393
|
const componentIdCacheRef = useRef(new Map());
|
|
6304
6394
|
const componentCounterRef = useRef(0);
|
|
6305
6395
|
const renderFormComponent = (component) => {
|
|
6306
|
-
// CRITICAL: Ensure component has a valid unique ID
|
|
6396
|
+
// CRITICAL: Ensure component has a valid unique string ID
|
|
6307
6397
|
// NEVER regenerate IDs - always use existing or cached ID
|
|
6308
|
-
let finalComponentId;
|
|
6309
|
-
if (
|
|
6310
|
-
// Component already has an ID - use it (most common case)
|
|
6311
|
-
finalComponentId = component.id;
|
|
6312
|
-
}
|
|
6398
|
+
let finalComponentId = ensureStringId$1(component.id);
|
|
6399
|
+
if (finalComponentId && finalComponentId.trim() !== '') ;
|
|
6313
6400
|
else {
|
|
6314
6401
|
// Component is missing an ID - need to generate and cache it
|
|
6315
6402
|
// Create a stable cache key using component properties that don't change
|
|
@@ -6795,6 +6882,32 @@ const DfFormComments = ({ comment = '', onSave, placeholder = 'Enter your reason
|
|
|
6795
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 }) }) }) })] }));
|
|
6796
6883
|
};
|
|
6797
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
|
+
};
|
|
6798
6911
|
// Normalize a row from the API format (object with numeric keys) into a proper TableCell array.
|
|
6799
6912
|
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
|
|
6800
6913
|
const normalizeRow = (row) => {
|
|
@@ -6989,13 +7102,15 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
6989
7102
|
? cell.components.map((comp, compIndex) => {
|
|
6990
7103
|
// CRITICAL: Only generate ID if it's missing - never regenerate existing IDs
|
|
6991
7104
|
// This prevents component remounting and losing input state
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
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 };
|
|
6995
7109
|
}
|
|
6996
7110
|
// Generate unique ID that includes table ID, row, cell, and component index
|
|
6997
7111
|
// This ensures no conflicts with other components
|
|
6998
|
-
const
|
|
7112
|
+
const sanitizedTableId = ensureStringId(id);
|
|
7113
|
+
const uniqueId = `${comp.name || 'component'}-table-${sanitizedTableId}-row-${rowIndex}-cell-${cellIndex}-comp-${compIndex}`;
|
|
6999
7114
|
return {
|
|
7000
7115
|
...comp,
|
|
7001
7116
|
id: uniqueId
|