@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.
- package/README.md +81 -36
- package/diConfig.json +148 -0
- package/dist/ej2-react-form-builder.min.js +10 -0
- package/dist/ej2-react-form-builder.umd.min.js +11 -0
- package/dist/ej2-react-form-builder.umd.min.js.map +1 -0
- package/dist/es6/ej2-react-form-builder.es2015.js +60 -0
- package/dist/es6/ej2-react-form-builder.es2015.js.map +1 -0
- package/form-builder.d.ts +4 -0
- package/form-builder.js +4 -0
- package/index.d.ts +2 -4
- package/index.js +2 -4
- package/license +6 -13
- package/package.json +19 -43
- package/src/form-builder/formbuilder.component.d.ts +37 -0
- package/src/form-builder/formbuilder.component.js +50 -0
- package/src/form-builder/index.d.ts +2 -0
- package/src/form-builder/index.js +2 -0
- package/src/form-builder/toolboxitems-directive.d.ts +28 -0
- package/src/form-builder/toolboxitems-directive.js +47 -0
- package/src/global.js +1 -0
- package/src/index.d.ts +2 -16
- package/src/index.js +2 -6
- package/Common/CheckboxGroup.d.ts +0 -13
- package/Common/CheckboxGroup.js +0 -50
- package/Common/ConditionalRuleEngine.d.ts +0 -296
- package/Common/ConditionalRuleEngine.js +0 -566
- package/Common/CustomTabComponent.d.ts +0 -17
- package/Common/CustomTabComponent.js +0 -30
- package/Common/CustomValidationEngine.d.ts +0 -58
- package/Common/CustomValidationEngine.js +0 -146
- package/Common/DataGridComponent.d.ts +0 -20
- package/Common/DataGridComponent.js +0 -273
- package/Common/FormValidator.d.ts +0 -485
- package/Common/FormValidator.js +0 -575
- package/Common/MinMaxRuleEngine.d.ts +0 -105
- package/Common/MinMaxRuleEngine.js +0 -365
- package/Common/StaticHtmlRenderer.d.ts +0 -14
- package/Common/StaticHtmlRenderer.js +0 -24
- package/Common/expressions/DependencyTracker.d.ts +0 -30
- package/Common/expressions/DependencyTracker.js +0 -128
- package/Common/expressions/ExpressionEngine.d.ts +0 -95
- package/Common/expressions/ExpressionEngine.js +0 -506
- package/Common/expressions/ExpressionParser.d.ts +0 -41
- package/Common/expressions/ExpressionParser.js +0 -269
- package/Common/expressions/useGridExpressions.d.ts +0 -12
- package/Common/expressions/useGridExpressions.js +0 -71
- package/Common/globalFormId.d.ts +0 -26
- package/Common/globalFormId.js +0 -45
- package/Common/json-converter.d.ts +0 -444
- package/Common/json-converter.js +0 -1184
- package/Common/parser.d.ts +0 -98
- package/Common/parser.js +0 -753
- package/Common/utils.d.ts +0 -130
- package/Common/utils.js +0 -574
- package/src/FormBuilder.d.ts +0 -211
- package/src/FormBuilder.js +0 -1299
- package/src/components/Database/ConnectionForm.d.ts +0 -8
- package/src/components/Database/ConnectionForm.js +0 -28
- package/src/components/TopBar.d.ts +0 -10
- package/src/components/TopBar.js +0 -7
- package/src/components/icons/ComponentIcons.d.ts +0 -44
- package/src/components/icons/ComponentIcons.js +0 -40
- package/src/components/layout/FormFieldWrapper.d.ts +0 -41
- package/src/components/layout/FormFieldWrapper.js +0 -112
- package/src/components/layout/LeftPane.d.ts +0 -23
- package/src/components/layout/LeftPane.js +0 -310
- package/src/components/layout/ListBoxPane.d.ts +0 -24
- package/src/components/layout/ListBoxPane.js +0 -94
- package/src/components/layout/MainSection.d.ts +0 -39
- package/src/components/layout/MainSection.js +0 -1766
- package/src/components/layout/Preview.d.ts +0 -12
- package/src/components/layout/Preview.js +0 -337
- package/src/components/layout/RightPane.d.ts +0 -22
- package/src/components/layout/RightPane.js +0 -370
- package/src/components/theme/ThemeSwitcher.d.ts +0 -14
- package/src/components/theme/ThemeSwitcher.js +0 -24
- package/src/components/theme/theme-constant.d.ts +0 -37
- package/src/components/theme/theme-constant.js +0 -23
- package/src/config/component-properties.json +0 -4929
- package/src/config/form-setting.json +0 -56
- package/src/config/locale.d.ts +0 -449
- package/src/config/locale.js +0 -449
- package/src/context/FormSchemaContext.d.ts +0 -32
- package/src/context/FormSchemaContext.js +0 -155
- package/src/context/LocalizationContext.d.ts +0 -27
- package/src/context/LocalizationContext.js +0 -43
- package/src/context/ThemeContext.d.ts +0 -23
- package/src/context/ThemeContext.js +0 -161
- package/src/context/contexts.d.ts +0 -6
- package/src/context/contexts.js +0 -6
- package/src/context/defaultFormSchema.d.ts +0 -6
- package/src/context/defaultFormSchema.js +0 -20
- package/src/defaultPalette.d.ts +0 -9
- package/src/defaultPalette.js +0 -45
- package/src/defaultTemplate.d.ts +0 -3
- package/src/defaultTemplate.js +0 -185
- package/src/import/schemaImportUtils.d.ts +0 -24
- package/src/import/schemaImportUtils.js +0 -121
- package/src/types/ActionButtons.d.ts +0 -44
- package/src/types/ActionButtons.js +0 -27
- package/src/types/ComponentProperties.d.ts +0 -33
- package/src/types/ComponentProperties.js +0 -2
- package/src/types/FormSchema.d.ts +0 -585
- package/src/types/FormSchema.js +0 -147
- package/src/types/connection.d.ts +0 -19
- package/src/types/connection.js +0 -9
- package/src/utils/AttributesEditor.d.ts +0 -13
- package/src/utils/AttributesEditor.js +0 -117
- package/src/utils/ButtonGroupEditor.d.ts +0 -15
- package/src/utils/ButtonGroupEditor.js +0 -141
- package/src/utils/ChoiceBasedFieldEditor.d.ts +0 -16
- package/src/utils/ChoiceBasedFieldEditor.js +0 -87
- package/src/utils/ClipboardHelper.d.ts +0 -26
- package/src/utils/ClipboardHelper.js +0 -83
- package/src/utils/ColumnBuilder.d.ts +0 -11
- package/src/utils/ColumnBuilder.js +0 -153
- package/src/utils/ColumnSpanEditor.d.ts +0 -8
- package/src/utils/ColumnSpanEditor.js +0 -98
- package/src/utils/ConditionDataEditor.d.ts +0 -29
- package/src/utils/ConditionDataEditor.js +0 -177
- package/src/utils/ConditionalEditorUtils.d.ts +0 -27
- package/src/utils/ConditionalEditorUtils.js +0 -310
- package/src/utils/ConditionsEditor.d.ts +0 -20
- package/src/utils/ConditionsEditor.js +0 -571
- package/src/utils/CustomAccordion.d.ts +0 -13
- package/src/utils/CustomAccordion.js +0 -38
- package/src/utils/CustomValidationEditor.d.ts +0 -11
- package/src/utils/CustomValidationEditor.js +0 -208
- package/src/utils/DataSourceCollector.d.ts +0 -3
- package/src/utils/DataSourceCollector.js +0 -252
- package/src/utils/ExpressionEditor.d.ts +0 -13
- package/src/utils/ExpressionEditor.js +0 -99
- package/src/utils/FormSettingsPanel.d.ts +0 -9
- package/src/utils/FormSettingsPanel.js +0 -60
- package/src/utils/LookupConfig.d.ts +0 -11
- package/src/utils/LookupConfig.js +0 -159
- package/src/utils/MinMaxValueEditor.d.ts +0 -25
- package/src/utils/MinMaxValueEditor.js +0 -188
- package/src/utils/OptionsEditor.d.ts +0 -8
- package/src/utils/OptionsEditor.js +0 -79
- package/src/utils/PropertyRenderer.d.ts +0 -22
- package/src/utils/PropertyRenderer.js +0 -210
- package/src/utils/ValueRenderer.d.ts +0 -2
- package/src/utils/ValueRenderer.js +0 -91
- package/src/utils/ej2DbAdaptor.d.ts +0 -6
- package/src/utils/ej2DbAdaptor.js +0 -38
- package/src/utils/mappingHeuristics.d.ts +0 -10
- package/src/utils/mappingHeuristics.js +0 -33
- package/src/utils/renderComponent.d.ts +0 -18
- package/src/utils/renderComponent.js +0 -300
- package/styles/tailwind3.css +0 -67
- package/styles/themes/action-buttons.css +0 -110
- package/styles/themes/datagrid.css +0 -380
- package/styles/themes/drag-reorder.css +0 -248
- package/styles/themes/import-dialog.css +0 -292
- package/styles/themes/index.css +0 -658
- package/styles/themes/left-pane.css +0 -253
- package/styles/themes/options-editor.css +0 -63
- package/styles/themes/preview.css +0 -702
- package/styles/themes/property-dialog.css +0 -371
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import React, { useEffect, useRef, useState, useMemo } from 'react';
|
|
3
|
-
import { TabComponent, TabItemDirective, TabItemsDirective } from '@syncfusion/ej2-react-navigations';
|
|
4
|
-
import { PropertyGroupRenderer } from '../../utils/PropertyRenderer';
|
|
5
|
-
import { useLocalization } from '../../context/LocalizationContext';
|
|
6
|
-
import { FormSettingsPanel } from '../../utils/FormSettingsPanel';
|
|
7
|
-
import { useFormSchema } from '../../context/FormSchemaContext';
|
|
8
|
-
import { ConditionsEditor } from '../../utils/ConditionsEditor';
|
|
9
|
-
import { collectAvailableFieldNames, extractAllDescendantIds } from '../../../Common/utils';
|
|
10
|
-
/**
|
|
11
|
-
* Extract all form field names from components recursively
|
|
12
|
-
*
|
|
13
|
-
* Traverses the form schema and extracts all data field names (excluding layout containers).
|
|
14
|
-
* Used to populate the field list for conditional rule authoring.
|
|
15
|
-
*
|
|
16
|
-
* @spec CONDITIONAL-VALIDATION.md - PropertyDialog integration
|
|
17
|
-
* @requirement Task 7.3-7.5: Extract all form field names recursively
|
|
18
|
-
*
|
|
19
|
-
* @param components - Array of FormComponent from schema
|
|
20
|
-
* @returns Array of FormComponent objects representing data fields only
|
|
21
|
-
*/
|
|
22
|
-
function extractAllFormFieldNames(components) {
|
|
23
|
-
const fields = [];
|
|
24
|
-
// Layout component types to exclude (non-data fields)
|
|
25
|
-
const layoutTypes = ['panel', 'table', 'tabs', 'button', 'message'];
|
|
26
|
-
function traverse(comps) {
|
|
27
|
-
for (const comp of comps) {
|
|
28
|
-
// Skip layout containers and non-data components
|
|
29
|
-
if (!layoutTypes.includes(comp.type)) {
|
|
30
|
-
fields.push(comp);
|
|
31
|
-
}
|
|
32
|
-
// Recursively traverse nested structures
|
|
33
|
-
if (comp.children && Array.isArray(comp.children)) {
|
|
34
|
-
traverse(comp.children);
|
|
35
|
-
}
|
|
36
|
-
// Handle table cells (3D array: [rows][columns][components])
|
|
37
|
-
if (comp.tableCells && Array.isArray(comp.tableCells)) {
|
|
38
|
-
comp.tableCells.forEach((row) => {
|
|
39
|
-
if (Array.isArray(row)) {
|
|
40
|
-
row.forEach((cell) => {
|
|
41
|
-
if (Array.isArray(cell)) {
|
|
42
|
-
traverse(cell);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
// Handle tab items
|
|
49
|
-
if (comp.tabItems && Array.isArray(comp.tabItems)) {
|
|
50
|
-
comp.tabItems.forEach((tabItem) => {
|
|
51
|
-
if (tabItem.content && Array.isArray(tabItem.content)) {
|
|
52
|
-
traverse(tabItem.content);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
traverse(components);
|
|
59
|
-
return fields;
|
|
60
|
-
}
|
|
61
|
-
const shouldShowPropertyInMode = (property, currentMode) => {
|
|
62
|
-
// If property requires developer mode and we're in Simple mode, hide it
|
|
63
|
-
if (property.mode === 'developer' && currentMode === 'Simple') {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
return true;
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* RightPane Component
|
|
70
|
-
*/
|
|
71
|
-
export const RightPane = ({ mode, componentType, configData, formSettingsConfig, existingValues = {}, formSettings, onSave, onPropertyChanged, onClose, builderMode }) => {
|
|
72
|
-
// Store ALL values in refs - ZERO state in this component
|
|
73
|
-
const propertyValuesRef = useRef({});
|
|
74
|
-
const initializedRef = useRef(false);
|
|
75
|
-
const savedButtonsGroupsRef = useRef(null);
|
|
76
|
-
const allowMultipleValueRef = useRef(undefined);
|
|
77
|
-
const columnsValueRef = useRef(null);
|
|
78
|
-
const { l10n } = useLocalization();
|
|
79
|
-
// Get form schema for extracting all field names (for Conditions tab)
|
|
80
|
-
const { formSchema } = useFormSchema();
|
|
81
|
-
// State to force re-render when needed (minimal)
|
|
82
|
-
const [, forceUpdate] = useState({});
|
|
83
|
-
// Get the component definition from the config
|
|
84
|
-
const componentDefinition = configData[componentType];
|
|
85
|
-
// Helper function to find current component in schema
|
|
86
|
-
const findCurrentComponent = (comps) => {
|
|
87
|
-
for (const comp of comps) {
|
|
88
|
-
if (comp.id === existingValues?.id)
|
|
89
|
-
return comp;
|
|
90
|
-
if (comp.children) {
|
|
91
|
-
const found = findCurrentComponent(comp.children);
|
|
92
|
-
if (found)
|
|
93
|
-
return found;
|
|
94
|
-
}
|
|
95
|
-
if (comp.tableCells) {
|
|
96
|
-
for (const row of comp.tableCells) {
|
|
97
|
-
for (const cell of row) {
|
|
98
|
-
const found = findCurrentComponent(cell);
|
|
99
|
-
if (found)
|
|
100
|
-
return found;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (comp.tabItems) {
|
|
105
|
-
for (const tab of comp.tabItems) {
|
|
106
|
-
if (tab.content) {
|
|
107
|
-
const found = findCurrentComponent(tab.content);
|
|
108
|
-
if (found)
|
|
109
|
-
return found;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
};
|
|
116
|
-
// Get current component and its child IDs for conditions editor
|
|
117
|
-
const currentComponent = useMemo(() => findCurrentComponent(formSchema.components), [formSchema.components, existingValues?.id]);
|
|
118
|
-
const excludeChildIds = useMemo(() => currentComponent ? extractAllDescendantIds(currentComponent) : [], [currentComponent]);
|
|
119
|
-
// Initialize property values with defaults - only when sidebar opens
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
if (componentDefinition) {
|
|
122
|
-
const values = {};
|
|
123
|
-
componentDefinition.groups.forEach((group) => {
|
|
124
|
-
group.properties.forEach((property) => {
|
|
125
|
-
let value = property.default;
|
|
126
|
-
// Handle Validation group properties
|
|
127
|
-
if (group.name === 'Validation') {
|
|
128
|
-
if (existingValues?.[property.key] !== undefined) {
|
|
129
|
-
value = existingValues[property.key];
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
value = property.default;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// Handle Layout group properties
|
|
136
|
-
else if (group.name === 'Layout') {
|
|
137
|
-
if (existingValues.layout?.[property.key] !== undefined) {
|
|
138
|
-
value = existingValues.layout[property.key];
|
|
139
|
-
}
|
|
140
|
-
else if (existingValues[property.key] !== undefined) {
|
|
141
|
-
value = existingValues[property.key];
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
value = property.default;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
// Handle all other groups
|
|
148
|
-
else {
|
|
149
|
-
if (existingValues[property.key] !== undefined) {
|
|
150
|
-
value = existingValues[property.key];
|
|
151
|
-
}
|
|
152
|
-
else if (property.key === 'value' && existingValues.defaultValue !== undefined) {
|
|
153
|
-
value = existingValues.defaultValue;
|
|
154
|
-
}
|
|
155
|
-
else if (property.key === 'rows' && existingValues.textareaRows !== undefined) {
|
|
156
|
-
value = existingValues.textareaRows;
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
value = property.default;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
values[property.key] = value;
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
// Store in refs only (NO state)
|
|
166
|
-
propertyValuesRef.current = values;
|
|
167
|
-
initializedRef.current = true;
|
|
168
|
-
// Initialize allowMultiple state for button component
|
|
169
|
-
if (componentType === 'button') {
|
|
170
|
-
const initialAllowMultiple = values.allowMultiple ?? false;
|
|
171
|
-
allowMultipleValueRef.current = initialAllowMultiple;
|
|
172
|
-
savedButtonsGroupsRef.current = values.buttonsGroups || [];
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}, [componentType, componentDefinition, existingValues]);
|
|
176
|
-
// Determine which properties should be visible based on allowMultiple flag
|
|
177
|
-
const shouldShowProperty = (propKey, allowMultiple) => {
|
|
178
|
-
if (allowMultiple) {
|
|
179
|
-
const visibleKeys = ['allowMultiple', 'name', 'buttonsGroups', 'gap', 'cssClass', 'width', 'position', 'size', 'conditions'];
|
|
180
|
-
return visibleKeys.includes(propKey);
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
const visibleKeys = ['allowMultiple', 'name', 'buttonType', 'cssClass', 'disabled', 'iconCss', 'iconPosition', 'label', 'position', 'style', 'size', 'conditions'];
|
|
184
|
-
return visibleKeys.includes(propKey);
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
// Filter groups and properties based on visibility rules
|
|
188
|
-
const getFilteredGroups = (groups, allowMultiple) => {
|
|
189
|
-
return groups.map(group => ({
|
|
190
|
-
...group,
|
|
191
|
-
properties: group.properties.filter(prop => shouldShowProperty(prop.key, allowMultiple))
|
|
192
|
-
})).filter(group => group.properties.length > 0);
|
|
193
|
-
};
|
|
194
|
-
const applyModeFiltering = (groups) => {
|
|
195
|
-
return groups.map(group => ({
|
|
196
|
-
...group,
|
|
197
|
-
properties: group.properties.filter(prop => shouldShowPropertyInMode(prop, builderMode))
|
|
198
|
-
})).filter(group => group.properties.length > 0);
|
|
199
|
-
};
|
|
200
|
-
/**
|
|
201
|
-
* Filter lookup properties based on displayFormat selection
|
|
202
|
-
* When displayFormat is Radio or CheckboxGroup, remove specific properties
|
|
203
|
-
*/
|
|
204
|
-
const getFilteredLookupGroups = (groups, displayFormat) => {
|
|
205
|
-
const isRadioOrCheckbox = ['Radio', 'Checkbox', 'CheckboxGroup'].includes(displayFormat);
|
|
206
|
-
if (!isRadioOrCheckbox) {
|
|
207
|
-
return groups; // No filtering needed for Dropdown and MultiSelect
|
|
208
|
-
}
|
|
209
|
-
// Properties to remove for Radio/CheckboxGroup
|
|
210
|
-
const removeFromDisplay = ['placeholder', 'showClearButton', 'readOnly', 'enableVirtualization', 'floatLabelType', 'popupHeight', 'popupWidth'];
|
|
211
|
-
const removeFromValidation = ['validateOn'];
|
|
212
|
-
return groups.map(group => {
|
|
213
|
-
let filteredProps = group.properties;
|
|
214
|
-
if (group.name === 'Display') {
|
|
215
|
-
filteredProps = filteredProps.filter(prop => !removeFromDisplay.includes(prop.key));
|
|
216
|
-
}
|
|
217
|
-
else if (group.name === 'Validation') {
|
|
218
|
-
filteredProps = filteredProps.filter(prop => !removeFromValidation.includes(prop.key));
|
|
219
|
-
}
|
|
220
|
-
else if (group.name === 'Conditions') {
|
|
221
|
-
// For Conditions, keep only conditionalReadonly if it exists
|
|
222
|
-
filteredProps = filteredProps.map(prop => {
|
|
223
|
-
if (prop.key === 'conditions') {
|
|
224
|
-
return {
|
|
225
|
-
...prop,
|
|
226
|
-
supportedConditions: [
|
|
227
|
-
"visibleWhen",
|
|
228
|
-
"hideWhen",
|
|
229
|
-
"requiredWhen",
|
|
230
|
-
"setValueWhen",
|
|
231
|
-
"disabledWhen"
|
|
232
|
-
]
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
return prop;
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
return {
|
|
239
|
-
...group,
|
|
240
|
-
properties: filteredProps
|
|
241
|
-
};
|
|
242
|
-
}).filter(group => group.properties.length > 0);
|
|
243
|
-
};
|
|
244
|
-
// Real-time property change - saves immediately on change
|
|
245
|
-
const handlePropertyChange = (key, value) => {
|
|
246
|
-
// Update ref immediately
|
|
247
|
-
propertyValuesRef.current = {
|
|
248
|
-
...propertyValuesRef.current,
|
|
249
|
-
[key]: value,
|
|
250
|
-
};
|
|
251
|
-
// Handle allowMultiple toggle for button component
|
|
252
|
-
if (key === 'allowMultiple' && componentType === 'button') {
|
|
253
|
-
const prevAllowMultiple = allowMultipleValueRef.current;
|
|
254
|
-
allowMultipleValueRef.current = value;
|
|
255
|
-
if (value === false) {
|
|
256
|
-
savedButtonsGroupsRef.current = propertyValuesRef.current.buttonsGroups;
|
|
257
|
-
propertyValuesRef.current.buttonsGroups = [];
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
propertyValuesRef.current.buttonsGroups = savedButtonsGroupsRef.current || [];
|
|
261
|
-
}
|
|
262
|
-
// Only re-render if visibility actually changed
|
|
263
|
-
if (prevAllowMultiple !== value) {
|
|
264
|
-
forceUpdate({});
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
// Track buttonsGroups changes when allowMultiple is true
|
|
268
|
-
if (key === 'buttonsGroups' && componentType === 'button' && allowMultipleValueRef.current === true) {
|
|
269
|
-
savedButtonsGroupsRef.current = value;
|
|
270
|
-
}
|
|
271
|
-
// Handle columns change for table component
|
|
272
|
-
if (key === 'columns' && componentType === 'table') {
|
|
273
|
-
const prevColumns = columnsValueRef.current;
|
|
274
|
-
columnsValueRef.current = value;
|
|
275
|
-
propertyValuesRef.current.columns = value;
|
|
276
|
-
// Only re-render if columns actually changed
|
|
277
|
-
if (prevColumns !== value) {
|
|
278
|
-
forceUpdate({});
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
const propertyDef = componentDefinition?.groups
|
|
282
|
-
.flatMap(g => g.properties)
|
|
283
|
-
.find(p => p.key === key);
|
|
284
|
-
const fieldLabel = propertyDef?.label || key;
|
|
285
|
-
const label = propertyValuesRef.current.label || '';
|
|
286
|
-
// FIRE the property changed event
|
|
287
|
-
if (onPropertyChanged) {
|
|
288
|
-
onPropertyChanged({
|
|
289
|
-
field: label,
|
|
290
|
-
property: fieldLabel,
|
|
291
|
-
value,
|
|
292
|
-
name: existingValues?.name
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
// AUTO-SAVE: Save to parent immediately on every change
|
|
296
|
-
// This triggers real-time updates to the form schema
|
|
297
|
-
const valuesToSave = { ...propertyValuesRef.current };
|
|
298
|
-
onSave(valuesToSave);
|
|
299
|
-
};
|
|
300
|
-
/**
|
|
301
|
-
* Handle conditions change from ConditionsEditor
|
|
302
|
-
*
|
|
303
|
-
* @spec CONDITIONAL-VALIDATION.md - PropertyDialog integration
|
|
304
|
-
* @requirement Task 7.10-7.11: Store condition changes and call preview callback
|
|
305
|
-
*/
|
|
306
|
-
const handleConditionsChange = (conditions) => {
|
|
307
|
-
// Store conditions in the ref first
|
|
308
|
-
propertyValuesRef.current = {
|
|
309
|
-
...propertyValuesRef.current,
|
|
310
|
-
conditions,
|
|
311
|
-
};
|
|
312
|
-
onSave(propertyValuesRef.current);
|
|
313
|
-
};
|
|
314
|
-
const handleClose = () => {
|
|
315
|
-
propertyValuesRef.current = {};
|
|
316
|
-
initializedRef.current = false;
|
|
317
|
-
savedButtonsGroupsRef.current = null;
|
|
318
|
-
allowMultipleValueRef.current = false;
|
|
319
|
-
columnsValueRef.current = null;
|
|
320
|
-
onClose();
|
|
321
|
-
};
|
|
322
|
-
// If component definition doesn't exist, show error
|
|
323
|
-
if (!componentDefinition && mode === 'component') {
|
|
324
|
-
return (_jsxs("div", { className: "right-sidebar-content", children: [_jsxs("div", { className: "sidebar-header", children: [_jsx("h3", { children: "Error" }), _jsx("button", { "aria-label": "Close panel", className: "close-btn", onClick: handleClose, title: "Close (Esc)", children: "\u2715" })] }), _jsx("div", { className: "sidebar-body", children: _jsxs("p", { style: { color: 'var(--sf-error-color, red)', padding: '1rem' }, children: ["Component definition not found for: ", componentType] }) })] }));
|
|
325
|
-
}
|
|
326
|
-
if (mode === 'formSettings') {
|
|
327
|
-
return (_jsx(FormSettingsPanel, { settings: formSettings, formSettingsConfig: formSettingsConfig, onSave: onSave }));
|
|
328
|
-
}
|
|
329
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sidebar-header", children: [_jsx("h3", { children: l10n.getConstant('fieldSettings') }), _jsx("button", { "aria-label": "Close panel", className: "close-btn", onClick: handleClose, title: "Close (Esc)", children: "\u2715" })] }), _jsx("div", { className: `rightpane-property-content single-view`, role: "region", "aria-labelledby": "field-settings-heading", children: _jsx("div", { className: "properties-section", "aria-label": l10n.getConstant('fieldSettings'), children: _jsx("div", { className: "property-tabs-wrapper", children: _jsx(TabComponent, { className: "property-tabs", heightAdjustMode: "Auto", "aria-label": l10n.getConstant('fieldSettings'), animation: { previous: { effect: 'None' }, next: { effect: 'None' } }, children: _jsx(TabItemsDirective, { children: useMemo(() => {
|
|
330
|
-
let groupsToRender = componentDefinition.groups;
|
|
331
|
-
// Filter for button component based on allowMultiple
|
|
332
|
-
if (componentType === 'button') {
|
|
333
|
-
groupsToRender = getFilteredGroups(componentDefinition.groups, (allowMultipleValueRef.current || existingValues?.allowMultiple));
|
|
334
|
-
}
|
|
335
|
-
// Filter for lookup component based on displayFormat
|
|
336
|
-
else if (componentType === 'lookup') {
|
|
337
|
-
const displayFormat = propertyValuesRef.current?.lookUpConfig?.displayFormat || 'Dropdown';
|
|
338
|
-
groupsToRender = getFilteredLookupGroups(componentDefinition.groups, displayFormat);
|
|
339
|
-
}
|
|
340
|
-
groupsToRender = applyModeFiltering(groupsToRender);
|
|
341
|
-
return groupsToRender.map((group, index) => (_jsx(TabItemDirective, { header: { text: l10n.getConstant(group.name.toLowerCase()) }, content: () => {
|
|
342
|
-
// Special handling for Conditions group
|
|
343
|
-
if (group.name === 'Conditions') {
|
|
344
|
-
// Extract all form fields dynamically
|
|
345
|
-
const allFormFields = extractAllFormFieldNames(formSchema.components);
|
|
346
|
-
const conditionsProperty = group.properties.find(p => p.key === 'conditions');
|
|
347
|
-
const supportedConditions = conditionsProperty?.supportedConditions ||
|
|
348
|
-
['visibleWhen', 'readOnlyWhen', 'disabledWhen'];
|
|
349
|
-
return (_jsxs("div", { children: [_jsx(ConditionsEditor, { componentFields: allFormFields, excludeFieldId: existingValues?.id, componentForEdit: currentComponent || undefined, excludeChildIds: excludeChildIds, existingConditions: existingValues?.conditions, onChange: handleConditionsChange, supportedConditions: supportedConditions, builderMode: builderMode }, currentComponent?.options?.length), _jsx("input", { style: { opacity: 0, pointerEvents: 'none', width: 0, height: 0 }, "aria-hidden": "true", tabIndex: 0, onFocus: (e) => {
|
|
350
|
-
const input = e.currentTarget;
|
|
351
|
-
// Only forward focus the first time, then remove from tab order
|
|
352
|
-
if (input.dataset.forwarded === 'true') {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
input.dataset.forwarded = 'true';
|
|
356
|
-
input.tabIndex = -1;
|
|
357
|
-
const btn = input.parentElement?.querySelector('.conditions-editor-wrapper button, .conditions-editor-wrapper [role="button"]');
|
|
358
|
-
if (btn) {
|
|
359
|
-
btn.focus();
|
|
360
|
-
}
|
|
361
|
-
}, type: "text" })] }));
|
|
362
|
-
}
|
|
363
|
-
// Default: render PropertyGroupRenderer
|
|
364
|
-
return (_jsx(PropertyGroupRenderer, { groupName: group.name, properties: group.properties, existingValues: existingValues, initialValues: { ...propertyValuesRef.current,
|
|
365
|
-
availableFields: collectAvailableFieldNames(formSchema.components)
|
|
366
|
-
}, onChange: handlePropertyChange, mode: builderMode }));
|
|
367
|
-
} }, `tab-${componentType}-${index}`)));
|
|
368
|
-
}, [componentType, allowMultipleValueRef.current, propertyValuesRef.current?.lookUpConfig?.displayFormat, componentDefinition.groups]) }) }, `tabs-${componentType}-${columnsValueRef.current}-${propertyValuesRef.current}`) }) }) })] }));
|
|
369
|
-
};
|
|
370
|
-
export default React.memo(RightPane);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ThemeSwitcher - Dropdown component for selecting Syncfusion theme variants
|
|
3
|
-
*/
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import type { ThemeVariant } from './theme-constant';
|
|
6
|
-
interface ThemeSwitcherProps {
|
|
7
|
-
currentTheme: ThemeVariant;
|
|
8
|
-
setTheme: (variant: ThemeVariant) => void;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* ThemeSwitcher component renders a DropDownButton for theme selection
|
|
12
|
-
*/
|
|
13
|
-
export declare function ThemeSwitcher({ currentTheme, setTheme }: ThemeSwitcherProps): React.JSX.Element;
|
|
14
|
-
export {};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { DropDownButtonComponent } from '@syncfusion/ej2-react-splitbuttons';
|
|
3
|
-
import { AVAILABLE_THEMES } from './theme-constant';
|
|
4
|
-
/**
|
|
5
|
-
* ThemeSwitcher component renders a DropDownButton for theme selection
|
|
6
|
-
*/
|
|
7
|
-
export function ThemeSwitcher({ currentTheme, setTheme }) {
|
|
8
|
-
// Convert theme options to DropDownButton items
|
|
9
|
-
const items = AVAILABLE_THEMES.map(theme => ({
|
|
10
|
-
id: theme.id,
|
|
11
|
-
text: theme.text,
|
|
12
|
-
iconCss: currentTheme === theme.id ? 'e-icons e-check' : ''
|
|
13
|
-
}));
|
|
14
|
-
/**
|
|
15
|
-
* Handle theme selection from dropdown
|
|
16
|
-
*/
|
|
17
|
-
const handleSelect = (args) => {
|
|
18
|
-
const selectedTheme = AVAILABLE_THEMES.find(t => t.id === args.item.id);
|
|
19
|
-
if (selectedTheme) {
|
|
20
|
-
setTheme(selectedTheme.id);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
return (_jsx("div", { className: "theme-switcher", style: { display: 'inline-block', marginRight: '10px' }, children: _jsx(DropDownButtonComponent, { cssClass: "action-btn theme-dropdown", items: items, select: handleSelect, content: "Choose Theme", title: "Choose theme" }) }));
|
|
24
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Theme configuration constants for Syncfusion EJ2 components
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Supported theme variants
|
|
6
|
-
*/
|
|
7
|
-
export type ThemeVariant = 'material3' | 'tailwind3' | 'bootstrap5.3' | 'fluent2';
|
|
8
|
-
/**
|
|
9
|
-
* Theme mode (light or dark)
|
|
10
|
-
*/
|
|
11
|
-
export type ThemeMode = 'light' | 'dark';
|
|
12
|
-
/**
|
|
13
|
-
* Complete theme configuration
|
|
14
|
-
*/
|
|
15
|
-
export interface ThemeConfig {
|
|
16
|
-
variant: ThemeVariant;
|
|
17
|
-
mode: ThemeMode;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Theme option for dropdown selection
|
|
21
|
-
*/
|
|
22
|
-
export interface ThemeOption {
|
|
23
|
-
id: ThemeVariant;
|
|
24
|
-
text: string;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Available theme options for theme switcher dropdown
|
|
28
|
-
*/
|
|
29
|
-
export declare const AVAILABLE_THEMES: ThemeOption[];
|
|
30
|
-
/**
|
|
31
|
-
* Default theme configuration
|
|
32
|
-
*/
|
|
33
|
-
export declare const DEFAULT_THEME: ThemeConfig;
|
|
34
|
-
/**
|
|
35
|
-
* LocalStorage key for theme persistence
|
|
36
|
-
*/
|
|
37
|
-
export declare const THEME_STORAGE_KEY = "form-builder-theme";
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Theme configuration constants for Syncfusion EJ2 components
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Available theme options for theme switcher dropdown
|
|
6
|
-
*/
|
|
7
|
-
export const AVAILABLE_THEMES = [
|
|
8
|
-
{ id: 'material3', text: 'Material 3' },
|
|
9
|
-
{ id: 'tailwind3', text: 'Tailwind 3' },
|
|
10
|
-
{ id: 'bootstrap5.3', text: 'Bootstrap 5.3' },
|
|
11
|
-
{ id: 'fluent2', text: 'Fluent 2' }
|
|
12
|
-
];
|
|
13
|
-
/**
|
|
14
|
-
* Default theme configuration
|
|
15
|
-
*/
|
|
16
|
-
export const DEFAULT_THEME = {
|
|
17
|
-
variant: 'tailwind3',
|
|
18
|
-
mode: 'light'
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* LocalStorage key for theme persistence
|
|
22
|
-
*/
|
|
23
|
-
export const THEME_STORAGE_KEY = 'form-builder-theme';
|