@conform-to/react 1.0.0 → 1.0.1

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/README CHANGED
@@ -8,25 +8,30 @@
8
8
  ╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
9
9
 
10
10
 
11
- Version 1.0.0-rc.1 / License MIT / Copyright (c) 2024 Edmund Hung
11
+ Version 1.0.1 / License MIT / Copyright (c) 2024 Edmund Hung
12
12
 
13
13
  A type-safe form validation library utilizing web fundamentals to progressively enhance HTML Forms with full support for server frameworks like Remix and Next.js.
14
14
 
15
- > Getting Started
15
+ # Getting Started
16
16
 
17
17
  Check out the overview and tutorial at our website https://conform.guide
18
18
 
19
- > Documentation
19
+ # Features
20
20
 
21
- The documentation is divided into several sections:
21
+ - Progressive enhancement first APIs
22
+ - Type-safe field inference
23
+ - Fine-grained subscription
24
+ - Built-in accessibility helpers
25
+ - Automatic type coercion with Zod
22
26
 
23
- * Overview: https://conform.guide/overview
24
- * Examples: https://conform.guide/examples
25
- * Complex structures: https://conform.guide/complex-structures
26
- * UI Integrations: https://conform.guide/integrations
27
- * Accessibility Guide: https://conform.guide/accessibility
28
- * API Reference: https://conform.guide/references
27
+ # Documentation
29
28
 
30
- > Support
29
+ - Validation: https://conform.guide/validation
30
+ - Nested object and Array: https://conform.guide/complex-structures
31
+ - UI Integrations: https://conform.guide/integration/ui-libraries
32
+ - Intent button: https://conform.guide/intent-button
33
+ - Accessibility Guide: https://conform.guide/accessibility
34
+
35
+ # Support
31
36
 
32
37
  To report a bug, please open an issue on the repository at https://github.com/edmundhung/conform. For feature requests and questions, you can post them in the Discussions section.
