UNPKG

@vaadin/hilla-lit-form

Version:

Hilla form utils

378 lines 17.4 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _AbstractFieldStrategy_instances, _AbstractFieldStrategy_element, _AbstractFieldStrategy_validityFallback, _AbstractFieldStrategy_eventHandlers, _AbstractFieldStrategy_getEventHandler, _AbstractFieldStrategy_setEventHandler, _AbstractFieldStrategy_detectValidityError, _VaadinFieldStrategy_instances, _VaadinFieldStrategy_invalid, _VaadinFieldStrategy_boundOnValidated, _VaadinFieldStrategy_boundOnUnparsableChange, _VaadinFieldStrategy_onValidated, _VaadinFieldStrategy_onUnparsableChange; import { noChange, nothing } from 'lit'; import { directive, Directive, PartType } from 'lit/directive.js'; import { getBinderNode } from './BinderNode.js'; import { _fromString, ArrayModel, BooleanModel, hasFromString, NumberModel, ObjectModel, } from './Models.js'; import { StringModel } from './Models.js'; import { _validity, defaultValidity } from './Validity.js'; const props = ['required', 'invalid', 'errorMessage', 'value', 'validity', 'checkValidity']; export function isFieldElement(element) { return props.some((prop) => prop in element); } export class AbstractFieldStrategy { constructor(element, model) { _AbstractFieldStrategy_instances.add(this); Object.defineProperty(this, "model", { enumerable: true, configurable: true, writable: true, value: void 0 }); _AbstractFieldStrategy_element.set(this, void 0); _AbstractFieldStrategy_validityFallback.set(this, defaultValidity); _AbstractFieldStrategy_eventHandlers.set(this, new Map()); __classPrivateFieldSet(this, _AbstractFieldStrategy_element, element, "f"); this.model = model; } get element() { return __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f"); } set element(element) { __classPrivateFieldSet(this, _AbstractFieldStrategy_element, element, "f"); } get value() { return __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").value; } set value(value) { if (this.model instanceof StringModel || this.model instanceof NumberModel) { __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").value = value ?? ''; return; } __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").value = value; } set errorMessage(_) { } get validity() { return __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").validity ?? __classPrivateFieldGet(this, _AbstractFieldStrategy_validityFallback, "f"); } get onChange() { return __classPrivateFieldGet(this, _AbstractFieldStrategy_eventHandlers, "f").get('change'); } set onChange(onChange) { __classPrivateFieldGet(this, _AbstractFieldStrategy_instances, "m", _AbstractFieldStrategy_setEventHandler).call(this, 'change', onChange); } get onInput() { return __classPrivateFieldGet(this, _AbstractFieldStrategy_instances, "m", _AbstractFieldStrategy_getEventHandler).call(this, 'input'); } set onInput(onInput) { __classPrivateFieldGet(this, _AbstractFieldStrategy_instances, "m", _AbstractFieldStrategy_setEventHandler).call(this, 'input', onInput); } checkValidity() { if (!__classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").checkValidity) { return true; } const valid = __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").checkValidity(); __classPrivateFieldSet(this, _AbstractFieldStrategy_validityFallback, { ...defaultValidity, valid, ...(valid ? {} : __classPrivateFieldGet(this, _AbstractFieldStrategy_instances, "m", _AbstractFieldStrategy_detectValidityError).call(this)), }, "f"); return valid; } setAttribute(key, val) { if (val) { __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").setAttribute(key, ''); } else { __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").removeAttribute(key); } } removeEventListeners() { for (const [type, handler] of __classPrivateFieldGet(this, _AbstractFieldStrategy_eventHandlers, "f")) { this.element.removeEventListener(type, handler); __classPrivateFieldGet(this, _AbstractFieldStrategy_eventHandlers, "f").delete(type); } } } _AbstractFieldStrategy_element = new WeakMap(), _AbstractFieldStrategy_validityFallback = new WeakMap(), _AbstractFieldStrategy_eventHandlers = new WeakMap(), _AbstractFieldStrategy_instances = new WeakSet(), _AbstractFieldStrategy_getEventHandler = function _AbstractFieldStrategy_getEventHandler(type) { return __classPrivateFieldGet(this, _AbstractFieldStrategy_eventHandlers, "f").get(type); }, _AbstractFieldStrategy_setEventHandler = function _AbstractFieldStrategy_setEventHandler(type, handler) { if (__classPrivateFieldGet(this, _AbstractFieldStrategy_eventHandlers, "f").has(type)) { this.element.removeEventListener(type, __classPrivateFieldGet(this, _AbstractFieldStrategy_eventHandlers, "f").get(type)); } if (handler) { this.element.addEventListener(type, handler); __classPrivateFieldGet(this, _AbstractFieldStrategy_eventHandlers, "f").set(type, handler); } else { __classPrivateFieldGet(this, _AbstractFieldStrategy_eventHandlers, "f").delete(type); } }, _AbstractFieldStrategy_detectValidityError = function _AbstractFieldStrategy_detectValidityError() { if (!('inputElement' in __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f"))) { return { customError: true }; } const inputElement = __classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").inputElement; if (__classPrivateFieldGet(this, _AbstractFieldStrategy_element, "f").value === '') { if (inputElement.value === '') { return { valueMissing: true }; } return { badInput: true }; } return { customError: true }; }; export class VaadinFieldStrategy extends AbstractFieldStrategy { constructor(element, model) { super(element, model); _VaadinFieldStrategy_instances.add(this); _VaadinFieldStrategy_invalid.set(this, false); _VaadinFieldStrategy_boundOnValidated.set(this, __classPrivateFieldGet(this, _VaadinFieldStrategy_instances, "m", _VaadinFieldStrategy_onValidated).bind(this)); _VaadinFieldStrategy_boundOnUnparsableChange.set(this, __classPrivateFieldGet(this, _VaadinFieldStrategy_instances, "m", _VaadinFieldStrategy_onUnparsableChange).bind(this)); element.addEventListener('validated', __classPrivateFieldGet(this, _VaadinFieldStrategy_boundOnValidated, "f")); element.addEventListener('unparsable-change', __classPrivateFieldGet(this, _VaadinFieldStrategy_boundOnUnparsableChange, "f")); } set required(value) { this.element.required = value; } set invalid(value) { __classPrivateFieldSet(this, _VaadinFieldStrategy_invalid, value, "f"); this.element.invalid = value; } set errorMessage(value) { this.element.errorMessage = value; } removeEventListeners() { this.element.removeEventListener('validated', __classPrivateFieldGet(this, _VaadinFieldStrategy_boundOnValidated, "f")); this.element.removeEventListener('unparsable-change', __classPrivateFieldGet(this, _VaadinFieldStrategy_boundOnUnparsableChange, "f")); } checkValidity() { const isElementInvalid = this.element.invalid; this.element.invalid = false; const valid = super.checkValidity(); this.element.invalid = isElementInvalid; return valid; } } _VaadinFieldStrategy_invalid = new WeakMap(), _VaadinFieldStrategy_boundOnValidated = new WeakMap(), _VaadinFieldStrategy_boundOnUnparsableChange = new WeakMap(), _VaadinFieldStrategy_instances = new WeakSet(), _VaadinFieldStrategy_onValidated = function _VaadinFieldStrategy_onValidated(e) { if (!(e instanceof CustomEvent) || typeof e.detail !== 'object') { return; } const invalid = !(e.detail ?? {}).valid; if (__classPrivateFieldGet(this, _VaadinFieldStrategy_invalid, "f") !== invalid) { this.element.invalid = __classPrivateFieldGet(this, _VaadinFieldStrategy_invalid, "f"); } this.onInput?.call(this.element, e); }, _VaadinFieldStrategy_onUnparsableChange = function _VaadinFieldStrategy_onUnparsableChange(e) { this.onChange?.call(this.element, e); }; export class GenericFieldStrategy extends AbstractFieldStrategy { set required(value) { this.setAttribute('required', value); } set invalid(value) { this.setAttribute('invalid', value); } } export class CheckedFieldStrategy extends GenericFieldStrategy { get value() { if (this.model instanceof BooleanModel) { return this.element.checked; } return this.element.checked ? this.element.value : undefined; } set value(val) { this.element.checked = /^(true|on)$/iu.test(String(val)); } } export class CheckedGroupFieldStrategy extends GenericFieldStrategy { get value() { return super.value; } set value(val) { super.value = val ?? []; } } export class ComboBoxFieldStrategy extends VaadinFieldStrategy { get value() { if (this.model && (this.model instanceof ObjectModel || this.model instanceof ArrayModel)) { const { selectedItem } = this.element; return selectedItem ?? undefined; } return super.value; } set value(val) { if (this.model instanceof ObjectModel || this.model instanceof ArrayModel) { this.element.selectedItem = val ?? null; } else { super.value = val; } } } export class VaadinStringFieldStrategy extends VaadinFieldStrategy { get value() { return super.value; } set value(val) { super.value = val ?? ''; } } function isEmptyObject(val) { return val && typeof val === 'object' && !Array.isArray(val) && Object.keys(val).length === 0; } export class VaadinDateTimeFieldStrategy extends VaadinFieldStrategy { get value() { return super.value; } set value(val) { const timestamp = Date.parse(val); if (!val || isEmptyObject(val) || Number.isNaN(timestamp)) { super.value = ''; return; } const date = new Date(timestamp); const tzOffsetMs = 60 * 1000 * date.getTimezoneOffset(); super.value = new Date(timestamp - tzOffsetMs).toISOString().slice(0, 19); } } export class MultiSelectComboBoxFieldStrategy extends VaadinFieldStrategy { get value() { return this.element.selectedItems; } set value(val) { this.element.selectedItems = val; } } export class SelectedFieldStrategy extends GenericFieldStrategy { get value() { return this.element.selected; } set value(val) { this.element.selected = val; } } export function getDefaultFieldStrategy(elm, model) { switch (elm.localName) { case 'vaadin-checkbox': case 'vaadin-radio-button': return new CheckedFieldStrategy(elm, model); case 'vaadin-checkbox-group': return new CheckedGroupFieldStrategy(elm, model); case 'vaadin-combo-box': return new ComboBoxFieldStrategy(elm, model); case 'vaadin-list-box': return new SelectedFieldStrategy(elm, model); case 'vaadin-multi-select-combo-box': return new MultiSelectComboBoxFieldStrategy(elm, model); case 'vaadin-rich-text-editor': return new GenericFieldStrategy(elm, model); case 'vaadin-time-picker': return new VaadinStringFieldStrategy(elm, model); case 'vaadin-date-time-picker': return new VaadinDateTimeFieldStrategy(elm, model); default: if (elm.localName === 'input' && /^(checkbox|radio)$/u.test(elm.type)) { return new CheckedFieldStrategy(elm, model); } if (elm.constructor.version) { return new VaadinFieldStrategy(elm, model); } return new GenericFieldStrategy(elm, model); } } function convertFieldValue(model, fieldValue) { return typeof fieldValue === 'string' && hasFromString(model) ? model[_fromString](fieldValue) : fieldValue; } export const field = directive(class extends Directive { constructor(partInfo) { super(partInfo); Object.defineProperty(this, "fieldState", { enumerable: true, configurable: true, writable: true, value: void 0 }); if (partInfo.type !== PartType.PROPERTY && partInfo.type !== PartType.ELEMENT) { throw new Error('Use as "<element {field(...)}" or <element ...={field(...)}"'); } } render(_model, _effect) { return nothing; } update(part, [model, effect]) { const element = part.element; const binderNode = getBinderNode(model); if (!this.fieldState) { const fieldState = { errorMessage: '', name: '', value: '', required: false, invalid: false, model, validity: defaultValidity, element, strategy: binderNode.binder.getFieldStrategy(element, model), }; this.fieldState = fieldState; const inputHandler = () => { fieldState.strategy.checkValidity(); if (!fieldState.strategy.validity.badInput) { fieldState.value = fieldState.strategy.value; } fieldState.validity = fieldState.strategy.validity; binderNode[_validity] = fieldState.validity; binderNode.value = convertFieldValue(model, fieldState.value); if (effect !== undefined) { effect.call(element, element); } }; fieldState.strategy.onInput = inputHandler; fieldState.strategy.onChange = () => { inputHandler(); void binderNode.validate(); }; const blurHandler = () => { inputHandler(); void binderNode.validate(); binderNode.visited = true; }; element.addEventListener('blur', blurHandler); } const { fieldState } = this; if (fieldState.element !== element || fieldState.model !== model) { const { onInput } = fieldState.strategy; fieldState.strategy = binderNode.binder.getFieldStrategy(element, model); fieldState.strategy.onInput = onInput; } const { name } = binderNode; if (name !== fieldState.name) { fieldState.name = name; element.setAttribute('name', name); } const { value } = binderNode; const valueFromField = convertFieldValue(model, fieldState.value); if (value !== valueFromField && !(Number.isNaN(value) && Number.isNaN(valueFromField))) { const nonNanValue = Number.isNaN(value) ? '' : value; fieldState.value = nonNanValue; fieldState.strategy.value = nonNanValue; } const { required } = binderNode; if (required !== fieldState.required) { fieldState.required = required; fieldState.strategy.required = required; } const firstError = binderNode.ownErrors[0]; const errorMessage = firstError?.message || ''; if (errorMessage !== fieldState.errorMessage) { fieldState.errorMessage = errorMessage; fieldState.strategy.errorMessage = errorMessage; } const { invalid } = binderNode; if (invalid !== fieldState.invalid) { fieldState.invalid = invalid; fieldState.strategy.invalid = invalid; } return noChange; } }); //# sourceMappingURL=Field.js.map