@vaadin/hilla-lit-form 24.6.2 → 24.6.3

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 +1 @@
1
- {"version":3,"file":"BinderRoot.d.ts","sourceRoot":"","sources":["src/BinderRoot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BinderRoot.d.ts","sourceRoot":"","sources":["src/BinderRoot.ts"],"names":[],"mappings":"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"}
package/BinderRoot.js CHANGED
@@ -164,7 +164,9 @@ class BinderRoot extends BinderNode {
164
164
  const [property, value, message] = res ? res.splice(2) : [data.parameterName ?? "", void 0, data.message];
165
165
  valueErrors.push({
166
166
  message,
167
- property,
167
+ // Convert property from bracket notation to dot notation
168
+ // Example: 'orders[0].description' becomes 'orders.0.description'
169
+ property: property.replace(/\[(\d+)\]/gu, ".$1"),
168
170
  validator: new ServerValidator(message),
169
171
  value,
170
172
  validatorMessage: data.validatorMessage
package/BinderRoot.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["src/BinderRoot.ts"],
4
- "sourcesContent": ["import { EndpointValidationError, type ValidationErrorData } from '@vaadin/hilla-frontend/EndpointErrors.js';\nimport {\n _clearValidation,\n _setErrorsWithDescendants,\n _update,\n _updateValidation,\n BinderNode,\n CHANGED,\n} from './BinderNode.js';\nimport { type FieldElement, type FieldStrategy, getDefaultFieldStrategy } from './Field.js';\nimport {\n _parent,\n type AbstractModel,\n createDetachedModel,\n type DetachedModelConstructor,\n type Value,\n} from './Models.js';\nimport type { ClassStaticProperties } from './types.js';\nimport {\n type InterpolateMessageCallback,\n runValidator,\n ServerValidator,\n ValidationError,\n type Validator,\n type ValueError,\n} from './Validation.js';\n\nexport type BinderConfiguration<T> = Readonly<{\n onChange?(oldValue?: T): void;\n onSubmit?(value: T): Promise<T | undefined | void>;\n}>;\n\nexport type BinderRootConfiguration<T> = BinderConfiguration<T> &\n Readonly<{\n context?: unknown;\n }>;\n\n/**\n * A simplified Binder that does not require a context.\n * It can be used as root when there is no Element to use as context.\n *\n * @typeParam T - Type of the value that binds to a form\n * @typeParam M - Type of the model that describes the structure of the value\n */\nexport class BinderRoot<M extends AbstractModel = AbstractModel> extends BinderNode<M> {\n static interpolateMessageCallback?: InterpolateMessageCallback<any>;\n\n #defaultValue!: Value<M>; // Initialized in the `read()` method\n\n #value!: Value<M>; // Initialized in the `read()` method\n\n readonly #emptyValue: Value<M>;\n\n #submitting = false;\n\n #validating = false;\n\n #validationRequest?: Promise<void>;\n\n readonly #config?: BinderRootConfiguration<Value<M>>;\n\n readonly #validations = new Map<AbstractModel, Map<Validator, Promise<readonly ValueError[]>>>();\n\n readonly #context: unknown = this;\n\n declare readonly ['constructor']: ClassStaticProperties<typeof BinderRoot<M>>;\n\n /**\n *\n * @param Model - The constructor (the class reference) of the form model. The Binder instantiates the top-level model\n * @param config - The options object, which can be used to config the onChange and onSubmit callbacks.\n *\n * ```\n * binder = new BinderRoot(OrderModel);\n * or\n * binder = new BinderRoot(OrderModel, {onSubmit: async (order) => {endpoint.save(order)}});\n * ```\n */\n constructor(Model: DetachedModelConstructor<M>, config?: BinderRootConfiguration<Value<M>>) {\n super(createDetachedModel(Model));\n // @ts-expect-error the model's parent is the binder\n this.model[_parent] = this;\n this.#context = config?.context ?? this;\n this.#config = config;\n // Initialize value instead of the parent.\n this.initializeValue(true);\n this.#emptyValue = this.value;\n }\n\n /**\n * The initial value of the form, before any fields are edited by the user.\n */\n override get defaultValue(): Value<M> {\n return this.#defaultValue;\n }\n\n override set defaultValue(newValue: Value<M>) {\n this.#defaultValue = newValue;\n this.dispatchEvent(CHANGED);\n }\n\n override get binder(): BinderRoot {\n return this as BinderRoot;\n }\n\n /**\n * The current value of the form.\n */\n override get value(): Value<M> {\n return this.#value;\n }\n\n override set value(newValue: Value<M>) {\n if (newValue === this.#value) {\n return;\n }\n\n const oldValue = this.#value;\n this.#value = newValue;\n this[_update](oldValue);\n this[_updateValidation]().catch(() => {});\n }\n\n /**\n * Indicates the submitting status of the form.\n * True if the form was submitted, but the submit promise is not resolved yet.\n */\n get submitting(): boolean {\n return this.#submitting;\n }\n\n /**\n * Indicates the validating status of the form.\n * True when there is an ongoing validation.\n */\n get validating(): boolean {\n return this.#validating;\n }\n\n /**\n * Read the given value into the form and clear validation errors. Clears the form if the value is undefined.\n *\n * @param value - The value to read, or undefined to clear.\n */\n read(value: Value<M> | null | undefined): void {\n if (value === undefined || value === null) {\n this.clear();\n return;\n }\n this.defaultValue = value;\n if (\n // Skip when no value is set yet (e.g., invoked from constructor)\n this.value &&\n // Clear validation state, then proceed if update is needed\n this[_clearValidation]() &&\n // When value is dirty, another update is coming from invoking the value\n // setter below, so we skip this one to prevent duplicate updates\n this.value === value\n ) {\n this[_update](this.value);\n }\n\n this.value = this.defaultValue;\n }\n\n /**\n * Reset the form to the previous value\n */\n reset(): void {\n this.read(this.#defaultValue);\n }\n\n /**\n * Sets the form to empty value, as defined in the Model.\n */\n clear(): void {\n this.read(this.#emptyValue);\n }\n\n /**\n * Submit the current form value to a predefined\n * onSubmit callback.\n *\n * It's a no-op if the onSubmit callback is undefined.\n */\n async submit(): Promise<Value<M> | undefined | void> {\n const onSubmit = this.#config?.onSubmit;\n if (onSubmit) {\n return this.submitTo(onSubmit);\n }\n\n return undefined;\n }\n\n /**\n * Submit the current form value to callback\n *\n * @param endpointMethod - the callback function\n */\n async submitTo<V>(endpointMethod: (value: Value<M>) => Promise<V>): Promise<V> {\n const errors = await this.validate();\n if (errors.length) {\n throw new ValidationError(errors);\n }\n\n this.#submitting = true;\n this[_update](this.value);\n this.dispatchEvent(CHANGED);\n try {\n return await endpointMethod.call(this.#context, this.value);\n } catch (error: unknown) {\n if (error instanceof EndpointValidationError && error.validationErrorData.length) {\n const valueErrors: Array<ValueError<any>> = [];\n error.validationErrorData.forEach((data: ValidationErrorData) => {\n const res =\n /Object of type '(.+)' has invalid property '(.+)' with value '(.+)', validation error: '(.+)'/u.exec(\n data.message,\n );\n const [property, value, message] = res ? res.splice(2) : [data.parameterName ?? '', undefined, data.message];\n valueErrors.push({\n message,\n property,\n validator: new ServerValidator(message),\n value,\n validatorMessage: data.validatorMessage,\n });\n });\n this[_setErrorsWithDescendants](valueErrors);\n throw new ValidationError(valueErrors);\n }\n\n throw error;\n } finally {\n this.#submitting = false;\n this.defaultValue = this.value;\n this[_update](this.value);\n }\n }\n\n async requestValidation<NM extends AbstractModel>(\n model: NM,\n validator: Validator<Value<NM>>,\n ): Promise<ReadonlyArray<ValueError<Value<NM>>>> {\n let modelValidations: Map<Validator<Value<NM>>, Promise<ReadonlyArray<ValueError<Value<NM>>>>>;\n\n if (this.#validations.has(model)) {\n modelValidations = this.#validations.get(model) as Map<\n Validator<Value<NM>>,\n Promise<ReadonlyArray<ValueError<Value<NM>>>>\n >;\n } else {\n modelValidations = new Map();\n this.#validations.set(model, modelValidations);\n }\n\n await this.performValidation();\n\n if (modelValidations.has(validator)) {\n return modelValidations.get(validator)!;\n }\n\n const promise = runValidator(model, validator, this.constructor.interpolateMessageCallback);\n modelValidations.set(validator, promise);\n const valueErrors = await promise;\n\n modelValidations.delete(validator);\n if (modelValidations.size === 0) {\n this.#validations.delete(model);\n }\n if (this.#validations.size === 0) {\n this.completeValidation();\n }\n\n return valueErrors;\n }\n\n /**\n * Determines and returns the field directive strategy for the bound element.\n * Override to customise the binding strategy for a component.\n * The Binder extends BinderNode, see the inherited properties and methods below.\n *\n * @param elm - the bound element\n * @param model - the bound model\n */\n // eslint ignored to allow overriding\n // eslint-disable-next-line @typescript-eslint/class-methods-use-this\n getFieldStrategy<TField>(elm: HTMLElement, model?: AbstractModel<TField>): FieldStrategy {\n return getDefaultFieldStrategy(elm as FieldElement, model);\n }\n\n protected performValidation(): Promise<void> | void {\n if (!this.#validationRequest) {\n this.#validating = true;\n this.dispatchEvent(CHANGED);\n this.#validationRequest = Promise.resolve().then(() => {\n this.#validationRequest = undefined;\n });\n }\n return this.#validationRequest;\n }\n\n protected completeValidation(): void {\n this.#validating = false;\n this.dispatchEvent(CHANGED);\n }\n\n protected override [_update](oldValue: Value<M>): void {\n this.#config?.onChange?.call(this.#context, oldValue);\n this.dispatchEvent(CHANGED);\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { EndpointValidationError, type ValidationErrorData } from '@vaadin/hilla-frontend/EndpointErrors.js';\nimport {\n _clearValidation,\n _setErrorsWithDescendants,\n _update,\n _updateValidation,\n BinderNode,\n CHANGED,\n} from './BinderNode.js';\nimport { type FieldElement, type FieldStrategy, getDefaultFieldStrategy } from './Field.js';\nimport {\n _parent,\n type AbstractModel,\n createDetachedModel,\n type DetachedModelConstructor,\n type Value,\n} from './Models.js';\nimport type { ClassStaticProperties } from './types.js';\nimport {\n type InterpolateMessageCallback,\n runValidator,\n ServerValidator,\n ValidationError,\n type Validator,\n type ValueError,\n} from './Validation.js';\n\nexport type BinderConfiguration<T> = Readonly<{\n onChange?(oldValue?: T): void;\n onSubmit?(value: T): Promise<T | undefined | void>;\n}>;\n\nexport type BinderRootConfiguration<T> = BinderConfiguration<T> &\n Readonly<{\n context?: unknown;\n }>;\n\n/**\n * A simplified Binder that does not require a context.\n * It can be used as root when there is no Element to use as context.\n *\n * @typeParam T - Type of the value that binds to a form\n * @typeParam M - Type of the model that describes the structure of the value\n */\nexport class BinderRoot<M extends AbstractModel = AbstractModel> extends BinderNode<M> {\n static interpolateMessageCallback?: InterpolateMessageCallback<any>;\n\n #defaultValue!: Value<M>; // Initialized in the `read()` method\n\n #value!: Value<M>; // Initialized in the `read()` method\n\n readonly #emptyValue: Value<M>;\n\n #submitting = false;\n\n #validating = false;\n\n #validationRequest?: Promise<void>;\n\n readonly #config?: BinderRootConfiguration<Value<M>>;\n\n readonly #validations = new Map<AbstractModel, Map<Validator, Promise<readonly ValueError[]>>>();\n\n readonly #context: unknown = this;\n\n declare readonly ['constructor']: ClassStaticProperties<typeof BinderRoot<M>>;\n\n /**\n *\n * @param Model - The constructor (the class reference) of the form model. The Binder instantiates the top-level model\n * @param config - The options object, which can be used to config the onChange and onSubmit callbacks.\n *\n * ```\n * binder = new BinderRoot(OrderModel);\n * or\n * binder = new BinderRoot(OrderModel, {onSubmit: async (order) => {endpoint.save(order)}});\n * ```\n */\n constructor(Model: DetachedModelConstructor<M>, config?: BinderRootConfiguration<Value<M>>) {\n super(createDetachedModel(Model));\n // @ts-expect-error the model's parent is the binder\n this.model[_parent] = this;\n this.#context = config?.context ?? this;\n this.#config = config;\n // Initialize value instead of the parent.\n this.initializeValue(true);\n this.#emptyValue = this.value;\n }\n\n /**\n * The initial value of the form, before any fields are edited by the user.\n */\n override get defaultValue(): Value<M> {\n return this.#defaultValue;\n }\n\n override set defaultValue(newValue: Value<M>) {\n this.#defaultValue = newValue;\n this.dispatchEvent(CHANGED);\n }\n\n override get binder(): BinderRoot {\n return this as BinderRoot;\n }\n\n /**\n * The current value of the form.\n */\n override get value(): Value<M> {\n return this.#value;\n }\n\n override set value(newValue: Value<M>) {\n if (newValue === this.#value) {\n return;\n }\n\n const oldValue = this.#value;\n this.#value = newValue;\n this[_update](oldValue);\n this[_updateValidation]().catch(() => {});\n }\n\n /**\n * Indicates the submitting status of the form.\n * True if the form was submitted, but the submit promise is not resolved yet.\n */\n get submitting(): boolean {\n return this.#submitting;\n }\n\n /**\n * Indicates the validating status of the form.\n * True when there is an ongoing validation.\n */\n get validating(): boolean {\n return this.#validating;\n }\n\n /**\n * Read the given value into the form and clear validation errors. Clears the form if the value is undefined.\n *\n * @param value - The value to read, or undefined to clear.\n */\n read(value: Value<M> | null | undefined): void {\n if (value === undefined || value === null) {\n this.clear();\n return;\n }\n this.defaultValue = value;\n if (\n // Skip when no value is set yet (e.g., invoked from constructor)\n this.value &&\n // Clear validation state, then proceed if update is needed\n this[_clearValidation]() &&\n // When value is dirty, another update is coming from invoking the value\n // setter below, so we skip this one to prevent duplicate updates\n this.value === value\n ) {\n this[_update](this.value);\n }\n\n this.value = this.defaultValue;\n }\n\n /**\n * Reset the form to the previous value\n */\n reset(): void {\n this.read(this.#defaultValue);\n }\n\n /**\n * Sets the form to empty value, as defined in the Model.\n */\n clear(): void {\n this.read(this.#emptyValue);\n }\n\n /**\n * Submit the current form value to a predefined\n * onSubmit callback.\n *\n * It's a no-op if the onSubmit callback is undefined.\n */\n async submit(): Promise<Value<M> | undefined | void> {\n const onSubmit = this.#config?.onSubmit;\n if (onSubmit) {\n return this.submitTo(onSubmit);\n }\n\n return undefined;\n }\n\n /**\n * Submit the current form value to callback\n *\n * @param endpointMethod - the callback function\n */\n async submitTo<V>(endpointMethod: (value: Value<M>) => Promise<V>): Promise<V> {\n const errors = await this.validate();\n if (errors.length) {\n throw new ValidationError(errors);\n }\n\n this.#submitting = true;\n this[_update](this.value);\n this.dispatchEvent(CHANGED);\n try {\n return await endpointMethod.call(this.#context, this.value);\n } catch (error: unknown) {\n if (error instanceof EndpointValidationError && error.validationErrorData.length) {\n const valueErrors: Array<ValueError<any>> = [];\n error.validationErrorData.forEach((data: ValidationErrorData) => {\n const res =\n /Object of type '(.+)' has invalid property '(.+)' with value '(.+)', validation error: '(.+)'/u.exec(\n data.message,\n );\n const [property, value, message] = res ? res.splice(2) : [data.parameterName ?? '', undefined, data.message];\n valueErrors.push({\n message,\n // Convert property from bracket notation to dot notation\n // Example: 'orders[0].description' becomes 'orders.0.description'\n property: property.replace(/\\[(\\d+)\\]/gu, '.$1'),\n validator: new ServerValidator(message),\n value,\n validatorMessage: data.validatorMessage,\n });\n });\n this[_setErrorsWithDescendants](valueErrors);\n throw new ValidationError(valueErrors);\n }\n\n throw error;\n } finally {\n this.#submitting = false;\n this.defaultValue = this.value;\n this[_update](this.value);\n }\n }\n\n async requestValidation<NM extends AbstractModel>(\n model: NM,\n validator: Validator<Value<NM>>,\n ): Promise<ReadonlyArray<ValueError<Value<NM>>>> {\n let modelValidations: Map<Validator<Value<NM>>, Promise<ReadonlyArray<ValueError<Value<NM>>>>>;\n\n if (this.#validations.has(model)) {\n modelValidations = this.#validations.get(model) as Map<\n Validator<Value<NM>>,\n Promise<ReadonlyArray<ValueError<Value<NM>>>>\n >;\n } else {\n modelValidations = new Map();\n this.#validations.set(model, modelValidations);\n }\n\n await this.performValidation();\n\n if (modelValidations.has(validator)) {\n return modelValidations.get(validator)!;\n }\n\n const promise = runValidator(model, validator, this.constructor.interpolateMessageCallback);\n modelValidations.set(validator, promise);\n const valueErrors = await promise;\n\n modelValidations.delete(validator);\n if (modelValidations.size === 0) {\n this.#validations.delete(model);\n }\n if (this.#validations.size === 0) {\n this.completeValidation();\n }\n\n return valueErrors;\n }\n\n /**\n * Determines and returns the field directive strategy for the bound element.\n * Override to customise the binding strategy for a component.\n * The Binder extends BinderNode, see the inherited properties and methods below.\n *\n * @param elm - the bound element\n * @param model - the bound model\n */\n // eslint ignored to allow overriding\n // eslint-disable-next-line @typescript-eslint/class-methods-use-this\n getFieldStrategy<TField>(elm: HTMLElement, model?: AbstractModel<TField>): FieldStrategy {\n return getDefaultFieldStrategy(elm as FieldElement, model);\n }\n\n protected performValidation(): Promise<void> | void {\n if (!this.#validationRequest) {\n this.#validating = true;\n this.dispatchEvent(CHANGED);\n this.#validationRequest = Promise.resolve().then(() => {\n this.#validationRequest = undefined;\n });\n }\n return this.#validationRequest;\n }\n\n protected completeValidation(): void {\n this.#validating = false;\n this.dispatchEvent(CHANGED);\n }\n\n protected override [_update](oldValue: Value<M>): void {\n this.#config?.onChange?.call(this.#context, oldValue);\n this.dispatchEvent(CHANGED);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/index.js CHANGED
@@ -2,7 +2,7 @@ function __REGISTER__(feature, vaadinObj = window.Vaadin ??= {}) {
2
2
  vaadinObj.registrations ??= [];
3
3
  vaadinObj.registrations.push({
4
4
  is: feature ? `${"@vaadin/hilla-lit-form"}/${feature}` : "@vaadin/hilla-lit-form",
5
- version: "24.6.2"
5
+ version: "24.6.3"
6
6
  });
7
7
  }
8
8
  export * from "./Binder.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/hilla-lit-form",
3
- "version": "24.6.2",
3
+ "version": "24.6.3",
4
4
  "description": "Hilla form utils",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -71,7 +71,7 @@
71
71
  "access": "public"
72
72
  },
73
73
  "dependencies": {
74
- "@vaadin/hilla-frontend": "24.6.2",
74
+ "@vaadin/hilla-frontend": "24.6.3",
75
75
  "validator": "^13.11.0"
76
76
  },
77
77
  "peerDependencies": {