@vaadin/hilla-lit-form
Version:
Hilla form utils
378 lines • 17.4 kB
JavaScript
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