@syncfusion/ej2-react-form-builder 0.1.0-beta → 35.1.37

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.
Files changed (160) hide show
  1. package/README.md +81 -36
  2. package/diConfig.json +148 -0
  3. package/dist/ej2-react-form-builder.min.js +10 -0
  4. package/dist/ej2-react-form-builder.umd.min.js +11 -0
  5. package/dist/ej2-react-form-builder.umd.min.js.map +1 -0
  6. package/dist/es6/ej2-react-form-builder.es2015.js +60 -0
  7. package/dist/es6/ej2-react-form-builder.es2015.js.map +1 -0
  8. package/form-builder.d.ts +4 -0
  9. package/form-builder.js +4 -0
  10. package/index.d.ts +2 -4
  11. package/index.js +2 -4
  12. package/license +6 -13
  13. package/package.json +19 -43
  14. package/src/form-builder/formbuilder.component.d.ts +37 -0
  15. package/src/form-builder/formbuilder.component.js +50 -0
  16. package/src/form-builder/index.d.ts +2 -0
  17. package/src/form-builder/index.js +2 -0
  18. package/src/form-builder/toolboxitems-directive.d.ts +28 -0
  19. package/src/form-builder/toolboxitems-directive.js +47 -0
  20. package/src/global.js +1 -0
  21. package/src/index.d.ts +2 -16
  22. package/src/index.js +2 -6
  23. package/Common/CheckboxGroup.d.ts +0 -13
  24. package/Common/CheckboxGroup.js +0 -50
  25. package/Common/ConditionalRuleEngine.d.ts +0 -296
  26. package/Common/ConditionalRuleEngine.js +0 -566
  27. package/Common/CustomTabComponent.d.ts +0 -17
  28. package/Common/CustomTabComponent.js +0 -30
  29. package/Common/CustomValidationEngine.d.ts +0 -58
  30. package/Common/CustomValidationEngine.js +0 -146
  31. package/Common/DataGridComponent.d.ts +0 -20
  32. package/Common/DataGridComponent.js +0 -273
  33. package/Common/FormValidator.d.ts +0 -485
  34. package/Common/FormValidator.js +0 -575
  35. package/Common/MinMaxRuleEngine.d.ts +0 -105
  36. package/Common/MinMaxRuleEngine.js +0 -365
  37. package/Common/StaticHtmlRenderer.d.ts +0 -14
  38. package/Common/StaticHtmlRenderer.js +0 -24
  39. package/Common/expressions/DependencyTracker.d.ts +0 -30
  40. package/Common/expressions/DependencyTracker.js +0 -128
  41. package/Common/expressions/ExpressionEngine.d.ts +0 -95
  42. package/Common/expressions/ExpressionEngine.js +0 -506
  43. package/Common/expressions/ExpressionParser.d.ts +0 -41
  44. package/Common/expressions/ExpressionParser.js +0 -269
  45. package/Common/expressions/useGridExpressions.d.ts +0 -12
  46. package/Common/expressions/useGridExpressions.js +0 -71
  47. package/Common/globalFormId.d.ts +0 -26
  48. package/Common/globalFormId.js +0 -45
  49. package/Common/json-converter.d.ts +0 -444
  50. package/Common/json-converter.js +0 -1184
  51. package/Common/parser.d.ts +0 -98
  52. package/Common/parser.js +0 -753
  53. package/Common/utils.d.ts +0 -130
  54. package/Common/utils.js +0 -574
  55. package/src/FormBuilder.d.ts +0 -211
  56. package/src/FormBuilder.js +0 -1299
  57. package/src/components/Database/ConnectionForm.d.ts +0 -8
  58. package/src/components/Database/ConnectionForm.js +0 -28
  59. package/src/components/TopBar.d.ts +0 -10
  60. package/src/components/TopBar.js +0 -7
  61. package/src/components/icons/ComponentIcons.d.ts +0 -44
  62. package/src/components/icons/ComponentIcons.js +0 -40
  63. package/src/components/layout/FormFieldWrapper.d.ts +0 -41
  64. package/src/components/layout/FormFieldWrapper.js +0 -112
  65. package/src/components/layout/LeftPane.d.ts +0 -23
  66. package/src/components/layout/LeftPane.js +0 -310
  67. package/src/components/layout/ListBoxPane.d.ts +0 -24
  68. package/src/components/layout/ListBoxPane.js +0 -94
  69. package/src/components/layout/MainSection.d.ts +0 -39
  70. package/src/components/layout/MainSection.js +0 -1766
  71. package/src/components/layout/Preview.d.ts +0 -12
  72. package/src/components/layout/Preview.js +0 -337
  73. package/src/components/layout/RightPane.d.ts +0 -22
  74. package/src/components/layout/RightPane.js +0 -370
  75. package/src/components/theme/ThemeSwitcher.d.ts +0 -14
  76. package/src/components/theme/ThemeSwitcher.js +0 -24
  77. package/src/components/theme/theme-constant.d.ts +0 -37
  78. package/src/components/theme/theme-constant.js +0 -23
  79. package/src/config/component-properties.json +0 -4929
  80. package/src/config/form-setting.json +0 -56
  81. package/src/config/locale.d.ts +0 -449
  82. package/src/config/locale.js +0 -449
  83. package/src/context/FormSchemaContext.d.ts +0 -32
  84. package/src/context/FormSchemaContext.js +0 -155
  85. package/src/context/LocalizationContext.d.ts +0 -27
  86. package/src/context/LocalizationContext.js +0 -43
  87. package/src/context/ThemeContext.d.ts +0 -23
  88. package/src/context/ThemeContext.js +0 -161
  89. package/src/context/contexts.d.ts +0 -6
  90. package/src/context/contexts.js +0 -6
  91. package/src/context/defaultFormSchema.d.ts +0 -6
  92. package/src/context/defaultFormSchema.js +0 -20
  93. package/src/defaultPalette.d.ts +0 -9
  94. package/src/defaultPalette.js +0 -45
  95. package/src/defaultTemplate.d.ts +0 -3
  96. package/src/defaultTemplate.js +0 -185
  97. package/src/import/schemaImportUtils.d.ts +0 -24
  98. package/src/import/schemaImportUtils.js +0 -121
  99. package/src/types/ActionButtons.d.ts +0 -44
  100. package/src/types/ActionButtons.js +0 -27
  101. package/src/types/ComponentProperties.d.ts +0 -33
  102. package/src/types/ComponentProperties.js +0 -2
  103. package/src/types/FormSchema.d.ts +0 -585
  104. package/src/types/FormSchema.js +0 -147
  105. package/src/types/connection.d.ts +0 -19
  106. package/src/types/connection.js +0 -9
  107. package/src/utils/AttributesEditor.d.ts +0 -13
  108. package/src/utils/AttributesEditor.js +0 -117
  109. package/src/utils/ButtonGroupEditor.d.ts +0 -15
  110. package/src/utils/ButtonGroupEditor.js +0 -141
  111. package/src/utils/ChoiceBasedFieldEditor.d.ts +0 -16
  112. package/src/utils/ChoiceBasedFieldEditor.js +0 -87
  113. package/src/utils/ClipboardHelper.d.ts +0 -26
  114. package/src/utils/ClipboardHelper.js +0 -83
  115. package/src/utils/ColumnBuilder.d.ts +0 -11
  116. package/src/utils/ColumnBuilder.js +0 -153
  117. package/src/utils/ColumnSpanEditor.d.ts +0 -8
  118. package/src/utils/ColumnSpanEditor.js +0 -98
  119. package/src/utils/ConditionDataEditor.d.ts +0 -29
  120. package/src/utils/ConditionDataEditor.js +0 -177
  121. package/src/utils/ConditionalEditorUtils.d.ts +0 -27
  122. package/src/utils/ConditionalEditorUtils.js +0 -310
  123. package/src/utils/ConditionsEditor.d.ts +0 -20
  124. package/src/utils/ConditionsEditor.js +0 -571
  125. package/src/utils/CustomAccordion.d.ts +0 -13
  126. package/src/utils/CustomAccordion.js +0 -38
  127. package/src/utils/CustomValidationEditor.d.ts +0 -11
  128. package/src/utils/CustomValidationEditor.js +0 -208
  129. package/src/utils/DataSourceCollector.d.ts +0 -3
  130. package/src/utils/DataSourceCollector.js +0 -252
  131. package/src/utils/ExpressionEditor.d.ts +0 -13
  132. package/src/utils/ExpressionEditor.js +0 -99
  133. package/src/utils/FormSettingsPanel.d.ts +0 -9
  134. package/src/utils/FormSettingsPanel.js +0 -60
  135. package/src/utils/LookupConfig.d.ts +0 -11
  136. package/src/utils/LookupConfig.js +0 -159
  137. package/src/utils/MinMaxValueEditor.d.ts +0 -25
  138. package/src/utils/MinMaxValueEditor.js +0 -188
  139. package/src/utils/OptionsEditor.d.ts +0 -8
  140. package/src/utils/OptionsEditor.js +0 -79
  141. package/src/utils/PropertyRenderer.d.ts +0 -22
  142. package/src/utils/PropertyRenderer.js +0 -210
  143. package/src/utils/ValueRenderer.d.ts +0 -2
  144. package/src/utils/ValueRenderer.js +0 -91
  145. package/src/utils/ej2DbAdaptor.d.ts +0 -6
  146. package/src/utils/ej2DbAdaptor.js +0 -38
  147. package/src/utils/mappingHeuristics.d.ts +0 -10
  148. package/src/utils/mappingHeuristics.js +0 -33
  149. package/src/utils/renderComponent.d.ts +0 -18
  150. package/src/utils/renderComponent.js +0 -300
  151. package/styles/tailwind3.css +0 -67
  152. package/styles/themes/action-buttons.css +0 -110
  153. package/styles/themes/datagrid.css +0 -380
  154. package/styles/themes/drag-reorder.css +0 -248
  155. package/styles/themes/import-dialog.css +0 -292
  156. package/styles/themes/index.css +0 -658
  157. package/styles/themes/left-pane.css +0 -253
  158. package/styles/themes/options-editor.css +0 -63
  159. package/styles/themes/preview.css +0 -702
  160. package/styles/themes/property-dialog.css +0 -371
