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

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 (145) hide show
  1. package/Common/CheckboxGroup.d.ts +13 -0
  2. package/Common/CheckboxGroup.js +50 -0
  3. package/Common/ConditionalRuleEngine.d.ts +296 -0
  4. package/Common/ConditionalRuleEngine.js +566 -0
  5. package/Common/CustomTabComponent.d.ts +17 -0
  6. package/Common/CustomTabComponent.js +30 -0
  7. package/Common/CustomValidationEngine.d.ts +58 -0
  8. package/Common/CustomValidationEngine.js +146 -0
  9. package/Common/DataGridComponent.d.ts +20 -0
  10. package/Common/DataGridComponent.js +273 -0
  11. package/Common/FormValidator.d.ts +485 -0
  12. package/Common/FormValidator.js +575 -0
  13. package/Common/MinMaxRuleEngine.d.ts +105 -0
  14. package/Common/MinMaxRuleEngine.js +365 -0
  15. package/Common/StaticHtmlRenderer.d.ts +14 -0
  16. package/Common/StaticHtmlRenderer.js +24 -0
  17. package/Common/expressions/DependencyTracker.d.ts +30 -0
  18. package/Common/expressions/DependencyTracker.js +128 -0
  19. package/Common/expressions/ExpressionEngine.d.ts +95 -0
  20. package/Common/expressions/ExpressionEngine.js +506 -0
  21. package/Common/expressions/ExpressionParser.d.ts +41 -0
  22. package/Common/expressions/ExpressionParser.js +269 -0
  23. package/Common/expressions/useGridExpressions.d.ts +12 -0
  24. package/Common/expressions/useGridExpressions.js +71 -0
  25. package/Common/globalFormId.d.ts +26 -0
  26. package/Common/globalFormId.js +45 -0
  27. package/Common/json-converter.d.ts +444 -0
  28. package/Common/json-converter.js +1184 -0
  29. package/Common/parser.d.ts +98 -0
  30. package/Common/parser.js +753 -0
  31. package/Common/utils.d.ts +130 -0
  32. package/Common/utils.js +574 -0
  33. package/README.md +53 -0
  34. package/index.d.ts +6 -0
  35. package/index.js +6 -0
  36. package/license +13 -0
  37. package/package.json +54 -0
  38. package/src/FormBuilder.d.ts +211 -0
  39. package/src/FormBuilder.js +1299 -0
  40. package/src/components/Database/ConnectionForm.d.ts +8 -0
  41. package/src/components/Database/ConnectionForm.js +28 -0
  42. package/src/components/TopBar.d.ts +10 -0
  43. package/src/components/TopBar.js +7 -0
  44. package/src/components/icons/ComponentIcons.d.ts +44 -0
  45. package/src/components/icons/ComponentIcons.js +40 -0
  46. package/src/components/layout/FormFieldWrapper.d.ts +41 -0
  47. package/src/components/layout/FormFieldWrapper.js +112 -0
  48. package/src/components/layout/LeftPane.d.ts +23 -0
  49. package/src/components/layout/LeftPane.js +310 -0
  50. package/src/components/layout/ListBoxPane.d.ts +24 -0
  51. package/src/components/layout/ListBoxPane.js +94 -0
  52. package/src/components/layout/MainSection.d.ts +39 -0
  53. package/src/components/layout/MainSection.js +1766 -0
  54. package/src/components/layout/Preview.d.ts +12 -0
  55. package/src/components/layout/Preview.js +337 -0
  56. package/src/components/layout/RightPane.d.ts +22 -0
  57. package/src/components/layout/RightPane.js +370 -0
  58. package/src/components/theme/ThemeSwitcher.d.ts +14 -0
  59. package/src/components/theme/ThemeSwitcher.js +24 -0
  60. package/src/components/theme/theme-constant.d.ts +37 -0
  61. package/src/components/theme/theme-constant.js +23 -0
  62. package/src/config/component-properties.json +4929 -0
  63. package/src/config/form-setting.json +56 -0
  64. package/src/config/locale.d.ts +449 -0
  65. package/src/config/locale.js +449 -0
  66. package/src/context/FormSchemaContext.d.ts +32 -0
  67. package/src/context/FormSchemaContext.js +155 -0
  68. package/src/context/LocalizationContext.d.ts +27 -0
  69. package/src/context/LocalizationContext.js +43 -0
  70. package/src/context/ThemeContext.d.ts +23 -0
  71. package/src/context/ThemeContext.js +161 -0
  72. package/src/context/contexts.d.ts +6 -0
  73. package/src/context/contexts.js +6 -0
  74. package/src/context/defaultFormSchema.d.ts +6 -0
  75. package/src/context/defaultFormSchema.js +20 -0
  76. package/src/defaultPalette.d.ts +9 -0
  77. package/src/defaultPalette.js +45 -0
  78. package/src/defaultTemplate.d.ts +3 -0
  79. package/src/defaultTemplate.js +185 -0
  80. package/src/import/schemaImportUtils.d.ts +24 -0
  81. package/src/import/schemaImportUtils.js +121 -0
  82. package/src/index.d.ts +16 -0
  83. package/src/index.js +6 -0
  84. package/src/types/ActionButtons.d.ts +44 -0
  85. package/src/types/ActionButtons.js +27 -0
  86. package/src/types/ComponentProperties.d.ts +33 -0
  87. package/src/types/ComponentProperties.js +2 -0
  88. package/src/types/FormSchema.d.ts +585 -0
  89. package/src/types/FormSchema.js +147 -0
  90. package/src/types/connection.d.ts +19 -0
  91. package/src/types/connection.js +9 -0
  92. package/src/utils/AttributesEditor.d.ts +13 -0
  93. package/src/utils/AttributesEditor.js +117 -0
  94. package/src/utils/ButtonGroupEditor.d.ts +15 -0
  95. package/src/utils/ButtonGroupEditor.js +141 -0
  96. package/src/utils/ChoiceBasedFieldEditor.d.ts +16 -0
  97. package/src/utils/ChoiceBasedFieldEditor.js +87 -0
  98. package/src/utils/ClipboardHelper.d.ts +26 -0
  99. package/src/utils/ClipboardHelper.js +83 -0
  100. package/src/utils/ColumnBuilder.d.ts +11 -0
  101. package/src/utils/ColumnBuilder.js +153 -0
  102. package/src/utils/ColumnSpanEditor.d.ts +8 -0
  103. package/src/utils/ColumnSpanEditor.js +98 -0
  104. package/src/utils/ConditionDataEditor.d.ts +29 -0
  105. package/src/utils/ConditionDataEditor.js +177 -0
  106. package/src/utils/ConditionalEditorUtils.d.ts +27 -0
  107. package/src/utils/ConditionalEditorUtils.js +310 -0
  108. package/src/utils/ConditionsEditor.d.ts +20 -0
  109. package/src/utils/ConditionsEditor.js +571 -0
  110. package/src/utils/CustomAccordion.d.ts +13 -0
  111. package/src/utils/CustomAccordion.js +38 -0
  112. package/src/utils/CustomValidationEditor.d.ts +11 -0
  113. package/src/utils/CustomValidationEditor.js +208 -0
  114. package/src/utils/DataSourceCollector.d.ts +3 -0
  115. package/src/utils/DataSourceCollector.js +252 -0
  116. package/src/utils/ExpressionEditor.d.ts +13 -0
  117. package/src/utils/ExpressionEditor.js +99 -0
  118. package/src/utils/FormSettingsPanel.d.ts +9 -0
  119. package/src/utils/FormSettingsPanel.js +60 -0
  120. package/src/utils/LookupConfig.d.ts +11 -0
  121. package/src/utils/LookupConfig.js +159 -0
  122. package/src/utils/MinMaxValueEditor.d.ts +25 -0
  123. package/src/utils/MinMaxValueEditor.js +188 -0
  124. package/src/utils/OptionsEditor.d.ts +8 -0
  125. package/src/utils/OptionsEditor.js +79 -0
  126. package/src/utils/PropertyRenderer.d.ts +22 -0
  127. package/src/utils/PropertyRenderer.js +210 -0
  128. package/src/utils/ValueRenderer.d.ts +2 -0
  129. package/src/utils/ValueRenderer.js +91 -0
  130. package/src/utils/ej2DbAdaptor.d.ts +6 -0
  131. package/src/utils/ej2DbAdaptor.js +38 -0
  132. package/src/utils/mappingHeuristics.d.ts +10 -0
  133. package/src/utils/mappingHeuristics.js +33 -0
  134. package/src/utils/renderComponent.d.ts +18 -0
  135. package/src/utils/renderComponent.js +300 -0
  136. package/styles/tailwind3.css +67 -0
  137. package/styles/themes/action-buttons.css +110 -0
  138. package/styles/themes/datagrid.css +380 -0
  139. package/styles/themes/drag-reorder.css +248 -0
  140. package/styles/themes/import-dialog.css +292 -0
  141. package/styles/themes/index.css +658 -0
  142. package/styles/themes/left-pane.css +253 -0
  143. package/styles/themes/options-editor.css +63 -0
  144. package/styles/themes/preview.css +702 -0
  145. package/styles/themes/property-dialog.css +371 -0