package/context.d.ts CHANGED
@@ -3,7 +3,7 @@ import { type FormEvent, type ReactElement, type ReactNode, type MutableRefObjec
3
3
  export type Pretty<T> = {
4
4
  [K in keyof T]: T[K];
5
5
  } & {};
6
- export type Primitive = string | number | boolean | Date | File | null | undefined;
6
+ export type Primitive = string | number | bigint | boolean | Date | File | null | undefined;
7
7
  export type Metadata<Schema, FormSchema extends Record<string, unknown>, FormError = string[]> = {
8
8
  key: string | undefined;
9
9
  id: string;
package/integrations.d.ts CHANGED
@@ -1,17 +1,19 @@
1
- import { type FieldElement } from '@conform-to/dom';
2
1
  import { type Key } from 'react';
3
- export type InputControl = {
4
- value: string | undefined;
5
- change: (value: string) => void;
2
+ export type InputControl<Value> = {
3
+ value: Value | undefined;
4
+ change: (value: Value) => void;
6
5
  focus: () => void;
7
6
  blur: () => void;
8
7
  };
9
- export declare function getFieldElement(formId: string, name: string, match?: (element: FieldElement) => boolean): FieldElement | null;
10
- export declare function getEventTarget(formId: string, name: string): FieldElement;
11
- export type InputControlOptions = {
8
+ export declare function getFormElement(formId: string): HTMLFormElement;
9
+ export declare function getFieldElements(form: HTMLFormElement, name: string): Array<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>;
10
+ export declare function getEventTarget(form: HTMLFormElement, name: string): HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | null;
11
+ export declare function createDummySelect(form: HTMLFormElement, name: string, value?: string | string[] | undefined): HTMLSelectElement;
12
+ export declare function isDummySelect(element: HTMLElement): element is HTMLSelectElement;
13
+ export declare function updateFieldValue(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, value: string | string[]): void;
14
+ export declare function useInputControl<Value>(metaOrOptions: {
12
15
  key?: Key | null | undefined;
13
16
  name: string;
14
17
  formId: string;
15
- initialValue?: string | undefined;
16
- };
17
- export declare function useInputControl(metaOrOptions: InputControlOptions): InputControl;
18
+ initialValue?: Value | undefined;
19
+ }): InputControl<Value extends string ? string : string | string[]>;
package/integrations.js CHANGED
@@ -3,52 +3,141 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
6
- var dom = require('@conform-to/dom');
7
6
  var react = require('react');
8
7
 
9
- function getFieldElement(formId, name) {
10
- var _document$forms$named;
11
- var match = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : () => true;
12
- var element = (_document$forms$named = document.forms.namedItem(formId)) === null || _document$forms$named === void 0 ? void 0 : _document$forms$named.elements.namedItem(name);
13
- if (element) {
14
- var items = element instanceof Element ? [element] : Array.from(element.values());
15
- for (var item of items) {
16
- if (dom.isFieldElement(item) && match(item)) {
17
- return item;
18
- }
19
- }
8
+ function getFormElement(formId) {
9
+ var element = document.forms.namedItem(formId);
10
+ if (!element) {
11
+ throw new Error('Form not found');
12
+ }
13
+ return element;
14
+ }
15
+ function getFieldElements(form, name) {
16
+ var field = form.elements.namedItem(name);
17
+ var elements = !field ? [] : field instanceof Element ? [field] : Array.from(field.values());
18
+ return elements.filter(element => element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement);
19
+ }
20
+ function getEventTarget(form, name) {
21
+ var _elements$;
22
+ var elements = getFieldElements(form, name);
23
+ return (_elements$ = elements[0]) !== null && _elements$ !== void 0 ? _elements$ : null;
24
+ }
25
+ function createDummySelect(form, name, value) {
26
+ var select = document.createElement('select');
27
+ var options = typeof value === 'string' ? [value] : value !== null && value !== void 0 ? value : [];
28
+ select.name = name;
29
+ select.multiple = true;
30
+ select.dataset.conform = 'true';
31
+
32
+ // To make sure the input is hidden but still focusable
33
+ select.setAttribute('aria-hidden', 'true');
34
+ select.tabIndex = -1;
35
+ select.style.position = 'absolute';
36
+ select.style.width = '1px';
37
+ select.style.height = '1px';
38
+ select.style.padding = '0';
39
+ select.style.margin = '-1px';
40
+ select.style.overflow = 'hidden';
41
+ select.style.clip = 'rect(0,0,0,0)';
42
+ select.style.whiteSpace = 'nowrap';
43
+ select.style.border = '0';
44
+ for (var option of options) {
45
+ select.options.add(new Option(option, option, true, true));
20
46
  }
21
- return null;
47
+ form.appendChild(select);
48
+ return select;
22
49
  }
23
- function getEventTarget(formId, name) {
24
- var element = getFieldElement(formId, name);
25
- if (element) {
26
- return element;
50
+ function isDummySelect(element) {
51
+ return element.dataset.conform === 'true';
52
+ }
53
+ function updateFieldValue(element, value) {
54
+ if (element instanceof HTMLInputElement && (element.type === 'checkbox' || element.type === 'radio')) {
55
+ element.checked = element.value === value;
56
+ } else if (element instanceof HTMLSelectElement && element.multiple) {
57
+ var selectedValue = Array.isArray(value) ? [...value] : [value];
58
+ for (var option of element.options) {
59
+ var index = selectedValue.indexOf(option.value);
60
+ var selected = index > -1;
61
+
62
+ // Update the selected state of the option
63
+ option.selected = selected;
64
+ // Remove the option from the selected array
65
+ if (selected) {
66
+ selectedValue.splice(index, 1);
67
+ }
68
+ }
69
+
70
+ // Add the remaining options to the select element only if it's a dummy element managed by conform
71
+ if (isDummySelect(element)) {
72
+ for (var _option of selectedValue) {
73
+ element.options.add(new Option(_option, _option, false, true));
74
+ }
75
+ }
76
+ } else if (element.value !== value) {
77
+ // No `change` event will be triggered on React if `element.value` is already updated
78
+
79
+ /**
80
+ * Triggering react custom change event
81
+ * Solution based on dom-testing-library
82
+ * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
83
+ * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
84
+ */
85
+ var {
86
+ set: valueSetter
87
+ } = Object.getOwnPropertyDescriptor(element, 'value') || {};
88
+ var prototype = Object.getPrototypeOf(element);
89
+ var {
90
+ set: prototypeValueSetter
91
+ } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
92
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
93
+ prototypeValueSetter.call(element, value);
94
+ } else {
95
+ if (valueSetter) {
96
+ valueSetter.call(element, value);
97
+ } else {
98
+ throw new Error('The given element does not have a value setter');
99
+ }
100
+ }
27
101
  }
28
- var form = document.forms.namedItem(formId);
29
- var input = document.createElement('input');
30
- input.type = 'hidden';
31
- input.name = name;
32
- form === null || form === void 0 || form.appendChild(input);
33
- return input;
34
102
  }
35
103
  function useInputControl(metaOrOptions) {
104
+ // If the initialValue is an array, it must be a string array without undefined values
105
+ // as there is no way to skip an entry in a multiple select when they all share the same name
106
+ var inputInitialValue = metaOrOptions.initialValue;
36
107
  var eventDispatched = react.useRef({
37
108
  change: false,
38
109
  focus: false,
39
110
  blur: false
40
111
  });
41
112
  var [key, setKey] = react.useState(metaOrOptions.key);
42
- var [value, setValue] = react.useState(() => metaOrOptions.initialValue);
113
+ var [initialValue, setInitialValue] = react.useState(inputInitialValue);
114
+ var [value, setValue] = react.useState(inputInitialValue);
43
115
  if (key !== metaOrOptions.key) {
44
- setValue(metaOrOptions.initialValue);
116
+ setValue(inputInitialValue);
117
+ setInitialValue(inputInitialValue);
45
118
  setKey(metaOrOptions.key);
46
119
  }
120
+ react.useEffect(() => {
121
+ var form = getFormElement(metaOrOptions.formId);
122
+ if (getEventTarget(form, metaOrOptions.name)) {
123
+ return;
124
+ }
125
+ createDummySelect(form, metaOrOptions.name, initialValue);
126
+ return () => {
127
+ var elements = getFieldElements(form, metaOrOptions.name);
128
+ for (var element of elements) {
129
+ if (isDummySelect(element)) {
130
+ element.remove();
131
+ }
132
+ }
133
+ };
134
+ }, [metaOrOptions.formId, metaOrOptions.name, initialValue]);
47
135
  react.useEffect(() => {
48
136
  var createEventListener = listener => {
49
137
  return event => {
50
- var element = getFieldElement(metaOrOptions.formId, metaOrOptions.name, element => element === event.target);
51
- if (element) {
138
+ var _element$form;
139
+ var element = event.target;
140
+ if ((element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement) && element.name === metaOrOptions.name && ((_element$form = element.form) === null || _element$form === void 0 ? void 0 : _element$form.id) === metaOrOptions.formId) {
52
141
  eventDispatched.current[listener] = true;
53
142
  }
54
143
  };
@@ -69,68 +158,50 @@ function useInputControl(metaOrOptions) {
69
158
  return {
70
159
  change(value) {
71
160
  if (!eventDispatched.current.change) {
72
- var _element = getEventTarget(metaOrOptions.formId, metaOrOptions.name);
73
161
  eventDispatched.current.change = true;
74
- if (_element instanceof HTMLInputElement && (_element.type === 'checkbox' || _element.type === 'radio')) {
75
- _element.checked = _element.value === value;
76
- } else if (_element.value !== value) {
77
- // No change event will be triggered on React if `element.value` is already updated
162
+ var form = getFormElement(metaOrOptions.formId);
163
+ var element = getEventTarget(form, metaOrOptions.name);
164
+ if (element) {
165
+ updateFieldValue(element, value);
78
166
 
79
- /**
80
- * Triggering react custom change event
81
- * Solution based on dom-testing-library
82
- * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
83
- * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
84
- */
85
- var {
86
- set: valueSetter
87
- } = Object.getOwnPropertyDescriptor(_element, 'value') || {};
88
- var prototype = Object.getPrototypeOf(_element);
89
- var {
90
- set: prototypeValueSetter
91
- } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
92
- if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
93
- prototypeValueSetter.call(_element, value);
94
- } else {
95
- if (valueSetter) {
96
- valueSetter.call(_element, value);
97
- } else {
98
- throw new Error('The given element does not have a value setter');
99
- }
100
- }
167
+ // Dispatch input event with the updated input value
168
+ element.dispatchEvent(new InputEvent('input', {
169
+ bubbles: true
170
+ }));
171
+ // Dispatch change event (necessary for select to update the selected option)
172
+ element.dispatchEvent(new Event('change', {
173
+ bubbles: true
174
+ }));
101
175
  }
102
-
103
- // Dispatch input event with the updated input value
104
- _element.dispatchEvent(new InputEvent('input', {
105
- bubbles: true
106
- }));
107
- // Dispatch change event (necessary for select to update the selected option)
108
- _element.dispatchEvent(new Event('change', {
109
- bubbles: true
110
- }));
111
176
  }
112
177
  setValue(value);
113
178
  eventDispatched.current.change = false;
114
179
  },
115
180
  focus() {
116
181
  if (!eventDispatched.current.focus) {
117
- var _element2 = getEventTarget(metaOrOptions.formId, metaOrOptions.name);
118
182
  eventDispatched.current.focus = true;
119
- _element2.dispatchEvent(new FocusEvent('focusin', {
120
- bubbles: true
121
- }));
122
- _element2.dispatchEvent(new FocusEvent('focus'));
183
+ var form = getFormElement(metaOrOptions.formId);
184
+ var element = getEventTarget(form, metaOrOptions.name);
185
+ if (element) {
186
+ element.dispatchEvent(new FocusEvent('focusin', {
187
+ bubbles: true
188
+ }));
189
+ element.dispatchEvent(new FocusEvent('focus'));
190
+ }
123
191
  }
124
192
  eventDispatched.current.focus = false;
125
193
  },
126
194
  blur() {
127
195
  if (!eventDispatched.current.blur) {
128
- var _element3 = getEventTarget(metaOrOptions.formId, metaOrOptions.name);
129
196
  eventDispatched.current.blur = true;
130
- _element3.dispatchEvent(new FocusEvent('focusout', {
131
- bubbles: true
132
- }));
133
- _element3.dispatchEvent(new FocusEvent('blur'));
197
+ var form = getFormElement(metaOrOptions.formId);
198
+ var element = getEventTarget(form, metaOrOptions.name);
199
+ if (element) {
200
+ element.dispatchEvent(new FocusEvent('focusout', {
201
+ bubbles: true
202
+ }));
203
+ element.dispatchEvent(new FocusEvent('blur'));
204
+ }
134
205
  }
135
206
  eventDispatched.current.blur = false;
136
207
  }
@@ -141,6 +212,10 @@ function useInputControl(metaOrOptions) {
141
212
  });
142
213
  }
143
214
 
215
+ exports.createDummySelect = createDummySelect;
144
216
  exports.getEventTarget = getEventTarget;
145
- exports.getFieldElement = getFieldElement;
217
+ exports.getFieldElements = getFieldElements;
218
+ exports.getFormElement = getFormElement;
219
+ exports.isDummySelect = isDummySelect;
220
+ exports.updateFieldValue = updateFieldValue;
146
221
  exports.useInputControl = useInputControl;
package/integrations.mjs CHANGED
@@ -1,50 +1,139 @@
1
1
  import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
2
- import { isFieldElement } from '@conform-to/dom';
3
2
  import { useRef, useState, useEffect, useMemo } from 'react';
4
3
 
5
- function getFieldElement(formId, name) {
6
- var _document$forms$named;
7
- var match = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : () => true;
8
- var element = (_document$forms$named = document.forms.namedItem(formId)) === null || _document$forms$named === void 0 ? void 0 : _document$forms$named.elements.namedItem(name);
9
- if (element) {
10
- var items = element instanceof Element ? [element] : Array.from(element.values());
11
- for (var item of items) {
12
- if (isFieldElement(item) && match(item)) {
13
- return item;
14
- }
15
- }
4
+ function getFormElement(formId) {
5
+ var element = document.forms.namedItem(formId);
6
+ if (!element) {
7
+ throw new Error('Form not found');
8
+ }
9
+ return element;
10
+ }
11
+ function getFieldElements(form, name) {
12
+ var field = form.elements.namedItem(name);
13
+ var elements = !field ? [] : field instanceof Element ? [field] : Array.from(field.values());
14
+ return elements.filter(element => element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement);
15
+ }
16
+ function getEventTarget(form, name) {
17
+ var _elements$;
18
+ var elements = getFieldElements(form, name);
19
+ return (_elements$ = elements[0]) !== null && _elements$ !== void 0 ? _elements$ : null;
20
+ }
21
+ function createDummySelect(form, name, value) {
22
+ var select = document.createElement('select');
23
+ var options = typeof value === 'string' ? [value] : value !== null && value !== void 0 ? value : [];
24
+ select.name = name;
25
+ select.multiple = true;
26
+ select.dataset.conform = 'true';
27
+
28
+ // To make sure the input is hidden but still focusable
29
+ select.setAttribute('aria-hidden', 'true');
30
+ select.tabIndex = -1;
31
+ select.style.position = 'absolute';
32
+ select.style.width = '1px';
33
+ select.style.height = '1px';
34
+ select.style.padding = '0';
35
+ select.style.margin = '-1px';
36
+ select.style.overflow = 'hidden';
37
+ select.style.clip = 'rect(0,0,0,0)';
38
+ select.style.whiteSpace = 'nowrap';
39
+ select.style.border = '0';
40
+ for (var option of options) {
41
+ select.options.add(new Option(option, option, true, true));
16
42
  }
17
- return null;
43
+ form.appendChild(select);
44
+ return select;
18
45
  }
19
- function getEventTarget(formId, name) {
20
- var element = getFieldElement(formId, name);
21
- if (element) {
22
- return element;
46
+ function isDummySelect(element) {
47
+ return element.dataset.conform === 'true';
48
+ }
49
+ function updateFieldValue(element, value) {
50
+ if (element instanceof HTMLInputElement && (element.type === 'checkbox' || element.type === 'radio')) {
51
+ element.checked = element.value === value;
52
+ } else if (element instanceof HTMLSelectElement && element.multiple) {
53
+ var selectedValue = Array.isArray(value) ? [...value] : [value];
54
+ for (var option of element.options) {
55
+ var index = selectedValue.indexOf(option.value);
56
+ var selected = index > -1;
57
+
58
+ // Update the selected state of the option
59
+ option.selected = selected;
60
+ // Remove the option from the selected array
61
+ if (selected) {
62
+ selectedValue.splice(index, 1);
63
+ }
64
+ }
65
+
66
+ // Add the remaining options to the select element only if it's a dummy element managed by conform
67
+ if (isDummySelect(element)) {
68
+ for (var _option of selectedValue) {
69
+ element.options.add(new Option(_option, _option, false, true));
70
+ }
71
+ }
72
+ } else if (element.value !== value) {
73
+ // No `change` event will be triggered on React if `element.value` is already updated
74
+
75
+ /**
76
+ * Triggering react custom change event
77
+ * Solution based on dom-testing-library
78
+ * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
79
+ * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
80
+ */
81
+ var {
82
+ set: valueSetter
83
+ } = Object.getOwnPropertyDescriptor(element, 'value') || {};
84
+ var prototype = Object.getPrototypeOf(element);
85
+ var {
86
+ set: prototypeValueSetter
87
+ } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
88
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
89
+ prototypeValueSetter.call(element, value);
90
+ } else {
91
+ if (valueSetter) {
92
+ valueSetter.call(element, value);
93
+ } else {
94
+ throw new Error('The given element does not have a value setter');
95
+ }
96
+ }
23
97
  }
24
- var form = document.forms.namedItem(formId);
25
- var input = document.createElement('input');
26
- input.type = 'hidden';
27
- input.name = name;
28
- form === null || form === void 0 || form.appendChild(input);
29
- return input;
30
98
  }
31
99
  function useInputControl(metaOrOptions) {
100
+ // If the initialValue is an array, it must be a string array without undefined values
101
+ // as there is no way to skip an entry in a multiple select when they all share the same name
102
+ var inputInitialValue = metaOrOptions.initialValue;
32
103
  var eventDispatched = useRef({
33
104
  change: false,
34
105
  focus: false,
35
106
  blur: false
36
107
  });
37
108
  var [key, setKey] = useState(metaOrOptions.key);
38
- var [value, setValue] = useState(() => metaOrOptions.initialValue);
109
+ var [initialValue, setInitialValue] = useState(inputInitialValue);
110
+ var [value, setValue] = useState(inputInitialValue);
39
111
  if (key !== metaOrOptions.key) {
40
- setValue(metaOrOptions.initialValue);
112
+ setValue(inputInitialValue);
113
+ setInitialValue(inputInitialValue);
41
114
  setKey(metaOrOptions.key);
42
115
  }
116
+ useEffect(() => {
117
+ var form = getFormElement(metaOrOptions.formId);
118
+ if (getEventTarget(form, metaOrOptions.name)) {
119
+ return;
120
+ }
121
+ createDummySelect(form, metaOrOptions.name, initialValue);
122
+ return () => {
123
+ var elements = getFieldElements(form, metaOrOptions.name);
124
+ for (var element of elements) {
125
+ if (isDummySelect(element)) {
126
+ element.remove();
127
+ }
128
+ }
129
+ };
130
+ }, [metaOrOptions.formId, metaOrOptions.name, initialValue]);
43
131
  useEffect(() => {
44
132
  var createEventListener = listener => {
45
133
  return event => {
46
- var element = getFieldElement(metaOrOptions.formId, metaOrOptions.name, element => element === event.target);
47
- if (element) {
134
+ var _element$form;
135
+ var element = event.target;
136
+ if ((element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement) && element.name === metaOrOptions.name && ((_element$form = element.form) === null || _element$form === void 0 ? void 0 : _element$form.id) === metaOrOptions.formId) {
48
137
  eventDispatched.current[listener] = true;
49
138
  }
50
139
  };
@@ -65,68 +154,50 @@ function useInputControl(metaOrOptions) {
65
154
  return {
66
155
  change(value) {
67
156
  if (!eventDispatched.current.change) {
68
- var _element = getEventTarget(metaOrOptions.formId, metaOrOptions.name);
69
157
  eventDispatched.current.change = true;
70
- if (_element instanceof HTMLInputElement && (_element.type === 'checkbox' || _element.type === 'radio')) {
71
- _element.checked = _element.value === value;
72
- } else if (_element.value !== value) {
73
- // No change event will be triggered on React if `element.value` is already updated
158
+ var form = getFormElement(metaOrOptions.formId);
159
+ var element = getEventTarget(form, metaOrOptions.name);
160
+ if (element) {
161
+ updateFieldValue(element, value);
74
162
 
75
- /**
76
- * Triggering react custom change event
77
- * Solution based on dom-testing-library
78
- * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
79
- * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
80
- */
81
- var {
82
- set: valueSetter
83
- } = Object.getOwnPropertyDescriptor(_element, 'value') || {};
84
- var prototype = Object.getPrototypeOf(_element);
85
- var {
86
- set: prototypeValueSetter
87
- } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
88
- if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
89
- prototypeValueSetter.call(_element, value);
90
- } else {
91
- if (valueSetter) {
92
- valueSetter.call(_element, value);
93
- } else {
94
- throw new Error('The given element does not have a value setter');
95
- }
96
- }
163
+ // Dispatch input event with the updated input value
164
+ element.dispatchEvent(new InputEvent('input', {
165
+ bubbles: true
166
+ }));
167
+ // Dispatch change event (necessary for select to update the selected option)
168
+ element.dispatchEvent(new Event('change', {
169
+ bubbles: true
170
+ }));
97
171
  }
98
-
99
- // Dispatch input event with the updated input value
100
- _element.dispatchEvent(new InputEvent('input', {
101
- bubbles: true
102
- }));
103
- // Dispatch change event (necessary for select to update the selected option)
104
- _element.dispatchEvent(new Event('change', {
105
- bubbles: true
106
- }));
107
172
  }
108
173
  setValue(value);
109
174
  eventDispatched.current.change = false;
110
175
  },
111
176
  focus() {
112
177
  if (!eventDispatched.current.focus) {
113
- var _element2 = getEventTarget(metaOrOptions.formId, metaOrOptions.name);
114
178
  eventDispatched.current.focus = true;
115
- _element2.dispatchEvent(new FocusEvent('focusin', {
116
- bubbles: true
117
- }));
118
- _element2.dispatchEvent(new FocusEvent('focus'));
179
+ var form = getFormElement(metaOrOptions.formId);
180
+ var element = getEventTarget(form, metaOrOptions.name);
181
+ if (element) {
182
+ element.dispatchEvent(new FocusEvent('focusin', {
183
+ bubbles: true
184
+ }));
185
+ element.dispatchEvent(new FocusEvent('focus'));
186
+ }
119
187
  }
120
188
  eventDispatched.current.focus = false;
121
189
  },
122
190
  blur() {
123
191
  if (!eventDispatched.current.blur) {
124
- var _element3 = getEventTarget(metaOrOptions.formId, metaOrOptions.name);
125
192
  eventDispatched.current.blur = true;
126
- _element3.dispatchEvent(new FocusEvent('focusout', {
127
- bubbles: true
128
- }));
129
- _element3.dispatchEvent(new FocusEvent('blur'));
193
+ var form = getFormElement(metaOrOptions.formId);
194
+ var element = getEventTarget(form, metaOrOptions.name);
195
+ if (element) {
196
+ element.dispatchEvent(new FocusEvent('focusout', {
197
+ bubbles: true
198
+ }));
199
+ element.dispatchEvent(new FocusEvent('blur'));
200
+ }
130
201
  }
131
202
  eventDispatched.current.blur = false;
132
203
  }
@@ -137,4 +208,4 @@ function useInputControl(metaOrOptions) {
137
208
  });
138
209
  }
139
210
 
140
- export { getEventTarget, getFieldElement, useInputControl };
211
+ export { createDummySelect, getEventTarget, getFieldElements, getFormElement, isDummySelect, updateFieldValue, useInputControl };
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.0.0",
6
+ "version": "1.0.1",
7
7
  "main": "index.js",
8
8
  "module": "index.mjs",
9
9
  "types": "index.d.ts",
@@ -30,7 +30,7 @@
30
30
  "url": "https://github.com/edmundhung/conform/issues"
31
31
  },
32
32
  "dependencies": {
33
- "@conform-to/dom": "1.0.0"
33
+ "@conform-to/dom": "1.0.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/react": "^18.2.43",