@@ -1,146 +0,0 @@
1
- import { ExpressionEngine } from './expressions/ExpressionEngine';
2
- /**
3
- * Custom Validation Engine
4
- *
5
- * Evaluates FormIO-style custom validation expressions:
6
- * valid = (condition) ? true : 'error message';
7
- *
8
- * Reuses ExpressionEngine for dependency extraction and expression parsing
9
- * @private
10
- * @spec custom_validation_spec_new.md
11
- */
12
- export class CustomValidationEngine {
13
- expressionEngine;
14
- constructor() {
15
- this.expressionEngine = new ExpressionEngine();
16
- }
17
- /**
18
- * Validate field using custom validation expression
19
- *
20
- * @param expression - FormIO-style validation expression (generated by UI)
21
- * @param fieldValue - Current field value (as 'input')
22
- * @param formValues - All form values for cross-field references
23
- * @returns true if valid, error message string if invalid
24
- */
25
- validate(expression, fieldValue, formValues) {
26
- if (!expression || expression.trim() === '') {
27
- return true; // No validation rule = valid
28
- }
29
- try {
30
- // Inject 'input' as current field value
31
- const context = {
32
- ...formValues,
33
- input: fieldValue,
34
- valid: true // Initialize valid variable
35
- };
36
- // Parse expression - FormIO pattern uses assignment: valid = ...
37
- // Pattern: valid = (condition) ? true : 'error message'
38
- const validPattern = /valid\s*=\s*(.+?)\s*\?\s*true\s*:\s*['"](.+?)['"]\s*$/;
39
- const match = expression.match(validPattern);
40
- if (!match) {
41
- console.warn('Custom validation expression must follow format: valid = (condition) ? true : "error message"');
42
- return 'Invalid validation expression format';
43
- }
44
- const condition = match[1].trim();
45
- const errorMessage = match[2];
46
- // Evaluate the condition (should return boolean)
47
- const conditionResult = this.expressionEngine.evaluate(condition, context, { throwOnError: false }, true);
48
- // If condition is true, validation passes
49
- if (conditionResult === true) {
50
- return true;
51
- }
52
- else {
53
- // Condition is false, return the error message
54
- return errorMessage;
55
- }
56
- }
57
- catch (error) {
58
- console.error('Custom validation error:', error);
59
- return 'Validation expression error';
60
- }
61
- }
62
- /**
63
- * Extract field dependencies from validation expression
64
- *
65
- * @param expression - Custom validation expression (or just condition)
66
- * @returns Array of field names referenced in expression
67
- */
68
- extractDependencies(expression) {
69
- if (!expression)
70
- return [];
71
- // Extract validation logic (right side of = sign if present)
72
- const validPattern = /valid\s*=\s*(.+)/;
73
- const match = expression.match(validPattern);
74
- const validationLogic = match ? match[1] : expression;
75
- // Use ExpressionEngine to extract field references
76
- const deps = this.expressionEngine.extractDependencies(validationLogic);
77
- // Filter out 'input' as it's the current field, not a dependency
78
- return deps.filter(dep => dep !== 'input');
79
- }
80
- /**
81
- * Validate condition syntax (simplified - no need for "valid =" check)
82
- *
83
- * @param condition - Validation condition (without "valid =" prefix)
84
- * @param availableFields - Available field names for reference validation
85
- * @returns Array of validation error messages
86
- */
87
- validateConditionSyntax(condition, availableFields) {
88
- if (!condition || condition.trim() === '') {
89
- return ['Condition cannot be empty'];
90
- }
91
- const errors = [];
92
- // Check for balanced parentheses
93
- const openParens = (condition.match(/\(/g) || []).length;
94
- const closeParens = (condition.match(/\)/g) || []).length;
95
- if (openParens !== closeParens) {
96
- errors.push(`Unbalanced parentheses (${openParens} open, ${closeParens} close)`);
97
- }
98
- // Check for balanced braces
99
- const openBraces = (condition.match(/\{/g) || []).length;
100
- const closeBraces = (condition.match(/\}/g) || []).length;
101
- if (openBraces !== closeBraces) {
102
- errors.push(`Unbalanced braces (${openBraces} open, ${closeBraces} close)`);
103
- }
104
- // Validate field references
105
- const deps = this.extractDependencies(condition);
106
- const invalidFields = deps.filter(field => !availableFields.includes(field));
107
- if (invalidFields.length > 0) {
108
- errors.push(`Unknown field references: ${invalidFields.join(', ')}`);
109
- }
110
- return errors;
111
- }
112
- /**
113
- * Build full FormIO expression from condition and error message
114
- *
115
- * @param condition - Validation condition (e.g., "(input === {password})")
116
- * @param errorMessage - Error message to show when validation fails
117
- * @returns Full FormIO expression
118
- */
119
- buildExpression(condition, errorMessage) {
120
- // Remove outer parentheses if present (we'll add them back in ternary)
121
- const trimmedCondition = condition.trim();
122
- // Escape single quotes in error message
123
- const escapedMessage = errorMessage.replace(/'/g, "\\'");
124
- // Build FormIO expression
125
- return `valid = ${trimmedCondition} ? true : '${escapedMessage}'`;
126
- }
127
- /**
128
- * Extract condition and error message from full FormIO expression
129
- * For editing existing rules
130
- *
131
- * @param expression - Full FormIO expression
132
- * @returns { condition, errorMessage } or null if invalid
133
- */
134
- parseExpression(expression) {
135
- // Pattern: valid = (condition) ? true : 'error message'
136
- const pattern = /valid\s*=\s*(.+?)\s*\?\s*true\s*:\s*'(.+)'/;
137
- const match = expression.match(pattern);
138
- if (match) {
139
- return {
140
- condition: match[1].trim(),
141
- errorMessage: match[2].replace(/\\'/g, "'") // Unescape quotes
142
- };
143
- }
144
- return null;
145
- }
146
- }
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- import type { GridComponentSchema } from '../FormBuilder/types/FormSchema';
3
- /**
4
- * @private
5
- */
6
- export interface DataGridRef {
7
- getGridData: () => Record<string, any>[];
8
- }
9
- /**
10
- * @private
11
- */
12
- export interface DataGridComponentProps extends GridComponentSchema {
13
- isPreviewMode?: boolean;
14
- onDataChange?: (data: Record<string, any>[]) => void;
15
- enableRtl?: boolean;
16
- }
17
- /**
18
- * @private
19
- */
20
- export declare const DataGridComponent: React.ForwardRefExoticComponent<DataGridComponentProps & React.RefAttributes<DataGridRef>>;
@@ -1,273 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useImperativeHandle, useRef, useState, useCallback, useMemo, useEffect } from 'react';
3
- import { GridComponent, ColumnsDirective, ColumnDirective, Inject, Toolbar, Edit, Page, Filter, Resize, Sort, } from '@syncfusion/ej2-react-grids';
4
- import { useGridExpressions } from './expressions/useGridExpressions';
5
- import { CustomValidationEngine } from './CustomValidationEngine';
6
- (() => {
7
- const filterPrefix = '[EJ2Grid.Warning]';
8
- const _origWarn = console.warn;
9
- const _origLog = console.log;
10
- const _origError = console.error;
11
- const makeFiltered = (orig) => (...args) => {
12
- const first = args[0];
13
- if (typeof first === 'string' && first.includes(filterPrefix))
14
- return;
15
- orig.apply(console, args);
16
- };
17
- // Apply only once
18
- if (!console.__ej2WarnsFiltered) {
19
- console.warn = makeFiltered(_origWarn);
20
- console.log = makeFiltered(_origLog);
21
- console.error = makeFiltered(_origError);
22
- console.__ej2WarnsFiltered = true;
23
- }
24
- })();
25
- /**
26
- * @private
27
- */
28
- export const DataGridComponent = React.forwardRef(({ id, columns, dataSource = [], height = '200px', width = '100%', locale, cssClass, pageSize = 6, allowPaging = true, allowAdding = true, allowEditing = true, allowDeleting = true, allowFiltering = false, onDataChange, isPreviewMode, enableRtl }, ref) => {
29
- // Internal state: maintain current grid data
30
- const [_currentData, setCurrentData] = useState(Array.isArray(dataSource) ? dataSource : []);
31
- const gridRef = useRef(null);
32
- const { evaluateRowExpressions, extractCalculatedColumns } = useGridExpressions();
33
- const validationEngine = useRef(new CustomValidationEngine()).current;
34
- const calculatedColumns = useMemo(() => extractCalculatedColumns(columns || []), [columns, extractCalculatedColumns]);
35
- const hasExpressions = calculatedColumns.length > 0;
36
- /**
37
- * Detect column definition changes and refresh grid
38
- * This ensures that changes to headerText, type, width, etc. are immediately reflected
39
- * Only enabled in preview mode to avoid issues in the main form builder view
40
- */
41
- useEffect(() => {
42
- if (gridRef.current) {
43
- if (columns && !(columns.length > 0)) {
44
- gridRef.current.columns = [];
45
- }
46
- else if (gridRef.current.columns.length === 0 && columns && columns.length == 1) {
47
- gridRef.current.columns = columns;
48
- }
49
- setTimeout(() => {
50
- if (gridRef.current?.refresh && !isPreviewMode) {
51
- if (dataSource && Array.isArray(dataSource) && dataSource.length > 0 && !hasExpressions) {
52
- gridRef.current.dataSource = dataSource;
53
- }
54
- gridRef.current.refresh();
55
- }
56
- }, 10);
57
- }
58
- }, [columns, allowAdding, allowDeleting, allowEditing, allowPaging, pageSize, allowFiltering, isPreviewMode]);
59
- useEffect(() => {
60
- const normalized = Array.isArray(dataSource) ? dataSource : [];
61
- if (hasExpressions && normalized.length > 0) {
62
- // Calculate expressions for initial data
63
- const calculated = normalized.map((row) => {
64
- const result = evaluateRowExpressions(row, columns || []);
65
- return { ...row, ...result };
66
- });
67
- setCurrentData(calculated);
68
- }
69
- else {
70
- setCurrentData(normalized);
71
- }
72
- }, [dataSource, hasExpressions, columns, evaluateRowExpressions]);
73
- /**
74
- * Expose getGridData() via ref - returns current grid data for form submission
75
- */
76
- useImperativeHandle(ref, () => ({
77
- getGridData: () => _currentData,
78
- gridRef
79
- }), [_currentData]);
80
- const mapCustomValidationToSyncfusion = useCallback((col) => {
81
- if (!col.customValidation || col.customValidation.length === 0) {
82
- return undefined;
83
- }
84
- // Return a custom validation function that receives the field value
85
- return (value) => {
86
- // Get the current form instance during edit (similar to grid-example pattern)
87
- const formObj = gridRef.current?.editModule?.formObj;
88
- if (!formObj)
89
- return true; // Form not available, skip validation
90
- // Build row context from current form values
91
- const rowContext = {};
92
- (columns || []).forEach((gridCol) => {
93
- const input = formObj.getInputElement(gridCol.field);
94
- if (input) {
95
- const value = input.value;
96
- rowContext[gridCol.field] = gridCol.type === 'number' ? parseInt(value, 10) : value;
97
- }
98
- });
99
- // Evaluate all custom validation rules for this column
100
- for (const rule of col.customValidation) {
101
- if (!rule.expression)
102
- continue;
103
- const fieldValue = col.type === 'number' ? parseInt(value.value, 10) : value.value;
104
- const result = validationEngine.validate(rule.expression, fieldValue, rowContext);
105
- // If validation fails, return error message
106
- return result === true;
107
- }
108
- return null; // All validations passed
109
- };
110
- }, [validationEngine, columns, gridRef]);
111
- /**
112
- * Create edit params with expression calculation callback
113
- * Attaches to columns that have dependencies
114
- */
115
- const createEditParams = useCallback((col) => {
116
- if (!hasExpressions)
117
- return undefined;
118
- // Check if any calculated column depends on this field
119
- const hasDependents = calculatedColumns.some((calcCol) => {
120
- if (!calcCol.expression)
121
- return false;
122
- return calcCol.expression.includes(`{${col.field}}`);
123
- });
124
- if (!hasDependents)
125
- return undefined;
126
- // Return edit params with change callback
127
- return {
128
- params: {
129
- change: () => {
130
- // Get form element and grid reference
131
- if (!gridRef.current?.element)
132
- return;
133
- const form = gridRef.current.element.querySelector('form');
134
- if (!form || !form.ej2_instances || !form.ej2_instances[0])
135
- return;
136
- const formInstance = form.ej2_instances[0];
137
- // Update all calculated columns
138
- calculatedColumns.forEach((calcCol) => {
139
- const input = formInstance.getInputElement(calcCol.field);
140
- if (!input)
141
- return;
142
- try {
143
- // Collect current form values
144
- const rowValues = {};
145
- columns?.forEach((col) => {
146
- const fieldInput = formInstance.getInputElement(col.field);
147
- if (fieldInput) {
148
- rowValues[col.field] = fieldInput.value;
149
- }
150
- });
151
- // Evaluate expression
152
- const result = evaluateRowExpressions(rowValues, columns || []);
153
- const calculatedValue = result[calcCol.field];
154
- // Update UI
155
- if (calculatedValue !== undefined && calculatedValue !== null) {
156
- if (calcCol.type === 'boolean') {
157
- input.checked = !!calculatedValue;
158
- }
159
- else if (calcCol.type === 'number') {
160
- const wrapper = input.closest('.e-control-wrapper');
161
- const numericInput = wrapper?.querySelector('input.e-control:not([type="hidden"])');
162
- if (numericInput?.ej2_instances?.[0]) {
163
- numericInput.ej2_instances[0].value = calculatedValue;
164
- }
165
- else {
166
- input.value = calculatedValue;
167
- }
168
- }
169
- else if (calcCol.type === 'date') {
170
- input.ej2_instances[0].value = new Date(calculatedValue);
171
- }
172
- else {
173
- input.value = calculatedValue;
174
- }
175
- }
176
- }
177
- catch (error) {
178
- console.warn(`Failed to calculate ${calcCol.field}:`, error);
179
- }
180
- });
181
- }
182
- }
183
- };
184
- }, [hasExpressions, calculatedColumns, columns, evaluateRowExpressions]);
185
- /**
186
- * Handle Syncfusion grid action events (add/edit/delete)
187
- * Update _currentData state when rows are modified
188
- */
189
- const handleActionComplete = useCallback((args) => {
190
- if (!gridRef.current)
191
- return;
192
- const eventType = args.requestType;
193
- // Handle different action types
194
- switch (eventType) {
195
- case 'save':
196
- case 'delete':
197
- case 'add':
198
- // After any data modification, sync grid data to state
199
- // Use dataSource directly as it's the current working data in Syncfusion
200
- if (gridRef.current.dataSource) {
201
- const updatedData = Array.isArray(gridRef.current.dataSource)
202
- ? gridRef.current.dataSource
203
- : [];
204
- setCurrentData(updatedData);
205
- onDataChange?.(updatedData);
206
- }
207
- break;
208
- default:
209
- break;
210
- }
211
- }, [onDataChange]);
212
- /**
213
- * Build toolbar array dynamically based on allowAdding/Editing/Deleting
214
- * Default toolbar includes: Add, Edit, Delete, Update, Cancel, ExcelExport, Search
215
- */
216
- const buildToolbar = useCallback(() => {
217
- const toolbarItems = [];
218
- if (allowAdding) {
219
- toolbarItems.push('Add');
220
- }
221
- if (allowEditing) {
222
- toolbarItems.push('Edit');
223
- }
224
- if (allowDeleting) {
225
- toolbarItems.push('Delete');
226
- }
227
- // Always include Update and Cancel for inline editing flow
228
- toolbarItems.push('Update', 'Cancel');
229
- return toolbarItems;
230
- }, [allowAdding, allowEditing, allowDeleting]);
231
- /**
232
- * Map validation rules from GridColumn.validationRules to Syncfusion format
233
- * Syncfusion ValidationRules type supports:
234
- * - required: boolean
235
- * - min/max: number (for numeric types)
236
- * - minLength/maxLength: number (for string types)
237
- */
238
- const mapValidationRules = useCallback((col) => {
239
- if (!col.validationRules) {
240
- return undefined;
241
- }
242
- return col.validationRules;
243
- }, []);
244
- /**
245
- * Memoize toolbar to prevent unnecessary re-renders
246
- */
247
- const toolbarConfig = useMemo(() => buildToolbar(), [buildToolbar]);
248
- return (_jsx("div", { className: "datagrid-wrapper", style: { width, height: 'auto' }, children: _jsx("div", { className: "datagrid-grid", children: _jsxs(GridComponent, { ref: gridRef, id: id, dataSource: _currentData, allowPaging: allowPaging, filterSettings: { mode: "Immediate" }, pageSettings: { pageSize }, editSettings: {
249
- allowEditing,
250
- allowAdding,
251
- allowDeleting,
252
- mode: 'Normal',
253
- }, enableRtl: enableRtl, locale: locale || 'en-US', cssClass: cssClass, toolbar: toolbarConfig, actionComplete: handleActionComplete, height: typeof height === 'string' ? height : `${height}px`, width: typeof width === 'string' ? width : `${width}px`, allowSorting: true, allowFiltering: allowFiltering, allowSelection: true, children: [_jsx(ColumnsDirective, { children: (columns || []).map((col) => {
254
- const validationRules = mapValidationRules(col);
255
- const customValidator = mapCustomValidationToSyncfusion(col);
256
- // Merge standard and custom validation rules
257
- const mergedValidationRules = validationRules ? { ...validationRules } : {};
258
- // Add custom validator to validationRules if custom validation exists
259
- if (customValidator) {
260
- // Extract error message from custom validation expression
261
- const errorMessage = col.customValidation?.[0]?.expression
262
- ? validationEngine.parseExpression(col.customValidation[0].expression)?.errorMessage || 'Validation failed'
263
- : 'Validation failed';
264
- mergedValidationRules.required = [true, errorMessage];
265
- mergedValidationRules.custom = [
266
- customValidator,
267
- errorMessage
268
- ];
269
- }
270
- return (_jsx(ColumnDirective, { field: col.field, headerText: col.headerText, type: col.type || 'string', isPrimaryKey: col.isPrimaryKey || false, width: col.width, format: col.type === 'date' ? (col.format || 'MM/dd/yyyy') : col.format, editType: col.editType, allowEditing: col.allowEditing !== false && !col.expression, validationRules: mergedValidationRules, edit: createEditParams(col) }, col.field));
271
- }) }), _jsx(Inject, { services: [Edit, Toolbar, Page, Resize, Sort, Filter] })] }) }) }));
272
- });
273
- DataGridComponent.displayName = 'DataGridComponent';