diff --git a/packages/field/docs/FormattingAndParsing.md b/packages/field/docs/FormattingAndParsing.md index 87faf49d7..982b8f742 100644 --- a/packages/field/docs/FormattingAndParsing.md +++ b/packages/field/docs/FormattingAndParsing.md @@ -101,12 +101,6 @@ function deserializeDate(serializeValue, options) { } ``` -### FieldCustomMixin - -When creating your own custom input, please use `FieldCustomMixin` as a basis for this. -Concrete examples can be found at [``](../../input-date/) and -[``](../../input-amount/). - ## Flow diagram The following flow diagram is based on both end user input and interaction programmed by the diff --git a/packages/field/index.js b/packages/field/index.js index 6c1d2d28d..090071db2 100644 --- a/packages/field/index.js +++ b/packages/field/index.js @@ -1,6 +1,5 @@ export { FocusMixin } from './src/FocusMixin.js'; export { FormatMixin } from './src/FormatMixin.js'; -export { FieldCustomMixin } from './src/FieldCustomMixin.js'; export { FormControlMixin } from './src/FormControlMixin.js'; export { InteractionStateMixin } from './src/InteractionStateMixin.js'; // applies FocusMixin export { LionField } from './src/LionField.js'; diff --git a/packages/field/src/FieldCustomMixin.js b/packages/field/src/FieldCustomMixin.js deleted file mode 100644 index 46777495c..000000000 --- a/packages/field/src/FieldCustomMixin.js +++ /dev/null @@ -1,46 +0,0 @@ -import { dedupeMixin, nothing } from '@lion/core'; - -/** - * #FieldCustomMixin - * - * @polymerMixin - * @mixinFunction - */ - -export const FieldCustomMixin = dedupeMixin( - superclass => - // eslint-disable-next-line no-shadow, max-len - class FieldCustomMixin extends superclass { - static get properties() { - return { - /** - * When no light dom defined and prop set - */ - disableHelpText: { - type: Boolean, - attribute: 'disable-help-text', - }, - }; - } - - get slots() { - return { - ...super.slots, - 'help-text': () => { - if (!this.disableHelpText) { - return super.slots['help-text'](); - } - return null; - }, - }; - } - - helpTextTemplate(...args) { - if (this.disableHelpText || !super.helpTextTemplate) { - return nothing; - } - - return super.helpTextTemplate.apply(this, args); - } - }, -); diff --git a/packages/field/test/FieldCustomMixin.test.js b/packages/field/test/FieldCustomMixin.test.js deleted file mode 100644 index a4b20e5a8..000000000 --- a/packages/field/test/FieldCustomMixin.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import { expect, fixture, defineCE } from '@open-wc/testing'; -import { LionField } from '../src/LionField.js'; - -import { FieldCustomMixin } from '../src/FieldCustomMixin.js'; - -describe('FieldCustomMixin', () => { - const inputSlot = ''; - let elem; - - before(async () => { - const FieldCustomMixinClass = class extends FieldCustomMixin(LionField) { - static get properties() { - return { - modelValue: { - type: String, - }, - }; - } - }; - elem = defineCE(FieldCustomMixinClass); - }); - - it('has the capability to disable help text', async () => { - const lionField = await fixture(` - <${elem} disable-help-text>${inputSlot} - `); - expect(Array.from(lionField.children).find(child => child.slot === 'help-text')).to.equal( - undefined, - ); - }); -}); diff --git a/packages/input-amount/src/LionInputAmount.js b/packages/input-amount/src/LionInputAmount.js index a6a856478..7f9ebcbdc 100644 --- a/packages/input-amount/src/LionInputAmount.js +++ b/packages/input-amount/src/LionInputAmount.js @@ -1,7 +1,6 @@ import { css } from '@lion/core'; import { LocalizeMixin, getCurrencyName } from '@lion/localize'; import { LionInput } from '@lion/input'; -import { FieldCustomMixin } from '@lion/field'; import { IsNumber } from '@lion/validate'; import { parseAmount } from './parsers.js'; import { formatAmount } from './formatters.js'; @@ -12,22 +11,26 @@ import { formatAmount } from './formatters.js'; * @customElement lion-input-amount * @extends {LionInput} */ -export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput)) { +export class LionInputAmount extends LocalizeMixin(LionInput) { static get properties() { return { - currency: { - type: String, - }, + /** + * @desc an iso code like 'EUR' or 'USD' that will be displayed next to the input + * and from which an accessible label (like 'euros') is computed for screen + * reader users + * @type {string} + */ + currency: String, + /** + * @desc the modelValue of the input-amount has the 'Number' type. This allows + * Application Developers to easily read from and write to this input or write custom + * validators. + * @type {number} + */ + modelValue: Number, }; } - updated(changedProps) { - super.updated(changedProps); - if (changedProps.has('currency')) { - this._onCurrencyChanged({ currency: this.currency }); - } - } - get slots() { return { ...super.slots, @@ -45,6 +48,21 @@ export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput)) }; } + get _currencyDisplayNode() { + return Array.from(this.children).find(child => child.slot === 'after'); + } + + static get styles() { + return [ + ...super.styles, + css` + .input-group__container > .input-group__input ::slotted(.form-control) { + text-align: right; + } + `, + ]; + } + constructor() { super(); this.parser = parseAmount; @@ -59,18 +77,6 @@ export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput)) this.defaultValidators.push(new IsNumber()); } - __callParser(value = this.formattedValue) { - // TODO: input and change events both trigger parsing therefore we need to handle the second parse - this.__parserCallcountSincePaste += 1; - this.__isPasting = this.__parserCallcountSincePaste === 2; - this.formatOptions.mode = this.__isPasting === true ? 'pasted' : 'auto'; - return super.__callParser(value); - } - - _reflectBackOn() { - return super._reflectBackOn() || this.__isPasting; - } - connectedCallback() { // eslint-disable-next-line wc/guard-super-call super.connectedCallback(); @@ -81,12 +87,29 @@ export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput)) } } - __setCurrencyDisplayLabel() { - this._currencyDisplayNode.setAttribute('aria-label', getCurrencyName(this.currency)); + updated(changedProps) { + super.updated(changedProps); + if (changedProps.has('currency')) { + this._onCurrencyChanged({ currency: this.currency }); + } } - get _currencyDisplayNode() { - return Array.from(this.children).find(child => child.slot === 'after'); + /** + * @override of FormatMixin + */ + __callParser(value = this.formattedValue) { + // TODO: input and change events both trigger parsing therefore we need to handle the second parse + this.__parserCallcountSincePaste += 1; + this.__isPasting = this.__parserCallcountSincePaste === 2; + this.formatOptions.mode = this.__isPasting === true ? 'pasted' : 'auto'; + return super.__callParser(value); + } + + /** + * @override of FormatMixin + */ + _reflectBackOn() { + return super._reflectBackOn() || this.__isPasting; } _onCurrencyChanged({ currency }) { @@ -98,14 +121,10 @@ export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput)) this.__setCurrencyDisplayLabel(); } - static get styles() { - return [ - ...super.styles, - css` - .input-group__container > .input-group__input ::slotted(.form-control) { - text-align: right; - } - `, - ]; + __setCurrencyDisplayLabel() { + // TODO: for optimal a11y, abbreviations should be part of aria-label + // example, for a language switch with text 'en', an aria-label of 'english' is not + // sufficient, it should also contain the abbreviation. + this._currencyDisplayNode.setAttribute('aria-label', getCurrencyName(this.currency)); } } diff --git a/packages/input-email/src/LionInputEmail.js b/packages/input-email/src/LionInputEmail.js index c7198eb0c..4fc769a4f 100644 --- a/packages/input-email/src/LionInputEmail.js +++ b/packages/input-email/src/LionInputEmail.js @@ -1,5 +1,4 @@ import { LocalizeMixin } from '@lion/localize'; -import { FieldCustomMixin } from '@lion/field'; import { LionInput } from '@lion/input'; import { IsEmail } from '@lion/validate'; @@ -9,7 +8,7 @@ import { IsEmail } from '@lion/validate'; * @customElement lion-input-email * @extends {LionInput} */ -export class LionInputEmail extends FieldCustomMixin(LocalizeMixin(LionInput)) { +export class LionInputEmail extends LocalizeMixin(LionInput) { constructor() { super(); // local-part@domain where the local part may be up to 64 characters long diff --git a/packages/input-iban/src/LionInputIban.js b/packages/input-iban/src/LionInputIban.js index f9de96c6d..399ef1842 100644 --- a/packages/input-iban/src/LionInputIban.js +++ b/packages/input-iban/src/LionInputIban.js @@ -1,6 +1,5 @@ import { LocalizeMixin } from '@lion/localize'; import { LionInput } from '@lion/input'; -import { FieldCustomMixin } from '@lion/field'; import { formatIBAN } from './formatters.js'; import { parseIBAN } from './parsers.js'; import { IsIBAN } from './validators.js'; @@ -10,7 +9,7 @@ import { IsIBAN } from './validators.js'; * * @extends {LionInput} */ -export class LionInputIban extends FieldCustomMixin(LocalizeMixin(LionInput)) { +export class LionInputIban extends LocalizeMixin(LionInput) { constructor() { super(); this.formatter = formatIBAN; diff --git a/packages/input-range/src/LionInputRange.js b/packages/input-range/src/LionInputRange.js index b05ae558a..e3c3bb158 100644 --- a/packages/input-range/src/LionInputRange.js +++ b/packages/input-range/src/LionInputRange.js @@ -1,6 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ import { LocalizeMixin, formatNumber } from '@lion/localize'; -import { FieldCustomMixin } from '@lion/field'; import { LionInput } from '@lion/input'; import { html, css, unsafeCSS } from '@lion/core'; @@ -10,7 +9,7 @@ import { html, css, unsafeCSS } from '@lion/core'; * @customElement `lion-input-range` * @extends LionInput */ -export class LionInputRange extends FieldCustomMixin(LocalizeMixin(LionInput)) { +export class LionInputRange extends LocalizeMixin(LionInput) { static get properties() { return { min: Number,