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