form-builder-pro 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.css CHANGED
@@ -530,6 +530,36 @@ video {
530
530
 
531
531
  --radius: 0.5rem;
532
532
  }
533
+
534
+ .dark {
535
+ --background: 222.2 84% 4.9%;
536
+ --foreground: 210 40% 98%;
537
+
538
+ --card: 222.2 84% 4.9%;
539
+ --card-foreground: 210 40% 98%;
540
+
541
+ --popover: 222.2 84% 4.9%;
542
+ --popover-foreground: 210 40% 98%;
543
+
544
+ --primary: 210 40% 98%;
545
+ --primary-foreground: 222.2 47.4% 11.2%;
546
+
547
+ --secondary: 019FA2;
548
+ --secondary-foreground: 210 40% 98%;
549
+
550
+ --muted: 217.2 32.6% 17.5%;
551
+ --muted-foreground: 215 20.2% 65.1%;
552
+
553
+ --accent: 217.2 32.6% 17.5%;
554
+ --accent-foreground: 210 40% 98%;
555
+
556
+ --destructive: 0 62.8% 30.6%;
557
+ --destructive-foreground: 210 40% 98%;
558
+
559
+ --border: 217.2 32.6% 17.5%;
560
+ --input: 217.2 32.6% 17.5%;
561
+ --ring: 212.7 26.8% 83.9%;
562
+ }
533
563
  * {
534
564
  border-color: hsl(var(--border));
535
565
  }
@@ -740,9 +770,15 @@ body {
740
770
  }
741
771
  /* ===== WIDTH SLIDER STYLES ===== */
742
772
  /* Custom range slider styling */
