@vaadin/hilla-react-form 25.0.5 → 25.1.0-alpha10
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/index.d.ts +9 -8
- package/index.js +16 -5
- package/index.js.map +1 -1
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ProvisionalModel, type BinderConfiguration, type Validator, type Value, type ValueError, type ArrayModel as BinderArrayModel, type ArrayItemModel, type ProvisionalModelConstructor } from "@vaadin/hilla-lit-form";
|
|
2
|
+
import { type ArrayModel } from "@vaadin/hilla-models";
|
|
2
3
|
export type FieldDirectiveResult = Readonly<{
|
|
3
4
|
name: string
|
|
4
5
|
onBlur(): void
|
|
@@ -6,8 +7,8 @@ export type FieldDirectiveResult = Readonly<{
|
|
|
6
7
|
onInput(): void
|
|
7
8
|
ref(element: HTMLElement | null): void
|
|
8
9
|
}>;
|
|
9
|
-
export type FieldDirective = (model:
|
|
10
|
-
export type UseFormPartResult<M extends
|
|
10
|
+
export type FieldDirective = (model: ProvisionalModel) => FieldDirectiveResult;
|
|
11
|
+
export type UseFormPartResult<M extends ProvisionalModel> = Readonly<{
|
|
11
12
|
defaultValue?: Value<M>
|
|
12
13
|
dirty: boolean
|
|
13
14
|
errors: readonly ValueError[]
|
|
@@ -26,7 +27,7 @@ export type UseFormPartResult<M extends AbstractModel> = Readonly<{
|
|
|
26
27
|
setVisited(visited: boolean): void
|
|
27
28
|
validate(): Promise<readonly ValueError[]>
|
|
28
29
|
}>;
|
|
29
|
-
export type UseFormResult<M extends
|
|
30
|
+
export type UseFormResult<M extends ProvisionalModel> = Omit<UseFormPartResult<M>, "setValue" | "value"> & Readonly<{
|
|
30
31
|
value: Value<M>
|
|
31
32
|
submitting: boolean
|
|
32
33
|
setDefaultValue(value: Value<M>): void
|
|
@@ -37,11 +38,11 @@ export type UseFormResult<M extends AbstractModel> = Omit<UseFormPartResult<M>,
|
|
|
37
38
|
read(value: Value<M> | null | undefined): void
|
|
38
39
|
update(): void
|
|
39
40
|
}>;
|
|
40
|
-
export type UseFormArrayPartResult<M extends ArrayModel> = Omit<UseFormPartResult<M>, "field"> & {
|
|
41
|
+
export type UseFormArrayPartResult<M extends BinderArrayModel | ArrayModel> = Omit<UseFormPartResult<M>, "field"> & {
|
|
41
42
|
items: ReadonlyArray<ArrayItemModel<M>>
|
|
42
43
|
};
|
|
43
|
-
export declare function useForm<M extends
|
|
44
|
-
export declare function useFormPart<M extends
|
|
44
|
+
export declare function useForm<M extends ProvisionalModel>(modelClass: ProvisionalModelConstructor<M>, config?: BinderConfiguration<Value<M>>): UseFormResult<M>;
|
|
45
|
+
export declare function useFormPart<M extends ProvisionalModel>(model: M): UseFormPartResult<M>;
|
|
45
46
|
/**
|
|
46
47
|
* Hook to access an array model part of a form. It provides the same API as `useFormPart`,
|
|
47
48
|
* but adds an `items` property that allows to iterate over the items in form of an array of models.
|
|
@@ -49,4 +50,4 @@ export declare function useFormPart<M extends AbstractModel>(model: M): UseFormP
|
|
|
49
50
|
* @param model - The array model to access
|
|
50
51
|
* @returns The array model part of the form
|
|
51
52
|
*/
|
|
52
|
-
export declare function useFormArrayPart<M extends
|
|
53
|
+
export declare function useFormArrayPart<M extends BinderArrayModel>(model: M): UseFormArrayPartResult<M>;
|
package/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { _fromString, _validity, BinderRoot, CHANGED, getBinderNode, getDefaultFieldStrategy, hasFromString, isFieldElement } from "@vaadin/hilla-lit-form";
|
|
1
|
+
import { _fromString, _validity, BinderRoot, CHANGED, getBinderNode, getDefaultFieldStrategy, hasFromString, isFieldElement, getStringConverter } from "@vaadin/hilla-lit-form";
|
|
2
|
+
import { Model } from "@vaadin/hilla-models";
|
|
2
3
|
import { useEffect, useMemo, useReducer, useRef } from "react";
|
|
3
4
|
((feature, vaadinObj = globalThis.Vaadin ??= {}) => {
|
|
4
5
|
vaadinObj.registrations ??= [];
|
|
5
6
|
vaadinObj.registrations.push({
|
|
6
7
|
is: feature ? `@vaadin/hilla-react-form/${feature}` : "@vaadin/hilla-react-form",
|
|
7
|
-
version: "25.0
|
|
8
|
+
version: "25.1.0-alpha10"
|
|
8
9
|
});
|
|
9
10
|
})();
|
|
10
11
|
let isRendering = false;
|
|
@@ -18,7 +19,17 @@ function useUpdate() {
|
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
function convertFieldValue(model, fieldValue) {
|
|
21
|
-
|
|
22
|
+
if (typeof fieldValue !== "string") {
|
|
23
|
+
return fieldValue;
|
|
24
|
+
}
|
|
25
|
+
const stringConverter = getStringConverter(model);
|
|
26
|
+
if (stringConverter) {
|
|
27
|
+
return stringConverter.fromString(fieldValue);
|
|
28
|
+
}
|
|
29
|
+
if (hasFromString(model)) {
|
|
30
|
+
return model[_fromString](fieldValue);
|
|
31
|
+
}
|
|
32
|
+
return fieldValue;
|
|
22
33
|
}
|
|
23
34
|
function getFormPart(node) {
|
|
24
35
|
return {
|
|
@@ -132,12 +143,12 @@ function useFields(node) {
|
|
|
132
143
|
};
|
|
133
144
|
}, [node]);
|
|
134
145
|
}
|
|
135
|
-
export function useForm(
|
|
146
|
+
export function useForm(modelClass, config) {
|
|
136
147
|
const configRef = useRef({});
|
|
137
148
|
configRef.current.onSubmit = config?.onSubmit;
|
|
138
149
|
configRef.current.onChange = config?.onChange;
|
|
139
150
|
const update = useUpdate();
|
|
140
|
-
const binder = useMemo(() => new BinderRoot(
|
|
151
|
+
const binder = useMemo(() => new BinderRoot(modelClass, configRef.current), [Model]);
|
|
141
152
|
const field = useFields(binder);
|
|
142
153
|
const clear = binder.clear.bind(binder);
|
|
143
154
|
useEffect(() => {
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AACA,SACE,aACA,WAIA,YACA,SAGA,eACA,yBACA,eACA,8CAM8B;AAChC,SAAS,WAAW,SAAS,YAAY,qBAAsB;AAK/D,CAAC,CAAC,SAAS,YAAa,WAAW,WAAW,CAAE,MAAM;AACpD,WAAU,kBAAkB,CAAE;AAC9B,WAAU,cAAc,KAAK;EAC3B,IAAI,WAAW,2BAA2B,QAAQ,IAAI;EACtD,SAAS;CACV,EAAC;AACH,IAAG;AAEJ,IAAI,cAAc;AAElB,SAAS,YAAY;CACnB,MAAM,CAAC,GAAG,MAAM,GAAG,WAAW,CAACA,MAAc,IAAI,GAAG,EAAE;AACtD,QAAO,MAAM;AACX,MAAI,aAAa;AACf;EACD;AACD,SAAO;CACR;AACF;AA6DD,SAAS,kBAA2CC,OAAUC,YAAqB;AACjF,eAAc,eAAe,YAAY,cAAc,MAAM,GAAG,MAAM,aAAa,WAAW,GAAG;AAClG;AAED,SAAS,YAAqCC,MAA0D;AACtG,QAAO;EACL,cAAc,KAAK,aAAa,KAAK,KAAK;EAC1C,IAAI,eAAe;AACjB,UAAO,KAAK;EACb;EACD,OAAO,KAAK;EACZ,QAAQ,KAAK;EACb,SAAS,KAAK;EACd,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,WAAW,KAAK;EAChB,UAAU,KAAK;EACf,cAAc,YAAY;AACxB,QAAK,aAAa;EACnB;EACD,SAAS,OAAO;AACd,QAAK,QAAQ;EACd;EACD,WAAWC,SAAkB;AAC3B,QAAK,UAAU;EAChB;EACD,UAAU,KAAK,SAAS,KAAK,KAAK;EAClC,YAAY,KAAK;EACjB,IAAI,QAAQ;AACV,UAAO,KAAK;EACb;EACD,SAAS,KAAK;CACf;AACF;AAED,SAAS,UAAmCD,MAAqC;CAC/E,MAAM,SAAS,WAAW;AAE1B,QAAO,QAAQ,MAAM;EACnB,MAAM,WAAW,IAAI;AAErB,SAAQ,CAACE,UAAyB;AAChC,iBAAc;GACd,MAAM,IAAI,cAAc,MAAM;GAE9B,IAAI,aAAa,SAAS,IAAI,MAAM;AAEpC,QAAK,YAAY;AACf,iBAAa;KACX,gBAAgB;AACd,iBAAY,cAAc;AAC1B,QAAE,UAAU,CAAC,MAAM,MAAM,CAAE,EAAC;KAC7B;KACD,SAAS;KACT,cAAc;KACd,eAAe;AACb,UAAI,WAAY,UAAU;AAGxB,kBAAY,SAAS,UAAU;AAE/B,kBAAY,SAAS,eAAe;AACpC,SAAE,aAAa,WAAY,SAAS;AACpC,SAAE,QAAQ,kBAAkB,OAAO,WAAY,SAAS,MAAM;MAC/D;KACF;KACD,SAAS;KACT,cAAc;AACZ,iBAAY,cAAc;AAC1B,QAAE,UAAU,CAAC,MAAM,MAAM,CAAE,EAAC;AAC5B,QAAE,UAAU;KACb;KACD,IAAIC,SAA6B;AAC/B,WAAK,SAAS;AACZ,kBAAY,SAAS,oBAAoB,QAAQ,WAAY,YAAY;AACzE,kBAAY,UAAU,sBAAsB;AAC5C,kBAAY,UAAU;AACtB,kBAAY,WAAW;AACvB,eAAQ;AACR;MACD;AAED,WAAK,eAAe,QAAQ,EAAE;AAC5B,aAAM,IAAI,WAAW,WAAW,QAAQ,UAAU;MACnD;AAED,UAAI,WAAY,YAAY,SAAS;AACnC,kBAAY,UAAU;AACtB,kBAAY,QAAQ,iBAAiB,QAAQ,WAAY,YAAY;AACrE,kBAAY,WAAW,wBAAwB,SAAS,MAAM;AAC9D,kBAAY,SAAS,UAAU,WAAY;AAC3C,kBAAY,SAAS,WAAW,WAAY;AAC5C,eAAQ;MACT;KACF;KACD,UAAU;KACV,UAAU;IACX;AAED,aAAS,IAAI,OAAO,WAAW;GAChC;AAED,OAAI,WAAW,UAAU;IACvB,MAAM,iBAAiB,kBAAkB,OAAO,WAAW,SAAS,MAAM;AAC1E,QAAI,mBAAmB,EAAE,WAAW,OAAO,MAAM,EAAE,MAAM,IAAI,OAAO,MAAM,eAAe,GAAG;AAC1F,gBAAW,SAAS,QAAQ,OAAO,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE;IAC5D;AAED,QAAI,WAAW,aAAa,EAAE,UAAU;AACtC,gBAAW,WAAW,EAAE;AACxB,gBAAW,SAAS,WAAW,EAAE;IAClC;IAED,MAAM,aAAa,EAAE,UAAU,GAAG,EAAE;IAEpC,MAAM,eAAe,YAAY,WAAW;AAC5C,QAAI,WAAW,iBAAiB,cAAc;AAC5C,gBAAW,eAAe;AAC1B,gBAAW,SAAS,eAAe;IACpC;AAGD,eAAW,UAAU,EAAE;AACvB,eAAW,SAAS,UAAU,EAAE;GACjC;AAED,iBAAc;AACd,UAAO;IACL,MAAM,EAAE;IACR,KAAK,WAAW;GACjB;EACF;CACF,GAAE,CAAC,IAAK,EAAC;AACX;AAED,OAAO,SAAS,QACdC,OACAC,QACkB;CAClB,MAAM,YAAY,OAAgD,CAAE,EAAC;AACrE,WAAU,QAAQ,WAAW,QAAQ;AACrC,WAAU,QAAQ,WAAW,QAAQ;CACrC,MAAM,SAAS,WAAW;CAC1B,MAAM,SAAS,QAAQ,MAAM,IAAI,WAAW,OAAO,UAAU,UAAU,CAAC,KAAM,EAAC;CAC/E,MAAM,QAAQ,UAAU,OAAO;CAC/B,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO;AAEvC,WAAU,MAAM;AACd,SAAO,iBAAiB,QAAQ,MAAM,OAAO;AAC7C,SAAO;AACP,SAAO,MAAM,OAAO,oBAAoB,QAAQ,MAAM,OAAO;CAC9D,GAAE,CAAC,MAAO,EAAC;AAEZ,QAAO;EACL,GAAG,YAAe,OAAO;EACzB;EACA;EACA,MAAM,OAAO,KAAK,KAAK,OAAO;EAC9B,OAAO,OAAO,MAAM,KAAK,OAAO;EAChC,gBAAgB,cAAc;AAC5B,UAAO,eAAe;EACvB;EACD,SAAS,OAAO;AACd,UAAO,QAAQ;EAChB;EACD,QAAQ,OAAO,OAAO,KAAK,OAAO;EAClC,OAAO,OAAO;EACd,YAAY,OAAO;EACnB;CACD;AACF;AAED,OAAO,SAAS,YAAqCC,OAAgC;AACnF,eAAc;CACd,MAAM,aAAa,cAAc,MAAM;CACvC,MAAM,QAAQ,UAAU,WAAW;AACnC,eAAc;AAEd,QAAO;EACL,GAAG,YAAY,WAAW;EAC1B;CACD;AACF;;;;;;;;AASD,OAAO,SAAS,iBAAuCA,OAAqC;AAC1F,eAAc;CACd,MAAM,aAAa,cAAc,MAAM;AACvC,eAAc;AACd,QAAO;EACL,GAAG,YAAY,WAAW;EAC1B,OAAO,MAAM,KAAK,OAAO,CAAC,SAAS,KAAK,MAA2B;CACpE;AACF","names":["x: number","model: T","fieldValue: unknown","node: BinderNode<M>","visited: boolean","model: AbstractModel","element: HTMLElement | null","Model: DetachedModelConstructor<M>","config?: BinderConfiguration<Value<M>>","model: M"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/react-form/src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport {\n _fromString,\n _validity,\n type AbstractModel,\n type BinderConfiguration,\n type BinderNode,\n BinderRoot,\n CHANGED,\n type DetachedModelConstructor,\n type FieldStrategy,\n getBinderNode,\n getDefaultFieldStrategy,\n hasFromString,\n isFieldElement,\n type Validator,\n type Value,\n type ValueError,\n type ArrayModel,\n type ArrayItemModel,\n} from '@vaadin/hilla-lit-form';\nimport { useEffect, useMemo, useReducer, useRef } from 'react';\nimport type { Writable } from 'type-fest';\n\n// @ts-expect-error: esbuild injection\n// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n((feature, vaadinObj = (globalThis.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-react-form/${feature}` : '@vaadin/hilla-react-form',\n version: '25.0.5',\n });\n})();\n\nlet isRendering = false;\n\nfunction useUpdate() {\n const [_, count] = useReducer((x: number) => x + 1, 0);\n return () => {\n if (isRendering) {\n return;\n }\n count();\n };\n}\n\nexport type FieldDirectiveResult = Readonly<{\n name: string;\n onBlur(): void;\n onChange(): void;\n onInput(): void;\n ref(element: HTMLElement | null): void;\n}>;\n\nexport type FieldDirective = (model: AbstractModel) => FieldDirectiveResult;\n\nexport type UseFormPartResult<M extends AbstractModel> = Readonly<{\n defaultValue?: Value<M>;\n dirty: boolean;\n errors: readonly ValueError[];\n invalid: boolean;\n model: M;\n name: string;\n field: FieldDirective;\n ownErrors: ReadonlyArray<ValueError<Value<M>>>;\n required: boolean;\n validators: ReadonlyArray<Validator<Value<M>>>;\n value?: Value<M>;\n visited: boolean;\n addValidator(validator: Validator<Value<M>>): void;\n setValidators(validators: ReadonlyArray<Validator<Value<M>>>): void;\n setValue(value: Value<M> | undefined): void;\n setVisited(visited: boolean): void;\n validate(): Promise<readonly ValueError[]>;\n}>;\n\nexport type UseFormResult<M extends AbstractModel> = Omit<UseFormPartResult<M>, 'setValue' | 'value'> &\n Readonly<{\n value: Value<M>;\n submitting: boolean;\n setDefaultValue(value: Value<M>): void;\n setValue(value: Value<M>): void;\n submit(): Promise<Value<M> | void>;\n reset(): void;\n clear(): void;\n read(value: Value<M> | null | undefined): void;\n update(): void;\n }>;\n\nexport type UseFormArrayPartResult<M extends ArrayModel> = Omit<UseFormPartResult<M>, 'field'> & {\n items: ReadonlyArray<ArrayItemModel<M>>;\n};\n\ntype FieldState<T = unknown> = {\n required: boolean;\n invalid: boolean;\n errorMessage: string;\n strategy?: FieldStrategy<T>;\n element?: HTMLElement;\n inputHandler(): void;\n changeHandler(): void;\n blurHandler(): void;\n ref(element: HTMLElement | null): void;\n};\n\nfunction convertFieldValue<T extends AbstractModel>(model: T, fieldValue: unknown) {\n return typeof fieldValue === 'string' && hasFromString(model) ? model[_fromString](fieldValue) : fieldValue;\n}\n\nfunction getFormPart<M extends AbstractModel>(node: BinderNode<M>): Omit<UseFormPartResult<M>, 'field'> {\n return {\n addValidator: node.addValidator.bind(node),\n get defaultValue() {\n return node.defaultValue;\n },\n dirty: node.dirty,\n errors: node.errors,\n invalid: node.invalid,\n model: node.model,\n name: node.name,\n ownErrors: node.ownErrors,\n required: node.required,\n setValidators(validators) {\n node.validators = validators;\n },\n setValue(value) {\n node.value = value;\n },\n setVisited(visited: boolean) {\n node.visited = visited;\n },\n validate: node.validate.bind(node),\n validators: node.validators,\n get value() {\n return node.value;\n },\n visited: node.visited,\n };\n}\n\nfunction useFields<M extends AbstractModel>(node: BinderNode<M>): FieldDirective {\n const update = useUpdate();\n\n return useMemo(() => {\n const registry = new WeakMap<AbstractModel, FieldState>();\n\n return ((model: AbstractModel) => {\n isRendering = true;\n const n = getBinderNode(model);\n\n let fieldState = registry.get(model);\n\n if (!fieldState) {\n fieldState = {\n changeHandler() {\n fieldState!.inputHandler();\n n.validate().catch(() => {});\n },\n element: undefined,\n errorMessage: '',\n inputHandler() {\n if (fieldState!.strategy) {\n // Remove invalid flag, so that .checkValidity() in Vaadin Components\n // does not interfere with errors from Hilla.\n fieldState!.strategy.invalid = false;\n // When bad input is detected, skip reading new value in binder state\n fieldState!.strategy.checkValidity();\n n[_validity] = fieldState!.strategy.validity;\n n.value = convertFieldValue(model, fieldState!.strategy.value);\n }\n },\n invalid: false,\n blurHandler() {\n fieldState!.inputHandler();\n n.validate().catch(() => {});\n n.visited = true;\n },\n ref(element: HTMLElement | null) {\n if (!element) {\n fieldState!.element?.removeEventListener('blur', fieldState!.blurHandler);\n fieldState!.strategy?.removeEventListeners();\n fieldState!.element = undefined;\n fieldState!.strategy = undefined;\n update();\n return;\n }\n\n if (!isFieldElement(element)) {\n throw new TypeError(`Element '${element.localName}' is not a form element`);\n }\n\n if (fieldState!.element !== element) {\n fieldState!.element = element;\n fieldState!.element.addEventListener('blur', fieldState!.blurHandler);\n fieldState!.strategy = getDefaultFieldStrategy(element, model);\n fieldState!.strategy.onInput = fieldState!.inputHandler;\n fieldState!.strategy.onChange = fieldState!.changeHandler;\n update();\n }\n },\n required: false,\n strategy: undefined,\n };\n\n registry.set(model, fieldState);\n }\n\n if (fieldState.strategy) {\n const valueFromField = convertFieldValue(model, fieldState.strategy.value);\n if (valueFromField !== n.value && !(Number.isNaN(n.value) && Number.isNaN(valueFromField))) {\n fieldState.strategy.value = Number.isNaN(n.value) ? '' : n.value;\n }\n\n if (fieldState.required !== n.required) {\n fieldState.required = n.required;\n fieldState.strategy.required = n.required;\n }\n\n const firstError = n.ownErrors.at(0);\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const errorMessage = firstError?.message ?? '';\n if (fieldState.errorMessage !== errorMessage) {\n fieldState.errorMessage = errorMessage;\n fieldState.strategy.errorMessage = errorMessage;\n }\n\n // Make sure invalid state is always in sync\n fieldState.invalid = n.invalid;\n fieldState.strategy.invalid = n.invalid;\n }\n\n isRendering = false;\n return {\n name: n.name,\n ref: fieldState.ref,\n };\n }) as FieldDirective;\n }, [node]);\n}\n\nexport function useForm<M extends AbstractModel>(\n Model: DetachedModelConstructor<M>,\n config?: BinderConfiguration<Value<M>>,\n): UseFormResult<M> {\n const configRef = useRef<Writable<BinderConfiguration<Value<M>>>>({});\n configRef.current.onSubmit = config?.onSubmit;\n configRef.current.onChange = config?.onChange;\n const update = useUpdate();\n const binder = useMemo(() => new BinderRoot(Model, configRef.current), [Model]);\n const field = useFields(binder);\n const clear = binder.clear.bind(binder);\n\n useEffect(() => {\n binder.addEventListener(CHANGED.type, update);\n clear(); // this allows to initialize the validation strategies (issue 2282)\n return () => binder.removeEventListener(CHANGED.type, update);\n }, [binder]);\n\n return {\n ...getFormPart<M>(binder),\n clear,\n field,\n read: binder.read.bind(binder),\n reset: binder.reset.bind(binder),\n setDefaultValue(defaultValue) {\n binder.defaultValue = defaultValue;\n },\n setValue(value) {\n binder.value = value;\n },\n submit: binder.submit.bind(binder),\n value: binder.value,\n submitting: binder.submitting,\n update,\n };\n}\n\nexport function useFormPart<M extends AbstractModel>(model: M): UseFormPartResult<M> {\n isRendering = true;\n const binderNode = getBinderNode(model);\n const field = useFields(binderNode);\n isRendering = false;\n\n return {\n ...getFormPart(binderNode),\n field,\n };\n}\n\n/**\n * Hook to access an array model part of a form. It provides the same API as `useFormPart`,\n * but adds an `items` property that allows to iterate over the items in form of an array of models.\n *\n * @param model - The array model to access\n * @returns The array model part of the form\n */\nexport function useFormArrayPart<M extends ArrayModel>(model: M): UseFormArrayPartResult<M> {\n isRendering = true;\n const binderNode = getBinderNode(model);\n isRendering = false;\n return {\n ...getFormPart(binderNode),\n items: Array.from(model, (item) => item.model as ArrayItemModel<M>),\n };\n}\n"],"version":3}
|
|
1
|
+
{"mappings":"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","names":["x: number","model: T","fieldValue: unknown","node: BinderNode<M>","visited: boolean","model: ProvisionalModel","element: HTMLElement | null","modelClass: ProvisionalModelConstructor<M>","config?: BinderConfiguration<Value<M>>","model: M"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/react-form/src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport {\n _fromString,\n _validity,\n type ProvisionalModel,\n type BinderConfiguration,\n type BinderNode,\n BinderRoot,\n CHANGED,\n type FieldStrategy,\n getBinderNode,\n getDefaultFieldStrategy,\n hasFromString,\n isFieldElement,\n type Validator,\n type Value,\n type ValueError,\n type ArrayModel as BinderArrayModel,\n type ArrayItemModel,\n getStringConverter,\n type ProvisionalModelConstructor,\n} from '@vaadin/hilla-lit-form';\nimport { type ArrayModel, Model } from '@vaadin/hilla-models';\nimport { useEffect, useMemo, useReducer, useRef } from 'react';\nimport type { Writable } from 'type-fest';\n\n// @ts-expect-error: esbuild injection\n// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n((feature, vaadinObj = (globalThis.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-react-form/${feature}` : '@vaadin/hilla-react-form',\n version: '25.1.0-alpha10',\n });\n})();\n\nlet isRendering = false;\n\nfunction useUpdate() {\n const [_, count] = useReducer((x: number) => x + 1, 0);\n return () => {\n if (isRendering) {\n return;\n }\n count();\n };\n}\n\nexport type FieldDirectiveResult = Readonly<{\n name: string;\n onBlur(): void;\n onChange(): void;\n onInput(): void;\n ref(element: HTMLElement | null): void;\n}>;\n\nexport type FieldDirective = (model: ProvisionalModel) => FieldDirectiveResult;\n\nexport type UseFormPartResult<M extends ProvisionalModel> = Readonly<{\n defaultValue?: Value<M>;\n dirty: boolean;\n errors: readonly ValueError[];\n invalid: boolean;\n model: M;\n name: string;\n field: FieldDirective;\n ownErrors: ReadonlyArray<ValueError<Value<M>>>;\n required: boolean;\n validators: ReadonlyArray<Validator<Value<M>>>;\n value?: Value<M>;\n visited: boolean;\n addValidator(validator: Validator<Value<M>>): void;\n setValidators(validators: ReadonlyArray<Validator<Value<M>>>): void;\n setValue(value: Value<M> | undefined): void;\n setVisited(visited: boolean): void;\n validate(): Promise<readonly ValueError[]>;\n}>;\n\nexport type UseFormResult<M extends ProvisionalModel> = Omit<UseFormPartResult<M>, 'setValue' | 'value'> &\n Readonly<{\n value: Value<M>;\n submitting: boolean;\n setDefaultValue(value: Value<M>): void;\n setValue(value: Value<M>): void;\n submit(): Promise<Value<M> | void>;\n reset(): void;\n clear(): void;\n read(value: Value<M> | null | undefined): void;\n update(): void;\n }>;\n\nexport type UseFormArrayPartResult<M extends BinderArrayModel | ArrayModel> = Omit<UseFormPartResult<M>, 'field'> & {\n items: ReadonlyArray<ArrayItemModel<M>>;\n};\n\ntype FieldState<T = unknown> = {\n required: boolean;\n invalid: boolean;\n errorMessage: string;\n strategy?: FieldStrategy<T>;\n element?: HTMLElement;\n inputHandler(): void;\n changeHandler(): void;\n blurHandler(): void;\n ref(element: HTMLElement | null): void;\n};\n\nfunction convertFieldValue<T extends ProvisionalModel>(model: T, fieldValue: unknown) {\n if (typeof fieldValue !== 'string') {\n return fieldValue;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n const stringConverter = getStringConverter(model);\n if (stringConverter) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access\n return stringConverter.fromString(fieldValue);\n }\n\n if (hasFromString(model)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n return model[_fromString](fieldValue);\n }\n\n return fieldValue;\n}\n\nfunction getFormPart<M extends ProvisionalModel>(node: BinderNode<M>): Omit<UseFormPartResult<M>, 'field'> {\n return {\n addValidator: node.addValidator.bind(node),\n get defaultValue() {\n return node.defaultValue;\n },\n dirty: node.dirty,\n errors: node.errors,\n invalid: node.invalid,\n model: node.model,\n name: node.name,\n ownErrors: node.ownErrors,\n required: node.required,\n setValidators(validators) {\n node.validators = validators;\n },\n setValue(value) {\n node.value = value;\n },\n setVisited(visited: boolean) {\n node.visited = visited;\n },\n validate: node.validate.bind(node),\n validators: node.validators,\n get value() {\n return node.value;\n },\n visited: node.visited,\n };\n}\n\nfunction useFields<M extends ProvisionalModel>(node: BinderNode<M>): FieldDirective {\n const update = useUpdate();\n\n return useMemo(() => {\n const registry = new WeakMap<ProvisionalModel, FieldState>();\n\n return ((model: ProvisionalModel) => {\n isRendering = true;\n const n = getBinderNode(model);\n\n let fieldState = registry.get(model);\n\n if (!fieldState) {\n fieldState = {\n changeHandler() {\n fieldState!.inputHandler();\n n.validate().catch(() => {});\n },\n element: undefined,\n errorMessage: '',\n inputHandler() {\n if (fieldState!.strategy) {\n // Remove invalid flag, so that .checkValidity() in Vaadin Components\n // does not interfere with errors from Hilla.\n fieldState!.strategy.invalid = false;\n // When bad input is detected, skip reading new value in binder state\n fieldState!.strategy.checkValidity();\n n[_validity] = fieldState!.strategy.validity;\n n.value = convertFieldValue(model, fieldState!.strategy.value);\n }\n },\n invalid: false,\n blurHandler() {\n fieldState!.inputHandler();\n n.validate().catch(() => {});\n n.visited = true;\n },\n ref(element: HTMLElement | null) {\n if (!element) {\n fieldState!.element?.removeEventListener('blur', fieldState!.blurHandler);\n fieldState!.strategy?.removeEventListeners();\n fieldState!.element = undefined;\n fieldState!.strategy = undefined;\n update();\n return;\n }\n\n if (!isFieldElement(element)) {\n throw new TypeError(`Element '${element.localName}' is not a form element`);\n }\n\n if (fieldState!.element !== element) {\n fieldState!.element = element;\n fieldState!.element.addEventListener('blur', fieldState!.blurHandler);\n fieldState!.strategy = getDefaultFieldStrategy(element, model);\n fieldState!.strategy.onInput = fieldState!.inputHandler;\n fieldState!.strategy.onChange = fieldState!.changeHandler;\n update();\n }\n },\n required: false,\n strategy: undefined,\n };\n\n registry.set(model, fieldState);\n }\n\n if (fieldState.strategy) {\n const valueFromField = convertFieldValue(model, fieldState.strategy.value);\n if (valueFromField !== n.value && !(Number.isNaN(n.value) && Number.isNaN(valueFromField))) {\n fieldState.strategy.value = Number.isNaN(n.value) ? '' : n.value;\n }\n\n if (fieldState.required !== n.required) {\n fieldState.required = n.required;\n fieldState.strategy.required = n.required;\n }\n\n const firstError = n.ownErrors.at(0);\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const errorMessage = firstError?.message ?? '';\n if (fieldState.errorMessage !== errorMessage) {\n fieldState.errorMessage = errorMessage;\n fieldState.strategy.errorMessage = errorMessage;\n }\n\n // Make sure invalid state is always in sync\n fieldState.invalid = n.invalid;\n fieldState.strategy.invalid = n.invalid;\n }\n\n isRendering = false;\n return {\n name: n.name,\n ref: fieldState.ref,\n };\n }) as FieldDirective;\n }, [node]);\n}\n\nexport function useForm<M extends ProvisionalModel>(\n modelClass: ProvisionalModelConstructor<M>,\n config?: BinderConfiguration<Value<M>>,\n): UseFormResult<M> {\n const configRef = useRef<Writable<BinderConfiguration<Value<M>>>>({});\n configRef.current.onSubmit = config?.onSubmit;\n configRef.current.onChange = config?.onChange;\n const update = useUpdate();\n const binder = useMemo(() => new BinderRoot(modelClass, configRef.current), [Model]);\n const field = useFields(binder);\n const clear = binder.clear.bind(binder);\n\n useEffect(() => {\n binder.addEventListener(CHANGED.type, update);\n clear(); // this allows to initialize the validation strategies (issue 2282)\n return () => binder.removeEventListener(CHANGED.type, update);\n }, [binder]);\n\n return {\n ...getFormPart<M>(binder),\n clear,\n field,\n read: binder.read.bind(binder),\n reset: binder.reset.bind(binder),\n setDefaultValue(defaultValue) {\n binder.defaultValue = defaultValue;\n },\n setValue(value) {\n binder.value = value;\n },\n submit: binder.submit.bind(binder),\n value: binder.value,\n submitting: binder.submitting,\n update,\n };\n}\n\nexport function useFormPart<M extends ProvisionalModel>(model: M): UseFormPartResult<M> {\n isRendering = true;\n const binderNode = getBinderNode(model);\n const field = useFields(binderNode);\n isRendering = false;\n\n return {\n ...getFormPart(binderNode),\n field,\n };\n}\n\n/**\n * Hook to access an array model part of a form. It provides the same API as `useFormPart`,\n * but adds an `items` property that allows to iterate over the items in form of an array of models.\n *\n * @param model - The array model to access\n * @returns The array model part of the form\n */\nexport function useFormArrayPart<M extends BinderArrayModel>(model: M): UseFormArrayPartResult<M> {\n isRendering = true;\n const binderNode = getBinderNode(model);\n isRendering = false;\n return {\n ...getFormPart(binderNode),\n items: Array.from(model, (item) => item.model as ArrayItemModel<M>),\n };\n}\n"],"version":3}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/hilla-react-form",
|
|
3
|
-
"version": "25.0
|
|
3
|
+
"version": "25.1.0-alpha10",
|
|
4
4
|
"description": "Hilla form utils for React",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@vaadin/hilla-lit-form": "25.0
|
|
47
|
+
"@vaadin/hilla-lit-form": "25.1.0-alpha10"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"react": "18 || 19",
|