impact-nova 2.3.0 → 2.4.0

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 (147) hide show
  1. package/dist/filter-shell/index.d.ts +12 -0
  2. package/dist/filter-shell/index.js +9 -0
  3. package/dist/filter-shell/utils/buildFilterFieldValidationRules.d.ts +1 -0
  4. package/dist/filter-shell/utils/validateVisibleRequiredFilterFields.d.ts +1 -0
  5. package/dist/filter-shell/utils/validationNavigation.utils.d.ts +26 -0
  6. package/dist/filter-shell/utils/validationNavigation.utils.js +38 -0
  7. package/dist/form-engine/field-dependency-graph.d.ts +17 -0
  8. package/dist/form-engine/field-dependency-graph.js +90 -0
  9. package/dist/form-engine/index.d.ts +9 -0
  10. package/dist/form-engine/index.js +16 -0
  11. package/dist/form-engine/is-empty-value.d.ts +1 -0
  12. package/dist/form-engine/is-empty-value.js +8 -0
  13. package/dist/form-engine/types.d.ts +17 -0
  14. package/dist/form-react/Fields/ButtonsGroupField.d.ts +3 -0
  15. package/dist/form-react/Fields/ButtonsGroupField.js +52 -0
  16. package/dist/form-react/Fields/CheckboxField.d.ts +3 -0
  17. package/dist/form-react/Fields/CheckboxField.js +46 -0
  18. package/dist/form-react/Fields/ChipsField.d.ts +3 -0
  19. package/dist/form-react/Fields/ChipsField.js +146 -0
  20. package/dist/form-react/Fields/DateInputField.d.ts +8 -0
  21. package/dist/form-react/Fields/DateInputField.js +134 -0
  22. package/dist/form-react/Fields/DateRangeField.d.ts +8 -0
  23. package/dist/form-react/Fields/DateRangeField.js +57 -0
  24. package/dist/form-react/Fields/DividerField.d.ts +3 -0
  25. package/dist/form-react/Fields/DividerField.js +9 -0
  26. package/dist/form-react/Fields/DividerWithLabelField.d.ts +3 -0
  27. package/dist/form-react/Fields/DividerWithLabelField.js +31 -0
  28. package/dist/form-react/Fields/FileUploadField.d.ts +3 -0
  29. package/dist/form-react/Fields/FileUploadField.js +42 -0
  30. package/dist/form-react/Fields/FillFormByFileUploadField.d.ts +3 -0
  31. package/dist/form-react/Fields/FillFormByFileUploadField.js +65 -0
  32. package/dist/form-react/Fields/FillFormByPasteField.d.ts +3 -0
  33. package/dist/form-react/Fields/FillFormByPasteField.js +106 -0
  34. package/dist/form-react/Fields/LabelField.d.ts +3 -0
  35. package/dist/form-react/Fields/LabelField.js +14 -0
  36. package/dist/form-react/Fields/MonthRangeField.d.ts +8 -0
  37. package/dist/form-react/Fields/MonthRangeField.js +72 -0
  38. package/dist/form-react/Fields/MultiMonthPickerField.d.ts +8 -0
  39. package/dist/form-react/Fields/MultiMonthPickerField.js +46 -0
  40. package/dist/form-react/Fields/MultiWeekPickerField.d.ts +8 -0
  41. package/dist/form-react/Fields/MultiWeekPickerField.js +47 -0
  42. package/dist/form-react/Fields/NumericComboboxField.d.ts +18 -0
  43. package/dist/form-react/Fields/NumericComboboxField.js +51 -0
  44. package/dist/form-react/Fields/RadioField.d.ts +3 -0
  45. package/dist/form-react/Fields/RadioField.js +68 -0
  46. package/dist/form-react/Fields/SelectField.d.ts +3 -0
  47. package/dist/form-react/Fields/SelectField.js +76 -0
  48. package/dist/form-react/Fields/SwitchField.d.ts +3 -0
  49. package/dist/form-react/Fields/SwitchField.js +47 -0
  50. package/dist/form-react/Fields/TextAreaField.d.ts +3 -0
  51. package/dist/form-react/Fields/TextAreaField.js +41 -0
  52. package/dist/form-react/Fields/TextField.d.ts +3 -0
  53. package/dist/form-react/Fields/TextField.js +75 -0
  54. package/dist/form-react/Fields/TextFieldWithBackendValidation.d.ts +3 -0
  55. package/dist/form-react/Fields/TextFieldWithBackendValidation.js +117 -0
  56. package/dist/form-react/Fields/WeekRangePicker.d.ts +8 -0
  57. package/dist/form-react/Fields/WeekRangePicker.js +71 -0
  58. package/dist/form-react/ReactHooksForm.d.ts +3 -0
  59. package/dist/form-react/ReactHooksForm.js +132 -0
  60. package/dist/form-react/components/ArrayFieldRenderer.d.ts +13 -0
  61. package/dist/form-react/components/ArrayFieldRenderer.js +90 -0
  62. package/dist/form-react/components/FieldRenderer.d.ts +16 -0
  63. package/dist/form-react/components/FieldRenderer.js +68 -0
  64. package/dist/form-react/components/FormFieldRow.d.ts +13 -0
  65. package/dist/form-react/components/FormFieldRow.js +47 -0
  66. package/dist/form-react/components/FormFileUploadWrapper.d.ts +22 -0
  67. package/dist/form-react/components/FormFileUploadWrapper.js +88 -0
  68. package/dist/form-react/components/ObjectFieldRenderer.d.ts +13 -0
  69. package/dist/form-react/components/ObjectFieldRenderer.js +46 -0
  70. package/dist/form-react/components/SetToEmptyWrapper.d.ts +16 -0
  71. package/dist/form-react/components/SetToEmptyWrapper.js +49 -0
  72. package/dist/form-react/fields.d.ts +23 -0
  73. package/dist/form-react/fields.js +40 -0
  74. package/dist/form-react/hooks/useCascadingForm.d.ts +17 -0
  75. package/dist/form-react/hooks/useCascadingForm.js +122 -0
  76. package/dist/form-react/hooks/useFieldVisibility.d.ts +14 -0
  77. package/dist/form-react/hooks/useFieldVisibility.js +60 -0
  78. package/dist/form-react/hooks/useFillFormByFileUpload.d.ts +33 -0
  79. package/dist/form-react/hooks/useFillFormByFileUpload.js +199 -0
  80. package/dist/form-react/hooks/useFillFormByPaste.d.ts +33 -0
  81. package/dist/form-react/hooks/useFillFormByPaste.js +104 -0
  82. package/dist/form-react/hooks/useFormFieldChangeSubscription.d.ts +13 -0
  83. package/dist/form-react/hooks/useFormFieldChangeSubscription.js +42 -0
  84. package/dist/form-react/hooks/useReactHookForm.d.ts +3 -0
  85. package/dist/form-react/hooks/useReactHookForm.js +161 -0
  86. package/dist/form-react/hooks/useSelectOptions.d.ts +8 -0
  87. package/dist/form-react/hooks/useSelectOptions.js +116 -0
  88. package/dist/form-react/index.d.ts +62 -0
  89. package/dist/form-react/index.js +97 -0
  90. package/dist/form-react/registry/defaultFieldRegistrations.d.ts +2 -0
  91. package/dist/form-react/registry/defaultFieldRegistrations.js +30 -0
  92. package/dist/form-react/registry/fieldRegistry.d.ts +14 -0
  93. package/dist/form-react/registry/fieldRegistry.js +19 -0
  94. package/dist/form-react/registry/resolveFieldComponent.d.ts +10 -0
  95. package/dist/form-react/registry/resolveFieldComponent.js +137 -0
  96. package/dist/form-react/types/fields.types.d.ts +402 -0
  97. package/dist/form-react/types/fieldsOutput.types.d.ts +73 -0
  98. package/dist/form-react/types/reactHookForm.types.d.ts +196 -0
  99. package/dist/form-react/utils/batchFormFieldUpdates.d.ts +14 -0
  100. package/dist/form-react/utils/batchFormFieldUpdates.js +13 -0
  101. package/dist/form-react/utils/buildFieldValidationRules.d.ts +6 -0
  102. package/dist/form-react/utils/buildFieldValidationRules.js +13 -0
  103. package/dist/form-react/utils/buildSelectRemountKey.d.ts +14 -0
  104. package/dist/form-react/utils/buildSelectRemountKey.js +14 -0
  105. package/dist/form-react/utils/calendar-boundary.d.ts +3 -0
  106. package/dist/form-react/utils/calendar-boundary.js +33 -0
  107. package/dist/form-react/utils/date.utils.d.ts +31 -0
  108. package/dist/form-react/utils/date.utils.js +86 -0
  109. package/dist/form-react/utils/evaluateFieldValidation.d.ts +19 -0
  110. package/dist/form-react/utils/evaluateFieldValidation.js +53 -0
  111. package/dist/form-react/utils/fieldDefaults.utils.d.ts +6 -0
  112. package/dist/form-react/utils/fieldDefaults.utils.js +25 -0
  113. package/dist/form-react/utils/fieldPath.utils.d.ts +23 -0
  114. package/dist/form-react/utils/fieldPath.utils.js +26 -0
  115. package/dist/form-react/utils/fieldRangeValidation.utils.d.ts +3 -0
  116. package/dist/form-react/utils/fieldRangeValidation.utils.js +24 -0
  117. package/dist/form-react/utils/fieldRendererUtils.d.ts +10 -0
  118. package/dist/form-react/utils/fieldRendererUtils.js +47 -0
  119. package/dist/form-react/utils/fieldTestIds.d.ts +3 -0
  120. package/dist/form-react/utils/fieldTestIds.js +13 -0
  121. package/dist/form-react/utils/formDate.utils.d.ts +13 -0
  122. package/dist/form-react/utils/formDate.utils.js +9 -0
  123. package/dist/form-react/utils/formValidationFeedback.utils.d.ts +32 -0
  124. package/dist/form-react/utils/formValidationFeedback.utils.js +153 -0
  125. package/dist/form-react/utils/icons.d.ts +5 -0
  126. package/dist/form-react/utils/icons.js +10 -0
  127. package/dist/form-react/utils/optionFlag.d.ts +11 -0
  128. package/dist/form-react/utils/optionFlag.js +17 -0
  129. package/dist/form-react/utils/pastedValues.d.ts +1 -0
  130. package/dist/form-react/utils/resolveFormSubmittable.d.ts +18 -0
  131. package/dist/form-react/utils/resolveFormSubmittable.js +32 -0
  132. package/dist/form-react/utils/select-option-filter-values.d.ts +5 -0
  133. package/dist/form-react/utils/select-option-filter-values.js +30 -0
  134. package/dist/form-react/utils/serializeFormStateForQueryKey.d.ts +1 -0
  135. package/dist/form-react/utils/serializeFormStateForQueryKey.js +21 -0
  136. package/dist/form-react/utils/stableSerialize.d.ts +5 -0
  137. package/dist/form-react/utils/stableSerialize.js +11 -0
  138. package/dist/form-react/utils/validateVisibleRequiredFormFields.d.ts +21 -0
  139. package/dist/form-react/utils/validateVisibleRequiredFormFields.js +64 -0
  140. package/dist/form-react/utils/validationUtils.d.ts +3 -0
  141. package/dist/form-react/utils/validationUtils.js +77 -0
  142. package/dist/impact-nova.css +1 -1
  143. package/dist/lib/primitives/use-field-chrome.js +16 -16
  144. package/dist/llms/rules/installation.js +1 -1
  145. package/dist/llms/rules/real-world-patterns.js +1 -1
  146. package/dist/llms/rules/requirements.js +1 -1
  147. package/package.json +21 -2