773
+ .dark .width-slider {
774
+ background: linear-gradient(to right, #019FA2 0%, #019FA2 var(--slider-progress, 50%), #374151 var(--slider-progress, 50%), #374151 100%);
775
+ }
743
776
  /* Slider thumb (WebKit - Chrome, Safari, Edge) */
744
777
  /* Slider thumb (Firefox) */
745
778
  /* Slider track (Firefox) */
779
+ .dark .width-slider::-moz-range-track {
780
+ background: #374151;
781
+ }
746
782
  /* Width value badge animation */
747
783
  /* Preset buttons */
748
784
  /* Breakpoint markers */
@@ -843,6 +879,9 @@ body {
843
879
  .visible {
844
880
  visibility: visible;
845
881
  }
882
+ .collapse {
883
+ visibility: collapse;
884
+ }
846
885
  .static {
847
886
  position: static;
848
887
  }
@@ -1057,6 +1096,9 @@ body {
1057
1096
  .flex-shrink-0 {
1058
1097
  flex-shrink: 0;
1059
1098
  }
1099
+ .transform {
1100
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1101
+ }
1060
1102
  .cursor-move {
1061
1103
  cursor: move;
1062
1104
  }
@@ -1227,6 +1269,10 @@ body {
1227
1269
  --tw-border-opacity: 1;
1228
1270
  border-color: rgb(1 159 162 / var(--tw-border-opacity, 1));
1229
1271
  }
1272
+ .border-\[\#635bff\] {
1273
+ --tw-border-opacity: 1;
1274
+ border-color: rgb(99 91 255 / var(--tw-border-opacity, 1));
1275
+ }
1230
1276
  .border-\[\#635bff\]\/35 {
1231
1277
  border-color: rgb(99 91 255 / 0.35);
1232
1278
  }
@@ -1577,6 +1623,9 @@ body {
1577
1623
  --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
1578
1624
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1579
1625
  }
1626
+ .outline {
1627
+ outline-style: solid;
1628
+ }
1580
1629
  .ring-2 {
1581
1630
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
1582
1631
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
@@ -1784,6 +1833,11 @@ input[type="radio"]:checked::after {
1784
1833
  content: var(--tw-content);
1785
1834
  }
1786
1835
 
1836
+ .hover\:border-\[\#635bff\]:hover {
1837
+ --tw-border-opacity: 1;
1838
+ border-color: rgb(99 91 255 / var(--tw-border-opacity, 1));
1839
+ }
1840
+
1787
1841
  .hover\:border-blue-200:hover {
1788
1842
  --tw-border-opacity: 1;
1789
1843
  border-color: rgb(191 219 254 / var(--tw-border-opacity, 1));
@@ -1856,6 +1910,11 @@ input[type="radio"]:checked::after {
1856
1910
  background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1));
1857
1911
  }
1858
1912
 
1913
+ .hover\:text-\[\#635bff\]:hover {
1914
+ --tw-text-opacity: 1;
1915
+ color: rgb(99 91 255 / var(--tw-text-opacity, 1));
1916
+ }
1917
+
1859
1918
  .hover\:text-blue-700:hover {
1860
1919
  --tw-text-opacity: 1;
1861
1920
  color: rgb(29 78 216 / var(--tw-text-opacity, 1));
@@ -1881,6 +1940,11 @@ input[type="radio"]:checked::after {
1881
1940
  color: rgb(239 68 68 / var(--tw-text-opacity, 1));
1882
1941
  }
1883
1942
 
1943
+ .hover\:text-red-700:hover {
1944
+ --tw-text-opacity: 1;
1945
+ color: rgb(185 28 28 / var(--tw-text-opacity, 1));
1946
+ }
1947
+
1884
1948
  .hover\:text-white:hover {
1885
1949
  --tw-text-opacity: 1;
1886
1950
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import * as zustand_vanilla from 'zustand/vanilla';
3
3
 
4
- type FieldType = 'text' | 'textarea' | 'number' | 'date' | 'datetime' | 'select' | 'checkbox' | 'radio' | 'toggle' | 'binary_choice' | 'repeater' | 'file' | 'image' | 'email' | 'phone' | 'name_generator';
4
+ type FieldType = 'text' | 'textarea' | 'number' | 'date' | 'datetime' | 'select' | 'checkbox' | 'radio' | 'toggle' | 'binary_choice' | 'repeater' | 'file' | 'image' | 'email' | 'phone' | 'name_generator' | 'formula';
5
5
  /** Name generator format options for name_generator field type */
6
6
  type NameGeneratorFormat = 'TEXT_HYPHEN_ID' | 'TEXT_UNDERSCORE_ID' | 'TEXT_SLASH_ID' | 'TEXT_ID' | 'ID_HYPHEN_TEXT' | 'ID_UNDERSCORE_TEXT' | 'TEXT_YEAR_ID' | 'TEXT_MONTH_ID' | 'TEXT_YEAR_MONTH_ID' | 'TEXT_ACCOUNT_CODE_ID' | 'TEXT_BRANCH_ID' | 'PREFIX_TEXT_ID' | 'TEXT_ID_SUFFIX' | 'TEXT_RANDOM_4' | 'TEXT_YEAR_MONTH_DAY_ID' | 'TEXT_HYPHEN_USER_INPUT' | 'TEXT_UNDERSCORE_USER_INPUT' | 'TEXT_SLASH_USER_INPUT' | 'USER_INPUT_HYPHEN_TEXT' | 'USER_INPUT_UNDERSCORE_TEXT';
7
7
  type FieldWidth = '25%' | '33%' | '50%' | '66%' | '75%' | '100%' | number;
@@ -135,6 +135,7 @@ interface FormField {
135
135
  nameGeneratorPrefix?: string;
136
136
  nameGeneratorSuffix?: string;
137
137
  nameGeneratorIdPadding?: number;
138
+ formulaConfig?: FormulaConfig;
138
139
  }
139
140
  /**
140
141
  * Conditional date constraint — evaluated at runtime against the current date or another field's value.
@@ -146,6 +147,32 @@ interface DateConstraint {
146
147
  compareWith: 'CURRENT_DATE' | 'FIELD';
147
148
  fieldName?: string;
148
149
  }
150
+ /**
151
+ * A single condition row for multi-condition formula fields.
152
+ * When the compare field equals `value`, evaluate `expression`.
153
+ */
154
+ interface FormulaCondition {
155
+ value: string;
156
+ expression: string;
157
+ }
158
+ /**
159
+ * Configuration for the formula field type.
160
+ * Supports two modes: single expression or multiple conditions.
161
+ */
162
+ interface FormulaConfig {
163
+ mode: 'single' | 'multiple';
164
+ /** Used when mode === 'single' */
165
+ single: {
166
+ expression: string;
167
+ };
168
+ /** Used when mode === 'multiple' */
169
+ multiple: {
170
+ compareField: string;
171
+ conditions: FormulaCondition[];
172
+ fallbackExpression: string;
173
+ };
174
+ decimalPlaces: number;
175
+ }
149
176
  /**
150
177
  * ISD (International Subscriber Dialing) configuration for phone fields
151
178
  */
@@ -509,6 +536,52 @@ declare function getNumericFieldsForFormula(schema: FormSchema, excludeFieldId?:
509
536
  fieldName: string;
510
537
  label: string;
511
538
  }[];
539
+ /**
540
+ * Extracts `{fieldName}` placeholder references from a formula expression.
541
+ * Returns unique field names in order of first appearance.
542
+ */
543
+ declare function extractBracketFields(expression: string): string[];
544
+ /**
545
+ * Evaluates a formula expression that uses `{fieldName}` placeholders.
546
+ * Placeholders are resolved to numeric values from `values` before evaluation.
547
+ * Missing/non-numeric values default to 0.
548
+ * Returns NaN on divide-by-zero or syntax error.
549
+ */
550
+ declare function evaluateFormulaExpression(expression: string, values: Record<string, number | string | undefined>): number;
551
+ /**
552
+ * Evaluates a complete FormulaConfig using the provided field values.
553
+ * For `multiple` mode, `compareValue` is the current value of the compare field.
554
+ * Returns `{ result, error? }`.
555
+ */
556
+ declare function evaluateFormulaConfig(config: FormulaConfig, values: Record<string, number | string | undefined>, compareValue?: string): {
557
+ result: number;
558
+ error?: string;
559
+ };
560
+ /**
561
+ * Validates a `{fieldName}` expression for the formula field type.
562
+ * Checks that all `{ref}` names exist in `availableFieldNames` and parentheses are balanced.
563
+ */
564
+ declare function validateFormulaExpression(expression: string, availableFieldNames: string[]): {
565
+ valid: true;
566
+ } | {
567
+ valid: false;
568
+ error: string;
569
+ };
570
+ /**
571
+ * Get all fields usable as formula references for a 'formula' type field.
572
+ * Includes numeric (number) and other formula-type fields (excluding the field itself).
573
+ * Returns all non-excluded fields so users can reference any form value.
574
+ */
575
+ declare function getFieldsForFormula(schema: FormSchema, excludeFieldId?: string): {
576
+ id: string;
577
+ fieldName: string;
578
+ label: string;
579
+ }[];
580
+ /**
581
+ * Detects circular dependencies for a 'formula' type field.
582
+ * Builds a dependency graph from all expression placeholders and checks for cycles.
583
+ */
584
+ declare function detectFormulaFieldCircularDependency(schema: FormSchema, formulaFieldId: string, config: FormulaConfig): boolean;
512
585
 
513
586
  /** Reset counter (for testing or new form load) */
514
587
  declare function resetNameGeneratorCounter(): void;
@@ -523,4 +596,4 @@ declare const initFormBuilder: (options: FormBuilderOptions & {
523
596
  containerId: string;
524
597
  }) => FormBuilder;
525
598
 
526
- export { type AsyncOptionSource, type DateConstraint, type FieldType, type FieldValidations, type FieldWidth, FormBuilder, type FormBuilderOptions, type FormField, FormRenderer, type FormSchema, FormSchemaValidation, type FormSection, type GroupPosition, type ISDConfig, LOOKUP_SOURCE_TYPE_OPTIONS, type LookupSourceType, type MasterType, type NameGeneratorFormat, type ValidationObject, type ValidationRule, builderToPlatform, cleanFormSchema, convertValidationObjectToArray, detectCircularDependency, evaluateFormula, formStore, generateName, getColSpanFromWidth, getNumericFieldsForFormula, getValidationConfigForAngular, initFormBuilder, parseFormulaDependencies, parseWidth, platformToBuilder, resetNameGeneratorCounter, validateFormula };
599
+ export { type AsyncOptionSource, type DateConstraint, type FieldType, type FieldValidations, type FieldWidth, FormBuilder, type FormBuilderOptions, type FormField, FormRenderer, type FormSchema, FormSchemaValidation, type FormSection, type FormulaCondition, type FormulaConfig, type GroupPosition, type ISDConfig, LOOKUP_SOURCE_TYPE_OPTIONS, type LookupSourceType, type MasterType, type NameGeneratorFormat, type ValidationObject, type ValidationRule, builderToPlatform, cleanFormSchema, convertValidationObjectToArray, detectCircularDependency, detectFormulaFieldCircularDependency, evaluateFormula, evaluateFormulaConfig, evaluateFormulaExpression, extractBracketFields, formStore, generateName, getColSpanFromWidth, getFieldsForFormula, getNumericFieldsForFormula, getValidationConfigForAngular, initFormBuilder, parseFormulaDependencies, parseWidth, platformToBuilder, resetNameGeneratorCounter, validateFormula, validateFormulaExpression };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import * as zustand_vanilla from 'zustand/vanilla';
3
3
 
4
- type FieldType = 'text' | 'textarea' | 'number' | 'date' | 'datetime' | 'select' | 'checkbox' | 'radio' | 'toggle' | 'binary_choice' | 'repeater' | 'file' | 'image' | 'email' | 'phone' | 'name_generator';
4
+ type FieldType = 'text' | 'textarea' | 'number' | 'date' | 'datetime' | 'select' | 'checkbox' | 'radio' | 'toggle' | 'binary_choice' | 'repeater' | 'file' | 'image' | 'email' | 'phone' | 'name_generator' | 'formula';
5
5
  /** Name generator format options for name_generator field type */
6
6
  type NameGeneratorFormat = 'TEXT_HYPHEN_ID' | 'TEXT_UNDERSCORE_ID' | 'TEXT_SLASH_ID' | 'TEXT_ID' | 'ID_HYPHEN_TEXT' | 'ID_UNDERSCORE_TEXT' | 'TEXT_YEAR_ID' | 'TEXT_MONTH_ID' | 'TEXT_YEAR_MONTH_ID' | 'TEXT_ACCOUNT_CODE_ID' | 'TEXT_BRANCH_ID' | 'PREFIX_TEXT_ID' | 'TEXT_ID_SUFFIX' | 'TEXT_RANDOM_4' | 'TEXT_YEAR_MONTH_DAY_ID' | 'TEXT_HYPHEN_USER_INPUT' | 'TEXT_UNDERSCORE_USER_INPUT' | 'TEXT_SLASH_USER_INPUT' | 'USER_INPUT_HYPHEN_TEXT' | 'USER_INPUT_UNDERSCORE_TEXT';
7
7
  type FieldWidth = '25%' | '33%' | '50%' | '66%' | '75%' | '100%' | number;
@@ -135,6 +135,7 @@ interface FormField {
135
135
  nameGeneratorPrefix?: string;
136
136
  nameGeneratorSuffix?: string;
137
137
  nameGeneratorIdPadding?: number;
138
+ formulaConfig?: FormulaConfig;
138
139
  }
139
140
  /**
140
141
  * Conditional date constraint — evaluated at runtime against the current date or another field's value.
@@ -146,6 +147,32 @@ interface DateConstraint {
146
147
  compareWith: 'CURRENT_DATE' | 'FIELD';
147
148
  fieldName?: string;
148
149
  }
150
+ /**
151
+ * A single condition row for multi-condition formula fields.
152
+ * When the compare field equals `value`, evaluate `expression`.
153
+ */
154
+ interface FormulaCondition {
155
+ value: string;
156
+ expression: string;
157
+ }
158
+ /**
159
+ * Configuration for the formula field type.
160
+ * Supports two modes: single expression or multiple conditions.
161
+ */
162
+ interface FormulaConfig {
163
+ mode: 'single' | 'multiple';
164
+ /** Used when mode === 'single' */
165
+ single: {
166
+ expression: string;
167
+ };
168
+ /** Used when mode === 'multiple' */
169
+ multiple: {
170
+ compareField: string;
171
+ conditions: FormulaCondition[];
172
+ fallbackExpression: string;
173
+ };
174
+ decimalPlaces: number;
175
+ }
149
176
  /**
150
177
  * ISD (International Subscriber Dialing) configuration for phone fields
151
178
  */
@@ -509,6 +536,52 @@ declare function getNumericFieldsForFormula(schema: FormSchema, excludeFieldId?:
509
536
  fieldName: string;
510
537
  label: string;
511
538
  }[];
539
+ /**
540
+ * Extracts `{fieldName}` placeholder references from a formula expression.
541
+ * Returns unique field names in order of first appearance.
542
+ */
543
+ declare function extractBracketFields(expression: string): string[];
544
+ /**
545
+ * Evaluates a formula expression that uses `{fieldName}` placeholders.
546
+ * Placeholders are resolved to numeric values from `values` before evaluation.
547
+ * Missing/non-numeric values default to 0.
548
+ * Returns NaN on divide-by-zero or syntax error.
549
+ */
550
+ declare function evaluateFormulaExpression(expression: string, values: Record<string, number | string | undefined>): number;
551
+ /**
552
+ * Evaluates a complete FormulaConfig using the provided field values.
553
+ * For `multiple` mode, `compareValue` is the current value of the compare field.
554
+ * Returns `{ result, error? }`.
555
+ */
556
+ declare function evaluateFormulaConfig(config: FormulaConfig, values: Record<string, number | string | undefined>, compareValue?: string): {
557
+ result: number;
558
+ error?: string;
559
+ };
560
+ /**
561
+ * Validates a `{fieldName}` expression for the formula field type.
562
+ * Checks that all `{ref}` names exist in `availableFieldNames` and parentheses are balanced.
563
+ */
564
+ declare function validateFormulaExpression(expression: string, availableFieldNames: string[]): {
565
+ valid: true;
566
+ } | {
567
+ valid: false;
568
+ error: string;
569
+ };
570
+ /**
571
+ * Get all fields usable as formula references for a 'formula' type field.
572
+ * Includes numeric (number) and other formula-type fields (excluding the field itself).
573
+ * Returns all non-excluded fields so users can reference any form value.
574
+ */
575
+ declare function getFieldsForFormula(schema: FormSchema, excludeFieldId?: string): {
576
+ id: string;
577
+ fieldName: string;
578
+ label: string;
579
+ }[];
580
+ /**
581
+ * Detects circular dependencies for a 'formula' type field.
582
+ * Builds a dependency graph from all expression placeholders and checks for cycles.
583
+ */
584
+ declare function detectFormulaFieldCircularDependency(schema: FormSchema, formulaFieldId: string, config: FormulaConfig): boolean;
512
585
 
513
586
  /** Reset counter (for testing or new form load) */
514
587
  declare function resetNameGeneratorCounter(): void;
@@ -523,4 +596,4 @@ declare const initFormBuilder: (options: FormBuilderOptions & {
523
596
  containerId: string;
524
597
  }) => FormBuilder;
525
598
 
526
- export { type AsyncOptionSource, type DateConstraint, type FieldType, type FieldValidations, type FieldWidth, FormBuilder, type FormBuilderOptions, type FormField, FormRenderer, type FormSchema, FormSchemaValidation, type FormSection, type GroupPosition, type ISDConfig, LOOKUP_SOURCE_TYPE_OPTIONS, type LookupSourceType, type MasterType, type NameGeneratorFormat, type ValidationObject, type ValidationRule, builderToPlatform, cleanFormSchema, convertValidationObjectToArray, detectCircularDependency, evaluateFormula, formStore, generateName, getColSpanFromWidth, getNumericFieldsForFormula, getValidationConfigForAngular, initFormBuilder, parseFormulaDependencies, parseWidth, platformToBuilder, resetNameGeneratorCounter, validateFormula };
599
+ export { type AsyncOptionSource, type DateConstraint, type FieldType, type FieldValidations, type FieldWidth, FormBuilder, type FormBuilderOptions, type FormField, FormRenderer, type FormSchema, FormSchemaValidation, type FormSection, type FormulaCondition, type FormulaConfig, type GroupPosition, type ISDConfig, LOOKUP_SOURCE_TYPE_OPTIONS, type LookupSourceType, type MasterType, type NameGeneratorFormat, type ValidationObject, type ValidationRule, builderToPlatform, cleanFormSchema, convertValidationObjectToArray, detectCircularDependency, detectFormulaFieldCircularDependency, evaluateFormula, evaluateFormulaConfig, evaluateFormulaExpression, extractBracketFields, formStore, generateName, getColSpanFromWidth, getFieldsForFormula, getNumericFieldsForFormula, getValidationConfigForAngular, initFormBuilder, parseFormulaDependencies, parseWidth, platformToBuilder, resetNameGeneratorCounter, validateFormula, validateFormulaExpression };