@@ -0,0 +1,210 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React, { useRef, useState } from 'react';
3
+ import { TextBoxComponent, NumericTextBoxComponent, ColorPickerComponent } from '@syncfusion/ej2-react-inputs';
4
+ import { CheckBoxComponent, SwitchComponent, RadioButtonComponent } from '@syncfusion/ej2-react-buttons';
5
+ import { DropDownListComponent, MultiSelectComponent } from '@syncfusion/ej2-react-dropdowns';
6
+ import { DatePickerComponent, TimePickerComponent, DateTimePickerComponent, DateRangePickerComponent } from '@syncfusion/ej2-react-calendars';
7
+ import { RichTextEditorComponent, Inject, Toolbar, HtmlEditor, QuickToolbar } from '@syncfusion/ej2-react-richtexteditor';
8
+ import { OptionsEditor } from './OptionsEditor';
9
+ import { AttributesEditor } from './AttributesEditor';
10
+ import { ColumnBuilder } from './ColumnBuilder';
11
+ import ButtonGroupEditor from './ButtonGroupEditor';
12
+ import { ColumnSpanEditor } from './ColumnSpanEditor';
13
+ import { useLocalization } from '../context/LocalizationContext';
14
+ import { DataSourceCollector } from './DataSourceCollector';
15
+ import { ExpressionEditor } from './ExpressionEditor';
16
+ import MinMaxValueEditor from './MinMaxValueEditor';
17
+ import LookupConfig from './LookupConfig';
18
+ import { CustomValidationEditor } from './CustomValidationEditor';
19
+ export const PropertyRenderer = ({ propertiesValues, property, initialValue, onChange, existingValues, mode }) => {
20
+ const rteRef = useRef(null);
21
+ const handleChange = (newValue) => {
22
+ onChange(property.key, newValue);
23
+ };
24
+ const { l10n, locale } = useLocalization();
25
+ switch (property.type) {
26
+ case 'text':
27
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(TextBoxComponent, { id: `prop-text-${property.key}`, locale: locale, value: property.key !== 'name' && property.key !== 'width' ?
28
+ initialValue !== undefined ? l10n.getConstant(initialValue) || initialValue : property.default || ''
29
+ : initialValue !== undefined ? initialValue : property.default || '', placeholder: l10n.getConstant(property.placeholder), onChange: (property.key === 'defaultValue' || property.key === 'prefix' || property.key === 'suffix') ? undefined : (e) => handleChange(e.value), change: (property.key === 'defaultValue' || property.key === 'prefix' || property.key === 'suffix') ? (e) => handleChange(e.value) : undefined, floatLabelType: "Never", htmlAttributes: { 'maxLength': `${property.length}`, 'aria-label': `${l10n.getConstant(property.label)} textbox` } })] }));
30
+ case 'number':
31
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(NumericTextBoxComponent, { id: `prop-number-${property.key}`, locale: locale, value: initialValue !== null && initialValue !== undefined ? initialValue : property.default, placeholder: l10n.getConstant(property.placeholder), min: property.min, max: property.max, format: 'n', step: property.step || 1, change: (e) => handleChange(e.value), floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} numeric textbox` } })] }));
32
+ case 'boolean':
33
+ return (_jsxs("div", { className: "property-field property-field-checkbox", children: [property.description && (_jsx("p", { className: "property-description property-description-inline", children: l10n.getConstant(property.description) })), _jsx(CheckBoxComponent, { id: `prop-boolean-${property.key}`, locale: locale, label: l10n.getConstant(property.label), checked: initialValue !== undefined ? initialValue : property.default, change: (e) => handleChange(e.checked), htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} checkbox` } })] }));
34
+ case 'dropdown':
35
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(DropDownListComponent, { id: `prop-dropdown-${property.key}`, dataSource: (property.options || []).map(option => ({
36
+ text: l10n.getConstant(option) || option,
37
+ value: option.charAt(0).toUpperCase() + option.slice(1)
38
+ })), locale: locale, fields: { text: 'text', value: 'value' }, value: initialValue || property.default, placeholder: l10n.getConstant(property.placeholder), change: (e) => handleChange(e.value), floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} dropdown` } })] }));
39
+ case 'multiselect':
40
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(MultiSelectComponent, { id: `prop-dropdown-${property.key}`, dataSource: (property.options || []).map(option => ({
41
+ text: l10n.getConstant(option) || option,
42
+ value: option.charAt(0).toUpperCase() + option.slice(1)
43
+ })), allowCustomValue: true, locale: locale, fields: { text: 'text', value: 'value' }, value: initialValue || property.default, placeholder: l10n.getConstant(property.placeholder), change: (e) => handleChange(e.value), floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} multiselect` } })] }));
44
+ case 'radio':
45
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", id: `label-${property.key}`, children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", id: `desc-${property.key}`, children: l10n.getConstant(property.description) })), _jsx("div", { role: "radiogroup", "aria-labelledby": `label-${property.key}`, className: "radio-options", children: (property.options || []).map((opt, index) => {
46
+ const isLast = index === (property.options || []).length - 1;
47
+ return (_jsxs("div", { className: "radio-option", "aria-label": l10n.getConstant(property.label), children: [_jsx(RadioButtonComponent, { name: `prop-radio-${property.key}`, id: `prop-radio-${property.key}-${opt}`, label: l10n.getConstant(opt), value: opt, checked: initialValue === opt, change: () => handleChange(opt), htmlAttributes: { 'aria-describedby': `desc-${property.key}` } }), _jsx("div", { className: "property-description property-description-inline", style: { marginBottom: isLast ? '0' : '0.5rem', marginTop: '0.3rem' }, children: l10n.getConstant(`visibility_${opt}_description`) })] }, opt));
48
+ }) })] }));
49
+ case 'object':
50
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(TextBoxComponent, { id: `prop-object-${property.key}`, value: typeof initialValue === 'object' ? JSON.stringify(initialValue, null, 2) : (initialValue || JSON.stringify(property.default || {})), placeholder: l10n.getConstant(property.placeholder), multiline: true, locale: locale, change: (e) => {
51
+ try {
52
+ const parsed = JSON.parse(e.value);
53
+ handleChange(parsed);
54
+ }
55
+ catch {
56
+ handleChange(e.value);
57
+ }
58
+ }, floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} json input` } })] }));
59
+ case 'array':
60
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(TextBoxComponent, { id: `prop-array-${property.key}`, value: Array.isArray(initialValue) ? JSON.stringify(initialValue) : (initialValue || JSON.stringify(property.default || [])), placeholder: 'e.g., ["item1", "item2"]', multiline: true, locale: locale, change: (e) => {
61
+ try {
62
+ const parsed = JSON.parse(e.value);
63
+ handleChange(Array.isArray(parsed) ? parsed : []);
64
+ }
65
+ catch (err) {
66
+ // Invalid JSON, keep as is for now
67
+ handleChange(e.value);
68
+ }
69
+ }, floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} array textbox` } })] }));
70
+ case 'html':
71
+ const toolbarSettings = {
72
+ items: ['Undo', 'Redo', '|', 'SourceCode']
73
+ };
74
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(RichTextEditorComponent, { ref: rteRef, id: `prop-html-${property.key}`, editorMode: "HTML", locale: locale, toolbarSettings: toolbarSettings, value: initialValue || property.default || '', change: (e) => handleChange(e.value), saveInterval: 1, height: "180px", enableHtmlSanitizer: false, created: () => {
75
+ if (rteRef.current) {
76
+ setTimeout(() => {
77
+ rteRef.current?.showSourceCode();
78
+ }, 150);
79
+ }
80
+ }, htmlAttributes: { 'aria-label': `HTML Editor` }, children: _jsx(Inject, { services: [Toolbar, HtmlEditor, QuickToolbar] }) })] }));
81
+ case 'conditionBuilder':
82
+ return (_jsxs("div", { className: "property-field", children: [_jsx("label", { className: "property-label", children: l10n.getConstant(property.label) }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx("div", { className: "condition-builder-placeholder", children: _jsx("p", { style: { margin: 0, color: '#999', fontSize: '0.875rem' }, children: "Condition Builder (Coming Soon)" }) })] }));
83
+ case 'expression':
84
+ return (_jsxs("div", { className: "property-field", children: [_jsx("label", { className: "property-label", children: l10n.getConstant(property.label) }), property.description && (_jsx("div", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(ExpressionEditor, { expression: initialValue || property.default || '', availableFields: propertiesValues.availableFields || [], onExpressionChange: (expr) => { if (expr !== undefined && expr !== "" && expr !== initialValue) {
85
+ handleChange(expr);
86
+ } } })] }));
87
+ case 'customValidation':
88
+ return (_jsx("div", { className: "property-field", children: _jsx(CustomValidationEditor, { componentFields: propertiesValues.availableFields || [], excludeFieldId: existingValues?.name, values: property, existingRules: existingValues?.customValidation, onChange: handleChange }) }));
89
+ case 'minMaxEditor':
90
+ return (_jsxs("div", { className: "property-field", children: [_jsx("label", { className: "property-label", children: l10n.getConstant(property.label) }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(MinMaxValueEditor, { label: l10n.getConstant(property.label), initialValue: initialValue || [], mode: property.editorMode || 'number', onChange: handleChange, locale: locale, description: property.description ? l10n.getConstant(property.description) : undefined, currentFieldId: propertiesValues?.name, builderMode: mode })] }));
91
+ case 'lookupconfig':
92
+ return (_jsx(LookupConfig, { value: initialValue, onChange: (newValue) => handleChange(newValue) }));
93
+ case 'options':
94
+ const componentType = property.componentType || 'options';
95
+ const useDataSourceCollector = mode != 'Simple' && ['fromurl'].includes(componentType.toLowerCase());
96
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), useDataSourceCollector ? (_jsx(DataSourceCollector, { value: initialValue || [l10n.getConstant('defaultOptionValue')], onChange: handleChange, type: componentType })) : (_jsx(OptionsEditor, { options: Array.isArray(initialValue) ? initialValue : [l10n.getConstant('defaultOptionValue')], onChange: handleChange, type: componentType }))] }));
97
+ case 'buttonGroup':
98
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(ButtonGroupEditor, { buttons: Array.isArray(initialValue) ? initialValue : (property.default || []), onChange: (val) => handleChange(val) })] }));
99
+ case 'attributes':
100
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), _jsx(AttributesEditor, { attributes: initialValue || [], onChange: handleChange })] }));
101
+ case 'color':
102
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), _jsx(ColorPickerComponent, { locale: locale, value: initialValue || property.default || '', change: (e) => { handleChange(e.value); } }, `form`)] }));
103
+ case 'day':
104
+ const formatDate = (date) => {
105
+ if (!date)
106
+ return '';
107
+ const month = String(date.getMonth() + 1).padStart(2, '0');
108
+ const day = String(date.getDate()).padStart(2, '0');
109
+ const year = date.getFullYear();
110
+ return `${month}/${day}/${year}`;
111
+ };
112
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(DatePickerComponent, { id: `prop-day-${property.key}`, locale: locale, value: initialValue ? new Date(initialValue) : undefined, format: "MM/dd/yyyy", placeholder: l10n.getConstant(property.placeholder) || 'Select a date', change: (e) => handleChange(e.value ? formatDate(e.value) : ''), floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} datePicker` } })] }));
113
+ case 'time':
114
+ const formatTime = (date) => {
115
+ if (!date)
116
+ return '';
117
+ let hours = date.getHours();
118
+ const minutes = String(date.getMinutes()).padStart(2, '0');
119
+ const ampm = hours >= 12 ? 'PM' : 'AM';
120
+ hours = hours % 12 || 12; // Convert to 12-hour format (1-12)
121
+ const hoursStr = String(hours).padStart(2, '0');
122
+ return `${hoursStr}:${minutes} ${ampm}`;
123
+ };
124
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(TimePickerComponent, { id: `prop-time-${property.key}`, locale: locale, value: initialValue ? new Date(`2000-01-01 ${initialValue}`) : undefined, format: "hh:mm a", placeholder: l10n.getConstant(property.placeholder) || 'Select a time', change: (e) => handleChange(e.value ? formatTime(e.value) : ''), floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} timepicker` } })] }));
125
+ case 'datetime':
126
+ const formatDateTime = (date) => {
127
+ if (!date)
128
+ return '';
129
+ const month = String(date.getMonth() + 1).padStart(2, '0');
130
+ const day = String(date.getDate()).padStart(2, '0');
131
+ const year = date.getFullYear();
132
+ let hours = date.getHours();
133
+ const ampm = hours >= 12 ? 'PM' : 'AM';
134
+ hours = hours % 12 || 12; // Convert to 12-hour format (1-12)
135
+ const hoursStr = String(hours).padStart(2, '0');
136
+ const minutes = String(date.getMinutes()).padStart(2, '0');
137
+ return `${month}/${day}/${year} ${hoursStr}:${minutes} ${ampm}`;
138
+ };
139
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(DateTimePickerComponent, { id: `prop-datetime-${property.key}`, locale: locale, value: initialValue ? new Date(initialValue) : undefined, format: "MM/dd/yyyy hh:mm a", placeholder: l10n.getConstant(property.placeholder) || 'Select date and time', change: (e) => handleChange(e.value ? formatDateTime(e.value) : ''), floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} datetimepicker` } })] }));
140
+ case 'daterange':
141
+ const formatDateRange = (startDate, endDate) => {
142
+ if (!startDate || !endDate)
143
+ return '';
144
+ const formatDate = (date) => {
145
+ const month = String(date.getMonth() + 1).padStart(2, '0');
146
+ const day = String(date.getDate()).padStart(2, '0');
147
+ const year = date.getFullYear();
148
+ return `${month}/${day}/${year}`;
149
+ };
150
+ return `${formatDate(startDate)} - ${formatDate(endDate)}`;
151
+ };
152
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(DateRangePickerComponent, { id: `prop-daterange-${property.key}`, locale: locale, startDate: initialValue?.startDate ? new Date(initialValue.startDate) : undefined, endDate: initialValue?.endDate ? new Date(initialValue.endDate) : undefined, format: "MM/dd/yyyy", placeholder: l10n.getConstant(property.placeholder) || 'Select date range', change: (e) => {
153
+ if (e.startDate && e.endDate) {
154
+ handleChange(formatDateRange(e.startDate, e.endDate));
155
+ }
156
+ else {
157
+ handleChange('');
158
+ }
159
+ }, floatLabelType: "Never", htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} daterangepicker` } })] }));
160
+ case 'datagridcolumns':
161
+ return (_jsx("div", { className: "property-field", children: _jsx(ColumnBuilder, { columns: Array.isArray(initialValue) ? initialValue : [], onChange: handleChange, name: propertiesValues.name || [], label: property.label }) }));
162
+ case 'json':
163
+ return (_jsx("div", { className: "property-field", children: _jsx(DataSourceCollector, { datakey: 'data', value: initialValue || property.default || '[]', onChange: handleChange, type: "grid", isAccordion: true }) }));
164
+ case 'columnspaneditor':
165
+ return (_jsxs("div", { className: "property-field", children: [_jsxs("label", { className: "property-label", children: [l10n.getConstant(property.label), property.required && _jsx("span", { className: "required", children: "*" })] }), property.description && (_jsx("p", { className: "property-description", children: l10n.getConstant(property.description) })), _jsx(ColumnSpanEditor, { columnCount: propertiesValues.columns || 2, initialWidths: initialValue?.widths, onChange: (widths) => handleChange({ widths }) }, property.key)] }));
166
+ case 'switch':
167
+ return (_jsxs("div", { className: "property-field", children: [property.description && (_jsx("p", { className: "property-description property-description-inline", children: l10n.getConstant(property.description) })), _jsxs("div", { className: "property-field property-field-checkbox", children: [_jsxs("div", { children: [l10n.getConstant(property.label), ":"] }), _jsx(SwitchComponent, { id: `prop-boolean-${property.key}`, locale: locale, offLabel: l10n.getConstant('off'), onLabel: l10n.getConstant('on'), checked: initialValue !== undefined ? initialValue : property.default, change: (e) => handleChange(e.checked), htmlAttributes: { 'aria-label': `${l10n.getConstant(property.label)} switch` } })] })] }));
168
+ case 'URLImport':
169
+ const [isEnabled, setIsEnabled] = useState(typeof initialValue === 'object'
170
+ ? initialValue?.enabled ?? false
171
+ : Boolean(initialValue));
172
+ const currentValue = {
173
+ enabled: isEnabled,
174
+ serviceUrl: typeof initialValue === 'object'
175
+ ? initialValue?.serviceUrl ?? ''
176
+ : ''
177
+ };
178
+ const handleEnabledChange = (checked) => {
179
+ checked ? handleChange({
180
+ enabled: currentValue.serviceUrl ? true : false,
181
+ serviceUrl: checked ? currentValue.serviceUrl || '' : ''
182
+ }) : handleChange(null);
183
+ setIsEnabled(checked);
184
+ };
185
+ const handleServiceChange = (value) => {
186
+ handleChange({
187
+ enabled: true,
188
+ serviceUrl: value
189
+ });
190
+ };
191
+ return (_jsxs("div", { className: "property-field", children: [_jsx("div", { className: "property-field property-field-checkbox", style: { marginBottom: '0.5rem' }, children: _jsx(CheckBoxComponent, { id: `prop-urlimport-${property.key}`, locale: locale, label: l10n.getConstant(property.label), checked: isEnabled, change: (e) => handleEnabledChange(e.checked === true) }, `${property.key}-${isEnabled}`) }), isEnabled && (_jsxs(_Fragment, { children: [property.description && (_jsx("p", { className: "property-description property-description-inline", children: l10n.getConstant(property.description) })), _jsx("div", { children: _jsx(TextBoxComponent, { id: `prop-url-${property.key}`, locale: locale, value: currentValue.serviceUrl, placeholder: l10n.getConstant(`${property.placeholder}`) || 'Enter service URL', change: (e) => handleServiceChange(e.value), floatLabelType: "Never" }) })] }))] }));
192
+ default:
193
+ return null;
194
+ }
195
+ };
196
+ // Memoize PropertyRenderer to prevent unnecessary re-renders
197
+ const MemoizedPropertyRenderer = React.memo(PropertyRenderer);
198
+ export const PropertyGroupRenderer = React.memo(({ properties, existingValues, initialValues, onChange, mode }) => {
199
+ return (_jsx("div", { className: "property-group", "aria-label": 'property-group', children: _jsx("div", { className: "property-group-content", children: properties.map((property) => {
200
+ // Conditionally hide labelWidth when labelPosition is top/bottom
201
+ if (property.key === 'labelWidth') {
202
+ const labelPosition = initialValues['labelPosition'];
203
+ if (!labelPosition || labelPosition === 'top' || labelPosition === 'bottom') {
204
+ return null; // Don't render labelWidth for top/bottom positions
205
+ }
206
+ }
207
+ return (_jsx(MemoizedPropertyRenderer, { propertiesValues: initialValues, property: property, initialValue: initialValues[property.key], existingValues: existingValues, onChange: onChange, mode: mode }, property.key));
208
+ }) }) }));
209
+ });
210
+ export default MemoizedPropertyRenderer;
@@ -0,0 +1,2 @@
1
+ declare const ValueRenderer: React.FC<any>;
2
+ export default ValueRenderer;
@@ -0,0 +1,91 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { DropDownListComponent, MultiSelectComponent } from "@syncfusion/ej2-react-dropdowns";
3
+ import { useLocalization } from "../context/LocalizationContext";
4
+ import { DatePickerComponent, DateRangePickerComponent, DateTimePickerComponent, TimePickerComponent } from "@syncfusion/ej2-react-calendars";
5
+ import { NumericTextBoxComponent, TextBoxComponent } from "@syncfusion/ej2-react-inputs";
6
+ import { useFormSchema } from "../context/FormSchemaContext";
7
+ import { useMemo } from "react";
8
+ import { Internationalization } from '@syncfusion/ej2-base';
9
+ import { getComponentFromSchema, resolveOptions, useFetchOptions } from "../../Common/utils";
10
+ const ValueRenderer = ({ componentForEdit, conditionsRef, handleSetValueValueChange }) => {
11
+ const { l10n, locale } = useLocalization();
12
+ const { formSchema } = useFormSchema();
13
+ // Get live component with updated options from formSchema
14
+ const liveComponent = useMemo(() => {
15
+ return componentForEdit ? getComponentFromSchema(componentForEdit.id, formSchema) || componentForEdit : componentForEdit;
16
+ }, [componentForEdit, formSchema]);
17
+ const fetchedOptions = useFetchOptions(liveComponent.options);
18
+ const resolvedOptions = Array.isArray(liveComponent.options)
19
+ ? liveComponent.options
20
+ : liveComponent.options?.type === 'url' ? resolveOptions(liveComponent.options, fetchedOptions) : [];
21
+ return (_jsxs("div", { style: { margin: "10px", marginTop: "15px" }, children: [_jsx("label", { className: "property-description", style: { marginBottom: "5px", display: "block" }, children: l10n.getConstant('setValue') }), liveComponent && ((liveComponent.type === 'multiselect' || liveComponent.type === 'checkboxGroup') && liveComponent.options ? (_jsx(MultiSelectComponent, { id: `${liveComponent.id}_setValue`, locale: locale, dataSource: resolvedOptions.map((opt) => {
22
+ const val = typeof opt === 'string' ? opt : opt.value;
23
+ const label = typeof opt === 'string' ? opt : opt.label || opt.text || opt.value;
24
+ return { text: label, value: val };
25
+ }), fields: { text: 'text', value: 'value' }, value: Array.isArray(conditionsRef.current.setValueWhen?.value) ? conditionsRef.current.setValueWhen.value : [], change: (e) => handleSetValueValueChange({ target: { value: e.value } }), placeholder: "Select values", popupHeight: "300px" })) : (liveComponent.type === 'dropdown' || liveComponent.type === 'radio') && liveComponent.options ? (_jsx(DropDownListComponent, { id: `${liveComponent.id}_setValue`, locale: locale, dataSource: resolvedOptions.map((opt) => {
26
+ const val = typeof opt === 'string' ? opt : opt.value;
27
+ const label = typeof opt === 'string' ? opt : opt.label || opt.text || opt.value;
28
+ return { text: label, value: val };
29
+ }), fields: { text: 'text', value: 'value' }, value: conditionsRef.current.setValueWhen?.value || '', change: (e) => handleSetValueValueChange({ target: { value: e.value } }), placeholder: "Select value", popupHeight: "300px" })) : liveComponent.type === 'date' ? (_jsx(DatePickerComponent, { id: `${liveComponent.id}_setValue`, locale: locale, value: conditionsRef.current.setValueWhen?.value ? new Date(conditionsRef.current.setValueWhen.value) : undefined, change: (e) => {
30
+ if (e.value !== null && e.value !== undefined) {
31
+ // Format date using Syncfusion Internationalization
32
+ const intl = new Internationalization();
33
+ const formatter = intl.getDateFormat({
34
+ format: 'MM/dd/yyyy',
35
+ type: 'date'
36
+ });
37
+ handleSetValueValueChange({ target: { value: formatter(e.value) } });
38
+ }
39
+ }, placeholder: "Select date", format: "MM/dd/yyyy" })) : liveComponent.type === 'time' ? (_jsx(TimePickerComponent, { id: `${liveComponent.id}_setValue`, locale: locale, value: conditionsRef.current.setValueWhen?.value ? (typeof conditionsRef.current.setValueWhen.value === 'string'
40
+ ? new Date(`2000-01-01 ${conditionsRef.current.setValueWhen.value}`)
41
+ : conditionsRef.current.setValueWhen.value) : undefined, change: (e) => {
42
+ if (e.value !== null && e.value !== undefined) {
43
+ // Format time using Syncfusion Internationalization
44
+ const intl = new Internationalization();
45
+ const formatter = intl.getDateFormat({
46
+ format: 'hh:mm a',
47
+ type: 'time'
48
+ });
49
+ handleSetValueValueChange({ target: { value: formatter(e.value) } });
50
+ }
51
+ }, placeholder: "Select time", format: "hh:mm a" })) : liveComponent.type === 'dateTime' ? (_jsx(DateTimePickerComponent, { id: `${liveComponent.id}_setValue`, locale: locale, value: conditionsRef.current.setValueWhen?.value ? new Date(conditionsRef.current.setValueWhen.value) : undefined, change: (e) => {
52
+ if (e.value !== null && e.value !== undefined) {
53
+ // Format dateTime using Syncfusion Internationalization
54
+ const intl = new Internationalization();
55
+ const formatter = intl.getDateFormat({
56
+ format: 'MM/dd/yyyy hh:mm a',
57
+ type: 'dateTime'
58
+ });
59
+ handleSetValueValueChange({ target: { value: formatter(e.value) } });
60
+ }
61
+ }, placeholder: "Select date and time", format: "MM/dd/yyyy hh:mm a" })) : liveComponent.type === 'dateRange' ? (_jsx(DateRangePickerComponent, { id: `${liveComponent.id}_setValue`, locale: locale, value: conditionsRef.current.setValueWhen?.value ? (Array.isArray(conditionsRef.current.setValueWhen.value)
62
+ ? [new Date(conditionsRef.current.setValueWhen.value[0]), new Date(conditionsRef.current.setValueWhen.value[1])]
63
+ : undefined) : undefined, change: (e) => {
64
+ if (e.value !== null && e.value !== undefined && Array.isArray(e.value) && e.value.length === 2) {
65
+ // Format date range using Syncfusion Internationalization
66
+ const intl = new Internationalization();
67
+ const formatter = intl.getDateFormat({
68
+ format: 'MM/dd/yyyy',
69
+ type: 'date'
70
+ });
71
+ const startDate = formatter(e.value[0]);
72
+ const endDate = formatter(e.value[1]);
73
+ handleSetValueValueChange({ target: { value: [startDate, endDate] } });
74
+ }
75
+ }, placeholder: "Select date range", format: "MM/dd/yyyy" })) : liveComponent.type === 'number' || liveComponent.type === 'rating' || liveComponent.type === 'rangeSlider' ? (_jsx(NumericTextBoxComponent, { id: `${liveComponent.id}_setValue`, locale: locale, value: conditionsRef.current.setValueWhen?.value || 0, change: (e) => handleSetValueValueChange({ target: { value: e.value } }), placeholder: "Enter number", format: "n" })) : liveComponent.type === 'dateRange' ? (_jsx(DateRangePickerComponent, { id: `${liveComponent.id}_setValue`, locale: locale, value: conditionsRef.current.setValueWhen?.value ? (Array.isArray(conditionsRef.current.setValueWhen.value)
76
+ ? [new Date(conditionsRef.current.setValueWhen.value[0]), new Date(conditionsRef.current.setValueWhen.value[1])]
77
+ : undefined) : undefined, change: (e) => {
78
+ if (e.value !== null && e.value !== undefined && Array.isArray(e.value) && e.value.length === 2) {
79
+ // Format date range using Syncfusion Internationalization
80
+ const intl = new Internationalization();
81
+ const formatter = intl.getDateFormat({
82
+ format: 'MM/dd/yyyy',
83
+ type: 'date'
84
+ });
85
+ const startDate = formatter(e.value[0]);
86
+ const endDate = formatter(e.value[1]);
87
+ handleSetValueValueChange({ target: { value: [startDate, endDate] } });
88
+ }
89
+ }, placeholder: "Select date range", format: "MM/dd/yyyy" })) : (_jsx(TextBoxComponent, { id: `${liveComponent.id}_setValue`, type: "text", locale: locale, value: conditionsRef.current.setValueWhen?.value || '', change: (e) => handleSetValueValueChange({ target: { value: e.value } }), placeholder: `Enter value for ${liveComponent.label || liveComponent.id}` })))] }));
90
+ };
91
+ export default ValueRenderer;
@@ -0,0 +1,6 @@
1
+ import { UrlAdaptor, Query } from '@syncfusion/ej2-data';
2
+ export declare class DbImportAdaptor extends UrlAdaptor {
3
+ private sessionId;
4
+ constructor(sessionId: string);
5
+ read(request: any, _query?: Query): Promise<any>;
6
+ }
@@ -0,0 +1,38 @@
1
+ import { UrlAdaptor } from '@syncfusion/ej2-data';
2
+ export class DbImportAdaptor extends UrlAdaptor {
3
+ sessionId;
4
+ constructor(sessionId) {
5
+ super();
6
+ this.sessionId = sessionId;
7
+ }
8
+ async read(request, _query) {
9
+ const params = request.params || {};
10
+ const action = params.action;
11
+ const table = params.table || '';
12
+ const limit = params.limit || 10;
13
+ let url = '';
14
+ if (action === 'tables') {
15
+ url = `/api/db/tables?sessionId=${encodeURIComponent(this.sessionId)}`;
16
+ }
17
+ else if (action === 'columns') {
18
+ url = `/api/db/columns?sessionId=${encodeURIComponent(this.sessionId)}&table=${encodeURIComponent(table)}`;
19
+ }
20
+ else if (action === 'sample') {
21
+ url = `/api/db/sample?sessionId=${encodeURIComponent(this.sessionId)}&table=${encodeURIComponent(table)}&limit=${limit}`;
22
+ }
23
+ else {
24
+ throw new Error('DbImportAdaptor: action param required (tables|columns|sample)');
25
+ }
26
+ const resp = await fetch(url, { credentials: 'same-origin' });
27
+ if (!resp.ok)
28
+ throw new Error(`Request failed ${resp.status}`);
29
+ const json = await resp.json();
30
+ if (json.tables)
31
+ return { result: json.tables, count: json.tables.length };
32
+ if (json.columns)
33
+ return { result: json.columns, count: json.columns.length };
34
+ if (json.rows)
35
+ return { result: json.rows, count: json.rows.length };
36
+ return { result: [], count: 0 };
37
+ }
38
+ }
@@ -0,0 +1,10 @@
1
+ export type ColumnInfo = {
2
+ name: string;
3
+ dataType: string;
4
+ nullable?: boolean;
5
+ maxLength?: number | null;
6
+ isPrimary?: boolean;
7
+ };
8
+ export declare function suggestFieldType(col: ColumnInfo): string;
9
+ export declare function mapFieldType(col: ColumnInfo): string;
10
+ export declare function suggestDropdownCandidates(_: any[]): any[];
@@ -0,0 +1,33 @@
1
+ // Return a suggested form field type for a given column data type
2
+ export function suggestFieldType(col) {
3
+ const t = (col.dataType || '').toLowerCase();
4
+ if (t.includes('char') || t.includes('text') || t === 'string' || t.includes('uuid'))
5
+ return 'textbox';
6
+ if (t === 'boolean' || t === 'bit' || t === 'tinyint(1)')
7
+ return 'Checkbox';
8
+ if (t.includes('int') || t === 'number' || t === 'numeric' || t === 'decimal' || t === 'bigint')
9
+ return 'number';
10
+ if (t.includes('date') || t.includes('time') || t.includes('timestamp'))
11
+ return 'datepicker';
12
+ if (t === 'json' || t === 'jsonb' || t === 'object')
13
+ return 'textarea';
14
+ // default fallback
15
+ return 'textBox';
16
+ }
17
+ export function mapFieldType(col) {
18
+ const t = (col.dataType || '').toLowerCase();
19
+ if (t.includes('char') || t.includes('text') || t === 'string' || t.includes('uuid'))
20
+ return 'string';
21
+ if (t === 'boolean' || t === 'bit' || t === 'tinyint(1)')
22
+ return 'Checkbox';
23
+ if (t.includes('int') || t === 'number' || t === 'numeric' || t === 'decimal' || t === 'bigint')
24
+ return 'number';
25
+ if (t.includes('date') || t.includes('time') || t.includes('timestamp'))
26
+ return 'date';
27
+ // default fallback
28
+ return 'textBox';
29
+ }
30
+ // Optionally derive dropdown candidates from sample rows (not implemented here)
31
+ export function suggestDropdownCandidates(_) {
32
+ return [];
33
+ }
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { type FormComponent } from '../types/FormSchema';
3
+ import { type FormState } from '../../Common/FormValidator';
4
+ import { type DataGridRef } from '../../Common/DataGridComponent';
5
+ import { L10n } from '@syncfusion/ej2-base';
6
+ export interface RenderComponentProps {
7
+ component: FormComponent;
8
+ formState?: FormState;
9
+ gridRefs?: Record<string, React.RefObject<DataGridRef>>;
10
+ l10n: L10n;
11
+ locale: string;
12
+ formSettings?: any;
13
+ }
14
+ /**
15
+ * Shared component rendering utility used by both MainSection and ComponentPreview
16
+ * Renders a FormComponent with all properties applied consistently
17
+ */
18
+ export declare const RenderComponent: ({ component, formState, gridRefs, l10n, locale, formSettings }: RenderComponentProps) => React.ReactNode;