@syncfusion/ej2-react-form-renderer 0.1.0-beta → 0.1.1-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.
@@ -13,7 +13,8 @@ import { UniversalJsonParser } from './parser';
13
13
  import { TooltipComponent } from '@syncfusion/ej2-react-popups';
14
14
  import { VALIDATION_REGEX } from './FormValidator';
15
15
  import StaticHtmlRenderer from './StaticHtmlRenderer';
16
- import { splitWidths } from './utils';
16
+ import { formatDateValues, splitWidths } from './utils';
17
+ import { ConditionalRuleEngine } from './ConditionalRuleEngine';
17
18
  enableRipple(true);
18
19
  /**
19
20
  * Form layout options (only applies when UI schema is NOT provided)
@@ -109,7 +110,7 @@ function parseStringToUISchema(input) {
109
110
  }
110
111
  }
111
112
  // ForwardRef to expose public methods
112
- export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit, onChange, onButtonClick, className = '', layout = FormLayout.SingleColumn, created, ...restProps }, ref) => {
113
+ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, locale, onSubmit, onChange, onButtonClick, className = '', layout = FormLayout.SingleColumn, created, ...restProps }, ref) => {
113
114
  const processedSchema = React.useMemo(() => {
114
115
  try {
115
116
  // Parse and normalize data schema
@@ -158,19 +159,22 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
158
159
  }
159
160
  // Scenario 4: Neither provided - return empty form
160
161
  console.warn('FormRenderer: No schema provided (dataSchema or uiSchema)');
161
- return { version: '1.0.0-beta', theme: 'tailwind3', components: [] };
162
+ return { version: '0.1.0', theme: 'tailwind3', components: [] };
162
163
  }
163
164
  catch (error) {
164
165
  console.error('FormRenderer schema processing error:', error);
165
- return { version: '1.0.0-beta', theme: 'tailwind3', components: [] };
166
+ return { version: '0.1.0', theme: 'tailwind3', components: [] };
166
167
  }
167
168
  }, [dataSchema, uiSchema]);
168
169
  const [formState, setFormState] = useState(undefined);
169
170
  const isInitializedRef = useRef(false);
171
+ const formLocale = locale || 'en-US';
170
172
  // Attach ref to the input element for getComponent
171
173
  let setInputRef;
172
174
  // Store input component refs by name/id
173
175
  const inputRefs = useRef({});
176
+ // Track which fields have active conditional values applied (to prevent re-applying while condition stays true)
177
+ const conditionalValueAppliedRef = useRef({});
174
178
  // Check if UI schema has layout components (table, tabs, or panel)
175
179
  const hasLayoutComponents = React.useMemo(() => {
176
180
  if (!processedSchema.components)
@@ -256,7 +260,7 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
256
260
  const map = {};
257
261
  const traverse = (comps) => {
258
262
  comps.forEach(comp => {
259
- if (comp.label && !['panel', 'table', 'tabs', 'card', 'button', 'message', 'splitbutton'].includes(comp.type)) {
263
+ if (comp.label && !['panel', 'table', 'tabs', 'card', 'button', 'message', 'splitButton'].includes(comp.type)) {
260
264
  map[comp.id] = comp.label;
261
265
  }
262
266
  if (comp.children)
@@ -282,20 +286,27 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
282
286
  */
