fix(form-core): type enhancements
This commit is contained in:
parent
0ec72ac330
commit
b83ef4eeeb
10 changed files with 84 additions and 40 deletions
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
'@lion/button': patch
|
||||
'@lion/overlays': patch
|
||||
'@lion/tooltip': patch
|
||||
---
|
||||
|
||||
Types for overlays, tooltip, button
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
'@lion/core': minor
|
||||
---
|
||||
|
||||
EventTargetShim
|
||||
|
||||
#### Features
|
||||
|
||||
EventTargetShim is a base class that works like EventTarget, on all browsers.
|
||||
|
|
@ -40,11 +40,26 @@ const FormControlMixinImplementation = superclass =>
|
|||
reflect: true,
|
||||
},
|
||||
/**
|
||||
* When no light dom defined and prop set
|
||||
* A Boolean attribute which, if present, indicates that the user should not be able to edit
|
||||
* the value of the input. The difference between disabled and readonly is that read-only
|
||||
* controls can still function, whereas disabled controls generally do not function as
|
||||
* controls until they are enabled.
|
||||
*
|
||||
* (From: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-readonly)
|
||||
*/
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
attribute: 'readonly',
|
||||
reflect: true,
|
||||
},
|
||||
/**
|
||||
* The label text for the input node.
|
||||
* When no light dom defined via [slot=label], this value will be used
|
||||
*/
|
||||
label: String, // FIXME: { attribute: false } breaks a bunch of tests, but shouldn't...
|
||||
/**
|
||||
* When no light dom defined and prop set
|
||||
* The helpt text for the input node.
|
||||
* When no light dom defined via [slot=help-text], this value will be used
|
||||
*/
|
||||
helpText: {
|
||||
type: String,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { InteractionStateMixin } from '../InteractionStateMixin.js';
|
|||
* @typedef {import('../../types/FormControlMixinTypes').FormControlHost} FormControlHost
|
||||
* @typedef {import('../../types/registration/FormRegistrarMixinTypes').ElementWithParentFormGroup} ElementWithParentFormGroup
|
||||
* @typedef {FormControlHost & HTMLElement & {__parentFormGroup?:HTMLElement, checked?:boolean}} FormControl
|
||||
* @typedef {import('../../types/choice-group/ChoiceInputMixinTypes').ChoiceInputHost} ChoiceInputHost
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -14,6 +15,7 @@ import { InteractionStateMixin } from '../InteractionStateMixin.js';
|
|||
* @param {import('@open-wc/dedupe-mixin').Constructor<import('@lion/core').LitElement>} superclass
|
||||
*/
|
||||
const ChoiceGroupMixinImplementation = superclass =>
|
||||
// @ts-expect-error
|
||||
class ChoiceGroupMixin extends FormRegistrarMixin(InteractionStateMixin(superclass)) {
|
||||
static get properties() {
|
||||
return {
|
||||
|
|
@ -32,25 +34,27 @@ const ChoiceGroupMixinImplementation = superclass =>
|
|||
get modelValue() {
|
||||
const elems = this._getCheckedElements();
|
||||
if (this.multipleChoice) {
|
||||
return elems.map(el => el.modelValue.value);
|
||||
return elems.map(el => el.choiceValue);
|
||||
}
|
||||
return elems[0] ? elems[0].modelValue.value : '';
|
||||
return elems[0] ? elems[0].choiceValue : '';
|
||||
}
|
||||
|
||||
set modelValue(value) {
|
||||
/**
|
||||
* @param {{ modelValue: { value: any; }; }} el
|
||||
* @param {ChoiceInputHost} el
|
||||
* @param {any} val
|
||||
*/
|
||||
const checkCondition = (el, val) => el.modelValue.value === val;
|
||||
const checkCondition = (el, val) => el.choiceValue === val;
|
||||
|
||||
if (this.__isInitialModelValue) {
|
||||
this.__isInitialModelValue = false;
|
||||
this.registrationComplete.then(() => {
|
||||
this._setCheckedElements(value, checkCondition);
|
||||
});
|
||||
this.requestUpdate('modelValue');
|
||||
} else {
|
||||
this._setCheckedElements(value, checkCondition);
|
||||
this.requestUpdate('modelValue');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +76,7 @@ const ChoiceGroupMixinImplementation = superclass =>
|
|||
|
||||
set serializedValue(value) {
|
||||
/**
|
||||
* @param {{ serializedValue: { value: any; }; }} el
|
||||
* @param {ChoiceInputHost} el
|
||||
* @param {string} val
|
||||
*/
|
||||
const checkCondition = (el, val) => el.serializedValue.value === val;
|
||||
|
|
@ -81,9 +85,11 @@ const ChoiceGroupMixinImplementation = superclass =>
|
|||
this.__isInitialSerializedValue = false;
|
||||
this.registrationComplete.then(() => {
|
||||
this._setCheckedElements(value, checkCondition);
|
||||
this.requestUpdate('serializedValue');
|
||||
});
|
||||
} else {
|
||||
this._setCheckedElements(value, checkCondition);
|
||||
this.requestUpdate('serializedValue');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,6 @@ import { FormatMixin } from '../FormatMixin.js';
|
|||
/**
|
||||
* @typedef {import('../../types/FormControlMixinTypes').FormControlHost} FormControlHost
|
||||
* @typedef {FormControlHost & HTMLElement & {__parentFormGroup?:HTMLElement, checked?:boolean}} FormControl
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {import('../../types/choice-group/ChoiceInputMixinTypes').ChoiceInputMixin} ChoiceInputMixin
|
||||
* @typedef {import('../../types/choice-group/ChoiceInputMixinTypes').ChoiceInputModelValue} ChoiceInputModelValue
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ function arrayDiff(array1 = [], array2 = []) {
|
|||
* @param {import('@open-wc/dedupe-mixin').Constructor<import('@lion/core').LitElement>} superclass
|
||||
*/
|
||||
export const ValidateMixinImplementation = superclass =>
|
||||
// eslint-disable-next-line no-unused-vars, no-shadow
|
||||
class extends FormControlMixin(
|
||||
SyncUpdatableMixin(DisabledMixin(SlotMixin(ScopedElementsMixin(superclass)))),
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -10,15 +10,6 @@ import { ChoiceInputMixin } from '../../src/choice-group/ChoiceInputMixin.js';
|
|||
* @typedef {import('../../types/choice-group/ChoiceInputMixinTypes').ChoiceInputHost} ChoiceInputHost
|
||||
*/
|
||||
|
||||
// class InputField extends LionField {
|
||||
// get slots() {
|
||||
// return {
|
||||
// ...super.slots,
|
||||
// input: () => document.createElement('input'),
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
describe('ChoiceInputMixin', () => {
|
||||
/** @typedef {Element & ChoiceClass} ChoiceInput */
|
||||
class ChoiceClass extends ChoiceInputMixin(LionInput) {
|
||||
|
|
|
|||
|
|
@ -8,14 +8,45 @@ import { FormRegisteringHost } from './registration/FormRegisteringMixinTypes';
|
|||
|
||||
export class FormControlHost {
|
||||
static get styles(): CSSResult | CSSResult[];
|
||||
|
||||
/**
|
||||
* A Boolean attribute which, if present, indicates that the user should not be able to edit
|
||||
* the value of the input. The difference between disabled and readonly is that read-only
|
||||
* controls can still function, whereas disabled controls generally do not function as
|
||||
* controls until they are enabled.
|
||||
* (From: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-readonly)
|
||||
*/
|
||||
readOnly: boolean;
|
||||
/**
|
||||
* The name the element will be registered on to the .formElements collection
|
||||
* of the parent.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* The model value is the result of the parser function(when available).
|
||||
* It should be considered as the internal value used for validation and reasoning/logic.
|
||||
* The model value is 'ready for consumption' by the outside world (think of a Date
|
||||
* object or a float). The modelValue can(and is recommended to) be used as both input
|
||||
* value and output value of the `LionField`.
|
||||
*
|
||||
* Examples:
|
||||
* - For a date input: a String '20/01/1999' will be converted to new Date('1999/01/20')
|
||||
* - For a number input: a formatted String '1.234,56' will be converted to a Number:
|
||||
* 1234.56
|
||||
*/
|
||||
modelValue: unknown;
|
||||
set label(arg: string);
|
||||
/**
|
||||
* The label text for the input node.
|
||||
* When no light dom defined via [slot=label], this value will be used
|
||||
*/
|
||||
get label(): string;
|
||||
set label(arg: string);
|
||||
__label: string | undefined;
|
||||
set helpText(arg: string);
|
||||
/**
|
||||
* The helpt text for the input node.
|
||||
* When no light dom defined via [slot=help-text], this value will be used
|
||||
*/
|
||||
get helpText(): string;
|
||||
set helpText(arg: string);
|
||||
__helpText: string | undefined;
|
||||
set fieldName(arg: string);
|
||||
get fieldName(): string;
|
||||
|
|
@ -28,7 +59,20 @@ export class FormControlHost {
|
|||
_inputId: string;
|
||||
_ariaLabelledNodes: HTMLElement[];
|
||||
_ariaDescribedNodes: HTMLElement[];
|
||||
_repropagationRole: string; // 'child' | 'choice-group' | 'fieldset';
|
||||
/**
|
||||
* Based on the role, details of handling model-value-changed repropagation differ.
|
||||
*/
|
||||
_repropagationRole: 'child' | 'choice-group' | 'fieldset';
|
||||
/**
|
||||
* By default, a field with _repropagationRole 'choice-group' will act as an
|
||||
* 'endpoint'. This means it will be considered as an individual field: for
|
||||
* a select, individual options will not be part of the formPath. They
|
||||
* will.
|
||||
* Similarly, components that (a11y wise) need to be fieldsets, but 'interaction wise'
|
||||
* (from Application Developer perspective) need to be more like fields
|
||||
* (think of an amount-input with a currency select box next to it), can set this
|
||||
* to true to hide private internals in the formPath.
|
||||
*/
|
||||
_isRepropagationEndpoint: boolean;
|
||||
|
||||
connectedCallback(): void;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,15 @@ export interface ChoiceInputModelValue {
|
|||
value: any;
|
||||
}
|
||||
|
||||
/** TODO: legacy code: serialization should happen on choice-group level */
|
||||
export interface ChoiceInputSerializedValue {
|
||||
checked: boolean;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export declare class ChoiceInputHost {
|
||||
modelValue: ChoiceInputModelValue;
|
||||
serializedValue: ChoiceInputSerializedValue;
|
||||
|
||||
get choiceValue(): any;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Constructor } from '@open-wc/dedupe-mixin';
|
|||
import { LitElement } from '@lion/core';
|
||||
|
||||
export declare class FormRegistrarPortalHost {
|
||||
registrationTarget: HTMLElement;
|
||||
__redispatchEventForFormRegistrarPortalMixin(ev: CustomEvent): void;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue