@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,43 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { useMemo, createContext, useContext } from 'react';
4
+ import { L10n } from '@syncfusion/ej2-base';
5
+ import { defaultLocale } from '../config/locale';
6
+ // Create the Localization context
7
+ export const LocalizationContext = createContext(undefined);
8
+ /**
9
+ * Hook to use Localization context
10
+ * Must be used within LocalizationProvider
11
+ */
12
+ export const useLocalization = () => {
13
+ const context = useContext(LocalizationContext);
14
+ if (!context) {
15
+ throw new Error('useLocalization must be used within LocalizationProvider');
16
+ }
17
+ return context;
18
+ };
19
+ /**
20
+ * LocalizationProvider manages the localization state with L10n
21
+ * Provides L10n instance to all components in the tree
22
+ */
23
+ export const LocalizationProvider = ({ children, locale }) => {
24
+ // State for current locale
25
+ const [currentLocale, setCurrentLocale] = React.useState(() => {
26
+ if (locale && L10n?.locale?.[locale]) {
27
+ return locale;
28
+ }
29
+ return 'en-US';
30
+ });
31
+ // Create L10n instance with current locale
32
+ const l10n = useMemo(() => {
33
+ return new L10n('formbuilder', defaultLocale, currentLocale);
34
+ }, [currentLocale]);
35
+ // Memoize the context value to prevent unnecessary re-renders
36
+ const value = useMemo(() => ({
37
+ l10n,
38
+ locale: locale || 'en-US',
39
+ setLocale: setCurrentLocale
40
+ }), [l10n, currentLocale]);
41
+ return (_jsx(LocalizationContext.Provider, { value: value, children: children }));
42
+ };
43
+ export default LocalizationProvider;
@@ -0,0 +1,23 @@
1
+ import { type ReactNode, type JSX } from 'react';
2
+ import { type ThemeVariant, type ThemeMode, type ThemeConfig } from '../components/theme/theme-constant';
3
+ interface ThemeContextValue {
4
+ currentTheme: ThemeVariant;
5
+ themeMode: ThemeMode;
6
+ setTheme: (variant: ThemeVariant) => void;
7
+ setMode: (mode: ThemeMode) => void;
8
+ setThemeConfig: (config: ThemeConfig) => void;
9
+ }
10
+ interface ThemeProviderProps {
11
+ children: ReactNode;
12
+ showTopBar?: boolean;
13
+ }
14
+ /**
15
+ * ThemeProvider component - wraps the app and provides theme context
16
+ */
17
+ export declare function ThemeProvider({ children, showTopBar }: ThemeProviderProps): JSX.Element;
18
+ /**
19
+ * Hook to access theme context
20
+ * @throws Error if used outside ThemeProvider
21
+ */
22
+ export declare function useTheme(): ThemeContextValue;
23
+ export {};
@@ -0,0 +1,161 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ThemeContext - Global theme state management for Syncfusion EJ2 components
4
+ * Manages theme variant selection and light/dark mode with localStorage persistence
5
+ */
6
+ import React from 'react';
7
+ import { createContext, useContext, useCallback, useLayoutEffect } from 'react';
8
+ import { DEFAULT_THEME, THEME_STORAGE_KEY } from '../components/theme/theme-constant';
9
+ import TopBar from '../components/TopBar';
10
+ // Import theme CSS files with ?url suffix so Vite processes them correctly for production
11
+ import material3ThemeUrl from '../../styles/material3.css?url';
12
+ import tailwind3ThemeUrl from '../../styles/tailwind3.css?url';
13
+ import bootstrap53ThemeUrl from '../../styles/bootstrap5.3.css?url';
14
+ import fluent2ThemeUrl from '../../styles/fluent2.css?url';
15
+ const ThemeContext = createContext(undefined);
16
+ /**
17
+ * Load theme configuration from localStorage
18
+ */
19
+ function loadThemeFromStorage() {
20
+ try {
21
+ const stored = localStorage.getItem(THEME_STORAGE_KEY);
22
+ if (stored) {
23
+ const parsed = JSON.parse(stored);
24
+ return {
25
+ variant: parsed.variant || DEFAULT_THEME.variant,
26
+ mode: parsed.mode || DEFAULT_THEME.mode
27
+ };
28
+ }
29
+ const legacy = localStorage.getItem('theme');
30
+ if (legacy === 'light' || legacy === 'dark') {
31
+ return { ...DEFAULT_THEME, mode: legacy };
32
+ }
33
+ }
34
+ catch (error) {
35
+ console.warn('Failed to load theme from localStorage:', error);
36
+ }
37
+ // Detect system preference for dark mode
38
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
39
+ return {
40
+ ...DEFAULT_THEME,
41
+ mode: prefersDark ? 'dark' : 'light'
42
+ };
43
+ }
44
+ /**
45
+ * Save theme configuration to localStorage
46
+ */
47
+ function saveThemeToStorage(config) {
48
+ try {
49
+ localStorage.setItem(THEME_STORAGE_KEY, JSON.stringify(config));
50
+ try {
51
+ localStorage.setItem('theme', config.mode);
52
+ }
53
+ catch (e) {
54
+ // ignore
55
+ }
56
+ }
57
+ catch (error) {
58
+ console.warn('Failed to save theme to localStorage:', error);
59
+ }
60
+ }
61
+ /**
62
+ * Apply theme variant by updating/creating a link element
63
+ * This ensures only ONE theme is active at a time
64
+ */
65
+ function applyThemeVariant(variant) {
66
+ const linkId = 'syncfusion-theme-dynamic';
67
+ let linkElement = document.getElementById(linkId);
68
+ if (!linkElement) {
69
+ // Create the link element if it doesn't exist
70
+ linkElement = document.createElement('link');
71
+ linkElement.id = linkId;
72
+ linkElement.rel = 'stylesheet';
73
+ linkElement.type = 'text/css';
74
+ document.head.appendChild(linkElement);
75
+ }
76
+ // Map variant to the actual theme file URL (Vite will handle these correctly in both dev and production)
77
+ const themePathMap = {
78
+ material3: material3ThemeUrl,
79
+ tailwind3: tailwind3ThemeUrl,
80
+ 'bootstrap5.3': bootstrap53ThemeUrl,
81
+ fluent2: fluent2ThemeUrl
82
+ };
83
+ // Update href to switch theme (this replaces the old theme)
84
+ linkElement.href = themePathMap[variant];
85
+ }
86
+ /**
87
+ * Apply theme mode (light/dark) and variant by updating data-theme attribute and body classes
88
+ */
89
+ function applyThemeMode(mode, variant) {
90
+ // Set data-theme attribute on root element
91
+ document.documentElement.setAttribute('data-theme', mode);
92
+ // Update body classes for Syncfusion components
93
+ if (mode === 'dark') {
94
+ document.body.classList.add('e-dark-mode');
95
+ document.body.classList.remove('e-light-mode');
96
+ }
97
+ else {
98
+ document.body.classList.add('e-light-mode');
99
+ document.body.classList.remove('e-dark-mode');
100
+ }
101
+ // Add theme variant class to body if variant is provided
102
+ if (variant) {
103
+ // Remove all existing theme variant classes first
104
+ document.body.classList.remove('theme-material3', 'theme-tailwind3', 'theme-bootstrap5-3', 'theme-fluent2');
105
+ // Add current theme variant class (normalize bootstrap5.3 to bootstrap5-3 for CSS class)
106
+ const themeClass = `theme-${variant.replace('.', '-')}`;
107
+ document.body.classList.add(themeClass);
108
+ }
109
+ }
110
+ /**
111
+ * ThemeProvider component - wraps the app and provides theme context
112
+ */
113
+ export function ThemeProvider({ children, showTopBar = true }) {
114
+ const [config, setConfig] = React.useState(() => {
115
+ const loaded = loadThemeFromStorage();
116
+ applyThemeMode(loaded.mode, loaded.variant);
117
+ return loaded;
118
+ });
119
+ // Apply theme when config changes (user switches theme)
120
+ useLayoutEffect(() => {
121
+ applyThemeVariant(config.variant);
122
+ applyThemeMode(config.mode, config.variant);
123
+ saveThemeToStorage(config);
124
+ }, [config]);
125
+ const setTheme = useCallback((variant) => {
126
+ setConfig((prev) => ({ ...prev, variant }));
127
+ }, []);
128
+ const setMode = useCallback((mode) => {
129
+ setConfig((prev) => ({ ...prev, mode }));
130
+ }, []);
131
+ const setThemeConfig = useCallback((newConfig) => {
132
+ setConfig(newConfig);
133
+ }, []);
134
+ const value = {
135
+ currentTheme: config.variant,
136
+ themeMode: config.mode,
137
+ setTheme,
138
+ setMode,
139
+ setThemeConfig
140
+ };
141
+ return (_jsxs(ThemeContext.Provider, { value: value, children: [showTopBar ? (_jsx(TopBar, { themeMode: value.themeMode, currentTheme: value.currentTheme, setMode: value.setMode, setTheme: value.setTheme })) : null, children] }));
142
+ }
143
+ /**
144
+ * Hook to access theme context
145
+ * @throws Error if used outside ThemeProvider
146
+ */
147
+ export function useTheme() {
148
+ const context = useContext(ThemeContext);
149
+ if (!context) {
150
+ console.warn('useTheme used without ThemeProvider — default theme will be assumed. Wrap your app with ThemeProvider to enable dynamic theming or import the theme CSS manually.');
151
+ const noop = () => { };
152
+ return {
153
+ currentTheme: DEFAULT_THEME.variant,
154
+ themeMode: DEFAULT_THEME.mode,
155
+ setTheme: noop,
156
+ setMode: noop,
157
+ setThemeConfig: noop
158
+ };
159
+ }
160
+ return context;
161
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Export all context-related exports from a single file
3
+ * This provides a clean import path for components
4
+ */
5
+ export { FormSchemaContext, useFormSchema, FormSchemaProvider } from './FormSchemaContext';
6
+ export { LocalizationContext, useLocalization, LocalizationProvider } from './LocalizationContext';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Export all context-related exports from a single file
3
+ * This provides a clean import path for components
4
+ */
5
+ export { FormSchemaContext, useFormSchema, FormSchemaProvider } from './FormSchemaContext';
6
+ export { LocalizationContext, useLocalization, LocalizationProvider } from './LocalizationContext';
@@ -0,0 +1,6 @@
1
+ import type { FormSchema } from '../types/FormSchema';
2
+ /**
3
+ * Default form schema with a submit button
4
+ * This is used when no saved schema exists in localStorage
5
+ */
6
+ export declare const defaultFormSchema: FormSchema;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Default form schema with a submit button
3
+ * This is used when no saved schema exists in localStorage
4
+ */
5
+ export const defaultFormSchema = {
6
+ version: '0.1.0',
7
+ components: [{
8
+ id: 'submit_button_initial',
9
+ name: 'defaultFormsubmit',
10
+ type: 'button',
11
+ label: 'Submit',
12
+ style: 'primary',
13
+ buttonType: 'submit',
14
+ disabled: false,
15
+ _configured: true
16
+ }],
17
+ settings: {
18
+ name: 'Untitled Form',
19
+ }
20
+ };
@@ -0,0 +1,9 @@
1
+ import { ComponentCategory, type PaletteItem } from './types/FormSchema';
2
+ export type DefaultPalette = {
3
+ [key in ComponentCategory]?: PaletteItem[];
4
+ };
5
+ /**
6
+ * Default palette configuration - all available components organized by category
7
+ * Users can override this by providing paletteConfig prop to FormBuilder
8
+ */
9
+ export declare const defaultPalette: DefaultPalette;
@@ -0,0 +1,45 @@
1
+ import { ComponentCategory, FormComponentType } from './types/FormSchema';
2
+ /**
3
+ * Default palette configuration - all available components organized by category
4
+ * Users can override this by providing paletteConfig prop to FormBuilder
5
+ */
6
+ export const defaultPalette = {
7
+ [ComponentCategory.BASIC]: [
8
+ { type: FormComponentType.TEXTBOX },
9
+ { type: FormComponentType.TEXTAREA },
10
+ { type: FormComponentType.CHECKBOX },
11
+ { type: FormComponentType.RADIO },
12
+ { type: FormComponentType.NUMBER },
13
+ { type: FormComponentType.INPUT_MASK },
14
+ { type: FormComponentType.DROPDOWN },
15
+ { type: FormComponentType.MULTISELECT },
16
+ { type: FormComponentType.DATE },
17
+ { type: FormComponentType.BUTTON }
18
+ ],
19
+ [ComponentCategory.ADVANCED]: [
20
+ { type: FormComponentType.CHECKBOX_GROUP },
21
+ { type: FormComponentType.DATE_TIME },
22
+ { type: FormComponentType.TIME },
23
+ { type: FormComponentType.DATE_RANGE },
24
+ { type: FormComponentType.SWITCH },
25
+ { type: FormComponentType.RATING },
26
+ { type: FormComponentType.SPLIT_BUTTON },
27
+ { type: FormComponentType.RANGE_SLIDER },
28
+ { type: FormComponentType.SIGNATURE },
29
+ { type: FormComponentType.IMAGE_EDITOR },
30
+ { type: FormComponentType.FILE_UPLOAD },
31
+ { type: FormComponentType.COLOR_PICKER },
32
+ // { type: FormComponentType.LOOKUP },
33
+ { type: FormComponentType.RICH_TEXT_EDITOR },
34
+ { type: FormComponentType.DATA_GRID },
35
+ // { type: FormComponentType.AUTO_NUMBER }
36
+ ],
37
+ [ComponentCategory.LAYOUT]: [
38
+ { type: FormComponentType.MESSAGE },
39
+ { type: FormComponentType.PANEL },
40
+ { type: FormComponentType.TABLE },
41
+ { type: FormComponentType.TABS },
42
+ { type: FormComponentType.CARD },
43
+ { type: FormComponentType.STATIC_HTML }
44
+ ]
45
+ };
@@ -0,0 +1,3 @@
1
+ import type { DefaultTemplates } from "./types/FormSchema";
2
+ export declare const defaultTemplates: DefaultTemplates[];
3
+ export default defaultTemplates;
@@ -0,0 +1,185 @@
1
+ export const defaultTemplates = [
2
+ {
3
+ id: 'loginForm',
4
+ title: 'Login Form',
5
+ schema: {
6
+ type: 'object',
7
+ properties: {
8
+ email: {
9
+ type: 'string',
10
+ title: 'Email Address',
11
+ name: 'emailAddress',
12
+ description: 'Enter your email',
13
+ format: 'email'
14
+ },
15
+ password: {
16
+ type: 'string',
17
+ title: 'Password',
18
+ name: 'password',
19
+ description: 'Enter your password',
20
+ minLength: 6
21
+ },
22
+ rememberMe: {
23
+ type: 'boolean',
24
+ title: 'Remember Me',
25
+ name: 'remember',
26
+ default: false
27
+ }
28
+ },
29
+ required: ['email', 'password']
30
+ }
31
+ },
32
+ {
33
+ id: 'registrationForm',
34
+ title: 'User Registration',
35
+ schema: {
36
+ "version": "0.1.0",
37
+ "properties": {
38
+ "firstName": {
39
+ "id": "textbox_1780395123369_348",
40
+ "type": "string",
41
+ "label": "First Name",
42
+ "name": 'firstName',
43
+ "minLength": 2,
44
+ "widget": "textbox"
45
+ },
46
+ "lastName": {
47
+ "id": "textbox_1780395123369_714",
48
+ "type": "string",
49
+ "label": "Last Name",
50
+ "name": 'lastName',
51
+ "minLength": 2,
52
+ "widget": "textbox"
53
+ },
54
+ "emailAddress": {
55
+ "id": "textbox_1780395123369_215",
56
+ "type": "string",
57
+ "label": "Email Address",
58
+ "name": 'emailAddress',
59
+ "textboxType": "email",
60
+ "widget": "textbox"
61
+ },
62
+ "password": {
63
+ "id": "textbox_1780395123369_201",
64
+ "name": "password_1",
65
+ "type": "string",
66
+ "label": "Password",
67
+ "textboxType": "password",
68
+ "minLength": 8,
69
+ "widget": "textbox"
70
+ },
71
+ "confirmPassword": {
72
+ "id": "textbox_1780395123369_608",
73
+ "name": "password_2",
74
+ "type": "string",
75
+ "label": "Confirm Password",
76
+ "textboxType": "password",
77
+ "minLength": 8,
78
+ "widget": "textbox",
79
+ "customValidation": [
80
+ {
81
+ "expression": "valid = (input === {password_1}) ? true : 'Confirm password should match the password'"
82
+ }
83
+ ]
84
+ },
85
+ "iAgreeToTheTermsAndConditions": {
86
+ "id": "checkbox_1780395123369_384",
87
+ "name": "agree",
88
+ "type": "boolean",
89
+ "label": "I agree to the Terms and Conditions",
90
+ "widget": "checkbox"
91
+ },
92
+ "submit": {
93
+ "id": "submit_button_initial",
94
+ "type": "button",
95
+ "name": "default_submit",
96
+ "label": "Submit",
97
+ "buttonType": "submit",
98
+ "widget": "button",
99
+ "style": "primary",
100
+ "disabled": false
101
+ }
102
+ },
103
+ "layout": [
104
+ {
105
+ "type": "field",
106
+ "propertyId": "firstName"
107
+ },
108
+ {
109
+ "type": "field",
110
+ "propertyId": "lastName"
111
+ },
112
+ {
113
+ "type": "field",
114
+ "propertyId": "emailAddress"
115
+ },
116
+ {
117
+ "type": "field",
118
+ "propertyId": "password"
119
+ },
120
+ {
121
+ "type": "field",
122
+ "propertyId": "confirmPassword"
123
+ },
124
+ {
125
+ "type": "field",
126
+ "propertyId": "iAgreeToTheTermsAndConditions"
127
+ },
128
+ {
129
+ "type": "field",
130
+ "propertyId": "submit"
131
+ }
132
+ ],
133
+ "settings": {
134
+ "name": "Untitled Form"
135
+ }
136
+ }
137
+ },
138
+ {
139
+ id: 'feedbackSurvey',
140
+ title: 'Feedback Survey',
141
+ schema: {
142
+ "version": "1.0",
143
+ "properties": {
144
+ "howSatisfiedAreYou": {
145
+ "id": "dropdown_1774507299146_461",
146
+ "type": "string",
147
+ "name": "satisfaction",
148
+ "label": "How satisfied are you?",
149
+ "options": [
150
+ "very_satisfied",
151
+ "satisfied",
152
+ "neutral",
153
+ "dissatisfied",
154
+ "very_dissatisfied"
155
+ ]
156
+ },
157
+ "wouldYouRecommendUs": {
158
+ "id": "dropdown_1774507299146_513",
159
+ "type": "string",
160
+ "name": "recommendation",
161
+ "label": "Would you recommend us?",
162
+ "options": [
163
+ "yes",
164
+ "maybe",
165
+ "no"
166
+ ]
167
+ },
168
+ "additionalFeedback": {
169
+ "id": "textarea_1774507317278_373",
170
+ "type": "string",
171
+ "name": "feedback",
172
+ "label": "Additional Feedback"
173
+ },
174
+ "submit": {
175
+ "id": "button_1774507299146_562",
176
+ "type": "button",
177
+ "name": "default_submit",
178
+ "label": "Submit",
179
+ "buttonType": "submit"
180
+ }
181
+ }
182
+ }
183
+ }
184
+ ];
185
+ export default defaultTemplates;
@@ -0,0 +1,24 @@
1
+ import { type ValidationResult } from '../../Common/parser';
2
+ import type { FormSchema } from '../types/FormSchema';
3
+ /**
4
+ * Utility functions for split and full schema import/validation
5
+ * Used by both ImportDialog and FileImportDialog
6
+ */
7
+ /**
8
+ * Validate unified schema (properties + layout)
9
+ */
10
+ export declare const validateSplitSchemas: (dataSchemaInput: string, _uiSchemaInput: string) => ValidationResult;
11
+ /**
12
+ * Validate full schema (single JSON)
13
+ */
14
+ export declare const validateFullSchema: (input: string) => ValidationResult;
15
+ /**
16
+ * Import unified schema with merge
17
+ * Accepts unified schema (properties + layout) and converts to FormSchema
18
+ * Also supports legacy format (FormComponent array) for backward compatibility
19
+ */
20
+ export declare const importSplitSchemas: (dataSchemaInput: string, currentFormSchema: FormSchema) => FormSchema;
21
+ /**
22
+ * Import full schema
23
+ */
24
+ export declare const importFullSchema: (input: string) => FormSchema;
@@ -0,0 +1,121 @@
1
+ import { UniversalJsonParser } from '../../Common/parser';
2
+ import { splitSchema, mergeSchema, mergeWithIDRemapping, convertComponentsToDataSchema } from '../../Common/json-converter';
3
+ /**
4
+ * Utility functions for split and full schema import/validation
5
+ * Used by both ImportDialog and FileImportDialog
6
+ */
7
+ /**
8
+ * Validate unified schema (properties + layout)
9
+ */
10
+ export const validateSplitSchemas = (dataSchemaInput, _uiSchemaInput) => {
11
+ const errors = [];
12
+ const trimmedDataInput = dataSchemaInput.trim();
13
+ if (!trimmedDataInput) {
14
+ return {
15
+ valid: false,
16
+ errors: ['Please provide a schema']
17
+ };
18
+ }
19
+ try {
20
+ const testParse = JSON.parse(trimmedDataInput);
21
+ // Check if it's unified schema (has properties and layout)
22
+ const isUnifiedSchema = testParse.properties && Array.isArray(testParse.layout);
23
+ if (isUnifiedSchema) {
24
+ // Validate unified schema structure
25
+ if (typeof testParse.properties !== 'object') {
26
+ errors.push('Invalid schema: "properties" must be an object');
27
+ return { valid: false, errors };
28
+ }
29
+ return { valid: true };
30
+ }
31
+ else {
32
+ // Try to parse as legacy format (FormComponent array)
33
+ const parser = new UniversalJsonParser();
34
+ const parseResult = parser.parse(trimmedDataInput);
35
+ if (!parseResult.success) {
36
+ errors.push(`Failed to parse schema: ${parseResult.errors.join(', ')}`);
37
+ return { valid: false, errors };
38
+ }
39
+ return { valid: true };
40
+ }
41
+ }
42
+ catch (e) {
43
+ errors.push(`Invalid JSON: ${e.message}`);
44
+ return { valid: false, errors };
45
+ }
46
+ };
47
+ /**
48
+ * Validate full schema (single JSON)
49
+ */
50
+ export const validateFullSchema = (input) => {
51
+ const trimmedInput = input.trim();
52
+ if (!trimmedInput || trimmedInput.length === 0) {
53
+ return {
54
+ valid: false,
55
+ errors: ['Please paste a full form schema JSON']
56
+ };
57
+ }
58
+ const parser = new UniversalJsonParser();
59
+ const parseResult = parser.parse(trimmedInput);
60
+ return {
61
+ valid: parseResult?.success || false,
62
+ errors: parseResult?.errors.length > 0 ? parseResult.errors : undefined,
63
+ warnings: parseResult?.warnings.length > 0 ? parseResult.warnings : undefined
64
+ };
65
+ };
66
+ /**
67
+ * Import unified schema with merge
68
+ * Accepts unified schema (properties + layout) and converts to FormSchema
69
+ * Also supports legacy format (FormComponent array) for backward compatibility
70
+ */
71
+ export const importSplitSchemas = (dataSchemaInput, currentFormSchema) => {
72
+ const trimmedDataInput = dataSchemaInput.trim();
73
+ if (!trimmedDataInput) {
74
+ throw new Error('Please provide a schema');
75
+ }
76
+ let mergedSchema;
77
+ // Parse the input
78
+ const testParse = JSON.parse(trimmedDataInput);
79
+ // Check if it's unified schema format (has properties and layout)
80
+ const isUnifiedSchema = testParse.properties && Array.isArray(testParse.layout);
81
+ if (isUnifiedSchema) {
82
+ // ✅ NEW PATH: Unified schema - merge directly
83
+ mergedSchema = mergeSchema(testParse);
84
+ }
85
+ else {
86
+ // ✅ LEGACY PATH: FormComponent array or old format - convert and merge with ID remapping
87
+ const parser = new UniversalJsonParser();
88
+ const parseResult = parser.parse(trimmedDataInput);
89
+ if (!parseResult.success || !parseResult.schema) {
90
+ throw new Error(`Failed to parse schema: ${parseResult.errors.join(', ')}`);
91
+ }
92
+ // Convert FormComponents to DataSchema
93
+ const dataSchema = convertComponentsToDataSchema(parseResult.schema.components);
94
+ // Get existing UI schema from current form
95
+ const currentUnified = splitSchema(currentFormSchema);
96
+ const currentUISchema = {
97
+ properties: currentUnified.properties,
98
+ layout: currentUnified.layout
99
+ };
100
+ // Merge with ID remapping to preserve layout stability
101
+ mergedSchema = mergeWithIDRemapping(dataSchema, currentUISchema);
102
+ }
103
+ return mergedSchema;
104
+ };
105
+ /**
106
+ * Import full schema
107
+ */
108
+ export const importFullSchema = (input) => {
109
+ const trimmedInput = input.trim();
110
+ if (!trimmedInput || trimmedInput.length === 0) {
111
+ throw new Error('Please paste JSON content');
112
+ }
113
+ const parser = new UniversalJsonParser();
114
+ const parseResult = parser.parse(trimmedInput);
115
+ if (parseResult?.success && parseResult?.schema) {
116
+ return parseResult.schema;
117
+ }
118
+ else {
119
+ throw new Error(parseResult?.errors.join(', ') || 'Failed to parse schema');
120
+ }
121
+ };