fix: removed FieldCustomMixin

This commit is contained in:
Thijs Louisse 2020-02-20 11:35:41 +01:00
parent d81764e9fd
commit f44d8aa26a
8 changed files with 59 additions and 127 deletions

View file

@ -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 [`<lion-input-date>`](../../input-date/) and
[`<lion-input-amount>`](../../input-amount/).
## Flow diagram ## Flow diagram
The following flow diagram is based on both end user input and interaction programmed by the The following flow diagram is based on both end user input and interaction programmed by the

View file

@ -1,6 +1,5 @@
export { FocusMixin } from './src/FocusMixin.js'; export { FocusMixin } from './src/FocusMixin.js';
export { FormatMixin } from './src/FormatMixin.js'; export { FormatMixin } from './src/FormatMixin.js';
export { FieldCustomMixin } from './src/FieldCustomMixin.js';
export { FormControlMixin } from './src/FormControlMixin.js'; export { FormControlMixin } from './src/FormControlMixin.js';
export { InteractionStateMixin } from './src/InteractionStateMixin.js'; // applies FocusMixin export { InteractionStateMixin } from './src/InteractionStateMixin.js'; // applies FocusMixin
export { LionField } from './src/LionField.js'; export { LionField } from './src/LionField.js';

View file

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

View file

@ -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 = '<input slot="input" />';
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}</${elem}>
`);
expect(Array.from(lionField.children).find(child => child.slot === 'help-text')).to.equal(
undefined,
);
});
});

View file

@ -1,7 +1,6 @@
import { css } from '@lion/core'; import { css } from '@lion/core';
import { LocalizeMixin, getCurrencyName } from '@lion/localize'; import { LocalizeMixin, getCurrencyName } from '@lion/localize';
import { LionInput } from '@lion/input'; import { LionInput } from '@lion/input';
import { FieldCustomMixin } from '@lion/field';
import { IsNumber } from '@lion/validate'; import { IsNumber } from '@lion/validate';
import { parseAmount } from './parsers.js'; import { parseAmount } from './parsers.js';
import { formatAmount } from './formatters.js'; import { formatAmount } from './formatters.js';
@ -12,22 +11,26 @@ import { formatAmount } from './formatters.js';
* @customElement lion-input-amount * @customElement lion-input-amount
* @extends {LionInput} * @extends {LionInput}
*/ */
export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput)) { export class LionInputAmount extends LocalizeMixin(LionInput) {
static get properties() { static get properties() {
return { 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() { get slots() {
return { return {
...super.slots, ...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() { constructor() {
super(); super();
this.parser = parseAmount; this.parser = parseAmount;
@ -59,18 +77,6 @@ export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput))
this.defaultValidators.push(new IsNumber()); 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() { connectedCallback() {
// eslint-disable-next-line wc/guard-super-call // eslint-disable-next-line wc/guard-super-call
super.connectedCallback(); super.connectedCallback();
@ -81,12 +87,29 @@ export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput))
} }
} }
__setCurrencyDisplayLabel() { updated(changedProps) {
this._currencyDisplayNode.setAttribute('aria-label', getCurrencyName(this.currency)); 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 }) { _onCurrencyChanged({ currency }) {
@ -98,14 +121,10 @@ export class LionInputAmount extends FieldCustomMixin(LocalizeMixin(LionInput))
this.__setCurrencyDisplayLabel(); this.__setCurrencyDisplayLabel();
} }
static get styles() { __setCurrencyDisplayLabel() {
return [ // TODO: for optimal a11y, abbreviations should be part of aria-label
...super.styles, // example, for a language switch with text 'en', an aria-label of 'english' is not
css` // sufficient, it should also contain the abbreviation.
.input-group__container > .input-group__input ::slotted(.form-control) { this._currencyDisplayNode.setAttribute('aria-label', getCurrencyName(this.currency));
text-align: right;
}
`,
];
} }
} }

View file

@ -1,5 +1,4 @@
import { LocalizeMixin } from '@lion/localize'; import { LocalizeMixin } from '@lion/localize';
import { FieldCustomMixin } from '@lion/field';
import { LionInput } from '@lion/input'; import { LionInput } from '@lion/input';
import { IsEmail } from '@lion/validate'; import { IsEmail } from '@lion/validate';
@ -9,7 +8,7 @@ import { IsEmail } from '@lion/validate';
* @customElement lion-input-email * @customElement lion-input-email
* @extends {LionInput} * @extends {LionInput}
*/ */
export class LionInputEmail extends FieldCustomMixin(LocalizeMixin(LionInput)) { export class LionInputEmail extends LocalizeMixin(LionInput) {
constructor() { constructor() {
super(); super();
// local-part@domain where the local part may be up to 64 characters long // local-part@domain where the local part may be up to 64 characters long

View file

@ -1,6 +1,5 @@
import { LocalizeMixin } from '@lion/localize'; import { LocalizeMixin } from '@lion/localize';
import { LionInput } from '@lion/input'; import { LionInput } from '@lion/input';
import { FieldCustomMixin } from '@lion/field';
import { formatIBAN } from './formatters.js'; import { formatIBAN } from './formatters.js';
import { parseIBAN } from './parsers.js'; import { parseIBAN } from './parsers.js';
import { IsIBAN } from './validators.js'; import { IsIBAN } from './validators.js';
@ -10,7 +9,7 @@ import { IsIBAN } from './validators.js';
* *
* @extends {LionInput} * @extends {LionInput}
*/ */
export class LionInputIban extends FieldCustomMixin(LocalizeMixin(LionInput)) { export class LionInputIban extends LocalizeMixin(LionInput) {
constructor() { constructor() {
super(); super();
this.formatter = formatIBAN; this.formatter = formatIBAN;

View file

@ -1,6 +1,5 @@
/* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable import/no-extraneous-dependencies */
import { LocalizeMixin, formatNumber } from '@lion/localize'; import { LocalizeMixin, formatNumber } from '@lion/localize';
import { FieldCustomMixin } from '@lion/field';
import { LionInput } from '@lion/input'; import { LionInput } from '@lion/input';
import { html, css, unsafeCSS } from '@lion/core'; import { html, css, unsafeCSS } from '@lion/core';
@ -10,7 +9,7 @@ import { html, css, unsafeCSS } from '@lion/core';
* @customElement `lion-input-range` * @customElement `lion-input-range`
* @extends LionInput * @extends LionInput
*/ */
export class LionInputRange extends FieldCustomMixin(LocalizeMixin(LionInput)) { export class LionInputRange extends LocalizeMixin(LionInput) {
static get properties() { static get properties() {
return { return {
min: Number, min: Number,