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

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,571 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useRef, useEffect, useState, useCallback } from 'react';
3
- import { QueryBuilderComponent } from '@syncfusion/ej2-react-querybuilder';
4
- import { getComponent } from '@syncfusion/ej2-base';
5
- import { DataManager, Query } from '@syncfusion/ej2-data';
6
- import { useLocalization } from '../context/LocalizationContext';
7
- import ValueRenderer from './ValueRenderer';
8
- import { extractDataFromPath, getAdaptorInstance } from '../../Common/utils';
9
- import { ConditionDataEditor } from './ConditionDataEditor';
10
- import { ChoiceBasedFieldEditor } from './ChoiceBasedFieldEditor';
11
- import { inferFieldType, isArrayField, hasSelectableOptions, createColumnTemplate } from './ConditionalEditorUtils';
12
- import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
13
- import { DialogComponent } from '@syncfusion/ej2-react-popups';
14
- import { ListBoxComponent } from '@syncfusion/ej2-react-dropdowns';
15
- export const ConditionsEditor = ({ componentFields, componentForEdit, excludeFieldId, excludeChildIds = [], existingConditions, onChange, builderMode, supportedConditions: supportedConditionsProp = ['visibleWhen', 'hideWhen', 'readOnlyWhen', 'disabledWhen', 'requiredWhen', 'setValueWhen', 'choiceBasedField'] }) => {
16
- // In Simple builder mode, only allow a subset of condition types
17
- const supportedConditions = builderMode === 'Simple'
18
- ? supportedConditionsProp.filter(c => c === 'visibleWhen' || c === 'disabledWhen' || c === 'readOnlyWhen')
19
- : supportedConditionsProp;
20
- // Use ref instead of state to avoid re-renders on condition updates
21
- // Only notify parent when conditions change via onChange callback
22
- const conditionsRef = useRef({
23
- visibleWhen: existingConditions?.visibleWhen,
24
- hideWhen: existingConditions?.hideWhen,
25
- readOnlyWhen: existingConditions?.readOnlyWhen,
26
- disabledWhen: existingConditions?.disabledWhen,
27
- requiredWhen: existingConditions?.requiredWhen,
28
- setValueWhen: existingConditions?.setValueWhen,
29
- choiceBasedField: existingConditions?.choiceBasedField
30
- });
31
- const { l10n } = useLocalization();
32
- // Track fetched options for components with URL-based options
33
- const [fetchedOptions, setFetchedOptions] = useState({});
34
- const fetchAbortControllers = useRef({});
35
- const [isDialogOpen, setIsDialogOpen] = useState(false);
36
- const [activeConditionType, setActiveConditionType] = useState('visibleWhen');
37
- const [savedConditions, setSavedConditions] = useState([]);
38
- const [showStyles, setShowStyles] = useState(false);
39
- // Initialize savedConditions based on existingConditions
40
- useEffect(() => {
41
- const conditions = [];
42
- if (existingConditions?.visibleWhen)
43
- conditions.push('visibleWhen');
44
- if (existingConditions?.hideWhen)
45
- conditions.push('hideWhen');
46
- if (existingConditions?.readOnlyWhen)
47
- conditions.push('readOnlyWhen');
48
- if (existingConditions?.disabledWhen)
49
- conditions.push('disabledWhen');
50
- if (existingConditions?.requiredWhen)
51
- conditions.push('requiredWhen');
52
- if (existingConditions?.setValueWhen)
53
- conditions.push('setValueWhen');
54
- if (existingConditions?.choiceBasedField)
55
- conditions.push('choiceBasedField');
56
- if (existingConditions?.conditionalData)
57
- conditions.push('conditionalData');
58
- setSavedConditions(conditions);
59
- }, [existingConditions]);
60
- // Fetch options for components that have URL-based options
61
- useEffect(() => {
62
- const newFetchedOptions = {};
63
- const newAbortControllers = {};
64
- componentFields.forEach(component => {
65
- if (component.options && typeof component.options === 'object' && !Array.isArray(component.options)) {
66
- const options = component.options;
67
- if (options.type === 'url' && options.url) {
68
- newAbortControllers[component.id] = new AbortController();
69
- try {
70
- const headers = {};
71
- if (options.headers && Array.isArray(options.headers)) {
72
- options.headers.forEach((h) => {
73
- if (h.key?.trim()) {
74
- headers[h.key] = h.value;
75
- }
76
- });
77
- }
78
- const dataManager = new DataManager({
79
- url: options.url,
80
- adaptor: getAdaptorInstance(options.adaptorType),
81
- headers: Object.keys(headers).length ? headers : undefined
82
- });
83
- let query = new Query();
84
- // Apply search query
85
- if (options.search && options.search.enabled && options.search.fields && options.search.fields.length > 0) {
86
- const searchKey = options.search.key || 'search';
87
- // Add search as a query parameter (will need search term at runtime or use generic placeholder)
88
- query = query.addParams(searchKey, '*');
89
- }
90
- // Apply sort query
91
- if (options.sort && options.sort.enabled && options.sort.field) {
92
- const sortDirection = options.sort.direction === 'descending' ? 'descending' : 'ascending';
93
- query = query.sortBy(options.sort.field, sortDirection);
94
- }
95
- // Apply filter queries
96
- if (options.filters && Array.isArray(options.filters) && options.filters.length > 0) {
97
- options.filters.forEach((f) => {
98
- if (f.field && f.operator && f.value) {
99
- query = query.where(f.field, f.operator, f.value);
100
- }
101
- });
102
- }
103
- // Apply query params (kept for backward compatibility)
104
- if (options.queryParams) {
105
- Object.keys(options.queryParams).forEach(key => {
106
- query = query.addParams(key, options.queryParams[key]);
107
- });
108
- }
109
- // Example: paging
110
- if (options.skip)
111
- query = query.skip(options.skip);
112
- if (options.take)
113
- query = query.take(options.take);
114
- dataManager.executeQuery(query).then((res) => {
115
- let data = res.result;
116
- if (options.dataPath) {
117
- data = extractDataFromPath(data, options.dataPath);
118
- }
119
- if (Array.isArray(data)) {
120
- newFetchedOptions[component.id] = data;
121
- }
122
- else if (typeof data === 'string') {
123
- newFetchedOptions[component.id] = [data];
124
- }
125
- setFetchedOptions(prev => ({ ...prev, [component.id]: newFetchedOptions[component.id] }));
126
- // Refresh any existing dropdowns with this component ID
127
- refreshComponentDropdowns(component.id, data);
128
- }).catch((err) => {
129
- console.error(`DataManager fetch error for ${component.id}:`, err);
130
- newFetchedOptions[component.id] = [];
131
- });
132
- }
133
- catch (err) {
134
- console.error(`Setup error for ${component.id}:`, err);
135
- newFetchedOptions[component.id] = [];
136
- }
137
- }
138
- }
139
- });
140
- fetchAbortControllers.current = newAbortControllers;
141
- // Cleanup on unmount
142
- return () => {
143
- Object.values(newAbortControllers).forEach(controller => controller.abort());
144
- };
145
- }, [componentFields]);
146
- // Helper function to refresh dropdowns when data is fetched
147
- const refreshComponentDropdowns = (componentId, data) => {
148
- setTimeout(() => {
149
- // Find all dropdown instances with this component ID
150
- const dropdownElements = document.querySelectorAll(`input[data-component-id="${componentId}"]`);
151
- dropdownElements.forEach(element => {
152
- const dropdown = getComponent(element, 'dropdownlist');
153
- if (dropdown) {
154
- try {
155
- const transformedData = (Array.isArray(data) ? data : [data]).map(opt => {
156
- if (typeof opt === 'string') {
157
- return { text: opt, value: opt };
158
- }
159
- else if (opt && typeof opt === 'object' && 'value' in opt) {
160
- return {
161
- text: opt.label || opt.text || opt.value,
162
- value: opt.value
163
- };
164
- }
165
- return { text: String(opt), value: String(opt) };
166
- });
167
- dropdown.dataSource = transformedData;
168
- dropdown.refresh();
169
- }
170
- catch (err) {
171
- console.error(`Error refreshing dropdown for ${componentId}:`, err);
172
- }
173
- }
174
- });
175
- }, 0);
176
- };
177
- const qbRefs = {
178
- visible: useRef(null),
179
- hidden: useRef(null),
180
- readOnly: useRef(null),
181
- disabled: useRef(null),
182
- required: useRef(null),
183
- setValue: useRef(null)
184
- };
185
- const buildColumnsForQueryBuilder = (qbRef) => {
186
- return componentFields
187
- .filter(c => {
188
- // Exclude current component to prevent self-reference
189
- if (excludeFieldId && c.id === excludeFieldId) {
190
- return false;
191
- }
192
- // Exclude child components to prevent circular dependencies
193
- if (excludeChildIds.includes(c.id)) {
194
- return false;
195
- }
196
- // Exclude non-data component types (layout, display-only, action components)
197
- const excludedTypes = [
198
- 'imageeditor',
199
- 'richtexteditor',
200
- 'datagrid',
201
- 'splitbutton',
202
- 'button',
203
- 'message',
204
- 'panel',
205
- 'table',
206
- 'tabs',
207
- 'card',
208
- 'statichtml',
209
- 'signature',
210
- 'fileupload'
211
- ];
212
- // Case-insensitive comparison
213
- return !excludedTypes.includes(c.type.toLowerCase());
214
- })
215
- .map((component) => {
216
- const fieldType = inferFieldType(component);
217
- const isArray = isArrayField(component);
218
- // Define operators based on field type
219
- let operators = [];
220
- // Special handling for array-like fields (multiselect, checkboxGroup)
221
- if (isArray) {
222
- operators = [
223
- { key: 'Is Empty', value: 'isempty' },
224
- { key: 'Is Not Empty', value: 'isnotempty' },
225
- { key: 'Contains', value: 'contains' },
226
- { key: 'Not Contains', value: 'notcontains' }
227
- ];
228
- }
229
- else {
230
- // Standard operators for non-array fields
231
- switch (fieldType) {
232
- case 'number':
233
- operators = [
234
- { key: 'Equal', value: 'equal' },
235
- { key: 'Not Equal', value: 'notequal' },
236
- { key: 'Greater than', value: 'greaterthan' },
237
- { key: 'Less than', value: 'lessthan' },
238
- { key: 'Greater than or equal', value: 'greaterthanorequal' },
239
- { key: 'Less than or equal', value: 'lessthanorequal' }
240
- ];
241
- break;
242
- case 'date':
243
- operators = [
244
- { key: 'Is Empty', value: 'isempty' },
245
- { key: 'Is Not Empty', value: 'isnotempty' },
246
- { key: 'Equal', value: 'equal' },
247
- { key: 'Not Equal', value: 'notequal' },
248
- { key: 'Greater than', value: 'dategreaterthan' },
249
- { key: 'Less than', value: 'datelessthan' }
250
- ];
251
- break;
252
- case 'boolean':
253
- operators = [
254
- { key: 'Equal', value: 'equal' },
255
- { key: 'Not Equal', value: 'notequal' }
256
- ];
257
- break;
258
- default: // 'string'
259
- if (component.type === 'time') {
260
- operators = [
261
- { key: 'Is Empty', value: 'isempty' },
262
- { key: 'Is Not Empty', value: 'isnotempty' },
263
- { key: 'Equal', value: 'equal' },
264
- { key: 'Not Equal', value: 'notequal' },
265
- { key: 'Greater than', value: 'timegreaterthan' },
266
- { key: 'Less than', value: 'timelessthan' }
267
- ];
268
- }
269
- else if (component.type === 'dateTime') {
270
- operators = [
271
- { key: 'Is Empty', value: 'isempty' },
272
- { key: 'Is Not Empty', value: 'isnotempty' },
273
- { key: 'Equal', value: 'equal' },
274
- { key: 'Not Equal', value: 'notequal' },
275
- { key: 'Greater than', value: 'datetimegreaterthan' },
276
- { key: 'Less than', value: 'datetimelessthan' }
277
- ];
278
- }
279
- else {
280
- // Standard string operators
281
- operators = [
282
- { key: 'Is Empty', value: 'isempty' },
283
- { key: 'Is Not Empty', value: 'isnotempty' },
284
- { key: 'Equal', value: 'equal' },
285
- { key: 'Not Equal', value: 'notequal' },
286
- { key: 'Starts With', value: 'startswith' },
287
- { key: 'Not Starts With', value: 'doesnotstartswith' },
288
- { key: 'Contains', value: 'contains' },
289
- { key: 'Not Contains', value: 'notcontains' },
290
- ];
291
- }
292
- }
293
- }
294
- // Build column configuration
295
- const column = {
296
- field: component.id,
297
- label: component.label || component.id,
298
- type: fieldType,
299
- format: fieldType === 'date' ? 'MM/dd/yyyy' : undefined,
300
- operators
301
- };
302
- // Determine if component should use column template
303
- const usesTemplate = hasSelectableOptions(component)
304
- || component.type === 'date'
305
- || component.type === 'time'
306
- || component.type === 'dateTime'
307
- || component.type === 'dateRange';
308
- // For fields with options or date/time types, add column template for custom input widget
309
- if (usesTemplate) {
310
- column.template = createColumnTemplate(component, qbRef, fetchedOptions);
311
- }
312
- // For array fields with options not using template, provide values for dropdown selection
313
- else if (isArray && component.options && Array.isArray(component.options)) {
314
- // Transform options to format QueryBuilder expects
315
- const values = component.options.map(opt => {
316
- if (typeof opt === 'string') {
317
- return opt;
318
- }
319
- else if (opt && typeof opt === 'object' && 'value' in opt) {
320
- return opt.value;
321
- }
322
- return String(opt);
323
- });
324
- column.values = values;
325
- }
326
- return column;
327
- });
328
- };
329
- const handleAddRule = () => {
330
- setActiveConditionType('visibleWhen');
331
- setIsDialogOpen(true);
332
- };
333
- const handleDialogClose = () => {
334
- setIsDialogOpen(false);
335
- };
336
- const handleSaveConditions = () => {
337
- const updatedConditions = [];
338
- const state = conditionsRef.current;
339
- if (state.visibleWhen?.rules?.length > 0)
340
- updatedConditions.push('visibleWhen');
341
- if (state.hideWhen?.rules?.length > 0)
342
- updatedConditions.push('hideWhen');
343
- if (state.readOnlyWhen?.rules?.length > 0)
344
- updatedConditions.push('readOnlyWhen');
345
- if (state.disabledWhen?.rules?.length > 0)
346
- updatedConditions.push('disabledWhen');
347
- if (state.requiredWhen?.rules?.length > 0)
348
- updatedConditions.push('requiredWhen');
349
- if (state.setValueWhen?.condition?.rules?.length > 0)
350
- updatedConditions.push('setValueWhen');
351
- if (state.choiceBasedField)
352
- updatedConditions.push('choiceBasedField');
353
- if (state.conditionalData && Array.isArray(state.conditionalData) && state.conditionalData.length > 0)
354
- updatedConditions.push('conditionalData');
355
- setSavedConditions(updatedConditions);
356
- setIsDialogOpen(false);
357
- notifyParent(conditionsRef.current);
358
- };
359
- const handleEditCondition = (conditionType) => {
360
- setActiveConditionType(conditionType);
361
- setIsDialogOpen(true);
362
- };
363
- const handleDeleteCondition = (conditionType) => {
364
- const type = conditionType;
365
- updateCondition(type, type === 'setValueWhen' ? { value: undefined } : undefined);
366
- setSavedConditions(savedConditions.filter(c => c !== conditionType));
367
- handleSaveConditions();
368
- };
369
- const getConditionLabel = (type) => {
370
- const labels = {
371
- visibleWhen: l10n.getConstant('conditionalVisibility') || 'Conditional Visibility',
372
- hideWhen: l10n.getConstant('conditionalHide') || 'Conditional Hide',
373
- readOnlyWhen: l10n.getConstant('conditionalReadOnly') || 'Conditional Read-Only',
374
- disabledWhen: l10n.getConstant('conditionalDisable') || 'Conditional Disable',
375
- requiredWhen: l10n.getConstant('conditionalRequired') || 'Conditional Required',
376
- setValueWhen: l10n.getConstant('conditionalSetValue') || 'Set Value When',
377
- choiceBasedField: l10n.getConstant('choiceBasedField') || 'Choice-Based Field',
378
- conditionalData: l10n.getConstant('conditionalData') || 'Conditional Data'
379
- };
380
- return labels[type] || type;
381
- };
382
- const conditionListData = supportedConditions
383
- .filter(c => {
384
- if (c === 'conditionalData') {
385
- return componentForEdit?.type === 'dataGrid';
386
- }
387
- return true;
388
- })
389
- .map(type => ({
390
- text: getConditionLabel(type),
391
- id: type
392
- }));
393
- const handleVisibilityRuleChange = (_args) => {
394
- if (qbRefs.visible.current) {
395
- const rule = qbRefs.visible.current.getValidRules(qbRefs.visible.current.rule);
396
- updateCondition('visibleWhen', rule);
397
- }
398
- };
399
- const handleHideRuleChange = (_args) => {
400
- if (qbRefs.hidden.current) {
401
- const rule = qbRefs.hidden.current.getValidRules(qbRefs.hidden.current.rule);
402
- updateCondition('hideWhen', rule);
403
- }
404
- };
405
- const handleReadOnlyRuleChange = (_args) => {
406
- if (qbRefs.readOnly.current) {
407
- const rule = qbRefs.readOnly.current.getValidRules(qbRefs.readOnly.current.rule);
408
- updateCondition('readOnlyWhen', rule);
409
- }
410
- };
411
- const handleDisabledRuleChange = (_args) => {
412
- if (qbRefs.disabled.current) {
413
- const rule = qbRefs.disabled.current.getValidRules(qbRefs.disabled.current.rule);
414
- updateCondition('disabledWhen', rule);
415
- }
416
- };
417
- const handleRequiredRuleChange = (_args) => {
418
- if (qbRefs.required.current) {
419
- const rule = qbRefs.required.current.getValidRules(qbRefs.required.current.rule);
420
- updateCondition('requiredWhen', rule);
421
- }
422
- };
423
- const handleSetValueRuleChange = (_args) => {
424
- if (qbRefs.setValue.current) {
425
- const rule = qbRefs.setValue.current.getValidRules(qbRefs.setValue.current.rule);
426
- updateCondition('setValueWhen', { ...conditionsRef.current.setValueWhen, condition: rule });
427
- }
428
- };
429
- const handleSetValueValueChange = (e) => {
430
- // Handle Syncfusion component events (which pass value via event object)
431
- const newValue = e.target?.value !== undefined ? e.target.value : (e.value !== undefined ? e.value : '');
432
- updateCondition('setValueWhen', { ...conditionsRef.current.setValueWhen, value: newValue });
433
- };
434
- const handleChoiceBasedFieldChange = (rule) => {
435
- updateCondition('choiceBasedField', rule);
436
- };
437
- const updateCondition = (type, rule) => {
438
- conditionsRef.current = { ...conditionsRef.current, [type]: rule };
439
- };
440
- const notifyParent = (cond) => {
441
- const finalConditions = {};
442
- // Only include supported conditions that have rules defined
443
- if (supportedConditions.includes('visibleWhen') &&
444
- cond.visibleWhen && cond.visibleWhen.rules && cond.visibleWhen.rules.length > 0) {
445
- finalConditions.visibleWhen = cond.visibleWhen;
446
- }
447
- if (supportedConditions.includes('hideWhen') &&
448
- cond.hideWhen && cond.hideWhen.rules && cond.hideWhen.rules.length > 0) {
449
- finalConditions.hideWhen = cond.hideWhen;
450
- }
451
- if (supportedConditions.includes('readOnlyWhen') &&
452
- cond.readOnlyWhen && cond.readOnlyWhen.rules && cond.readOnlyWhen.rules.length > 0) {
453
- finalConditions.readOnlyWhen = cond.readOnlyWhen;
454
- }
455
- if (supportedConditions.includes('disabledWhen') &&
456
- cond.disabledWhen && cond.disabledWhen.rules && cond.disabledWhen.rules.length > 0) {
457
- finalConditions.disabledWhen = cond.disabledWhen;
458
- }
459
- if (supportedConditions.includes('requiredWhen') &&
460
- cond.requiredWhen && cond.requiredWhen.rules && cond.requiredWhen.rules.length > 0) {
461
- finalConditions.requiredWhen = cond.requiredWhen;
462
- }
463
- if (supportedConditions.includes('setValueWhen') &&
464
- cond.setValueWhen && cond.setValueWhen.condition && cond.setValueWhen.condition.rules && cond.setValueWhen.condition.rules.length > 0 && cond.setValueWhen.value !== undefined && cond.setValueWhen.value !== '') {
465
- finalConditions.setValueWhen = {
466
- condition: cond.setValueWhen.condition,
467
- value: cond.setValueWhen.value
468
- };
469
- }
470
- if (supportedConditions.includes('choiceBasedField') && cond.choiceBasedField) {
471
- finalConditions.choiceBasedField = cond.choiceBasedField;
472
- }
473
- if (supportedConditions.includes('conditionalData') &&
474
- cond.conditionalData && Array.isArray(cond.conditionalData) &&
475
- cond.conditionalData.length > 0) {
476
- // Only include rules with valid conditions
477
- const validRules = cond.conditionalData.filter(rule => {
478
- if (!rule.condition || !rule.dataSource) {
479
- return false;
480
- }
481
- // Check if condition is composite (has rules array) or simple (has field)
482
- const hasRules = 'rules' in rule.condition && Array.isArray(rule.condition.rules) && rule.condition.rules.length > 0;
483
- const isSimple = 'field' in rule.condition;
484
- return hasRules || isSimple;
485
- });
486
- if (validRules.length > 0) {
487
- finalConditions.conditionalData = validRules;
488
- }
489
- }
490
- onChange(finalConditions);
491
- };
492
- // Update internal ref when existingConditions prop changes
493
- useEffect(() => {
494
- conditionsRef.current = {
495
- visibleWhen: existingConditions?.visibleWhen,
496
- hideWhen: existingConditions?.hideWhen,
497
- readOnlyWhen: existingConditions?.readOnlyWhen,
498
- disabledWhen: existingConditions?.disabledWhen,
499
- requiredWhen: existingConditions?.requiredWhen,
500
- setValueWhen: existingConditions?.setValueWhen,
501
- choiceBasedField: existingConditions?.choiceBasedField,
502
- conditionalData: existingConditions?.conditionalData
503
- };
504
- }, [existingConditions]);
505
- const visibleColumns = buildColumnsForQueryBuilder(qbRefs.visible);
506
- const hiddenColumns = buildColumnsForQueryBuilder(qbRefs.hidden);
507
- const readOnlyColumns = buildColumnsForQueryBuilder(qbRefs.readOnly);
508
- const disabledColumns = buildColumnsForQueryBuilder(qbRefs.disabled);
509
- const requiredColumns = buildColumnsForQueryBuilder(qbRefs.required);
510
- const setValueColumns = buildColumnsForQueryBuilder(qbRefs.setValue);
511
- useEffect(() => {
512
- if (isDialogOpen) {
513
- setShowStyles(true);
514
- }
515
- else {
516
- const timer = setTimeout(() => {
517
- setShowStyles(false);
518
- }, 400); // Remove styles after 300ms
519
- return () => clearTimeout(timer);
520
- }
521
- }, [isDialogOpen]);
522
- const footerTemplate = useCallback(() => {
523
- return (_jsxs("div", { className: "import-dialog-footer", children: [_jsx(ButtonComponent, { cssClass: "e-flat", onClick: handleDialogClose, "aria-label": l10n.getConstant('cancel'), children: l10n.getConstant('cancel') }), _jsx(ButtonComponent, { cssClass: "e-primary import-btn", onClick: handleSaveConditions, "aria-label": l10n.getConstant('save'), children: l10n.getConstant('save') })] }));
524
- }, [handleDialogClose, handleSaveConditions]);
525
- return (_jsxs("div", { className: "conditions-editor-wrapper", "aria-label": l10n.getConstant('conditions'), children: [savedConditions.length === 0 ? (_jsxs("div", { style: { padding: '0.75rem 1rem' }, children: [_jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', margin: '0 0 12px 0' }, children: l10n.getConstant('conditionsEditorLabel') }), _jsx(ButtonComponent, { onClick: handleAddRule, cssClass: "e-outline", style: { width: '100%' }, iconCss: "e-icons e-plus", content: l10n.getConstant('addRule'), "aria-label": l10n.getConstant('addRule') })] })) : (
526
- // Display saved conditions with Edit/Delete buttons
527
- _jsxs("div", { style: { padding: '0.75rem 1.2rem' }, className: "conditions-editor-dialog", role: "region", "aria-label": l10n.getConstant('conditions'), children: [_jsxs("div", { style: { marginBottom: '12px' }, children: [_jsx("p", { id: "conditions-editor-description", style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', margin: '0 0 12px 0' }, children: l10n.getConstant('conditionsEditorLabel') }), _jsx(ButtonComponent, { onClick: handleAddRule, cssClass: "e-outline", style: { width: '100%' }, iconCss: "e-icons e-plus", content: l10n.getConstant('addRule'), "aria-label": l10n.getConstant('addRule') })] }), _jsx(ListBoxComponent, { dataSource: savedConditions.map(c => ({ text: getConditionLabel(c), id: c })), fields: { text: 'text', value: 'id' }, selectionSettings: { mode: 'Single' }, value: [], itemTemplate: (props) => (_jsxs("div", { style: {
528
- display: 'flex',
529
- alignItems: 'center',
530
- justifyContent: 'space-between',
531
- padding: '10px 12px',
532
- borderRadius: '4px',
533
- fontSize: '14px'
534
- }, children: [_jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' }, children: _jsx("span", { children: props.text }) }), _jsxs("div", { style: { display: 'flex', gap: '8px' }, children: [_jsx(ButtonComponent, { onClick: (e) => {
535
- e.stopPropagation();
536
- handleEditCondition(props.id);
537
- }, cssClass: 'e-flat', iconCss: "e-icons e-edit", title: "Edit", "aria-label": `${l10n.getConstant('edit')} ${props.text}` }), _jsx(ButtonComponent, { onClick: (e) => {
538
- e.stopPropagation();
539
- handleDeleteCondition(props.id);
540
- }, cssClass: 'e-flat', iconCss: "e-icons e-trash", title: "Delete", "aria-label": `${l10n.getConstant('delete')} ${props.text}` })] })] })) })] })), _jsx("div", { id: "targetElement", "aria-hidden": !isDialogOpen, style: showStyles ? {
541
- position: 'fixed',
542
- top: '48px',
543
- left: 0,
544
- height: '100dvh',
545
- width: '100dvw'
546
- } : {}, children: _jsx(DialogComponent, { className: "conditions-editor-dialog", isModal: true, visible: isDialogOpen, close: handleDialogClose, showCloseIcon: true, target: '#targetElement', closeOnEscape: true, header: "Conditions", width: "990px", height: "80vh", footerTemplate: footerTemplate, animationSettings: { effect: 'FadeZoom' }, children: _jsxs("div", { style: { display: 'flex', height: '100%' }, children: [_jsx("div", { role: "navigation", "aria-label": l10n.getConstant('conditions'), style: {
547
- width: '280px',
548
- borderRight: '1px solid #e0e0e0',
549
- overflowY: 'auto',
550
- maxHeight: '60vh',
551
- padding: '20px 10px 0 0'
552
- }, children: _jsx(ListBoxComponent, { dataSource: conditionListData, fields: { text: 'text', value: 'id' }, change: (e) => {
553
- if (e.value) {
554
- setActiveConditionType(e.value[0]);
555
- }
556
- }, value: [activeConditionType], selectionSettings: { mode: 'Single' }, itemTemplate: (props) => (_jsx("div", { style: {
557
- padding: '12px 16px',
558
- cursor: 'pointer',
559
- fontSize: '14px',
560
- borderRadius: '6px',
561
- transition: 'all 0.2s ease',
562
- marginBottom: '4px'
563
- }, children: props.text })) }) }), _jsxs("div", { style: {
564
- flex: 1,
565
- padding: '16px',
566
- overflowY: 'auto',
567
- maxHeight: '60vh'
568
- }, role: "region", "aria-live": "polite", "aria-label": activeConditionType, children: [activeConditionType === 'visibleWhen' && supportedConditions.includes('visibleWhen') && (_jsxs("div", { children: [_jsx("h4", { style: { marginTop: 0, marginBottom: '12px' }, children: l10n.getConstant('conditionalVisibility') }), _jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', marginBottom: '12px' }, children: l10n.getConstant('conditionalVisibilityDescription') }), _jsx("div", { tabIndex: -1, "aria-describedby": "conditional-visibility-description", "aria-label": l10n.getConstant('conditionalVisibility'), children: _jsx(QueryBuilderComponent, { ref: qbRefs.visible, dataSource: [], columns: visibleColumns, rule: conditionsRef.current.visibleWhen, ruleChange: handleVisibilityRuleChange }) })] })), activeConditionType === 'hideWhen' && supportedConditions.includes('hideWhen') && (_jsxs("div", { children: [_jsx("h4", { style: { marginTop: 0, marginBottom: '12px' }, children: l10n.getConstant('conditionalHide') }), _jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', marginBottom: '12px' }, children: l10n.getConstant('conditionalHideDescription') }), _jsx("div", { tabIndex: -1, "aria-describedby": "conditional-readonly-description", "aria-label": l10n.getConstant('conditionalHideDescription'), children: _jsx(QueryBuilderComponent, { ref: qbRefs.hidden, dataSource: [], columns: hiddenColumns, rule: conditionsRef.current.hideWhen, ruleChange: handleHideRuleChange }) })] })), activeConditionType === 'readOnlyWhen' && supportedConditions.includes('readOnlyWhen') && (_jsxs("div", { children: [_jsx("h4", { style: { marginTop: 0, marginBottom: '12px' }, children: l10n.getConstant('conditionalReadOnly') }), _jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', marginBottom: '12px' }, children: l10n.getConstant('conditionalReadOnlyDescription') }), _jsx("div", { tabIndex: -1, "aria-describedby": "conditional-readonly-description", "aria-label": l10n.getConstant('conditionalReadOnlyDescription'), children: _jsx(QueryBuilderComponent, { ref: qbRefs.readOnly, dataSource: [], columns: readOnlyColumns, rule: conditionsRef.current.readOnlyWhen, ruleChange: handleReadOnlyRuleChange }) })] })), activeConditionType === 'disabledWhen' && supportedConditions.includes('disabledWhen') && (_jsxs("div", { children: [_jsx("h4", { style: { marginTop: 0, marginBottom: '12px' }, children: l10n.getConstant('conditionalDisable') }), _jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', marginBottom: '12px' }, children: l10n.getConstant('conditionalDisableDescription') }), _jsx("div", { tabIndex: -1, "aria-describedby": "conditional-readonly-description", "aria-label": l10n.getConstant('conditionalDisableDescription'), children: _jsx(QueryBuilderComponent, { ref: qbRefs.disabled, dataSource: [], columns: disabledColumns, rule: conditionsRef.current.disabledWhen, ruleChange: handleDisabledRuleChange }) })] })), activeConditionType === 'requiredWhen' && supportedConditions.includes('requiredWhen') && (_jsxs("div", { children: [_jsx("h4", { style: { marginTop: 0, marginBottom: '12px' }, children: l10n.getConstant('conditionalRequired') }), _jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', marginBottom: '12px' }, children: l10n.getConstant('conditionalRequiredDescription') }), _jsx("div", { tabIndex: -1, "aria-describedby": "conditional-readonly-description", "aria-label": l10n.getConstant('conditionalRequiredDescription'), children: _jsx(QueryBuilderComponent, { ref: qbRefs.required, dataSource: [], columns: requiredColumns, rule: conditionsRef.current.requiredWhen, ruleChange: handleRequiredRuleChange }) })] })), activeConditionType === 'setValueWhen' && supportedConditions.includes('setValueWhen') && (_jsxs("div", { children: [_jsx("h4", { style: { marginTop: 0, marginBottom: '12px' }, children: l10n.getConstant('conditionalSetValue') }), _jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', marginBottom: '12px' }, children: l10n.getConstant('conditionalSetValueDescription') }), _jsx("div", { tabIndex: -1, "aria-describedby": "conditional-readonly-description", "aria-label": l10n.getConstant('conditionalSetValueDescription'), children: _jsx(QueryBuilderComponent, { ref: qbRefs.setValue, dataSource: [], columns: setValueColumns, rule: conditionsRef.current.setValueWhen?.condition, ruleChange: handleSetValueRuleChange }) }), _jsx("div", { style: { marginTop: '16px' }, children: _jsx(ValueRenderer, { componentForEdit: componentForEdit, conditionsRef: conditionsRef, handleSetValueValueChange: handleSetValueValueChange }) })] })), activeConditionType === 'choiceBasedField' && supportedConditions.includes('choiceBasedField') && (_jsxs("div", { children: [_jsx("h4", { style: { marginTop: 0, marginBottom: '12px' }, children: l10n.getConstant('choiceBasedField') }), _jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', marginBottom: '12px' }, children: l10n.getConstant('choiceBasedFieldDescription') }), componentForEdit && (componentForEdit.type === 'dropdown' || componentForEdit.type === 'multiselect') ? (_jsx(ChoiceBasedFieldEditor, { componentForEdit: componentForEdit, componentFields: componentFields, existingRule: conditionsRef.current.choiceBasedField, onChange: handleChoiceBasedFieldChange })) : (_jsx("div", { className: "e-info", style: { padding: '10px', backgroundColor: '#e7f3ff', border: '1px solid #0066cc', borderRadius: '4px' }, role: "alert", "aria-live": "polite", children: l10n.getConstant('choiceBasedOnlyForDropdown') || 'Choice-Based Field Rules apply only to Dropdown and MultiSelect components' }))] })), activeConditionType === 'conditionalData' && supportedConditions.includes('conditionalData') && componentForEdit?.type === 'dataGrid' && (_jsxs("div", { role: "group", "aria-labelledby": "conditional-data-heading", "aria-describedby": "conditional-data-description", children: [_jsx("h4", { style: { marginTop: 0, marginBottom: '12px' }, children: l10n.getConstant('conditionalData') }), _jsx("p", { style: { fontSize: '13px', color: 'rgb(var(--sf-color-on-surface-variant))', marginBottom: '12px' }, children: l10n.getConstant('conditionalDataDescription') }), _jsx(ConditionDataEditor, { componentFields: componentFields, componentForEdit: componentForEdit, excludeFieldId: excludeFieldId, existingRules: conditionsRef.current.conditionalData || componentForEdit?.conditions?.conditionalData, onChange: (rules) => {
569
- updateCondition('conditionalData', rules);
570
- } })] }))] }, savedConditions.join(','))] }) }) })] }));
571
- };
@@ -1,13 +0,0 @@
1
- import React, { type ReactNode } from 'react';
2
- interface AccordionWrapperProps {
3
- title: string;
4
- children: ReactNode;
5
- }
6
- /**
7
- * Accordion Wrapper Component
8
- * Wraps any content in a collapsible accordion with expand/collapse icon
9
- * @param title - Accordion header title
10
- * @param children - Content to display inside accordion
11
- */
12
- export declare const AccordionWrapper: React.FC<AccordionWrapperProps>;
13
- export {};
@@ -1,38 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from 'react';
3
- /**
4
- * Accordion Wrapper Component
5
- * Wraps any content in a collapsible accordion with expand/collapse icon
6
- * @param title - Accordion header title
7
- * @param children - Content to display inside accordion
8
- */
9
- export const AccordionWrapper = ({ title, children }) => {
10
- const [isOpen, setIsOpen] = useState(false);
11
- return (_jsxs("div", { className: 'custom-accordion', style: {
12
- overflow: 'hidden'
13
- }, children: [_jsxs("div", { onClick: () => setIsOpen(!isOpen), role: "button", className: 'custom-accordion-header', tabIndex: 0, "aria-expanded": isOpen, "aria-labelledby": `accordion-content-${title}`, "aria-label": title, onKeyDown: (e) => {
14
- if (e.key === 'Enter' || e.key === ' ') {
15
- e.preventDefault();
16
- setIsOpen(!isOpen);
17
- }
18
- }, style: {
19
- display: 'flex',
20
- alignItems: 'center',
21
- gap: '10px',
22
- height: '45px',
23
- cursor: 'pointer',
24
- userSelect: 'none',
25
- borderBottom: isOpen ? 'none' : '1px solid rgb(var(--sf-color-line-color))'
26
- }, onMouseEnter: (e) => {
27
- e.currentTarget.style.backgroundColor = 'rgba(0, 0, 0, 0.04)';
28
- }, onMouseLeave: (e) => {
29
- e.currentTarget.style.backgroundColor = 'rgb(var(--sf-color-surface))';
30
- }, children: [_jsx("span", { style: { marginLeft: '10px' }, className: `e-icons ${isOpen ? 'e-chevron-down' : 'e-chevron-right'}`, "aria-hidden": "true" }), _jsx("span", { style: {
31
- fontWeight: 500,
32
- fontSize: '14px',
33
- color: 'var(--jsonview-text-color)'
34
- }, children: title })] }), isOpen && (_jsx("div", { id: `accordion-content-${title}`, role: "region", "aria-label": title, style: isOpen ? {
35
- padding: '0.5rem 1rem 1rem',
36
- borderBottom: '1px solid rgb(var(--sf-color-line-color))'
37
- } : undefined, children: children }))] }));
38
- };
@@ -1,11 +0,0 @@
1
- import React from 'react';
2
- import { type CustomValidationRule } from '../types/FormSchema';
3
- import { type FormComponent } from '../types/FormSchema';
4
- export interface CustomValidationEditorProps {
5
- componentFields: FormComponent[];
6
- excludeFieldId?: string;
7
- existingRules?: CustomValidationRule[];
8
- values?: any;
9
- onChange: (rules: CustomValidationRule[]) => void;
10
- }
11
- export declare const CustomValidationEditor: React.FC<CustomValidationEditorProps>;