@@ -0,0 +1,402 @@
1
+ import { Option } from '../../components/forms/select';
2
+ import { HTMLInputTypeAttribute } from 'react';
3
+ import { FieldOutputValue } from './fieldsOutput.types';
4
+ export type ValidationRule = {
5
+ /** Regex pattern string to test against */
6
+ regex?: string;
7
+ /** Zod method name, e.g. "email", "url", "min", "max", "uuid", "regex" */
8
+ zod?: string;
9
+ /** Arguments to pass to the Zod method, e.g. [5] for z.string().min(5) */
10
+ zodArgs?: unknown[];
11
+ /** Error message returned when validation fails */
12
+ message?: string;
13
+ /** Named sync validator → formContext.validators[name] */
14
+ validatorName?: string;
15
+ };
16
+ /**
17
+ * Copy for built-in `date_range` checks (supplied via remote field config — FE substitutes `{minDate}` / `{offset}` at validate time).
18
+ */
19
+ export type DateRangeValidationMessages = {
20
+ requiredBoth?: string;
21
+ partialPair?: string;
22
+ invalidDate?: string;
23
+ exitMustBeAfterStart?: string;
24
+ /** Template: `{minDate}` = YYYY-MM-DD, `{offset}` = minStartOffsetDays */
25
+ startBeforeMinimum?: string;
26
+ };
27
+ /**
28
+ * Single-date field (one calendar control). Values are stored as `YYYY-MM-DD` strings in form state.
29
+ * Messages come from `dateValidationMessages` on the field config.
30
+ */
31
+ export type DateInputValidationMessages = {
32
+ required?: string;
33
+ invalidDate?: string;
34
+ /** Template: `{minDate}`, `{offset}` when `minOffsetDaysFromToday` or `pastDateNotAllowed` applies */
35
+ beforeMinimum?: string;
36
+ /** When `dateAfterFieldId` is set: value must be after the referenced field's date (strict or inclusive based on `dateAfterFieldIdInclusive`) */
37
+ mustBeAfterOther?: string;
38
+ /** When `dateBeforeFieldId` is set: value must be before the referenced field's date (strict or inclusive based on `dateBeforeFieldIdInclusive`) */
39
+ mustBeBeforeOther?: string;
40
+ };
41
+ export type BaseField = {
42
+ order?: number;
43
+ id: string;
44
+ label?: string;
45
+ isDisabled?: boolean;
46
+ colSpan?: number;
47
+ clearable?: boolean;
48
+ placeholder?: string;
49
+ isRequired?: boolean;
50
+ helpText?: string;
51
+ className?: string;
52
+ labelOrientation?: "top" | "left";
53
+ isFieldReadonly?: boolean;
54
+ validation?: Array<ValidationRule>;
55
+ /** Group key used by `buildFieldGroups` / `fieldGroupTitles` for multi-section layout. */
56
+ fieldGroup?: string;
57
+ visibilityDependency?: Array<{
58
+ fieldId: string;
59
+ value: FieldOutputValue[] | FieldOutputValue;
60
+ }>;
61
+ disableDependency?: Array<{
62
+ fieldId: string;
63
+ value: FieldOutputValue[] | FieldOutputValue;
64
+ }>;
65
+ /** When "every", field is disabled only if ALL conditions match (AND). Default is "some" (OR). */
66
+ disableDependencyMode?: "some" | "every";
67
+ cascadingDependency?: Array<{
68
+ fieldId: string;
69
+ value: FieldOutputValue[] | FieldOutputValue;
70
+ }>;
71
+ doNotIncludeInSubmit?: boolean;
72
+ /** When true, this field is auxiliary/decorative and should not alone enable form submission (e.g. period selectors, dividers, labels). */
73
+ isNonValueField?: boolean;
74
+ /** When true, shows a "Set To Empty" action link that lets users explicitly null-out the field value. */
75
+ allowSetToEmpty?: boolean;
76
+ /**
77
+ * Name of formContext.functions[name].
78
+ * Runs on value change for any field; specialized fields (backend / paste / file)
79
+ * also use it for their validate/upload action. Omit = usual flow.
80
+ */
81
+ handlerName?: string;
82
+ };
83
+ export type LabelField = BaseField & {
84
+ fieldType: "label";
85
+ className?: string;
86
+ };
87
+ export type FileUploadField = BaseField & {
88
+ fieldType: "file_upload";
89
+ supportedFileTypes: Array<{
90
+ fileType: string;
91
+ templateUrl: string;
92
+ typeOverride: boolean;
93
+ }>;
94
+ numberOfFiles: number;
95
+ maxFileSize: number;
96
+ apiConfig?: {
97
+ apiEndpoint: string;
98
+ method: "GET" | "POST";
99
+ };
100
+ };
101
+ export type ButtonsGroupField = BaseField & {
102
+ fieldType: "button_group";
103
+ options: Array<Option>;
104
+ defaultSelectedValue?: string;
105
+ };
106
+ export type SelectField = BaseField & {
107
+ fieldType: "select";
108
+ options?: Array<Option>;
109
+ isMultiSelect?: boolean;
110
+ maxSelectLimit?: number;
111
+ disableClearAll?: boolean;
112
+ disableOptionSearch?: boolean;
113
+ disableSelectAll?: boolean;
114
+ /**
115
+ * Name of formContext.getSelectOptions[name].
116
+ * When set, that resolver is used instead of apiConfig fetch.
117
+ */
118
+ getSelectOptionsName?: string;
119
+ apiConfig?: {
120
+ apiEndpoint: string;
121
+ method: "GET" | "POST";
122
+ /** When true, cascaded POSTs send `filters: []` (no parent field values). Use for independent selects (e.g. optional attributes). */
123
+ doNotIncludeSectionFormStateInApiRequest?: boolean;
124
+ includeOnlyMandatoryFieldsInPayload?: boolean;
125
+ /** When true, enables cascade behaviour even when `formConfig.isCascading` is false. */
126
+ isCascading?: boolean;
127
+ /**
128
+ * Explicit list of field IDs whose values should be sent as cascade filters.
129
+ * When set, overrides the default positional behaviour (`getEarlierFieldsIds`) entirely —
130
+ * only these specific IDs are included, regardless of their array position.
131
+ * Use when you need precise control over which parent fields cascade into this field's options.
132
+ * Example: `["division_name", "l0_name"]` — only send Division and Department as filters.
133
+ */
134
+ cascadeFromFields?: string[];
135
+ };
136
+ };
137
+ export type DateInputField = BaseField & {
138
+ fieldType: "date";
139
+ /** Display format with moment-style tokens, e.g. "MM/DD/YYYY", "YYYY-MM-DD". Defaults to "YYYY-MM-DD". */
140
+ dateFormat?: string;
141
+ minDate?: string;
142
+ maxDate?: string;
143
+ /** Earliest selectable day is start-of-day of today + this many days. */
144
+ minOffsetDaysFromToday?: number;
145
+ /**
146
+ * When set (e.g. exit date), the picked date must be strictly after the referenced field’s date.
147
+ * The calendar `minDate` is the day after that field’s value when it is set.
148
+ */
149
+ dateAfterFieldId?: string | string[];
150
+ dateAfterFieldIdInclusive?: boolean;
151
+ /**
152
+ * When set (e.g. start date vs exit), the picked date must be strictly before the referenced field’s date.
153
+ * The calendar `maxDate` is the day before that field’s value when it is set.
154
+ */
155
+ dateBeforeFieldId?: string | string[];
156
+ dateBeforeFieldIdInclusive?: boolean;
157
+ pastDateNotAllowed?: boolean;
158
+ dateValidationMessages?: DateInputValidationMessages;
159
+ showFooter?: boolean;
160
+ };
161
+ export type DateRangeField = BaseField & {
162
+ fieldType: "date_range";
163
+ /** Display format with moment-style tokens, e.g. "MM/DD/YYYY", "YYYY-MM-DD". Defaults to "YYYY-MM-DD". */
164
+ dateFormat?: string;
165
+ /** ISO date string (YYYY-MM-DD) — calendar minimum for the range picker */
166
+ minDate?: string;
167
+ /** ISO date string (YYYY-MM-DD) — calendar maximum for the range picker */
168
+ maxDate?: string;
169
+ /**
170
+ * Earliest selectable **start** date is start-of-day of today + this many days.
171
+ * Example: `60` blocks choosing a start date before the calendar day that is 60 days from today.
172
+ */
173
+ minStartOffsetDays?: number;
174
+ defaultRange?: {
175
+ start: string;
176
+ end: string;
177
+ };
178
+ dateRangeValidationMessages?: DateRangeValidationMessages;
179
+ startPlaceholder?: string;
180
+ endPlaceholder?: string;
181
+ /** ISO date string — first month shown in picker navigation */
182
+ startMonth?: string;
183
+ /** ISO date string — last month shown in picker navigation */
184
+ endMonth?: string;
185
+ };
186
+ export type WeekRangeField = BaseField & {
187
+ fieldType: "week_range";
188
+ minDate?: string;
189
+ maxDate?: string;
190
+ /** Minimum selectable start date = today + N days (0 = today, blocks past dates). */
191
+ minStartOffsetDays?: number;
192
+ /** When true, past weeks/dates cannot be selected (equivalent to minStartOffsetDays: 0). */
193
+ disablePastWeeks?: boolean;
194
+ /** First month shown in the picker navigation (ISO date string). */
195
+ startMonth?: string;
196
+ /** Last month shown in the picker navigation (ISO date string). */
197
+ endMonth?: string;
198
+ defaultRange?: {
199
+ start: string;
200
+ end: string;
201
+ };
202
+ calendarType?: "fiscal" | "calendar";
203
+ fiscalMode?: "basic" | "advanced" | "custom";
204
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
205
+ selectionMode?: "week" | "fiscalMonth";
206
+ fiscalMonthPattern?: number[];
207
+ fiscalYearStartMonth?: number;
208
+ showFooter?: boolean;
209
+ format?: string;
210
+ /** Number of weeks before the current week to set as the minimum selectable date */
211
+ minWeeksOffset?: number;
212
+ /** Number of weeks after the current week to set as the maximum selectable date */
213
+ maxWeeksOffset?: number;
214
+ dateFormat?: string;
215
+ };
216
+ export type MultiWeekRangeField = BaseField & {
217
+ fieldType: "multi_week_picker";
218
+ minDate?: string;
219
+ maxDate?: string;
220
+ calendarType?: "fiscal" | "calendar";
221
+ fiscalMode?: "basic" | "advanced" | "custom";
222
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
223
+ selectionMode?: "week" | "fiscalMonth";
224
+ fiscalMonthPattern?: number[];
225
+ };
226
+ export type MonthRangeField = BaseField & {
227
+ fieldType: "month_range";
228
+ displayFormat?: "MM/YYYY" | "YYYY/MM";
229
+ defaultRange?: {
230
+ start: string;
231
+ end: string;
232
+ };
233
+ minDate?: string;
234
+ maxDate?: string;
235
+ startMonth?: string;
236
+ endMonth?: string;
237
+ showYearSelect?: boolean;
238
+ disablePastMonths?: boolean;
239
+ /** Number of months before the current month to set as the minimum selectable month */
240
+ minMonthsOffset?: number;
241
+ /** Number of months after the current month to set as the maximum selectable month */
242
+ maxMonthsOffset?: number;
243
+ customYears?: Array<{
244
+ label: string;
245
+ value: string;
246
+ }>;
247
+ isOutsideRange?: (month: Date) => boolean;
248
+ };
249
+ export type MultiMonthPickerField = BaseField & {
250
+ fieldType: "multi_month_picker";
251
+ minDate?: string;
252
+ maxDate?: string;
253
+ startMonth?: string;
254
+ endMonth?: string;
255
+ };
256
+ export type TextAreaField = BaseField & {
257
+ fieldType: "text_area";
258
+ maxRows?: number;
259
+ characterLimit?: number;
260
+ maxLength?: number;
261
+ defaultValue?: string;
262
+ };
263
+ export type RadioField = BaseField & {
264
+ fieldType: "radio";
265
+ orientation?: "row" | "column";
266
+ options: Array<Option>;
267
+ defaultSelectedValue?: string;
268
+ };
269
+ export type TextField = BaseField & {
270
+ fieldType: "text";
271
+ type: HTMLInputTypeAttribute;
272
+ defaultValue?: string | number;
273
+ nonNegative?: boolean;
274
+ allowDecimal?: boolean;
275
+ /**
276
+ * Reactively override `nonNegative` based on a flag on the currently
277
+ * selected option of another (select) field. Only meaningful when
278
+ * `nonNegative: true`. Reads `option.metadata[optionFlag]` from the
279
+ * selected option. Has no effect when `nonNegative` is falsy.
280
+ */
281
+ allowNegativeDependency?: {
282
+ fieldId: string;
283
+ /** Key inside the selected option's `metadata` object, e.g. `"allow_negative"`. */
284
+ optionFlag: string;
285
+ };
286
+ };
287
+ /**
288
+ * Numeric combobox: wraps Impact Nova `Combobox` with `isNumeric` plus
289
+ * `min` / `max` / `step` so callers can render a stepper-style dropdown
290
+ * (e.g. 0..95 in steps of 5). Value is stored as a number in form state.
291
+ */
292
+ export type NumericComboboxField = BaseField & {
293
+ fieldType: "numeric_combobox";
294
+ min?: number;
295
+ max?: number;
296
+ step?: number;
297
+ defaultValue?: number;
298
+ };
299
+ export type CopyPasteField = BaseField & {
300
+ fieldType: "fill_form_by_paste";
301
+ selectFieldConfig: {
302
+ selectFieldLabel?: string;
303
+ selectFieldPlaceholder?: string;
304
+ selectFieldOptions: Array<Option>;
305
+ labelOrientation?: "top" | "left";
306
+ };
307
+ textAreaConfig?: {
308
+ textAreaLabel?: string;
309
+ textAreaPlaceholder?: string;
310
+ };
311
+ /** Legacy built-in path — optional when field.handlerName is set */
312
+ validationConfig?: {
313
+ apiEndpoint: string;
314
+ };
315
+ };
316
+ export type FillFormByFileUploadField = BaseField & {
317
+ fieldType: "fill_form_by_file_upload";
318
+ supportedFileTypes: Array<{
319
+ fileType: string;
320
+ templateUrl: string;
321
+ typeOverride: boolean;
322
+ }>;
323
+ maxFileSize: number;
324
+ /** Legacy built-in path — optional when field.handlerName is set */
325
+ validationConfig?: {
326
+ apiEndpoint: string;
327
+ };
328
+ };
329
+ export type SwitchField = BaseField & {
330
+ fieldType: "switch";
331
+ leftLabel?: string;
332
+ rightLabel?: string;
333
+ defaultSelectedValue?: boolean;
334
+ };
335
+ export type CheckboxField = BaseField & {
336
+ fieldType: "checkbox";
337
+ defaultSelectedValue?: boolean;
338
+ };
339
+ export type TextFieldWithBackendValidation = BaseField & {
340
+ fieldType: "text_with_backend_validation";
341
+ /** Legacy built-in path — optional when field.handlerName is set */
342
+ validationConfig?: {
343
+ method?: "GET" | "POST";
344
+ apiEndpoint: string;
345
+ fieldValuesToIncludeInApiRequest?: Array<string>;
346
+ debounceTime?: number;
347
+ validateOnBlur?: boolean;
348
+ omitValidation?: Array<string>;
349
+ };
350
+ };
351
+ export type ChipsField = BaseField & {
352
+ fieldType: "chips";
353
+ options: Array<Option>;
354
+ chipsType?: "single" | "multi";
355
+ /** When true in single mode, re-clicking the active chip clears the selection. */
356
+ allowDeselect?: boolean;
357
+ };
358
+ export type DividerField = BaseField & {
359
+ fieldType: "divider";
360
+ className?: string;
361
+ };
362
+ export type DividerWithLabelField = BaseField & {
363
+ fieldType: "divider_with_label";
364
+ label: string;
365
+ labelAlignment?: "left" | "center" | "right";
366
+ labelClassName?: string;
367
+ dividerClassName?: string;
368
+ };
369
+ export type ObjectFieldConfig = BaseField & {
370
+ fieldType: "object";
371
+ /** Child fields rendered inside this object group */
372
+ fields: IField[];
373
+ /** Grid columns for the nested field group (defaults to parent formConfig.columns) */
374
+ columns?: number;
375
+ /** Whether to render a visual border/card around the group */
376
+ bordered?: boolean;
377
+ /** Collapsible section — user can expand/collapse */
378
+ collapsible?: boolean;
379
+ defaultCollapsed?: boolean;
380
+ };
381
+ export type ArrayFieldConfig = BaseField & {
382
+ fieldType: "array";
383
+ /** Template fields cloned for each array item */
384
+ itemFields: IField[];
385
+ /** Grid columns for each item's field group */
386
+ itemColumns?: number;
387
+ /** Minimum number of items (pre-populated on mount) */
388
+ minItems?: number;
389
+ /** Maximum number of items (disables "Add" when reached) */
390
+ maxItems?: number;
391
+ /** Label for the add-item button */
392
+ addButtonLabel?: string;
393
+ /** Label for each item's remove button */
394
+ removeButtonLabel?: string;
395
+ /** Whether items can be reordered via move-up / move-down */
396
+ orderable?: boolean;
397
+ /** Default values for a new item (keys match itemFields[].id) */
398
+ defaultItemValue?: Record<string, unknown>;
399
+ };
400
+ export type IField = FileUploadField | ButtonsGroupField | SelectField | DateInputField | DateRangeField | WeekRangeField | MonthRangeField | MultiMonthPickerField | TextAreaField | RadioField | TextField | NumericComboboxField | CopyPasteField | FillFormByFileUploadField | TextFieldWithBackendValidation | ChipsField | DividerField | DividerWithLabelField | LabelField | SwitchField | CheckboxField | MultiWeekRangeField | ObjectFieldConfig | ArrayFieldConfig;
401
+ /** Discriminant string union for every built-in field type */
402
+ export type FieldType = IField["fieldType"];
@@ -0,0 +1,73 @@
1
+ import { Option } from '../../components/forms/select';
2
+ import { MonthSelection, WeekSelection } from '../../components/data-display/calendar';
3
+ /** Shared range shape for date_range / week_range / month_range */
4
+ export type RangeFieldOutput = {
5
+ start: string | null;
6
+ end: string | null;
7
+ } | null;
8
+ export type FileUploadFieldOutput = File[] | null | undefined;
9
+ export type ButtonsGroupFieldOutput = string | null | undefined;
10
+ export type SelectFieldOutput = Array<Option> | null | undefined;
11
+ export type DateRangeFieldOutput = RangeFieldOutput;
12
+ export type WeekRangeFieldOutput = RangeFieldOutput;
13
+ export type MonthRangeFieldOutput = RangeFieldOutput;
14
+ export type DateInputFieldOutput = string | null | undefined;
15
+ export type TextAreaFieldOutput = string | null | undefined;
16
+ export type RadioFieldOutput = string | null | undefined;
17
+ export type TextFieldOutput = string | null | undefined;
18
+ export type TextFieldWithBackendValidationOutput = string | null | undefined;
19
+ export type CopyPasteFieldOutput = Array<Option> | null | undefined;
20
+ export type FillFormByFileUploadFieldOutput = Array<Option> | null | undefined;
21
+ export type MultiWeekPickerFieldOutput = WeekSelection[] | null | undefined;
22
+ export type MultiMonthPickerFieldOutput = MonthSelection[] | null | undefined;
23
+ /** Empty string is the unset default from getFieldDefaultValue */
24
+ export type NumericComboboxFieldOutput = number | "" | null | undefined;
25
+ export type ChipsFieldOutput = string | string[] | null | undefined;
26
+ export type SwitchFieldOutput = boolean | null | undefined;
27
+ export type CheckboxFieldOutput = boolean | null | undefined;
28
+ /** Presentational fields do not store a value */
29
+ export type PresentationalFieldOutput = null | undefined;
30
+ /**
31
+ * Union of all field output values (recursive for object / array nesting).
32
+ * Defined independently of FieldTypeToOutputMap to avoid circular map lookups.
33
+ */
34
+ export type FieldOutputValue = FileUploadFieldOutput | ButtonsGroupFieldOutput | SelectFieldOutput | DateInputFieldOutput | DateRangeFieldOutput | WeekRangeFieldOutput | MultiWeekPickerFieldOutput | MonthRangeFieldOutput | MultiMonthPickerFieldOutput | TextAreaFieldOutput | RadioFieldOutput | TextFieldOutput | NumericComboboxFieldOutput | CopyPasteFieldOutput | FillFormByFileUploadFieldOutput | TextFieldWithBackendValidationOutput | ChipsFieldOutput | SwitchFieldOutput | CheckboxFieldOutput | PresentationalFieldOutput | {
35
+ [key: string]: FieldOutputValue;
36
+ } | Array<{
37
+ [key: string]: FieldOutputValue;
38
+ }>;
39
+ /**
40
+ * Exhaustive map from every IField fieldType → form-state value shape.
41
+ */
42
+ export type FieldTypeToOutputMap = {
43
+ file_upload: FileUploadFieldOutput;
44
+ button_group: ButtonsGroupFieldOutput;
45
+ select: SelectFieldOutput;
46
+ date: DateInputFieldOutput;
47
+ date_range: DateRangeFieldOutput;
48
+ week_range: WeekRangeFieldOutput;
49
+ multi_week_picker: MultiWeekPickerFieldOutput;
50
+ month_range: MonthRangeFieldOutput;
51
+ multi_month_picker: MultiMonthPickerFieldOutput;
52
+ text_area: TextAreaFieldOutput;
53
+ radio: RadioFieldOutput;
54
+ text: TextFieldOutput;
55
+ numeric_combobox: NumericComboboxFieldOutput;
56
+ fill_form_by_paste: CopyPasteFieldOutput;
57
+ fill_form_by_file_upload: FillFormByFileUploadFieldOutput;
58
+ text_with_backend_validation: TextFieldWithBackendValidationOutput;
59
+ chips: ChipsFieldOutput;
60
+ switch: SwitchFieldOutput;
61
+ checkbox: CheckboxFieldOutput;
62
+ object: {
63
+ [key: string]: FieldOutputValue;
64
+ } | null | undefined;
65
+ array: Array<{
66
+ [key: string]: FieldOutputValue;
67
+ }> | null | undefined;
68
+ label: PresentationalFieldOutput;
69
+ divider: PresentationalFieldOutput;
70
+ divider_with_label: PresentationalFieldOutput;
71
+ };
72
+ /** @deprecated Prefer FieldOutputValue — kept for BaseField / filter-era imports */
73
+ export type IFilterFieldOutputValue = FieldOutputValue;
@@ -0,0 +1,196 @@
1
+ import { ComponentType } from 'react';
2
+ import { FieldErrors, FormState, RegisterOptions, UseFormReturn } from 'react-hook-form';
3
+ import { Option } from '../../components/forms/select';
4
+ import { FieldVisibilityBase } from '../../form-engine';
5
+ import { FieldType, IField, SelectField } from './fields.types';
6
+ export type { FieldVisibilityBase } from '../../form-engine';
7
+ export type IFormConfig = {
8
+ formId: string;
9
+ fields: Array<IField>;
10
+ title?: string;
11
+ columns?: number;
12
+ gapBetweenFields?: number;
13
+ isCascading?: boolean;
14
+ includeOnlyVisibleFieldsInSubmit?: boolean;
15
+ enableFieldOrdering?: boolean;
16
+ };
17
+ export interface FormFieldProps {
18
+ field: IField;
19
+ formHelpers: UseReactHookFormReturn;
20
+ validationRules: RegisterOptions;
21
+ isDisabled: boolean;
22
+ formConfig: IFormConfig;
23
+ supportedValues?: SupportedValuesMap;
24
+ }
25
+ /**
26
+ * Consumer-injected context passed to the form framework and all field adapters.
27
+ * Modeled after AG Grid's `context` prop — a typed bag of functions and overrides.
28
+ */
29
+ export type FormContextFieldChangeParams = {
30
+ formHelpers: UseReactHookFormReturn;
31
+ fieldId: string;
32
+ newValue: unknown;
33
+ oldValue: unknown;
34
+ };
35
+ export type FormContextFunctionParams = FormContextFieldChangeParams & {
36
+ /** Field-specific input (File, pasted string, included field values, etc.) */
37
+ payload?: unknown;
38
+ };
39
+ export type FormContextValidator = (params: FormContextFieldChangeParams) => string | true;
40
+ export type FormContextGetSelectOptions = (params: FormContextFieldChangeParams) => Option[] | Promise<Option[]>;
41
+ export type FormContextFunction = (params: FormContextFunctionParams) => unknown | Promise<unknown>;
42
+ export type FormContextOnFieldChange = (params: FormContextFieldChangeParams) => void;
43
+ export type FetchSelectOptionsParams = {
44
+ fieldId: string;
45
+ apiConfig: NonNullable<SelectField['apiConfig']>;
46
+ earlierFieldsValues: Record<string, unknown>;
47
+ fieldSupportedValues?: Record<string, unknown>;
48
+ };
49
+ export type PastedValuesValidationResult = {
50
+ valid_values: Array<{
51
+ label: string;
52
+ value: string;
53
+ }>;
54
+ invalid_values: string[];
55
+ message?: string;
56
+ };
57
+ export type ValidatePastedValuesParams = {
58
+ apiEndpoint: string;
59
+ values: string;
60
+ targetFieldId: string;
61
+ dimensionId?: string;
62
+ };
63
+ export type ValidateUploadedFileParams = {
64
+ apiEndpoint: string;
65
+ file: File;
66
+ signal?: AbortSignal;
67
+ onUploadProgress?: (progress: {
68
+ loaded: number;
69
+ total?: number;
70
+ }) => void;
71
+ };
72
+ export type UploadedFileValidationResult = {
73
+ filtered_values: Record<string, Array<{
74
+ label: string;
75
+ value: string;
76
+ }>>;
77
+ invalid_rows_count: number;
78
+ signed_url: string;
79
+ total_count: Record<string, number>;
80
+ valid_rows_count: number;
81
+ message?: string;
82
+ session_id?: string;
83
+ };
84
+ export type ValidateTextFieldWithBackendParams = {
85
+ formHelpers: UseReactHookFormReturn;
86
+ apiEndpoint: string;
87
+ value: string;
88
+ method?: 'GET' | 'POST';
89
+ fieldValuesToIncludeInApiRequest: Record<string, unknown>;
90
+ };
91
+ export type TextFieldBackendValidationResult = {
92
+ is_valid: boolean;
93
+ message?: string;
94
+ };
95
+ /** Network and app-specific side effects — must be provided by the host application. */
96
+ export interface FormTransport {
97
+ fetchSelectOptions?: (params: FetchSelectOptionsParams) => Promise<Option[]>;
98
+ validatePastedValues?: (params: ValidatePastedValuesParams) => Promise<PastedValuesValidationResult>;
99
+ validateUploadedFile?: (params: ValidateUploadedFileParams) => Promise<UploadedFileValidationResult>;
100
+ validateTextFieldWithBackend?: (params: ValidateTextFieldWithBackendParams) => Promise<TextFieldBackendValidationResult>;
101
+ showFormErrorToast?: (message: {
102
+ title: string;
103
+ description: string;
104
+ }) => void;
105
+ }
106
+ /** Built-in fieldType keys plus arbitrary custom string keys */
107
+ export type CustomFieldTypesMap = Partial<Record<FieldType, ComponentType<FormFieldProps>>> & Record<string, ComponentType<FormFieldProps>>;
108
+ export interface FormValidationMeta {
109
+ isSubmittable: boolean;
110
+ }
111
+ export interface FormContextValidateFormParams {
112
+ formValues: ReactHookFormState;
113
+ visibleFields: IField[];
114
+ }
115
+ export interface FormContext {
116
+ /** Per-instance field type overrides or custom field components */
117
+ customFieldTypes?: CustomFieldTypesMap;
118
+ /** Named sync validators — referenced via validation[].validatorName */
119
+ validators?: Record<string, FormContextValidator>;
120
+ /** Named select options resolvers — referenced via getSelectOptionsName */
121
+ getSelectOptions?: Record<string, FormContextGetSelectOptions>;
122
+ /** Named handlers — referenced via BaseField.handlerName (on change + specialized validate) */
123
+ functions?: Record<string, FormContextFunction>;
124
+ /** Called after any field value changes */
125
+ onFieldChange?: FormContextOnFieldChange;
126
+ /** Host-provided network transport (axios, fetch, etc.) — not implemented by Impact Nova */
127
+ transport?: FormTransport;
128
+ /** Optional cross-field validation (e.g. required-one-of groups) merged into submit + isSubmittable */
129
+ validateForm?: (params: FormContextValidateFormParams) => {
130
+ isValid: boolean;
131
+ fieldErrors?: Record<string, {
132
+ message: string;
133
+ }>;
134
+ };
135
+ }
136
+ export type ReactHookFormState = Record<string, unknown>;
137
+ /** Map of field IDs to their supported values for API injection */
138
+ export type SupportedValuesMap = Record<string, unknown>;
139
+ export interface UseReactHookFormReturn {
140
+ formConfig: IFormConfig;
141
+ highlightFirstError?: boolean;
142
+ formId: string;
143
+ form: UseFormReturn<ReactHookFormState>;
144
+ getValues: () => ReactHookFormState;
145
+ setValue: (fieldName: string, value: unknown) => void;
146
+ resetForm: (values?: ReactHookFormState) => void;
147
+ handleSubmit: (onSubmit?: (data: ReactHookFormState) => void) => (e?: React.BaseSyntheticEvent) => Promise<void>;
148
+ handleCancel: () => void;
149
+ isFieldVisible: (field: FieldVisibilityBase) => boolean;
150
+ isFieldDisabled: (field: FieldVisibilityBase) => boolean;
151
+ isFieldDisabledForSubmitValidation: (field: FieldVisibilityBase) => boolean;
152
+ submitValidatedForm: (onSubmit?: (data: ReactHookFormState) => void) => void;
153
+ getEarlierFieldsIds: (currentFieldId: string, onlyMandatory?: boolean) => string[];
154
+ scrollToFirstError: () => void;
155
+ /** Set of field IDs that the user has explicitly marked as "set to empty". */
156
+ setToEmptyFields: Set<string>;
157
+ /** Mark a field as explicitly empty (snapshots current value for undo). */
158
+ markFieldAsEmpty: (fieldId: string) => void;
159
+ /** Undo a "set to empty" action — restores the field's previous value. */
160
+ undoSetToEmpty: (fieldId: string) => void;
161
+ /** Snapshot of a field's value before the latest change (for validators / handlers). */
162
+ getPreviousFieldValue: (fieldId: string) => unknown;
163
+ /** Consumer-injected context — validators, custom field types, lifecycle hooks */
164
+ formContext?: FormContext;
165
+ }
166
+ export interface ReactHooksFormProps {
167
+ formId?: string;
168
+ formConfig: IFormConfig;
169
+ formInitialState?: ReactHookFormState;
170
+ onSubmit?: (data: ReactHookFormState) => void;
171
+ onCancel?: (data: ReactHookFormState) => void;
172
+ onReset?: (data: ReactHookFormState) => void;
173
+ sendFormStateToParent?: (formState: FormState<ReactHookFormState>, formValues?: ReactHookFormState, formMeta?: FormValidationMeta) => void;
174
+ /** Map of field IDs to values that should be injected into API calls */
175
+ supportedValues?: SupportedValuesMap;
176
+ /** Consumer-injected context — validators, custom field types, lifecycle hooks */
177
+ formContext?: FormContext;
178
+ }
179
+ export interface ReactHooksFormRef {
180
+ submitForm: () => Promise<boolean>;
181
+ hasErrors: boolean;
182
+ errors: FieldErrors<ReactHookFormState>;
183
+ isValid: boolean;
184
+ }
185
+ export interface UseSelectOptionsProps {
186
+ apiConfig?: SelectField["apiConfig"];
187
+ formHelpers?: UseReactHookFormReturn;
188
+ formConfig?: IFormConfig;
189
+ initialOptions?: Option[];
190
+ id: string;
191
+ isEnabled: boolean;
192
+ /** Name of formContext.getSelectOptions resolver */
193
+ getSelectOptionsName?: string;
194
+ /** Field-specific values to inject into API payload (e.g., viewSettings, globalFilters) */
195
+ fieldSupportedValues?: Record<string, unknown>;
196
+ }
@@ -0,0 +1,14 @@
1
+ import { UseFormReturn, Path, PathValue } from 'react-hook-form';
2
+ type BatchFieldUpdate<FormValues extends Record<string, unknown>> = {
3
+ fieldName: Path<FormValues>;
4
+ value: PathValue<FormValues, Path<FormValues>>;
5
+ };
6
+ /**
7
+ * Applies multiple setValue calls in one synchronous pass so React 18 can
8
+ * batch the resulting renders into a single commit.
9
+ */
10
+ export declare function batchSetFormFieldValues<FormValues extends Record<string, unknown>>(form: UseFormReturn<FormValues>, updates: BatchFieldUpdate<FormValues>[], options?: {
11
+ shouldDirty?: boolean;
12
+ shouldValidate?: boolean;
13
+ }): void;
14
+ export {};