283
287
  const buildValidationRules = useCallback(() => {
284
288
  const rules = {};
289
+ const formValues = formState?.values || {};
285
290
  const collectRules = (components) => {
286
291
  components.forEach((component) => {
287
292
  if (component) {
288
293
  const componentRules = {};
289
- if (component.required && !component.disabled && !component.readOnly) {
294
+ const conditionalRequired = ConditionalRuleEngine.isFieldRequired(component.conditions, formValues);
295
+ const conditionalDisabled = ConditionalRuleEngine.isFieldDisabled(component.conditions, formValues);
296
+ const conditionalReadOnly = ConditionalRuleEngine.isFieldReadOnly(component.conditions, formValues);
297
+ const finalRequired = component.required || conditionalRequired;
298
+ const finalDisabled = component.disabled || conditionalDisabled;
299
+ const finalReadOnly = component.readOnly || conditionalReadOnly;
300
+ if (finalRequired && !finalDisabled && !finalReadOnly) {
290
301
  componentRules.required = [true, component.validationMessage || `${component.label} is required`];
291
302
  }
292
- if (component.minLength && !component.disabled && !component.readOnly) {
303
+ if (component.minLength && !finalDisabled && !finalReadOnly) {
293
304
  componentRules.minLength = [component.minLength, `Minimum ${component.minLength} characters required`];
294
305
  }
295
- if (component.maxLength && !component.disabled && !component.readOnly) {
306
+ if (component.maxLength && !finalDisabled && !finalReadOnly) {
296
307
  componentRules.maxLength = [component.maxLength, `Maximum ${component.maxLength} characters allowed`];
297
308
  }
298
- if (component?.type === 'textbox' && component?.textboxType && !component?.regex && !componentRules.regex && !component.disabled && !component.readOnly) {
309
+ if (component?.type === 'textbox' && component?.textboxType && !component?.regex && !componentRules.regex && !finalDisabled && !finalReadOnly) {
299
310
  if (component.textboxType === 'email') {
300
311
  componentRules.regex = [VALIDATION_REGEX['EMAIL'], component?.validationMessage || 'Invalid format'];
301
312
  }
@@ -303,7 +314,7 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
303
314
  componentRules.regex = [VALIDATION_REGEX['URL'], component?.validationMessage || 'Invalid format'];
304
315
  }
305
316
  }
306
- if (component.regex && !component.disabled && !component.readOnly) {
317
+ if (component.regex && !finalDisabled && !finalReadOnly) {
307
318
  componentRules.regex = [component.regex, component.validationMessage || 'Invalid format'];
308
319
  }
309
320
  if (Object.keys(componentRules).length > 0) {
@@ -329,7 +340,7 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
329
340
  };
330
341
  collectRules(processedSchema.components);
331
342
  return rules;
332
- }, [processedSchema]);
343
+ }, [processedSchema, formState?.values]);
333
344
  const validationRules = buildValidationRules();
334
345
  /**
335
346
  * Build initial form values from component defaultValues
@@ -339,14 +350,23 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
339
350
  const allComponents = collectAllComponents(processedSchema.components);
340
351
  const componentIds = new Set();
341
352
  allComponents.forEach(comp => {
342
- // Do NOT store datagrid data inside the form state; grids manage their own internal data.
343
- if (comp.type === 'datagrid' || comp.type === 'richtexteditor') {
353
+ // Do NOT store dataGrid data inside the form state; grids manage their own internal data.
354
+ if (comp.type === 'dataGrid' || comp.type === 'richTextEditor') {
344
355
  componentIds.add(comp.id);
345
356
  return;
346
357
  }
347
358
  if (comp.defaultValue !== undefined) {
348
359
  values[comp.id] = comp.defaultValue;
349
360
  }
361
+ else {
362
+ // Initialize with type-appropriate defaults
363
+ switch (comp.type) {
364
+ case 'checkbox':
365
+ case 'switch':
366
+ values[comp.id] = false;
367
+ break;
368
+ }
369
+ }
350
370
  componentIds.add(comp.id);
351
371
  });
352
372
  if (formState) {
@@ -374,17 +394,22 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
374
394
  * Render a single field with label and error
375
395
  */
376
396
  const renderField = (component) => {
377
- // Skip invisible components
378
- if (component.visible === false)
379
- return null;
397
+ const formValues = formState?.values || {};
380
398
  // Skip layout and button components (handled separately)
381
- if (['panel', 'table', 'tabs', 'card', 'message', 'button', 'splitbutton', 'statichtml'].includes(component.type)) {
399
+ if (['panel', 'table', 'tabs', 'card', 'message', 'button', 'splitButton', 'staticHtml'].includes(component.type)) {
382
400
  return null;
383
401
  }
402
+ const conditionalReadOnly = ConditionalRuleEngine.isFieldReadOnly(component.conditions, formValues);
403
+ const conditionalDisabled = ConditionalRuleEngine.isFieldDisabled(component.conditions, formValues);
404
+ const conditionalRequired = ConditionalRuleEngine.isFieldRequired(component.conditions, formValues);
405
+ const conditionalValue = ConditionalRuleEngine.getConditionalValue(component.conditions, formValues);
406
+ const computedReadOnly = component.readOnly || conditionalReadOnly;
407
+ const computedDisabled = component.disabled || conditionalDisabled;
408
+ const computedRequired = component.required || conditionalRequired;
384
409
  const labelPos = component.labelPosition || 'top';
385
410
  const labelWidth = component.labelWidth || 'auto';
386
- const showLabel = !component.hideLabel && component.label && !['checkbox', 'button', 'statichtml'].includes(component.type);
387
- if ((component.type === 'radio' || component.type === 'checkboxgroup') && Array.isArray(component.options)) {
411
+ const showLabel = !component.hideLabel && component.label && !['checkbox', 'button', 'staticHtml'].includes(component.type);
412
+ if ((component.type === 'radio' || component.type === 'checkboxGroup') && Array.isArray(component.options)) {
388
413
  // For radio, store each option's ref with unique key
389
414
  setInputRef = (el, idx) => {
390
415
  if (el && typeof idx === 'number') {
@@ -399,16 +424,32 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
399
424
  }
400
425
  };
401
426
  }
402
- const hasError = !!formState?.errors[component.id];
403
- return (_jsx(FormField, { name: component.id, children: _jsx("div", { className: "form-group", children: _jsxs("div", { className: `field-wrapper label-${labelPos.toLowerCase()}`, children: [showLabel && (_jsxs("label", { className: "field-label", htmlFor: component.id, style: { width: labelPos.toLowerCase() === 'left' ? `${labelWidth}%` : 'auto' }, children: [_jsx("span", { children: component.label }), component?.required && _jsx("span", { className: "required-asterisk", children: "*" }), component.tooltip && (_jsx(TooltipComponent, { content: component.tooltip, children: _jsx("span", { className: "e-msg-icon", style: {
427
+ const shouldShowError = !!formState?.errors[component.id];
428
+ const isRequiredError = shouldShowError && formState?.errors[component.id].includes('required');
429
+ const hasError = shouldShowError && !(isRequiredError && !computedRequired);
430
+ // Apply conditional value only when condition transitions from false to true (start of new cycle)
431
+ const conditionIsActive = conditionalValue !== undefined;
432
+ const wasConditionActive = conditionalValueAppliedRef.current[component.id] || false;
433
+ if (formState) {
434
+ if (conditionIsActive && !wasConditionActive) {
435
+ formState.onChange(component.id, { value: conditionalValue });
436
+ conditionalValueAppliedRef.current[component.id] = true;
437
+ }
438
+ else if (!conditionIsActive && wasConditionActive) {
439
+ // Condition just became inactive - clear tracking (ready for next cycle)
440
+ conditionalValueAppliedRef.current[component.id] = false;
441
+ }
442
+ // If condition stays active (wasConditionActive && conditionIsActive), do nothing - let user edit
443
+ }
444
+ return (_jsx(FormField, { name: component.id, children: _jsx("div", { className: "form-group", children: _jsxs("div", { className: `field-wrapper label-${labelPos.toLowerCase()}`, children: [showLabel && (_jsxs("label", { className: "field-label", htmlFor: component.id, style: { width: labelPos.toLowerCase() === 'left' ? `${labelWidth}%` : 'auto' }, children: [_jsx("span", { children: component.label }), computedRequired && _jsx("span", { className: "required-asterisk", children: "*" }), component.tooltip && (_jsx(TooltipComponent, { content: component.tooltip, children: _jsx("span", { className: "e-msg-icon", style: {
404
445
  cursor: 'pointer',
405
446
  display: 'flex',
406
447
  alignItems: 'center',
407
448
  justifyContent: 'center',
408
449
  flexShrink: 0,
409
- } }) }))] })), _jsxs("div", { className: "field-input", children: [(component.type === 'radio' || component.type === 'checkboxgroup') && Array.isArray(component.options)
450
+ } }) }))] })), _jsxs("div", { className: "field-input", children: [(component.type === 'radio' || component.type === 'checkboxGroup') && Array.isArray(component.options)
410
451
  ? renderFormField({
411
- component,
452
+ component: { ...component, readOnly: computedReadOnly, disabled: computedDisabled, required: computedRequired },
412
453
  value: formState?.values[component.id],
413
454
  onChange: (value) => {
414
455
  formState?.onChange(component.id, { value });
@@ -416,34 +457,45 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
416
457
  onChange({ field: component.label || component.id, value });
417
458
  }
418
459
  },
460
+ locale: formLocale,
419
461
  onBlur: () => formState?.onBlur(component.id),
420
462
  ref: (el, idx) => setInputRef(el, idx),
421
463
  hasError,
422
464
  })
423
465
  : renderFormField({
424
- component,
466
+ component: { ...component, readOnly: computedReadOnly, disabled: computedDisabled, required: computedRequired },
425
467
  value: formState?.values[component.id],
426
468
  onChange: (value) => {
427
- if (component.type !== 'datagrid' && component.type !== 'signature' && component.type !== 'richtexteditor') {
469
+ if (component.type !== 'dataGrid' && component.type !== 'signature' && component.type !== 'richTextEditor') {
470
+ value = formatDateValues(component, value);
428
471
  formState?.onChange(component.id, { value });
429
472
  if (onChange) {
430
473
  onChange({ field: component.label || component.id, value });
431
474
  }
432
475
  }
433
476
  },
434
- onBlur: () => { if (component.type !== 'datagrid' && component.type !== 'richtexteditor')
477
+ locale: formLocale,
478
+ onBlur: () => { if (component.type !== 'dataGrid' && component.type !== 'richTextEditor')
435
479
  formState?.onBlur(component.id); },
436
480
  ref: setInputRef,
437
481
  hasError,
438
- }), formState?.errors[component.id] && _jsx("div", { className: "e-error", children: formState.errors[component.id] })] })] }) }) }, component.id));
482
+ }), hasError && _jsx("div", { className: "e-error", children: formState.errors[component.id] })] }), component.description && _jsx("div", { className: 'field-description', children: component.description })] }) }) }, component.id));
439
483
  };
440
484
  /**
441
485
  * Render component (including layouts)
442
486
  */
443
487
  const renderComponent = (component) => {
444
- // Skip invisible components
445
- if (component.visible === false)
488
+ const formValues = formState?.values || {};
489
+ const isVisible = component.visible === false
490
+ ? false
491
+ : ConditionalRuleEngine.isFieldVisible(component.conditions, formValues);
492
+ const isHidden = ConditionalRuleEngine.isFieldHidden(component.conditions, formValues);
493
+ if (!isVisible || isHidden) {
494
+ if (formState && formState.values[component.id] !== undefined && formState.values[component.id] !== null) {
495
+ formState.onChange(component.id, { value: null });
496
+ }
446
497
  return null;
498
+ }
447
499
  switch (component.type) {
448
500
  case 'panel':
449
501
  return (_jsxs("fieldset", { className: `form-panel-renderer ${component.cssClass}`, children: [(component.label && !component.hideLabel) && _jsx("legend", { className: `${!component.hideBorders ? 'panel-legend' : ''}`, children: component.label }), _jsx("div", { className: "panel-content", children: component.children?.map(child => renderComponent(child)) })] }, component.id));
@@ -453,13 +505,15 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
453
505
  const defaultColSpan = Math.floor(12 / tableCols);
454
506
  const columnWidthsProp = component.columnWidths;
455
507
  const splittedWidths = columnWidthsProp ? splitWidths(columnWidthsProp.widths) : [];
456
- return (_jsx("div", { className: `form-table-renderer ${component.hideBorders ? '' : 'table-border'} ${component.cssClass}`, children: Array.from({ length: tableRows }).map((_, rowIndex) => (_jsx("div", { className: "table-row", children: Array.from({ length: tableCols }).map((_, colIndex) => {
508
+ return (_jsx("div", { className: `form-table-renderer ${component.hideBorders ? '' : 'table-border'} ${component.cssClass}`, children: Array.from({ length: tableRows }).map((_, rowIndex) => (_jsx("div", { className: "e-form-table-row", style: component.hideBorders ? { display: 'flex', gap: '1.5rem' } : {}, children: Array.from({ length: tableCols }).map((_, colIndex) => {
457
509
  const cellComponents = component.tableCells?.[rowIndex]?.[colIndex] || [];
458
510
  const cellSpan = defaultColSpan;
459
511
  const colWidthValue = splittedWidths[colIndex];
460
- const cellStyle = colWidthValue ? { width: `${colWidthValue}%` } : {};
512
+ const isSingleColumn = tableCols === 1;
513
+ const cellStyle = isSingleColumn ? { width: '100%' } : (colWidthValue ? { width: `${colWidthValue}%` } : {});
461
514
  const allNullWidths = !columnWidthsProp || (Array.isArray(columnWidthsProp.widths) && columnWidthsProp.widths.every((w) => w === null));
462
- return (_jsx("div", { className: `table-cell ${colWidthValue ? '' : allNullWidths ? `col-${cellSpan}` : ''}`, style: cellStyle, children: cellComponents.map(comp => renderComponent(comp)) }, `cell-${rowIndex}-${colIndex}`));
515
+ const isFirstRow = rowIndex === 0;
516
+ return (_jsx("div", { className: `e-form-table-cell ${colWidthValue ? '' : allNullWidths ? `col-${cellSpan}` : ''}`, style: component.hideBorders ? { ...cellStyle, padding: isFirstRow ? '0' : '12px 0 0 0' } : cellStyle, children: cellComponents.map(comp => renderComponent(comp)) }, `cell-${rowIndex}-${colIndex}`));
463
517
  }) }, `row-${rowIndex}`))) }, component.id));
464
518
  case 'tabs':
465
519
  return (_jsx("div", { className: `form-tabs-renderer ${component.cssClass || ''}`, children: _jsx(CustomTabComponent, { tabs: component.tabItems?.map(tab => ({
@@ -468,15 +522,18 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
468
522
  })) || [], className: component.cssClass }) }, component.id));
469
523
  case 'card':
470
524
  return (_jsxs("fieldset", { className: `e-card form-card-renderer ${component.cssClass}`, style: { padding: 0 }, children: [_jsx("div", { className: "e-card-header", children: _jsxs("div", { className: "e-card-header-caption", children: [_jsx("div", { className: "e-card-title", children: component.cardTitle || component.label || 'Card Title' }), component.cardSubtitle && (_jsx("div", { className: "e-card-sub-title", children: component.cardSubtitle }))] }) }), _jsx("div", { className: "e-card-content card-content", children: component.children?.map(child => renderComponent(child)) })] }, component.id));
471
- case 'statichtml':
525
+ case 'staticHtml':
472
526
  return (_jsx(StaticHtmlRenderer, { id: component.id, content: component.defaultValue || '<p>HTML content</p>', enableHtmlSanitizer: component.enableHtmlSanitizer }, component.id));
473
527
  case 'message':
474
528
  return (_jsx("div", { className: "form-group", children: renderFormField({
475
529
  component,
530
+ locale: formLocale,
476
531
  value: undefined,
477
532
  onChange: () => { },
478
533
  }) }, component.id));
479
534
  case 'button':
535
+ const buttonlDisabled = ConditionalRuleEngine.isFieldDisabled(component.conditions, formValues);
536
+ const buttonComputed = component.disabled || buttonlDisabled;
480
537
  const handleButtonClick = (event) => {
481
538
  if (onButtonClick) {
482
539
  onButtonClick({
@@ -486,9 +543,10 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
486
543
  }
487
544
  };
488
545
  return (_jsx("div", { className: "form-group", children: renderFormField({
489
- component,
546
+ component: { ...component, disabled: buttonComputed },
490
547
  value: undefined,
491
548
  onChange: () => { },
549
+ locale: formLocale,
492
550
  onClick: (e) => { handleButtonClick(e); },
493
551
  ref: (el, idx) => {
494
552
  if (idx !== undefined) {
@@ -499,7 +557,9 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
499
557
  }
500
558
  }
501
559
  }) }, component.id));
502
- case 'splitbutton':
560
+ case 'splitButton':
561
+ const splitButtonDisabled = ConditionalRuleEngine.isFieldDisabled(component.conditions, formValues);
562
+ const computedDisabled = component.disabled || splitButtonDisabled;
503
563
  setInputRef = (el) => {
504
564
  if (el) {
505
565
  inputRefs.current[component.id] = el;
@@ -515,8 +575,9 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
515
575
  }
516
576
  };
517
577
  return (_jsx("div", { className: "form-group", children: renderFormField({
518
- component,
578
+ component: { ...component, disabled: computedDisabled },
519
579
  value: undefined,
580
+ locale: formLocale,
520
581
  onChange: () => { },
521
582
  onClick: (e) => { handleSplitButtonEvent(e); },
522
583
  ref: setInputRef
@@ -546,15 +607,36 @@ export const FormRenderer = React.forwardRef(({ dataSchema, uiSchema, onSubmit,
546
607
  },
547
608
  }), []);
548
609
  return (_jsx("div", { ...restProps, className: `form-renderer-container ${className}`, children: _jsx(Form, { rules: validationRules, initialValues: initialValues, onFormStateChange: (state) => setFormState(state), onSubmit: (data) => {
549
- const isValid = formState?.errors ? Object.keys(formState.errors).length === 0 : false;
610
+ const isValid = (formState?.errors ? Object.keys(formState.errors).length === 0 : false);
550
611
  const transformedData = {};
612
+ const formValues = formState?.values || {};
551
613
  // Exclude non-data components (buttons, messages, and layout-only components)
552
- const excludedTypes = new Set(['button', 'message', 'panel', 'table', 'tabs', 'card', 'splitbutton', 'statichtml']);
614
+ const excludedTypes = new Set(['button', 'message', 'panel', 'table', 'tabs']);
553
615
  const allComps = collectAllComponents(processedSchema.components || []);
554
616
  const excludedIds = new Set(allComps.filter(c => excludedTypes.has(c.type)).map(c => c.id));
617
+ const hiddenFieldIds = new Set(allComps.filter(c => {
618
+ if (c.visible === false)
619
+ return true;
620
+ if (c.conditions?.visibleWhen) {
621
+ if (!ConditionalRuleEngine.isFieldVisible(c.conditions, formValues))
622
+ return true;
623
+ }
624
+ if (c.conditions?.hideWhen) {
625
+ if (ConditionalRuleEngine.isFieldHidden(c.conditions, formValues))
626
+ return true;
627
+ }
628
+ return false;
629
+ }).map(c => c.id));
630
+ const disabledFieldIds = new Set(allComps.filter(c => {
631
+ if (c.disabled)
632
+ return true;
633
+ if (c.conditions?.disabledWhen) {
634
+ return ConditionalRuleEngine.isFieldDisabled(c.conditions, formValues);
635
+ }
636
+ return false;
637
+ }).map(c => c.id));
555
638
  Object.entries(data).forEach(([id, val]) => {
556
- // Skip excluded components so they don't appear as submitted values
557
- if (excludedIds.has(id))
639
+ if (excludedIds.has(id) || hiddenFieldIds.has(id) || disabledFieldIds.has(id))
558
640
  return;
559
641
  const label = idToLabel[id] || id;
560
642
  transformedData[label] = val;
@@ -1,5 +1,6 @@
1
1
  import type { FormSchema, FormComponent } from '../FormBuilder/types/FormSchema';
2
2
  export declare const generateId: (type: string) => string;
3
+ export declare const generateName: (type: string) => string;
3
4
  export interface SplitSchema {
4
5
  dataSchema: DataSchema;
5
6
  uiSchema: UISchema;
@@ -11,6 +12,7 @@ export interface DataSchema {
11
12
  export interface DataField {
12
13
  id: string;
13
14
  type: 'string' | 'number' | 'boolean' | 'array' | 'any' | 'button' | 'message' | 'sign' | 'image' | 'file' | 'color' | 'grid';
15
+ name: string;
14
16
  label?: string;
15
17
  format?: 'date' | 'date-time' | 'time' | 'email' | 'url';
16
18
  defaultValue?: any;
@@ -46,6 +48,7 @@ export interface FieldNode {
46
48
  export interface TableNode {
47
49
  type: 'table';
48
50
  id: string;
51
+ name: string;
49
52
  label?: string;
50
53
  cssClass?: string;
51
54
  hideBorders?: boolean;
@@ -55,6 +58,7 @@ export interface TableNode {
55
58
  columnWidths?: {
56
59
  widths: (number | null)[];
57
60
  };
61
+ conditions?: any;
58
62
  }
59
63
  export interface TableCell {
60
64
  row: number;
@@ -64,19 +68,23 @@ export interface TableCell {
64
68
  export interface PanelNode {
65
69
  type: 'panel';
66
70
  id: string;
71
+ name: string;
67
72
  label?: string;
68
73
  cssClass?: string;
69
74
  hideBorders?: boolean;
70
75
  hideLabel?: boolean;
71
76
  children: LayoutNode[];
77
+ conditions?: any;
72
78
  }
73
79
  export interface TabsNode {
74
80
  type: 'tabs';
75
81
  id: string;
82
+ name: string;
76
83
  cssClass?: string;
77
84
  label?: string;
78
85
  tabOptions?: string[];
79
86
  tabs: TabItem[];
87
+ conditions?: any;
80
88
  }
81
89
  export interface TabItem {
82
90
  header: string;
@@ -85,6 +93,7 @@ export interface TabItem {
85
93
  export interface CardNode {
86
94
  type: 'card';
87
95
  id: string;
96
+ name: string;
88
97
  label?: string;
89
98
  cssClass?: string;
90
99
  hideLabel?: boolean;
@@ -94,6 +103,7 @@ export interface CardNode {
94
103
  actionButtonLabel?: string;
95
104
  actionButtonType?: 'button' | 'submit';
96
105
  children: LayoutNode[];
106
+ conditions?: any;
97
107
  }
98
108
  /**
99
109
  * Convert label to camelCase identifier