@conform-to/react 1.17.0 → 1.18.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.
@@ -1,6 +1,6 @@
1
1
  import { objectSpread2 as _objectSpread2 } from '../_virtual/_rollupPluginBabelHelpers.mjs';
2
- import { getPathSegments, getRelativePath, serialize, appendPathSegment, deepEqual, getValueAtPath, formatPathSegments } from '@conform-to/dom/future';
3
- import { when, generateUniqueKey, merge, getArrayAtPath } from './util.mjs';
2
+ import { parsePath, getRelativePath, serialize, appendPath, deepEqual, getPathValue, normalize, formatPath } from '@conform-to/dom/future';
3
+ import { when, generateUniqueKey, merge, getPathArray } from './util.mjs';
4
4
 
5
5
  function initializeState(options) {
6
6
  var _options$resetKey, _options$defaultValue;
@@ -78,7 +78,7 @@ function updateState(state, action) {
78
78
  function pruneListKeys(listKeys, targetValue) {
79
79
  var result = listKeys;
80
80
  for (var [name, keys] of Object.entries(listKeys)) {
81
- var list = getArrayAtPath(targetValue, name);
81
+ var list = getPathArray(targetValue, name);
82
82
 
83
83
  // Reset list keys only if the length has changed
84
84
  // to minimize potential UI state loss due to key changes
@@ -94,10 +94,16 @@ function pruneListKeys(listKeys, targetValue) {
94
94
  }
95
95
  return result;
96
96
  }
97
- function getDefaultValue(context, name) {
97
+ function getDefaultPayload(context, name) {
98
98
  var _ref, _context$state$server;
99
99
  var serialize$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : serialize;
100
- var value = getValueAtPath((_ref = (_context$state$server = context.state.serverValue) !== null && _context$state$server !== void 0 ? _context$state$server : context.state.targetValue) !== null && _ref !== void 0 ? _ref : context.state.defaultValue, name);
100
+ var value = getPathValue((_ref = (_context$state$server = context.state.serverValue) !== null && _context$state$server !== void 0 ? _context$state$server : context.state.targetValue) !== null && _ref !== void 0 ? _ref : context.state.defaultValue, name);
101
+ return normalize(value, serialize$1);
102
+ }
103
+ function getDefaultValue(context, name) {
104
+ var _ref2, _context$state$server2;
105
+ var serialize$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : serialize;
106
+ var value = getPathValue((_ref2 = (_context$state$server2 = context.state.serverValue) !== null && _context$state$server2 !== void 0 ? _context$state$server2 : context.state.targetValue) !== null && _ref2 !== void 0 ? _ref2 : context.state.defaultValue, name);
101
107
  var serializedValue = serialize$1(value);
102
108
  if (typeof serializedValue === 'string') {
103
109
  return serializedValue;
@@ -105,9 +111,9 @@ function getDefaultValue(context, name) {
105
111
  return '';
106
112
  }
107
113
  function getDefaultOptions(context, name) {
108
- var _ref2, _context$state$server2;
114
+ var _ref3, _context$state$server3;
109
115
  var serialize$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : serialize;
110
- var value = getValueAtPath((_ref2 = (_context$state$server2 = context.state.serverValue) !== null && _context$state$server2 !== void 0 ? _context$state$server2 : context.state.targetValue) !== null && _ref2 !== void 0 ? _ref2 : context.state.defaultValue, name);
116
+ var value = getPathValue((_ref3 = (_context$state$server3 = context.state.serverValue) !== null && _context$state$server3 !== void 0 ? _context$state$server3 : context.state.targetValue) !== null && _ref3 !== void 0 ? _ref3 : context.state.defaultValue, name);
111
117
  var serializedValue = serialize$1(value);
112
118
  if (Array.isArray(serializedValue) && serializedValue.every(item => typeof item === 'string')) {
113
119
  return serializedValue;
@@ -118,12 +124,12 @@ function getDefaultOptions(context, name) {
118
124
  return [];
119
125
  }
120
126
  function isDefaultChecked(context, name) {
121
- var _ref3, _context$state$server3;
127
+ var _ref4, _context$state$server4;
122
128
  var serialize$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : serialize;
123
- var value = getValueAtPath((_ref3 = (_context$state$server3 = context.state.serverValue) !== null && _context$state$server3 !== void 0 ? _context$state$server3 : context.state.targetValue) !== null && _ref3 !== void 0 ? _ref3 : context.state.defaultValue, name);
129
+ var value = getPathValue((_ref4 = (_context$state$server4 = context.state.serverValue) !== null && _context$state$server4 !== void 0 ? _context$state$server4 : context.state.targetValue) !== null && _ref4 !== void 0 ? _ref4 : context.state.defaultValue, name);
124
130
  var serializedValue = serialize$1(value);
125
131
  if (typeof serializedValue === 'string') {
126
- return serializedValue === 'on';
132
+ return serializedValue === serialize$1(true);
127
133
  }
128
134
  return false;
129
135
  }
@@ -139,15 +145,15 @@ function isTouched(state) {
139
145
  if (state.touchedFields.includes(name)) {
140
146
  return true;
141
147
  }
142
- var paths = getPathSegments(name);
148
+ var paths = parsePath(name);
143
149
  return state.touchedFields.some(field => field !== name && getRelativePath(field, paths) !== null);
144
150
  }
145
151
  function getDefaultListKey(prefix, initialValue, name) {
146
- return getArrayAtPath(initialValue, name).map((_, index) => "".concat(prefix, "-").concat(appendPathSegment(name, index)));
152
+ return getPathArray(initialValue, name).map((_, index) => "".concat(prefix, "-").concat(appendPath(name, index)));
147
153
  }
148
154
  function getListKey(context, name) {
149
- var _context$state$listKe, _context$state$listKe2, _ref4, _context$state$server4;
150
- return (_context$state$listKe = (_context$state$listKe2 = context.state.listKeys) === null || _context$state$listKe2 === void 0 ? void 0 : _context$state$listKe2[name]) !== null && _context$state$listKe !== void 0 ? _context$state$listKe : getDefaultListKey(context.state.resetKey, (_ref4 = (_context$state$server4 = context.state.serverValue) !== null && _context$state$server4 !== void 0 ? _context$state$server4 : context.state.targetValue) !== null && _ref4 !== void 0 ? _ref4 : context.state.defaultValue, name);
155
+ var _context$state$listKe, _context$state$listKe2, _ref5, _context$state$server5;
156
+ return (_context$state$listKe = (_context$state$listKe2 = context.state.listKeys) === null || _context$state$listKe2 === void 0 ? void 0 : _context$state$listKe2[name]) !== null && _context$state$listKe !== void 0 ? _context$state$listKe : getDefaultListKey(context.state.resetKey, (_ref5 = (_context$state$server5 = context.state.serverValue) !== null && _context$state$server5 !== void 0 ? _context$state$server5 : context.state.targetValue) !== null && _ref5 !== void 0 ? _ref5 : context.state.defaultValue, name);
151
157
  }
152
158
  function getErrors(state, name) {
153
159
  var _state$serverError;
@@ -165,7 +171,7 @@ function getFieldErrors(state, name) {
165
171
  var result = {};
166
172
  var error = (_state$serverError2 = state.serverError) !== null && _state$serverError2 !== void 0 ? _state$serverError2 : state.clientError;
167
173
  if (error) {
168
- var basePath = getPathSegments(name);
174
+ var basePath = parsePath(name);
169
175
  for (var field of Object.keys(error.fieldErrors)) {
170
176
  var relativePath = getRelativePath(field, basePath);
171
177
 
@@ -175,12 +181,23 @@ function getFieldErrors(state, name) {
175
181
  }
176
182
  var _error = getErrors(state, field);
177
183
  if (typeof _error !== 'undefined') {
178
- result[formatPathSegments(relativePath)] = _error;
184
+ result[formatPath(relativePath)] = _error;
179
185
  }
180
186
  }
181
187
  }
182
188
  return result;
183
189
  }
190
+
191
+ /**
192
+ * Checks if fieldErrors contains any errors at the given name or any child path.
193
+ */
194
+ function hasFieldError(error, name) {
195
+ var basePath = parsePath(name);
196
+ return Object.keys(error.fieldErrors).some(field => {
197
+ var _error$fieldErrors$fi;
198
+ return getRelativePath(field, basePath) !== null && ((_error$fieldErrors$fi = error.fieldErrors[field]) === null || _error$fieldErrors$fi === void 0 ? void 0 : _error$fieldErrors$fi.length);
199
+ });
200
+ }
184
201
  function isValid(state, name) {
185
202
  var _state$serverError3;
186
203
  var error = (_state$serverError3 = state.serverError) !== null && _state$serverError3 !== void 0 ? _state$serverError3 : state.clientError;
@@ -189,7 +206,7 @@ function isValid(state, name) {
189
206
  if (!error) {
190
207
  return true;
191
208
  }
192
- var basePath = getPathSegments(name);
209
+ var basePath = parsePath(name);
193
210
  for (var field of Object.keys(error.fieldErrors)) {
194
211
  // When checking a specific field, only check that field and its children
195
212
  if (name && !getRelativePath(field, basePath)) {
@@ -209,34 +226,6 @@ function isValid(state, name) {
209
226
  }
210
227
  return true;
211
228
  }
212
-
213
- /**
214
- * Gets validation constraint for a field, with fallback to parent array patterns.
215
- * e.g. "array[0].key" falls back to "array[].key" if specific constraint not found.
216
- */
217
- function getConstraint(context, name) {
218
- var _context$constraint;
219
- var constraint = (_context$constraint = context.constraint) === null || _context$constraint === void 0 ? void 0 : _context$constraint[name];
220
- if (!constraint) {
221
- var path = getPathSegments(name);
222
- for (var i = path.length - 1; i >= 0; i--) {
223
- var segment = path[i];
224
- // Try searching a less specific path for the constraint
225
- // e.g. `array[0].anotherArray[1].key` -> `array[0].anotherArray[].key` -> `array[].anotherArray[].key`
226
- if (typeof segment === 'number') {
227
- // This overrides the current number segment with an empty string
228
- // which will be treated as an empty bracket
229
- path[i] = '';
230
- break;
231
- }
232
- }
233
- var alternative = formatPathSegments(path);
234
- if (name !== alternative) {
235
- constraint = getConstraint(context, alternative);
236
- }
237
- }
238
- return constraint;
239
- }
240
229
  function getFormMetadata(context, options) {
241
230
  var _options$extendFormMe, _options$extendFormMe2;
242
231
  var metadata = {
@@ -297,7 +286,7 @@ function getFormMetadata(context, options) {
297
286
  return extended;
298
287
  }
299
288
  function getField(context, options) {
300
- var _extendFieldMetadata;
289
+ var _context$constraint, _extendFieldMetadata;
301
290
  var {
302
291
  key,
303
292
  name,
@@ -309,7 +298,7 @@ function getField(context, options) {
309
298
  })
310
299
  } = options;
311
300
  var id = "".concat(context.formId, "-field-").concat(name.replace(/[^a-zA-Z0-9._-]/g, '_'));
312
- var constraint = getConstraint(context, name);
301
+ var constraint = (_context$constraint = context.constraint) === null || _context$constraint === void 0 ? void 0 : _context$constraint[name];
313
302
  var metadata = {
314
303
  key,
315
304
  name,
@@ -335,6 +324,9 @@ function getField(context, options) {
335
324
  get defaultChecked() {
336
325
  return isDefaultChecked(context, name, serialize$1);
337
326
  },
327
+ get defaultPayload() {
328
+ return getDefaultPayload(context, name, serialize$1);
329
+ },
338
330
  get touched() {
339
331
  return isTouched(context.state, name);
340
332
  },
@@ -396,7 +388,7 @@ function getFieldset(context, options) {
396
388
  extendFieldMetadata: options === null || options === void 0 ? void 0 : options.extendFieldMetadata
397
389
  });
398
390
  return getField(context, {
399
- name: appendPathSegment(options === null || options === void 0 ? void 0 : options.name, name),
391
+ name: appendPath(options === null || options === void 0 ? void 0 : options.name, name),
400
392
  serialize: options.serialize,
401
393
  extendFieldMetadata: options.extendFieldMetadata,
402
394
  form: options.form
@@ -414,7 +406,7 @@ function getFieldList(context, options) {
414
406
  var keys = getListKey(context, options.name);
415
407
  return keys.map((key, index) => {
416
408
  return getField(context, {
417
- name: appendPathSegment(options.name, index),
409
+ name: appendPath(options.name, index),
418
410
  serialize: options.serialize,
419
411
  extendFieldMetadata: options.extendFieldMetadata,
420
412
  key
@@ -422,4 +414,4 @@ function getFieldList(context, options) {
422
414
  });
423
415
  }
424
416
 
425
- export { getConstraint, getDefaultListKey, getDefaultOptions, getDefaultValue, getErrors, getField, getFieldErrors, getFieldList, getFieldset, getFormMetadata, getListKey, initializeState, isDefaultChecked, isTouched, isValid, pruneListKeys, updateState };
417
+ export { getDefaultListKey, getDefaultOptions, getDefaultPayload, getDefaultValue, getErrors, getField, getFieldErrors, getFieldList, getFieldset, getFormMetadata, getListKey, hasFieldError, initializeState, isDefaultChecked, isTouched, isValid, pruneListKeys, updateState };
@@ -5,39 +5,48 @@ export type Prettify<T> = {
5
5
  } & {};
6
6
  /** Reference to a form element. Can be either a React ref object or a form ID string. */
7
7
  export type FormRef = React.RefObject<HTMLFormElement | HTMLFieldSetElement | HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement | null> | string;
8
- export type InputSnapshot = {
9
- value?: string | undefined;
10
- options?: string[] | undefined;
11
- checked?: boolean | undefined;
12
- files?: File[] | undefined;
13
- };
14
- export type Control = {
8
+ export type DefaultControlValue = string | string[] | File | File[] | FileList;
9
+ export type Control<Value = DefaultControlValue, DefaultValue = Value, Payload = unknown> = {
15
10
  /**
16
- * Current value of the base input. Undefined if the registered input
17
- * is a multi-select, file input, or checkbox group.
11
+ * Current string value derived from the control payload.
18
12
  */
19
13
  value: string | undefined;
20
14
  /**
21
- * Selected options of the base input. Defined only when the registered input
22
- * is a multi-select or checkbox group.
15
+ * Checked state derived from the control payload.
23
16
  */
24
17
  checked: boolean | undefined;
25
18
  /**
26
- * Checked state of the base input. Defined only when the registered input
27
- * is a single checkbox or radio input.
19
+ * Current string array derived from the control payload.
28
20
  */
29
21
  options: string[] | undefined;
30
22
  /**
31
- * Selected files of the base input. Defined only when the registered input
32
- * is a file input.
23
+ * Current file array derived from the control payload.
33
24
  */
34
25
  files: File[] | undefined;
35
26
  /**
36
- * Registers the base input element(s). Accepts a single input or an array for groups.
27
+ * The rendered payload used as the source for base control(s).
28
+ *
29
+ * For simple native controls, this mirrors `defaultValue` / `defaultChecked`.
30
+ * For structural controls (i.e. `<fieldset>`), this is the latest payload
31
+ * snapshot that drives which hidden inputs are rendered.
32
+ */
33
+ defaultValue: DefaultValue | null | undefined;
34
+ /**
35
+ * Current payload snapshot derived from the registered base control(s).
36
+ *
37
+ * For structural controls (i.e. `<fieldset>`), this is reconstructed from
38
+ * descendant fields under the registered fieldset name.
37
39
  */
38
- register: (element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLCollectionOf<HTMLInputElement> | NodeListOf<HTMLInputElement> | null | undefined) => void;
40
+ payload: Payload | null | undefined;
39
41
  /**
40
- * A ref object containing the form element associated with the registered input.
42
+ * Registers the base control element.
43
+ *
44
+ * Accepts `<input>`, `<select>`, `<textarea>`, `<fieldset>`,
45
+ * or a collection of checkbox / radio inputs with the same name.
46
+ */
47
+ register: (element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLFieldSetElement | HTMLCollectionOf<HTMLInputElement> | NodeListOf<HTMLInputElement> | null | undefined) => void;
48
+ /**
49
+ * A ref object containing the form element associated with the registered base control.
41
50
  * Use this with hooks like useFormData() and useIntent().
42
51
  */
43
52
  formRef: React.RefObject<HTMLFormElement | null>;
@@ -46,21 +55,74 @@ export type Control = {
46
55
  * both [change](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) and
47
56
  * [input](https://developer.mozilla.org/en-US/docs/Web/API/Element/input_event) events.
48
57
  */
49
- change: (value: string | string[] | boolean | File | File[] | FileList | null) => void;
50
- /**
51
- * Emits [blur](https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event) and
52
- * [focusout](https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event) events.
53
- * Does not actually move focus.
54
- */
55
- focus: () => void;
58
+ change: (value: Value | null) => void;
56
59
  /**
57
60
  * Emits [focus](https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event) and
58
61
  * [focusin](https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event) events.
59
- * This does not move the actual keyboard focus to the input. Use `element.focus()` instead
62
+ *
63
+ * This does not move the actual keyboard focus to the input.
64
+ * Use [HTMLElement.focus()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)
60
65
  * if you want to move focus to the input.
61
66
  */
67
+ focus: () => void;
68
+ /**
69
+ * Emits [blur](https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event) and
70
+ * [focusout](https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event) events.
71
+ *
72
+ * This does not move the actual keyboard focus away from the input.
73
+ */
62
74
  blur: () => void;
63
75
  };
76
+ export type StandardControlOptions<Value extends DefaultControlValue = DefaultControlValue> = {
77
+ /**
78
+ * The initial value of the base control.
79
+ */
80
+ defaultValue?: Value | null | undefined;
81
+ /**
82
+ * A callback function that is triggered when the base control is focused.
83
+ * Use this to delegate focus to a custom input.
84
+ */
85
+ onFocus?: () => void;
86
+ };
87
+ export type CheckedControlOptions = {
88
+ /**
89
+ * Whether the base control should be checked by default.
90
+ */
91
+ defaultChecked?: boolean | undefined;
92
+ /**
93
+ * The value of a checkbox or radio control when checked.
94
+ */
95
+ value?: string;
96
+ /**
97
+ * A callback function that is triggered when the base control is focused.
98
+ * Use this to delegate focus to a custom input.
99
+ */
100
+ onFocus?: () => void;
101
+ };
102
+ export type CustomControlOptions<Value = unknown, DefaultValue = Value> = {
103
+ /**
104
+ * Initial value used to seed the control.
105
+ * For structural controls, this is the payload used to render hidden inputs.
106
+ */
107
+ defaultValue?: DefaultValue | null | undefined;
108
+ /**
109
+ * Payload parser applied to the current payload snapshot.
110
+ *
111
+ * Use this to coerce unknown DOM-derived data into a typed shape.
112
+ * Any thrown error is surfaced to the caller.
113
+ */
114
+ parse: (payload: unknown) => Value | null | undefined;
115
+ /**
116
+ * Optional serializer to convert the parsed payload back to a form value for populating the base control(s).
117
+ */
118
+ serialize?: (value: Value) => FormValue;
119
+ /**
120
+ * A callback function that is triggered when the base control is focused.
121
+ * Use this to delegate focus to a custom input.
122
+ */
123
+ onFocus?: () => void;
124
+ };
125
+ export type ControlOptions = StandardControlOptions | CheckedControlOptions | CustomControlOptions;
64
126
  export type Selector<FormValue, Result> = (formData: FormValue, lastResult: Result | undefined) => Result;
65
127
  export type UseFormDataOptions<Value = undefined> = {
66
128
  /**
@@ -278,7 +340,9 @@ export type GlobalFormOptions = {
278
340
  export type NonPartial<T> = {
279
341
  [K in keyof Required<T>]: T[K];
280
342
  };
281
- export type RequireKey<T, K extends keyof T> = Prettify<T & Pick<NonPartial<T>, K>>;
343
+ export type RequireKey<T, K extends keyof T> = Prettify<Omit<T, K> & {
344
+ [P in K]-?: Exclude<T[P], undefined>;
345
+ }>;
282
346
  export type BaseSchemaType = StandardSchemaV1<any, any>;
283
347
  /**
284
348
  * Infer schema input type.
@@ -570,6 +634,13 @@ export type FieldMetadata<FieldShape, ErrorShape extends BaseErrorShape = Defaul
570
634
  * For radio buttons, compare the field's `defaultValue` with the radio button's value attribute instead.
571
635
  */
572
636
  defaultChecked: boolean;
637
+ /**
638
+ * The normalized default payload at this field path.
639
+ *
640
+ * This is useful for non-native field shapes that need to render a set of
641
+ * hidden inputs before user interaction.
642
+ */
643
+ defaultPayload: unknown;
573
644
  /** Whether this field has been touched (through intent.validate() or the shouldValidate option). */
574
645
  touched: boolean;
575
646
  /** Whether this field currently has no validation errors. */
@@ -697,12 +768,12 @@ export type ValidateHandler<ErrorShape, Value, SchemaValue = undefined> = (ctx:
697
768
  ] | undefined;
698
769
  export interface FormInputEvent extends React.FormEvent<HTMLFormElement> {
699
770
  currentTarget: EventTarget & HTMLFormElement;
700
- target: EventTarget & (HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement);
771
+ target: EventTarget & (HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLFieldSetElement);
701
772
  }
702
773
  export interface FormFocusEvent extends React.FormEvent<HTMLFormElement> {
703
774
  currentTarget: EventTarget & HTMLFormElement;
704
775
  relatedTarget: EventTarget | null;
705
- target: EventTarget & (HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement);
776
+ target: EventTarget & (HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLFieldSetElement);
706
777
  }
707
778
  export type ErrorContext<ErrorShape> = {
708
779
  formElement: HTMLFormElement;
@@ -782,5 +853,47 @@ export type MakeConditional<T, ConditionalKeys extends Record<string, unknown>>
782
853
  [K in keyof ConditionalKeys]: K extends keyof T ? ConditionalFieldMetadata<T[K], ConditionalKeys[K]> : never;
783
854
  };
784
855
  export type MaybePromise<T> = T | Promise<T>;
856
+ type BaseFieldsetProps = RequireKey<Omit<React.ComponentPropsWithoutRef<'fieldset'>, 'children' | 'defaultValue'>, 'name'> & {
857
+ /**
858
+ * Renders a hidden `<fieldset>` base control with nested hidden `<input>` elements
859
+ * derived from `defaultValue`.
860
+ */
861
+ type: 'fieldset';
862
+ /**
863
+ * Structured default value used to render nested hidden inputs.
864
+ */
865
+ defaultValue: unknown;
866
+ };
867
+ type BaseSelectProps = RequireKey<Omit<React.ComponentPropsWithoutRef<'select'>, 'children' | 'value'>, 'name' | 'defaultValue'> & {
868
+ /**
869
+ * Renders a hidden `<select>` base control.
870
+ */
871
+ type: 'select';
872
+ };
873
+ type BaseTextareaProps = RequireKey<Omit<React.ComponentPropsWithoutRef<'textarea'>, 'children' | 'value'>, 'name' | 'defaultValue'> & {
874
+ /**
875
+ * Renders a hidden `<textarea>` base control.
876
+ */
877
+ type: 'textarea';
878
+ };
879
+ type BaseCheckedInputProps = RequireKey<Omit<React.ComponentPropsWithoutRef<'input'>, 'children' | 'type' | 'checked'>, 'name' | 'defaultChecked'> & {
880
+ /**
881
+ * Renders a hidden checkbox or radio base control.
882
+ */
883
+ type: 'checkbox' | 'radio';
884
+ };
885
+ type BaseFileInputProps = RequireKey<Omit<React.ComponentPropsWithoutRef<'input'>, 'children' | 'type' | 'value' | 'checked'>, 'name'> & {
886
+ /**
887
+ * Renders a hidden `<input type="file">` base control.
888
+ */
889
+ type: 'file';
890
+ };
891
+ type BaseInputProps = RequireKey<Omit<React.ComponentPropsWithoutRef<'input'>, 'children' | 'type' | 'value' | 'checked'>, 'name' | 'defaultValue'> & {
892
+ /**
893
+ * Renders a hidden `<input type="...">` base control.
894
+ */
895
+ type?: 'color' | 'date' | 'datetime-local' | 'email' | 'hidden' | 'month' | 'number' | 'password' | 'range' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week';
896
+ };
897
+ export type BaseControlProps = BaseFieldsetProps | BaseSelectProps | BaseTextareaProps | BaseCheckedInputProps | BaseFileInputProps | BaseInputProps;
785
898
  export {};
786
899
  //# sourceMappingURL=types.d.ts.map
@@ -6,12 +6,12 @@ export declare function isString(value: unknown): value is string;
6
6
  export declare function isNumber(value: unknown): value is number;
7
7
  export declare function isNullable<T>(value: unknown, typeGuard: (value: unknown) => value is T): value is T | null;
8
8
  export declare function isOptional<T>(value: unknown, typeGuard: (value: unknown) => value is T): value is T | undefined;
9
- export declare function getArrayAtPath<Type>(formValue: Record<string, Type> | null, name: string): Array<Type>;
9
+ export declare function getPathArray<Type>(formValue: Record<string, Type> | null, name: string): Array<Type>;
10
10
  /**
11
11
  * Immutably updates a value at the specified path.
12
12
  * Empty path replaces the entire object.
13
13
  */
14
- export declare function updateValueAtPath<Data>(data: Record<string, Data>, name: string, value: Data | Record<string, Data>): Record<string, Data>;
14
+ export declare function updatePathValue<Data>(data: Record<string, Data>, name: string, value: Data | Record<string, Data>): Record<string, Data>;
15
15
  /**
16
16
  * Creates a function that updates array indices in field paths.
17
17
  * Returns null to remove fields, or updated path with new index.
@@ -19,9 +19,9 @@ function isNullable(value, typeGuard) {
19
19
  function isOptional(value, typeGuard) {
20
20
  return isUndefined(value) || typeGuard(value);
21
21
  }
22
- function getArrayAtPath(formValue, name) {
23
- var _getValueAtPath;
24
- var value = (_getValueAtPath = future.getValueAtPath(formValue, name)) !== null && _getValueAtPath !== void 0 ? _getValueAtPath : [];
22
+ function getPathArray(formValue, name) {
23
+ var _getPathValue;
24
+ var value = (_getPathValue = future.getPathValue(formValue, name)) !== null && _getPathValue !== void 0 ? _getPathValue : [];
25
25
  if (!Array.isArray(value)) {
26
26
  throw new Error("The value of \"".concat(name, "\" is not an array"));
27
27
  }
@@ -32,14 +32,14 @@ function getArrayAtPath(formValue, name) {
32
32
  * Immutably updates a value at the specified path.
33
33
  * Empty path replaces the entire object.
34
34
  */
35
- function updateValueAtPath(data, name, value) {
35
+ function updatePathValue(data, name, value) {
36
36
  if (name === '') {
37
37
  if (!future.isPlainObject(value)) {
38
38
  throw new Error('The value must be an object');
39
39
  }
40
40
  return value;
41
41
  }
42
- return future.setValueAtPath(data, future.getPathSegments(name), value, {
42
+ return future.setPathValue(data, future.parsePath(name), value, {
43
43
  clone: true
44
44
  });
45
45
  }
@@ -49,9 +49,9 @@ function updateValueAtPath(data, name, value) {
49
49
  * Returns null to remove fields, or updated path with new index.
50
50
  */
51
51
  function createPathIndexUpdater(listName, update) {
52
- var listPaths = future.getPathSegments(listName);
52
+ var listPaths = future.parsePath(listName);
53
53
  return name => {
54
- var paths = future.getPathSegments(name);
54
+ var paths = future.parsePath(name);
55
55
  if (paths.length > listPaths.length && listPaths.every((path, index) => paths[index] === path)) {
56
56
  var currentIndex = paths[listPaths.length];
57
57
  if (typeof currentIndex === 'number') {
@@ -63,7 +63,7 @@ function createPathIndexUpdater(listName, update) {
63
63
  if (newIndex !== currentIndex) {
64
64
  // Replace the index
65
65
  paths.splice(listPaths.length, 1, newIndex);
66
- return future.formatPathSegments(paths);
66
+ return future.formatPath(paths);
67
67
  }
68
68
  }
69
69
  }
@@ -248,7 +248,7 @@ exports.appendUniqueItem = appendUniqueItem;
248
248
  exports.compactMap = compactMap;
249
249
  exports.createPathIndexUpdater = createPathIndexUpdater;
250
250
  exports.generateUniqueKey = generateUniqueKey;
251
- exports.getArrayAtPath = getArrayAtPath;
251
+ exports.getPathArray = getPathArray;
252
252
  exports.isNullable = isNullable;
253
253
  exports.isNumber = isNumber;
254
254
  exports.isOptional = isOptional;
@@ -262,6 +262,6 @@ exports.resolveStandardSchemaResult = resolveStandardSchemaResult;
262
262
  exports.resolveValidateResult = resolveValidateResult;
263
263
  exports.shape = shape;
264
264
  exports.transformKeys = transformKeys;
265
- exports.updateValueAtPath = updateValueAtPath;
265
+ exports.updatePathValue = updatePathValue;
266
266
  exports.validateStandardSchemaV1 = validateStandardSchemaV1;
267
267
  exports.when = when;
@@ -1,4 +1,4 @@
1
- import { formatIssues, getValueAtPath, isPlainObject, setValueAtPath, getPathSegments, formatPathSegments } from '@conform-to/dom/future';
1
+ import { formatIssues, getPathValue, isPlainObject, setPathValue, parsePath, formatPath } from '@conform-to/dom/future';
2
2
 
3
3
  function isUndefined(value) {
4
4
  return value === undefined;
@@ -15,9 +15,9 @@ function isNullable(value, typeGuard) {
15
15
  function isOptional(value, typeGuard) {
16
16
  return isUndefined(value) || typeGuard(value);
17
17
  }
18
- function getArrayAtPath(formValue, name) {
19
- var _getValueAtPath;
20
- var value = (_getValueAtPath = getValueAtPath(formValue, name)) !== null && _getValueAtPath !== void 0 ? _getValueAtPath : [];
18
+ function getPathArray(formValue, name) {
19
+ var _getPathValue;
20
+ var value = (_getPathValue = getPathValue(formValue, name)) !== null && _getPathValue !== void 0 ? _getPathValue : [];
21
21
  if (!Array.isArray(value)) {
22
22
  throw new Error("The value of \"".concat(name, "\" is not an array"));
23
23
  }
@@ -28,14 +28,14 @@ function getArrayAtPath(formValue, name) {
28
28
  * Immutably updates a value at the specified path.
29
29
  * Empty path replaces the entire object.
30
30
  */
31
- function updateValueAtPath(data, name, value) {
31
+ function updatePathValue(data, name, value) {
32
32
  if (name === '') {
33
33
  if (!isPlainObject(value)) {
34
34
  throw new Error('The value must be an object');
35
35
  }
36
36
  return value;
37
37
  }
38
- return setValueAtPath(data, getPathSegments(name), value, {
38
+ return setPathValue(data, parsePath(name), value, {
39
39
  clone: true
40
40
  });
41
41
  }
@@ -45,9 +45,9 @@ function updateValueAtPath(data, name, value) {
45
45
  * Returns null to remove fields, or updated path with new index.
46
46
  */
47
47
  function createPathIndexUpdater(listName, update) {
48
- var listPaths = getPathSegments(listName);
48
+ var listPaths = parsePath(listName);
49
49
  return name => {
50
- var paths = getPathSegments(name);
50
+ var paths = parsePath(name);
51
51
  if (paths.length > listPaths.length && listPaths.every((path, index) => paths[index] === path)) {
52
52
  var currentIndex = paths[listPaths.length];
53
53
  if (typeof currentIndex === 'number') {
@@ -59,7 +59,7 @@ function createPathIndexUpdater(listName, update) {
59
59
  if (newIndex !== currentIndex) {
60
60
  // Replace the index
61
61
  paths.splice(listPaths.length, 1, newIndex);
62
- return formatPathSegments(paths);
62
+ return formatPath(paths);
63
63
  }
64
64
  }
65
65
  }
@@ -240,4 +240,4 @@ function validateStandardSchemaV1(schema, payload) {
240
240
  return resolveStandardSchemaResult(result);
241
241
  }
242
242
 
243
- export { appendUniqueItem, compactMap, createPathIndexUpdater, generateUniqueKey, getArrayAtPath, isNullable, isNumber, isOptional, isStandardSchemaV1, isString, isUndefined, merge, normalizeFormError, normalizeValidateResult, resolveStandardSchemaResult, resolveValidateResult, shape, transformKeys, updateValueAtPath, validateStandardSchemaV1, when };
243
+ export { appendUniqueItem, compactMap, createPathIndexUpdater, generateUniqueKey, getPathArray, isNullable, isNumber, isOptional, isStandardSchemaV1, isString, isUndefined, merge, normalizeFormError, normalizeValidateResult, resolveStandardSchemaResult, resolveValidateResult, shape, transformKeys, updatePathValue, validateStandardSchemaV1, when };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Conform view adapter for react",
4
4
  "homepage": "https://conform.guide",
5
5
  "license": "MIT",
6
- "version": "1.17.0",
6
+ "version": "1.18.0",
7
7
  "main": "./dist/index.js",
8
8
  "module": "./dist/index.mjs",
9
9
  "types": "./dist/index.d.ts",
@@ -41,7 +41,7 @@
41
41
  "url": "https://github.com/edmundhung/conform/issues"
42
42
  },
43
43
  "dependencies": {
44
- "@conform-to/dom": "1.17.0"
44
+ "@conform-to/dom": "1.18.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@babel/core": "^7.17.8",
@@ -60,7 +60,8 @@
60
60
  "vitest-browser-react": "^1.0.1"
61
61
  },
62
62
  "peerDependencies": {
63
- "react": ">=18"
63
+ "react": ">=18",
64
+ "react-dom": ">=18"
64
65
  },
65
66
  "keywords": [
66
67
  "constraint-validation",