fix(form-core): type enhancements

This commit is contained in:
Thijs Louisse 2020-09-07 12:36:05 +02:00 committed by Thomas Allmer
parent 0ec72ac330
commit b83ef4eeeb
10 changed files with 84 additions and 40 deletions

View file

@ -1,7 +0,0 @@
---
'@lion/button': patch
'@lion/overlays': patch
'@lion/tooltip': patch
---
Types for overlays, tooltip, button

View file

@ -1,9 +0,0 @@
---
'@lion/core': minor
---
EventTargetShim
#### Features
EventTargetShim is a base class that works like EventTarget, on all browsers.

View file

@ -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,

View file

@ -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');
}
}

View file

@ -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
*/

View file

@ -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)))),
) {

View file

@ -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) {

View file

@ -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;

View file

@ -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;

View file

@ -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;
}