Merge remote-tracking branch 'upstream/master' into fix_issue_569

This commit is contained in:
Aymen Ben Amor 2020-03-19 16:38:34 +01:00
commit 5fbc5c506e
73 changed files with 1150 additions and 199 deletions

View file

@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.8.5](https://github.com/ing-bank/lion/compare/@lion/checkbox-group@0.8.4...@lion/checkbox-group@0.8.5) (2020-03-19)
**Note:** Version bump only for package @lion/checkbox-group
## [0.8.4](https://github.com/ing-bank/lion/compare/@lion/checkbox-group@0.8.3...@lion/checkbox-group@0.8.4) (2020-03-12)
**Note:** Version bump only for package @lion/checkbox-group
## [0.8.3](https://github.com/ing-bank/lion/compare/@lion/checkbox-group@0.8.2...@lion/checkbox-group@0.8.3) (2020-03-05) ## [0.8.3](https://github.com/ing-bank/lion/compare/@lion/checkbox-group@0.8.2...@lion/checkbox-group@0.8.3) (2020-03-05)
**Note:** Version bump only for package @lion/checkbox-group **Note:** Version bump only for package @lion/checkbox-group

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/checkbox-group", "name": "@lion/checkbox-group",
"version": "0.8.3", "version": "0.8.5",
"description": "A container for multiple checkboxes", "description": "A container for multiple checkboxes",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -34,10 +34,10 @@
"*.js" "*.js"
], ],
"dependencies": { "dependencies": {
"@lion/choice-input": "0.7.5", "@lion/choice-input": "0.7.7",
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/fieldset": "0.9.3", "@lion/fieldset": "0.9.4",
"@lion/input": "0.5.18" "@lion/input": "0.5.19"
}, },
"devDependencies": { "devDependencies": {
"@lion/localize": "0.8.10", "@lion/localize": "0.8.10",

View file

@ -3,6 +3,28 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.7.7](https://github.com/ing-bank/lion/compare/@lion/choice-input@0.7.6...@lion/choice-input@0.7.7) (2020-03-19)
### Bug Fixes
* normalization model-value-changed events ([1b6c3a4](https://github.com/ing-bank/lion/commit/1b6c3a44c820b9d61c26849b91bbb1bc8d6c772b))
## [0.7.6](https://github.com/ing-bank/lion/compare/@lion/choice-input@0.7.5...@lion/choice-input@0.7.6) (2020-03-12)
### Bug Fixes
* **choice-input:** fix serializedValue setter check ([0445b86](https://github.com/ing-bank/lion/commit/0445b86350f65649c03ed84bfaf9652838c43e55))
## [0.7.5](https://github.com/ing-bank/lion/compare/@lion/choice-input@0.7.4...@lion/choice-input@0.7.5) (2020-03-05) ## [0.7.5](https://github.com/ing-bank/lion/compare/@lion/choice-input@0.7.4...@lion/choice-input@0.7.5) (2020-03-05)
**Note:** Version bump only for package @lion/choice-input **Note:** Version bump only for package @lion/choice-input

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/choice-input", "name": "@lion/choice-input",
"version": "0.7.5", "version": "0.7.7",
"description": "Base for all choise inputs like checkbox/radio", "description": "Base for all choise inputs like checkbox/radio",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,11 +35,11 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3" "@lion/field": "0.11.4"
}, },
"devDependencies": { "devDependencies": {
"@lion/fieldset": "0.9.3", "@lion/fieldset": "0.9.4",
"@lion/input": "0.5.18", "@lion/input": "0.5.19",
"@lion/validate": "0.8.0", "@lion/validate": "0.8.0",
"@open-wc/demoing-storybook": "^1.10.4", "@open-wc/demoing-storybook": "^1.10.4",
"@open-wc/testing": "^2.5.0", "@open-wc/testing": "^2.5.0",

View file

@ -55,20 +55,7 @@ export const ChoiceGroupMixin = dedupeMixin(
constructor() { constructor() {
super(); super();
this.multipleChoice = false; this.multipleChoice = false;
} this._repropagationRole = 'choice-group'; // configures event propagation logic of FormControlMixin
connectedCallback() {
super.connectedCallback();
if (!this.multipleChoice) {
this.addEventListener('model-value-changed', this._checkSingleChoiceElements);
}
}
disconnectedCallback() {
super.disconnectedCallback();
if (!this.multipleChoice) {
this.removeEventListener('model-value-changed', this._checkSingleChoiceElements);
}
} }
/** /**
@ -157,9 +144,10 @@ export const ChoiceGroupMixin = dedupeMixin(
} }
} }
__triggerCheckedValueChanged() { __setChoiceGroupTouched() {
const value = this.modelValue; const value = this.modelValue;
if (value != null && value !== this.__previousCheckedValue) { if (value != null && value !== this.__previousCheckedValue) {
// TODO: what happens here exactly? Needs to be based on user interaction (?)
this.touched = true; this.touched = true;
this.__previousCheckedValue = value; this.__previousCheckedValue = value;
} }
@ -179,5 +167,24 @@ export const ChoiceGroupMixin = dedupeMixin(
); );
} }
} }
/**
* @override FormControlMixin
*/
_onBeforeRepropagateChildrenValues(ev) {
// Normalize target, since we might receive 'portal events' (from children in a modal,
// see select-rich)
const target = (ev.detail && ev.detail.element) || ev.target;
if (this.multipleChoice || !target.checked) {
return;
}
this.formElements.forEach(option => {
if (target.choiceValue !== option.choiceValue) {
option.checked = false; // eslint-disable-line no-param-reassign
}
});
this.__setChoiceGroupTouched();
this.requestUpdate('modelValue');
}
}, },
); );

View file

@ -3,7 +3,8 @@ import { FormGroupMixin } from '@lion/fieldset';
import '@lion/fieldset/lion-fieldset.js'; import '@lion/fieldset/lion-fieldset.js';
import { LionInput } from '@lion/input'; import { LionInput } from '@lion/input';
import { Required } from '@lion/validate'; import { Required } from '@lion/validate';
import { expect, fixture, nextFrame } from '@open-wc/testing'; import { expect, nextFrame } from '@open-wc/testing';
import { formFixture as fixture } from '@lion/field/test-helpers.js';
import { ChoiceGroupMixin } from '../src/ChoiceGroupMixin.js'; import { ChoiceGroupMixin } from '../src/ChoiceGroupMixin.js';
import { ChoiceInputMixin } from '../src/ChoiceInputMixin.js'; import { ChoiceInputMixin } from '../src/ChoiceInputMixin.js';
@ -194,21 +195,21 @@ describe('ChoiceGroupMixin', () => {
counter = 0; // reset after setup which may result in different results counter = 0; // reset after setup which may result in different results
el.formElements[0].checked = true; el.formElements[0].checked = true;
expect(counter).to.equal(2); // male becomes checked, female becomes unchecked expect(counter).to.equal(1); // male becomes checked, female becomes unchecked
// not changed values trigger no event // not changed values trigger no event
el.formElements[0].checked = true; el.formElements[0].checked = true;
expect(counter).to.equal(2); expect(counter).to.equal(1);
el.formElements[2].checked = true; el.formElements[2].checked = true;
expect(counter).to.equal(4); // other becomes checked, male becomes unchecked expect(counter).to.equal(2); // other becomes checked, male becomes unchecked
// not found values trigger no event // not found values trigger no event
el.modelValue = 'foo'; el.modelValue = 'foo';
expect(counter).to.equal(4); expect(counter).to.equal(2);
el.modelValue = 'male'; el.modelValue = 'male';
expect(counter).to.equal(6); // male becomes checked, other becomes unchecked expect(counter).to.equal(3); // male becomes checked, other becomes unchecked
}); });
it('can be required', async () => { it('can be required', async () => {

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.4.10](https://github.com/ing-bank/lion/compare/@lion/dialog@0.4.9...@lion/dialog@0.4.10) (2020-03-19)
**Note:** Version bump only for package @lion/dialog
## [0.4.9](https://github.com/ing-bank/lion/compare/@lion/dialog@0.4.8...@lion/dialog@0.4.9) (2020-03-11) ## [0.4.9](https://github.com/ing-bank/lion/compare/@lion/dialog@0.4.8...@lion/dialog@0.4.9) (2020-03-11)
**Note:** Version bump only for package @lion/dialog **Note:** Version bump only for package @lion/dialog

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/dialog", "name": "@lion/dialog",
"version": "0.4.9", "version": "0.4.10",
"description": "Show relative overlay content on click, as a webcomponent", "description": "Show relative overlay content on click, as a webcomponent",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -33,7 +33,7 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/overlays": "0.12.4" "@lion/overlays": "0.12.5"
}, },
"devDependencies": { "devDependencies": {
"@open-wc/demoing-storybook": "^1.10.4", "@open-wc/demoing-storybook": "^1.10.4",

View file

@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.11.4](https://github.com/ing-bank/lion/compare/@lion/field@0.11.3...@lion/field@0.11.4) (2020-03-19)
### Bug Fixes
* normalization model-value-changed events ([1b6c3a4](https://github.com/ing-bank/lion/commit/1b6c3a44c820b9d61c26849b91bbb1bc8d6c772b))
## [0.11.3](https://github.com/ing-bank/lion/compare/@lion/field@0.11.2...@lion/field@0.11.3) (2020-03-05) ## [0.11.3](https://github.com/ing-bank/lion/compare/@lion/field@0.11.2...@lion/field@0.11.3) (2020-03-05)
**Note:** Version bump only for package @lion/field **Note:** Version bump only for package @lion/field

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/field", "name": "@lion/field",
"version": "0.11.3", "version": "0.11.4",
"description": "Fields are the most fundamental building block of the Form System", "description": "Fields are the most fundamental building block of the Form System",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -31,6 +31,7 @@
"stories", "stories",
"test", "test",
"test-suites", "test-suites",
"test-helpers",
"translations", "translations",
"*.js" "*.js"
], ],

View file

@ -55,6 +55,22 @@ export const FormControlMixin = dedupeMixin(
* Contains all elements that should end up in aria-describedby of `._inputNode` * Contains all elements that should end up in aria-describedby of `._inputNode`
*/ */
_ariaDescribedNodes: Array, _ariaDescribedNodes: Array,
/**
* Based on the role, details of handling model-value-changed repropagation differ.
* @type {'child'|'fieldset'|'choice-group'}
*/
_repropagationRole: String,
/**
* 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,
}; };
} }
@ -151,6 +167,8 @@ export const FormControlMixin = dedupeMixin(
this._inputId = uuid(this.localName); this._inputId = uuid(this.localName);
this._ariaLabelledNodes = []; this._ariaLabelledNodes = [];
this._ariaDescribedNodes = []; this._ariaDescribedNodes = [];
this._repropagationRole = 'child';
this.addEventListener('model-value-changed', this.__repropagateChildrenValues);
} }
connectedCallback() { connectedCallback() {
@ -553,5 +571,95 @@ export const FormControlMixin = dedupeMixin(
__getDirectSlotChild(slotName) { __getDirectSlotChild(slotName) {
return [...this.children].find(el => el.slot === slotName); return [...this.children].find(el => el.slot === slotName);
} }
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties);
this.__dispatchInitialModelValueChangedEvent();
}
async __dispatchInitialModelValueChangedEvent() {
// When we are not a fieldset / choice-group, we don't need to wait for our children
// to send a unified event
if (this._repropagationRole === 'child') {
return;
}
await this.registrationComplete;
// Initially we don't repropagate model-value-changed events coming
// from children. On firstUpdated we re-dispatch this event to maintain
// 'count consistency' (to not confuse the application developer with a
// large number of initial events). Initially the source field will not
// be part of the formPath but afterwards it will.
this.__repropagateChildrenInitialized = true;
this.dispatchEvent(
new CustomEvent('model-value-changed', {
bubbles: true,
detail: { formPath: [this], initialize: true },
}),
);
}
// eslint-disable-next-line class-methods-use-this, no-unused-vars
_onBeforeRepropagateChildrenValues(ev) {}
__repropagateChildrenValues(ev) {
// Allows sub classes to internally listen to the children change events
// (before stopImmediatePropagation is called below).
this._onBeforeRepropagateChildrenValues(ev);
// Normalize target, we also might get it from 'portals' (rich select)
const target = (ev.detail && ev.detail.element) || ev.target;
const isEndpoint =
this._isRepropagationEndpoint || this._repropagationRole === 'choice-group';
// Prevent eternal loops after we sent the event below.
if (target === this) {
return;
}
// A. Stop sibling handlers
//
// Make sure our sibling event listeners (added by Application developers) will not get
// the child model-value-changed event, but the repropagated one at the bottom of this
// method
ev.stopImmediatePropagation();
// B1. Are we still initializing? If so, halt...
//
// Stop repropagating children events before firstUpdated and make sure we de not
// repropagate init events of our children (we already sent our own
// initial model-value-change event in firstUpdated)
const isGroup = this._repropagationRole !== 'child'; // => fieldset or choice-group
const isSelfInitializing = isGroup && !this.__repropagateChildrenInitialized;
const isChildGroupInitializing = ev.detail && ev.detail.initialize;
if (isSelfInitializing || isChildGroupInitializing) {
return;
}
// B2. Are we a single choice choice-group? If so, halt when unchecked
//
// We only send the checked changed up (not the unchecked). In this way a choice group
// (radio-group, checkbox-group, select/listbox) acts as an 'endpoint' (a single Field)
// just like the native <select>
if (this._repropagationRole === 'choice-group' && !this.multipleChoice && !target.checked) {
return;
}
// C1. We are ready to dispatch. Create a formPath
//
// Compute the formPath. Choice groups are regarded 'end points'
let parentFormPath = [];
if (!isEndpoint) {
parentFormPath = (ev.detail && ev.detail.formPath) || [target];
}
const formPath = [...parentFormPath, this];
// C2. Finally, redispatch a fresh model-value-changed event from our host, consumable
// for an Application Developer
//
// Since for a11y everything needs to be in lightdom, we don't add 'composed:true'
this.dispatchEvent(
new CustomEvent('model-value-changed', { bubbles: true, detail: { formPath } }),
);
}
}, },
); );

View file

@ -289,7 +289,10 @@ export const FormatMixin = dedupeMixin(
_dispatchModelValueChangedEvent() { _dispatchModelValueChangedEvent() {
/** @event model-value-changed */ /** @event model-value-changed */
this.dispatchEvent( this.dispatchEvent(
new CustomEvent('model-value-changed', { bubbles: true, composed: true }), new CustomEvent('model-value-changed', {
bubbles: true,
detail: { formPath: [this] },
}),
); );
} }

View file

@ -46,6 +46,9 @@ export const FormRegistrarMixin = dedupeMixin(
this.registrationReady = new Promise(resolve => { this.registrationReady = new Promise(resolve => {
this.__resolveRegistrationReady = resolve; this.__resolveRegistrationReady = resolve;
}); });
this.registrationComplete = new Promise(resolve => {
this.__resolveRegistrationComplete = resolve;
});
this._onRequestToAddFormElement = this._onRequestToAddFormElement.bind(this); this._onRequestToAddFormElement = this._onRequestToAddFormElement.bind(this);
this.addEventListener('form-element-register', this._onRequestToAddFormElement); this.addEventListener('form-element-register', this._onRequestToAddFormElement);
@ -76,6 +79,16 @@ export const FormRegistrarMixin = dedupeMixin(
super.firstUpdated(changedProperties); super.firstUpdated(changedProperties);
this.__resolveRegistrationReady(); this.__resolveRegistrationReady();
this.__readyForRegistration = true; this.__readyForRegistration = true;
// After we allow our children to register, we need to wait one tick before they
// all sent their 'form-element-register' event.
// TODO: allow developer to delay this moment, similar to LitElement.performUpdate can be
// delayed.
setTimeout(() => {
this.registrationHasCompleted = true;
this.__resolveRegistrationComplete();
});
formRegistrarManager.becomesReady(); formRegistrarManager.becomesReady();
this.__hasBeenRendered = true; this.__hasBeenRendered = true;
} }

View file

@ -0,0 +1 @@
export { formFixture } from './test-helpers/formFixture.js';

View file

@ -0,0 +1,11 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { fixture, aTimeout } from '@open-wc/testing';
export async function formFixture(...args) {
const el = await fixture(...args);
if (el.registrationComplete) {
await el.registrationComplete;
await aTimeout();
}
return el;
}

View file

@ -1,7 +1,9 @@
import { expect, fixture, html, defineCE, unsafeStatic } from '@open-wc/testing'; import { expect, html, defineCE, unsafeStatic } from '@open-wc/testing';
import { LitElement, SlotMixin } from '@lion/core'; import { LitElement, SlotMixin } from '@lion/core';
import sinon from 'sinon';
import { formFixture as fixture } from '../test-helpers/formFixture.js';
import { FormControlMixin } from '../src/FormControlMixin.js'; import { FormControlMixin } from '../src/FormControlMixin.js';
import { FormRegistrarMixin } from '../src/registration/FormRegistrarMixin.js';
describe('FormControlMixin', () => { describe('FormControlMixin', () => {
const inputSlot = '<input slot="input" />'; const inputSlot = '<input slot="input" />';
@ -179,4 +181,113 @@ describe('FormControlMixin', () => {
.getAttribute('aria-live'), .getAttribute('aria-live'),
).to.equal('polite'); ).to.equal('polite');
}); });
describe('Model-value-changed event propagation', () => {
const FormControlWithRegistrarMixinClass = class extends FormControlMixin(
FormRegistrarMixin(SlotMixin(LitElement)),
) {
static get properties() {
return {
modelValue: {
type: String,
},
};
}
};
const groupElem = defineCE(FormControlWithRegistrarMixinClass);
const groupTag = unsafeStatic(groupElem);
describe('On initialization', () => {
it('redispatches one event from host', async () => {
const formSpy = sinon.spy();
const fieldsetSpy = sinon.spy();
const formEl = await fixture(html`
<${groupTag} name="form" ._repropagationRole=${'form-group'} @model-value-changed=${formSpy}>
<${groupTag} name="fieldset" ._repropagationRole=${'form-group'} @model-value-changed=${fieldsetSpy}>
<${tag} name="field"></${tag}>
</${groupTag}>
</${groupTag}>
`);
const fieldsetEl = formEl.querySelector('[name=fieldset]');
expect(fieldsetSpy.callCount).to.equal(1);
const fieldsetEv = fieldsetSpy.firstCall.args[0];
expect(fieldsetEv.target).to.equal(fieldsetEl);
expect(fieldsetEv.detail.formPath).to.eql([fieldsetEl]);
expect(formSpy.callCount).to.equal(1);
const formEv = formSpy.firstCall.args[0];
expect(formEv.target).to.equal(formEl);
expect(formEv.detail.formPath).to.eql([formEl]);
});
});
describe('After initialization', () => {
it('redispatches one event from host and keeps formPath history', async () => {
const formSpy = sinon.spy();
const fieldsetSpy = sinon.spy();
const fieldSpy = sinon.spy();
const formEl = await fixture(html`
<${groupTag} name="form">
<${groupTag} name="fieldset">
<${tag} name="field"></${tag}>
</${groupTag}>
</${groupTag}>
`);
const fieldEl = formEl.querySelector('[name=field]');
const fieldsetEl = formEl.querySelector('[name=fieldset]');
formEl.addEventListener('model-value-changed', formSpy);
fieldsetEl.addEventListener('model-value-changed', fieldsetSpy);
fieldEl.addEventListener('model-value-changed', fieldSpy);
fieldEl.dispatchEvent(new Event('model-value-changed', { bubbles: true }));
expect(fieldsetSpy.callCount).to.equal(1);
const fieldsetEv = fieldsetSpy.firstCall.args[0];
expect(fieldsetEv.target).to.equal(fieldsetEl);
expect(fieldsetEv.detail.formPath).to.eql([fieldEl, fieldsetEl]);
expect(formSpy.callCount).to.equal(1);
const formEv = formSpy.firstCall.args[0];
expect(formEv.target).to.equal(formEl);
expect(formEv.detail.formPath).to.eql([fieldEl, fieldsetEl, formEl]);
});
it('sends one event for single select choice-groups', async () => {
const formSpy = sinon.spy();
const choiceGroupSpy = sinon.spy();
const formEl = await fixture(html`
<${groupTag} name="form">
<${groupTag} name="choice-group" ._repropagationRole=${'choice-group'}>
<${tag} name="choice-group" id="option1" .checked=${true}></${tag}>
<${tag} name="choice-group" id="option2"></${tag}>
</${groupTag}>
</${groupTag}>
`);
const choiceGroupEl = formEl.querySelector('[name=choice-group]');
const option1El = formEl.querySelector('#option1');
const option2El = formEl.querySelector('#option2');
formEl.addEventListener('model-value-changed', formSpy);
choiceGroupEl.addEventListener('model-value-changed', choiceGroupSpy);
// Simulate check
option2El.checked = true;
option2El.dispatchEvent(new Event('model-value-changed', { bubbles: true }));
option1El.checked = false;
option1El.dispatchEvent(new Event('model-value-changed', { bubbles: true }));
expect(choiceGroupSpy.callCount).to.equal(1);
const choiceGroupEv = choiceGroupSpy.firstCall.args[0];
expect(choiceGroupEv.target).to.equal(choiceGroupEl);
expect(choiceGroupEv.detail.formPath).to.eql([choiceGroupEl]);
expect(formSpy.callCount).to.equal(1);
const formEv = formSpy.firstCall.args[0];
expect(formEv.target).to.equal(formEl);
expect(formEv.detail.formPath).to.eql([choiceGroupEl, formEl]);
});
});
});
}); });

View file

@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.9.4](https://github.com/ing-bank/lion/compare/@lion/fieldset@0.9.3...@lion/fieldset@0.9.4) (2020-03-19)
### Bug Fixes
* normalization model-value-changed events ([1b6c3a4](https://github.com/ing-bank/lion/commit/1b6c3a44c820b9d61c26849b91bbb1bc8d6c772b))
## [0.9.3](https://github.com/ing-bank/lion/compare/@lion/fieldset@0.9.2...@lion/fieldset@0.9.3) (2020-03-05) ## [0.9.3](https://github.com/ing-bank/lion/compare/@lion/fieldset@0.9.2...@lion/fieldset@0.9.3) (2020-03-05)
**Note:** Version bump only for package @lion/fieldset **Note:** Version bump only for package @lion/fieldset

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/fieldset", "name": "@lion/fieldset",
"version": "0.9.3", "version": "0.9.4",
"description": "Allows to groups multiple input fields or other fieldsets together", "description": "Allows to groups multiple input fields or other fieldsets together",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,7 +35,7 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/validate": "0.8.0" "@lion/validate": "0.8.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -135,8 +135,8 @@ export const FormGroupMixin = dedupeMixin(
} }
async __initInteractionStates() { async __initInteractionStates() {
if (!this.__readyForRegistration) { if (!this.registrationHasCompleted) {
await this.registrationReady; await this.registrationComplete;
} }
this.formElements.forEach(el => { this.formElements.forEach(el => {
if (typeof el.initInteractionState === 'function') { if (typeof el.initInteractionState === 'function') {

View file

@ -25,5 +25,6 @@ export class LionFieldset extends FormGroupMixin(LitElement) {
super(); super();
/** @override from FormRegistrarMixin */ /** @override from FormRegistrarMixin */
this._isFormOrFieldset = true; this._isFormOrFieldset = true;
this._repropagationRole = 'fieldset'; // configures FormControlMixin
} }
} }

View file

@ -1,6 +1,5 @@
import { import {
expect, expect,
fixture,
fixtureSync, fixtureSync,
html, html,
unsafeStatic, unsafeStatic,
@ -8,6 +7,7 @@ import {
nextFrame, nextFrame,
defineCE, defineCE,
} from '@open-wc/testing'; } from '@open-wc/testing';
import { formFixture as fixture } from '@lion/field/test-helpers.js';
import sinon from 'sinon'; import sinon from 'sinon';
import { Validator, IsNumber } from '@lion/validate'; import { Validator, IsNumber } from '@lion/validate';
import { localizeTearDown } from '@lion/localize/test-helpers.js'; import { localizeTearDown } from '@lion/localize/test-helpers.js';

View file

@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.6.7](https://github.com/ing-bank/lion/compare/@lion/form-system@0.6.6...@lion/form-system@0.6.7) (2020-03-19)
**Note:** Version bump only for package @lion/form-system
## [0.6.6](https://github.com/ing-bank/lion/compare/@lion/form-system@0.6.5...@lion/form-system@0.6.6) (2020-03-19)
### Bug Fixes
* normalization model-value-changed events ([1b6c3a4](https://github.com/ing-bank/lion/commit/1b6c3a44c820b9d61c26849b91bbb1bc8d6c772b))
## [0.6.5](https://github.com/ing-bank/lion/compare/@lion/form-system@0.6.4...@lion/form-system@0.6.5) (2020-03-12)
**Note:** Version bump only for package @lion/form-system
## [0.6.4](https://github.com/ing-bank/lion/compare/@lion/form-system@0.6.3...@lion/form-system@0.6.4) (2020-03-09) ## [0.6.4](https://github.com/ing-bank/lion/compare/@lion/form-system@0.6.3...@lion/form-system@0.6.4) (2020-03-09)
**Note:** Version bump only for package @lion/form-system **Note:** Version bump only for package @lion/form-system

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/form-system", "name": "@lion/form-system",
"version": "0.6.4", "version": "0.6.7",
"description": "The Form System allows you to create complex forms with various validation in an easy way", "description": "The Form System allows you to create complex forms with various validation in an easy way",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -33,22 +33,23 @@
"*.js" "*.js"
], ],
"devDependencies": { "devDependencies": {
"@lion/checkbox-group": "0.8.3", "@lion/checkbox-group": "0.8.5",
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/fieldset": "0.9.3", "@lion/fieldset": "0.9.4",
"@lion/form": "0.4.18", "@lion/form": "0.4.20",
"@lion/input": "0.5.18", "@lion/input": "0.5.19",
"@lion/input-amount": "0.5.18", "@lion/input-amount": "0.5.19",
"@lion/input-date": "0.5.19", "@lion/input-date": "0.5.20",
"@lion/input-email": "0.6.3", "@lion/input-datepicker": "0.10.2",
"@lion/input-iban": "0.6.3", "@lion/input-email": "0.6.4",
"@lion/input-range": "0.2.18", "@lion/input-iban": "0.6.4",
"@lion/input-range": "0.2.19",
"@lion/localize": "0.8.10", "@lion/localize": "0.8.10",
"@lion/radio-group": "0.8.3", "@lion/radio-group": "0.8.5",
"@lion/select": "0.5.18", "@lion/select": "0.5.19",
"@lion/select-rich": "0.12.0", "@lion/select-rich": "0.12.3",
"@lion/textarea": "0.5.19", "@lion/textarea": "0.5.20",
"@lion/validate": "0.8.0", "@lion/validate": "0.8.0",
"@open-wc/demoing-storybook": "^1.10.4", "@open-wc/demoing-storybook": "^1.10.4",
"@open-wc/testing": "^2.5.0" "@open-wc/testing": "^2.5.0"

View file

@ -33,9 +33,9 @@ For usage and installation please see the appropriate packages.
{() => { {() => {
Required.getMessage = () => 'Please enter a value'; Required.getMessage = () => 'Please enter a value';
return html` return html`
<lion-form> <lion-form @model-value-changed="${(ev) => { console.log('lion-form::', ev.target.name, ':', ev.detail.formPath) }}">
<form> <form>
<lion-fieldset name="full_name"> <lion-fieldset name="full_name" @model-value-changed="${(ev) => { console.log('lion-fieldset::', ev.target.name, ':', ev.detail.formPath) }}">
<lion-input <lion-input
name="first_name" name="first_name"
label="First Name" label="First Name"
@ -69,6 +69,7 @@ For usage and installation please see the appropriate packages.
<lion-input-iban name="iban" label="Iban"></lion-input-iban> <lion-input-iban name="iban" label="Iban"></lion-input-iban>
<lion-input-email name="email" label="Email"></lion-input-email> <lion-input-email name="email" label="Email"></lion-input-email>
<lion-checkbox-group <lion-checkbox-group
@model-value-changed="${(ev) => { console.log('lion-cb-group::', ev.target.name, ':', ev.detail.formPath) }}"
label="What do you like?" label="What do you like?"
name="checkers" name="checkers"
.validators="${[new Required()]}" .validators="${[new Required()]}"
@ -78,6 +79,7 @@ For usage and installation please see the appropriate packages.
<lion-checkbox .choiceValue=${'baz'} label="I like baz"></lion-checkbox> <lion-checkbox .choiceValue=${'baz'} label="I like baz"></lion-checkbox>
</lion-checkbox-group> </lion-checkbox-group>
<lion-radio-group <lion-radio-group
@model-value-changed="${(ev) => { console.log('lion-radio-group::', ev.target.name, ':', ev.detail.formPath) }}"
name="dinosaurs" name="dinosaurs"
label="Favorite dinosaur" label="Favorite dinosaur"
.validators="${[new Required()]}" .validators="${[new Required()]}"

View file

@ -35,9 +35,11 @@ For an input that may mean that it is not an empty string,
while for a checkbox group it means at least one checkbox needs to be checked. while for a checkbox group it means at least one checkbox needs to be checked.
<Story name="Required Validator"> <Story name="Required Validator">
{html` {() => {
loadDefaultFeedbackMessages();
return html`
<lion-input .validators=${[new Required()]} label="Required"></lion-input> <lion-input .validators=${[new Required()]} label="Required"></lion-input>
`} `}}
</Story> </Story>
```html ```html
@ -242,7 +244,7 @@ const tomorrow = new Date(year, month, day + 1);
## Validation Types ## Validation Types
When defining your own component you can decide to allow for multiple types of validation. When defining your own component you can decide to allow for multiple types of validation.
By default only `error` is used however there are certainly use cases where warning or success messages make sense. By default only `error` is used, however there are certainly use cases where warning or success messages make sense.
<Story name="Validation Types"> <Story name="Validation Types">
{() => { {() => {
@ -258,29 +260,24 @@ By default only `error` is used however there are certainly use cases where warn
} }
return html` return html`
<style> <style>
my-types-input { .demo-types-input {
border-left: 2px solid #fff; padding: 0.5rem;
} }
my-types-input[shows-feedback-for]:not([shows-feedback-for='']) { .demo-types-input[shows-feedback-for~='success'] {
border-left: 2px dotted red; background-color: #e4ffe4;
border: 1px solid green;
} }
my-types-input[shows-feedback-for~='error'] input { .demo-types-input[shows-feedback-for~='error'] {
outline: 2px solid red; background-color: #ffd4d4;
border: 1px solid red;
} }
my-types-input[shows-feedback-for~='warning'] input { .demo-types-input[shows-feedback-for~='warning'] {
outline: 2px solid orange; background-color: #ffe4d4;
border: 1px solid orange;
} }
lion-validation-feedback[type='success'] { .demo-types-input[shows-feedback-for~='info'] {
color: green; background-color: #d4e4ff;
} border: 1px solid blue;
lion-validation-feedback[type='error'] {
color: red;
}
lion-validation-feedback[type='warning'] {
color: orange;
}
lion-validation-feedback[type='info'] {
color: blue;
} }
</style> </style>
<my-types-input <my-types-input
@ -295,6 +292,7 @@ By default only `error` is used however there are certainly use cases where warn
]}" ]}"
.modelValue="${'exactly'}" .modelValue="${'exactly'}"
label="Validation Types" label="Validation Types"
class="demo-types-input"
></my-types-input> ></my-types-input>
`; `;
}} }}
@ -315,29 +313,24 @@ try {
```html ```html
<style> <style>
my-types-input { .demo-types-input {
border-left: 2px solid #fff; padding: 0.5rem;
} }
my-types-input[shows-feedback-for]:not([shows-feedback-for='']) { .demo-types-input[shows-feedback-for~='success'] {
border-left: 2px dotted red; background-color: #e4ffe4;
border: 1px solid green;
} }
my-types-input[shows-feedback-for~='error'] input { .demo-types-input[shows-feedback-for~='error'] {
outline: 2px solid red; background-color: #ffd4d4;
border: 1px solid red;
} }
my-types-input[shows-feedback-for~='warning'] input { .demo-types-input[shows-feedback-for~='warning'] {
outline: 2px solid orange; background-color: #ffe4d4;
border: 1px solid orange;
} }
lion-validation-feedback[type='success'] { .demo-types-input[shows-feedback-for~='info'] {
color: green; background-color: #d4e4ff;
} border: 1px solid blue;
lion-validation-feedback[type='error'] {
color: red;
}
lion-validation-feedback[type='warning'] {
color: orange;
}
lion-validation-feedback[type='info'] {
color: blue;
} }
</style> </style>
<my-types-input <my-types-input
@ -352,6 +345,7 @@ try {
]}" ]}"
.modelValue="${'exactly'}" .modelValue="${'exactly'}"
label="Validation Types" label="Validation Types"
class="demo-types-input"
></my-types-input> ></my-types-input>
``` ```
@ -421,9 +415,11 @@ class MyValidator extends Validator {
></lion-input> ></lion-input>
``` ```
## Override default messages ## Default messages
Oftern To get default validation messages you need to import and call the `loadDefaultFeedbackMessages` function once in your application.
Sometimes the default messages don't make sense for your input field. In that case you want to override it by adding a `getMessage` function to your validator.
<Story name="Override default messages"> <Story name="Override default messages">
{html` {html`
@ -469,6 +465,8 @@ Oftern
## Override fieldName ## Override fieldName
In the scenario that the default messages are correct, but you only want to change the `fieldName`, this can both be done for a single specific validator or for all at once.
<Story name="Override fieldName"> <Story name="Override fieldName">
{html` {html`
<lion-input <lion-input
@ -584,7 +582,7 @@ class AsyncValidator extends Validator {
}); });
return html` return html`
<lion-input-date <lion-input-date
label="Your birth date" label="Birth date"
help-text="Adjust this date to retrigger validation of the input below..." help-text="Adjust this date to retrigger validation of the input below..."
.modelValue="${beginDate}" .modelValue="${beginDate}"
@model-value-changed="${({ target: { modelValue, errorState } }) => { @model-value-changed="${({ target: { modelValue, errorState } }) => {
@ -595,7 +593,7 @@ class AsyncValidator extends Validator {
}}" }}"
></lion-input-date> ></lion-input-date>
<lion-input-date <lion-input-date
label="Your graduation date" label="Graduation date"
.modelValue="${new Date('09/09/1989')}" .modelValue="${new Date('09/09/1989')}"
.validators="${[minDateValidatorRef]}" .validators="${[minDateValidatorRef]}"
></lion-input-date> ></lion-input-date>

View file

@ -52,18 +52,18 @@ Platform field wrappers add all of the functionality described above to native f
Dedicated fields are less generic fields in a sense that they by default expect a certain type of Dedicated fields are less generic fields in a sense that they by default expect a certain type of
modelValue. This means that they have validators, parsers and formatters preconfigured. modelValue. This means that they have validators, parsers and formatters preconfigured.
- [`LionInputDate`](?path=/docs/forms-input-date--default-story) - [LionInputDate](?path=/docs/forms-input-date--default-story)
- [`LionInputDatepicker`](?path=/docs/forms-input-datepicker--default-story) - [LionInputDatepicker](?path=/docs/forms-input-datepicker--default-story)
- [`LionInputEmail`](?path=/docs/forms-input-email--default-story) - [LionInputEmail](?path=/docs/forms-input-email--default-story)
- [`LionInputAmount`](?path=/docs/forms-input-amount--default-story) - [LionInputAmount](?path=/docs/forms-input-amount--default-story)
- [`LionInputIban`](?path=/docs/forms-input-iban--default-story) - [LionInputIban](?path=/docs/forms-input-iban--default-story)
### Custom fields ### Custom fields
Instead of wrapping native elements, this category of fields contains custom built Instead of wrapping native elements, this category of fields contains custom built
form elements. form elements.
- [`LionSelectRich`](?path=/docs/forms-select-rich--default-story), an advanced (rich) version of `<select>` - [LionSelectRich](?path=/docs/forms-select-rich--default-story), an advanced (rich) version of `<select>`
One could also think of components like: One could also think of components like:
@ -80,10 +80,10 @@ Fieldsets are groups of fields. They can be considered fields on their own as we
partly share the normalized api via `FormControlMixin`. partly share the normalized api via `FormControlMixin`.
Fieldsets are at the base of: Fieldsets are at the base of:
- [`LionFieldset`](?path=/docs/forms-fieldset-overview--page) - [LionFieldset](?path=/docs/forms-fieldset-overview--page)
- [`LionForm`](?path=/docs/forms-form-overview--page) - [LionForm](?path=/docs/forms-form-overview--page)
- [`LionRadioGroup`](?path=/docs/forms-radio-group--default-story) - [LionRadioGroup](?path=/docs/forms-radio-group--default-story)
- [`LionCheckboxGroup`](?path=/docs/forms-checkbox-group--default-story) - [LionCheckboxGroup](?path=/docs/forms-checkbox-group--default-story)
## Other Resources ## Other Resources

View file

@ -0,0 +1,274 @@
import { expect, html, unsafeStatic } from '@open-wc/testing';
import { formFixture as fixture } from '@lion/field/test-helpers.js';
// eslint-disable-next-line import/no-extraneous-dependencies
import sinon from 'sinon';
import '@lion/input/lion-input.js';
import '@lion/input-amount/lion-input-amount.js';
import '@lion/input-date/lion-input-date.js';
import '@lion/input-datepicker/lion-input-datepicker.js';
import '@lion/input-email/lion-input-email.js';
import '@lion/input-iban/lion-input-iban.js';
import '@lion/input-range/lion-input-range.js';
import '@lion/textarea/lion-textarea.js';
import '@lion/checkbox-group/lion-checkbox-group.js';
import '@lion/checkbox-group/lion-checkbox.js';
import '@lion/radio-group/lion-radio-group.js';
import '@lion/radio-group/lion-radio.js';
import '@lion/select/lion-select.js';
import '@lion/select-rich/lion-select-rich.js';
import '@lion/select-rich/lion-options.js';
import '@lion/select-rich/lion-option.js';
import '@lion/fieldset/lion-fieldset.js';
const featureName = 'model value';
const getFirstPaintTitle = count => `should dispatch ${count} time(s) on first paint`;
const getInteractionTitle = count => `should dispatch ${count} time(s) on interaction`;
const firstStampCount = 1;
const interactionCount = 1;
const fieldDispatchesCountOnFirstPaint = (tagname, count) => {
const tag = unsafeStatic(tagname);
const spy = sinon.spy();
it(getFirstPaintTitle(count), async () => {
await fixture(html`<${tag} @model-value-changed="${spy}"></${tag}>`);
expect(spy.callCount).to.equal(count);
});
};
const fieldDispatchesCountOnInteraction = (tagname, count) => {
const tag = unsafeStatic(tagname);
const spy = sinon.spy();
it(getInteractionTitle(count), async () => {
const el = await fixture(html`<${tag}></${tag}>`);
el.addEventListener('model-value-changed', spy);
// TODO: discuss if this is the "correct" way to interact with component
el.modelValue = 'foo';
await el.updateComplete;
expect(spy.callCount).to.equal(count);
});
};
const choiceDispatchesCountOnFirstPaint = (tagname, count) => {
const tag = unsafeStatic(tagname);
const spy = sinon.spy();
it(getFirstPaintTitle(count), async () => {
await fixture(html`<${tag} @model-value-changed="${spy}" .choiceValue="${'option'}"></${tag}>`);
expect(spy.callCount).to.equal(count);
});
};
const choiceDispatchesCountOnInteraction = (tagname, count) => {
const tag = unsafeStatic(tagname);
const spy = sinon.spy();
it(getInteractionTitle(count), async () => {
const el = await fixture(html`<${tag} .choiceValue="${'option'}"></${tag}>`);
el.addEventListener('model-value-changed', spy);
el.checked = true;
expect(spy.callCount).to.equal(count);
});
};
const choiceGroupDispatchesCountOnFirstPaint = (groupTagname, itemTagname, count) => {
const groupTag = unsafeStatic(groupTagname);
const itemTag = unsafeStatic(itemTagname);
it(getFirstPaintTitle(count), async () => {
const spy = sinon.spy();
await fixture(html`
<${groupTag} @model-value-changed="${spy}">
<${itemTag} .choiceValue="${'option1'}"></${itemTag}>
<${itemTag} .choiceValue="${'option2'}"></${itemTag}>
<${itemTag} .choiceValue="${'option3'}"></${itemTag}>
</${groupTag}>
`);
expect(spy.callCount).to.equal(count);
});
};
const choiceGroupDispatchesCountOnInteraction = (groupTagname, itemTagname, count) => {
const groupTag = unsafeStatic(groupTagname);
const itemTag = unsafeStatic(itemTagname);
it(getInteractionTitle(count), async () => {
const spy = sinon.spy();
const el = await fixture(html`
<${groupTag}>
<${itemTag} .choiceValue="${'option1'}"></${itemTag}>
<${itemTag} .choiceValue="${'option2'}"></${itemTag}>
<${itemTag} .choiceValue="${'option3'}"></${itemTag}>
</${groupTag}>
`);
el.addEventListener('model-value-changed', spy);
const option2 = el.querySelector(`${itemTagname}:nth-child(2)`);
option2.checked = true;
expect(spy.callCount).to.equal(count);
spy.resetHistory();
const option3 = el.querySelector(`${itemTagname}:nth-child(3)`);
option3.checked = true;
expect(spy.callCount).to.equal(count);
});
};
[
'input',
'input-amount',
'input-date',
'input-datepicker',
'input-email',
'input-iban',
'input-range',
'textarea',
].forEach(chunk => {
const tagname = `lion-${chunk}`;
describe(`${tagname}`, () => {
describe(featureName, () => {
fieldDispatchesCountOnFirstPaint(tagname, firstStampCount);
fieldDispatchesCountOnInteraction(tagname, interactionCount);
});
});
});
['checkbox', 'radio'].forEach(chunk => {
const groupTagname = `lion-${chunk}-group`;
const itemTagname = `lion-${chunk}`;
describe(`${itemTagname}`, () => {
describe(featureName, () => {
choiceDispatchesCountOnFirstPaint(itemTagname, firstStampCount);
choiceDispatchesCountOnInteraction(itemTagname, interactionCount);
});
});
describe(`${groupTagname}`, () => {
describe(featureName, () => {
choiceGroupDispatchesCountOnFirstPaint(groupTagname, itemTagname, firstStampCount);
choiceGroupDispatchesCountOnInteraction(groupTagname, itemTagname, interactionCount);
});
});
});
describe('lion-select', () => {
describe(featureName, () => {
it(getFirstPaintTitle(firstStampCount), async () => {
const spy = sinon.spy();
await fixture(html`
<lion-select @model-value-changed="${spy}">
<select slot="input">
<option value="option1"></option>
<option value="option2"></option>
<option value="option3"></option>
</select>
</lion-select>
`);
expect(spy.callCount).to.equal(firstStampCount);
});
it(getInteractionTitle(interactionCount), async () => {
const spy = sinon.spy();
const el = await fixture(html`
<lion-select>
<select slot="input">
<option value="option1"></option>
<option value="option2"></option>
<option value="option3"></option>
</select>
</lion-select>
`);
el.addEventListener('model-value-changed', spy);
const option2 = el.querySelector('option:nth-child(2)');
// mimic user input
option2.selected = true;
el._inputNode.dispatchEvent(new CustomEvent('change'));
expect(spy.callCount).to.equal(interactionCount);
spy.resetHistory();
const option3 = el.querySelector('option:nth-child(3)');
// mimic user input
option3.selected = true;
el._inputNode.dispatchEvent(new CustomEvent('change'));
expect(spy.callCount).to.equal(interactionCount);
});
});
});
describe('lion-select-rich', () => {
describe(featureName, () => {
it(getFirstPaintTitle(firstStampCount), async () => {
const spy = sinon.spy();
await fixture(html`
<lion-select-rich @model-value-changed="${spy}">
<lion-options slot="input">
<lion-option .choiceValue="${'option1'}"></lion-option>
<lion-option .choiceValue="${'option2'}"></lion-option>
<lion-option .choiceValue="${'option3'}"></lion-option>
</lion-options>
</lion-select-rich>
`);
expect(spy.callCount).to.equal(firstStampCount);
});
it(getInteractionTitle(interactionCount), async () => {
const spy = sinon.spy();
const el = await fixture(html`
<lion-select-rich>
<lion-options slot="input">
<lion-option .choiceValue="${'option1'}"></lion-option>
<lion-option .choiceValue="${'option2'}"></lion-option>
<lion-option .choiceValue="${'option3'}"></lion-option>
</lion-options>
</lion-select-rich>
`);
el.addEventListener('model-value-changed', spy);
const option2 = el.querySelector('lion-option:nth-child(2)');
option2.checked = true;
expect(spy.callCount).to.equal(interactionCount);
spy.resetHistory();
const option3 = el.querySelector('lion-option:nth-child(3)');
option3.checked = true;
expect(spy.callCount).to.equal(interactionCount);
});
});
});
describe('lion-fieldset', () => {
describe(featureName, () => {
it(getFirstPaintTitle(firstStampCount), async () => {
const spy = sinon.spy();
await fixture(html`
<lion-fieldset name="parent" @model-value-changed="${spy}">
<lion-input name="input"></lion-input>
</lion-fieldset>
`);
expect(spy.callCount).to.equal(firstStampCount);
});
it(getInteractionTitle(interactionCount), async () => {
const spy = sinon.spy();
const el = await fixture(html`
<lion-fieldset name="parent">
<lion-input name="input"></lion-input>
</lion-fieldset>
`);
el.addEventListener('model-value-changed', spy);
const input = el.querySelector('lion-input');
input.modelValue = 'foo';
expect(spy.callCount).to.equal(interactionCount);
});
});
});

View file

@ -0,0 +1,144 @@
import { expect, html } from '@open-wc/testing';
import { formFixture as fixture } from '@lion/field/test-helpers.js';
// eslint-disable-next-line import/no-extraneous-dependencies
import sinon from 'sinon';
import '@lion/input/lion-input.js';
import '@lion/fieldset/lion-fieldset.js';
describe('model value event', () => {
describe('form path', () => {
it('should be property', async () => {
const spy = sinon.spy();
const input = await fixture(html`
<lion-input></lion-input>
`);
input.addEventListener('model-value-changed', spy);
input.modelValue = 'woof';
const e = spy.firstCall.args[0];
expect(e.detail).to.have.a.property('formPath');
});
it('should contain dispatching field', async () => {
const spy = sinon.spy();
const input = await fixture(html`
<lion-input></lion-input>
`);
input.addEventListener('model-value-changed', spy);
input.modelValue = 'foo';
const e = spy.firstCall.args[0];
expect(e.detail.formPath).to.eql([input]);
});
it('should contain field and group', async () => {
const spy = sinon.spy();
const fieldset = await fixture(html`
<lion-fieldset name="fieldset">
<lion-input name="input"></lion-input>
</lion-fieldset>
`);
fieldset.addEventListener('model-value-changed', spy);
const input = fieldset.querySelector('lion-input');
input.modelValue = 'foo';
const e = spy.firstCall.args[0];
expect(e.detail.formPath).to.eql([input, fieldset]);
});
it('should contain deep elements', async () => {
const spy = sinon.spy();
const grandparent = await fixture(html`
<lion-fieldset name="grandparent">
<lion-fieldset name="parent">
<lion-input name="input"></lion-input>
</lion-fieldset>
</lion-fieldset>
`);
const parent = grandparent.querySelector('[name=parent]');
const input = grandparent.querySelector('[name=input]');
grandparent.addEventListener('model-value-changed', spy);
input.modelValue = 'foo';
const e = spy.firstCall.args[0];
expect(e.detail.formPath).to.eql([input, parent, grandparent]);
});
it('should ignore elements that are not fields or fieldsets', async () => {
const spy = sinon.spy();
const grandparent = await fixture(html`
<lion-fieldset name="grandparent">
<div>
<lion-fieldset name="parent">
<div>
<div>
<lion-input name="input"></lion-input>
</div>
</div>
</lion-fieldset>
</div>
</lion-fieldset>
`);
const parent = grandparent.querySelector('[name=parent]');
const input = grandparent.querySelector('[name=input]');
grandparent.addEventListener('model-value-changed', spy);
input.modelValue = 'foo';
const e = spy.firstCall.args[0];
expect(e.detail.formPath).to.eql([input, parent, grandparent]);
});
});
describe('signature', () => {
let e;
beforeEach(async () => {
const spy = sinon.spy();
const el = await fixture(
html`
<lion-input></lion-input>
`,
);
el.addEventListener('model-value-changed', spy);
el.modelValue = 'foo';
// eslint-disable-next-line prefer-destructuring
e = spy.firstCall.args[0];
});
// TODO: Re-enable at some point...
// In my opinion (@CubLion) we should not bubble events.
// Instead each parent should explicitly listen to children events,
// and then re-dispatch on themselves.
it.skip('should not bubble', async () => {
expect(e.bubbles).to.be.false;
});
it('should not leave shadow boundary', async () => {
expect(e.composed).to.be.false;
});
});
describe('propagation', () => {
it('should dispatch different event at each level', async () => {
const grandparent = await fixture(html`
<lion-fieldset name="grandparent">
<lion-fieldset name="parent">
<lion-input name="input"></lion-input>
</lion-fieldset>
</lion-fieldset>
`);
const parent = grandparent.querySelector('[name="parent"]');
const input = grandparent.querySelector('[name="input"]');
const spies = [];
[grandparent, parent, input].forEach(element => {
const spy = sinon.spy();
spies.push(spy);
element.addEventListener('model-value-changed', spy);
});
input.modelValue = 'foo';
spies.forEach((spy, index) => {
const currentEvent = spy.firstCall.args[0];
for (let i = index + 1; i < spies.length; i += 1) {
const nextEvent = spies[i].firstCall.args[0];
expect(currentEvent).not.to.eql(nextEvent);
}
});
});
});
});

View file

@ -3,6 +3,25 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.4.20](https://github.com/ing-bank/lion/compare/@lion/form@0.4.19...@lion/form@0.4.20) (2020-03-19)
### Bug Fixes
* **form:** remove correct reset event listener on teardown ([9cd0ed3](https://github.com/ing-bank/lion/commit/9cd0ed364fd440353c0b4a94bb1e5001ea9415c0))
## [0.4.19](https://github.com/ing-bank/lion/compare/@lion/form@0.4.18...@lion/form@0.4.19) (2020-03-19)
**Note:** Version bump only for package @lion/form
## [0.4.18](https://github.com/ing-bank/lion/compare/@lion/form@0.4.17...@lion/form@0.4.18) (2020-03-05) ## [0.4.18](https://github.com/ing-bank/lion/compare/@lion/form@0.4.17...@lion/form@0.4.18) (2020-03-05)
**Note:** Version bump only for package @lion/form **Note:** Version bump only for package @lion/form

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/form", "name": "@lion/form",
"version": "0.4.18", "version": "0.4.20",
"description": "It enhances the functionality of the native `form` component. It is designed to interact with (instances of) form fields", "description": "It enhances the functionality of the native `form` component. It is designed to interact with (instances of) form fields",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,10 +35,10 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/fieldset": "0.9.3" "@lion/fieldset": "0.9.4"
}, },
"devDependencies": { "devDependencies": {
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/validate": "0.8.0", "@lion/validate": "0.8.0",
"@open-wc/demoing-storybook": "^1.10.4", "@open-wc/demoing-storybook": "^1.10.4",
"@open-wc/testing": "^2.5.0", "@open-wc/testing": "^2.5.0",

View file

@ -57,6 +57,6 @@ export class LionForm extends LionFieldset {
__teardownEventsForLionForm() { __teardownEventsForLionForm() {
this._formNode.removeEventListener('submit', this._submit); this._formNode.removeEventListener('submit', this._submit);
this._formNode.removeEventListener('rest', this._reset); this._formNode.removeEventListener('reset', this._reset);
} }
} }

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.5.19](https://github.com/ing-bank/lion/compare/@lion/input-amount@0.5.18...@lion/input-amount@0.5.19) (2020-03-19)
**Note:** Version bump only for package @lion/input-amount
## [0.5.18](https://github.com/ing-bank/lion/compare/@lion/input-amount@0.5.17...@lion/input-amount@0.5.18) (2020-03-05) ## [0.5.18](https://github.com/ing-bank/lion/compare/@lion/input-amount@0.5.17...@lion/input-amount@0.5.18) (2020-03-05)
**Note:** Version bump only for package @lion/input-amount **Note:** Version bump only for package @lion/input-amount

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/input-amount", "name": "@lion/input-amount",
"version": "0.5.18", "version": "0.5.19",
"description": "Provide a way for users to fill in an amount", "description": "Provide a way for users to fill in an amount",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,8 +35,8 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/input": "0.5.18", "@lion/input": "0.5.19",
"@lion/localize": "0.8.10", "@lion/localize": "0.8.10",
"@lion/validate": "0.8.0" "@lion/validate": "0.8.0"
}, },

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.5.20](https://github.com/ing-bank/lion/compare/@lion/input-date@0.5.19...@lion/input-date@0.5.20) (2020-03-19)
**Note:** Version bump only for package @lion/input-date
## [0.5.19](https://github.com/ing-bank/lion/compare/@lion/input-date@0.5.18...@lion/input-date@0.5.19) (2020-03-09) ## [0.5.19](https://github.com/ing-bank/lion/compare/@lion/input-date@0.5.18...@lion/input-date@0.5.19) (2020-03-09)

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/input-date", "name": "@lion/input-date",
"version": "0.5.19", "version": "0.5.20",
"description": "Provide a way for users to fill in a date", "description": "Provide a way for users to fill in a date",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,8 +35,8 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/input": "0.5.18", "@lion/input": "0.5.19",
"@lion/localize": "0.8.10", "@lion/localize": "0.8.10",
"@lion/validate": "0.8.0" "@lion/validate": "0.8.0"
}, },

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.10.2](https://github.com/ing-bank/lion/compare/@lion/input-datepicker@0.10.1...@lion/input-datepicker@0.10.2) (2020-03-19)
**Note:** Version bump only for package @lion/input-datepicker
## [0.10.1](https://github.com/ing-bank/lion/compare/@lion/input-datepicker@0.10.0...@lion/input-datepicker@0.10.1) (2020-03-09) ## [0.10.1](https://github.com/ing-bank/lion/compare/@lion/input-datepicker@0.10.0...@lion/input-datepicker@0.10.1) (2020-03-09)
**Note:** Version bump only for package @lion/input-datepicker **Note:** Version bump only for package @lion/input-datepicker

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/input-datepicker", "name": "@lion/input-datepicker",
"version": "0.10.1", "version": "0.10.2",
"description": "Provide a way for users to fill in a date via a calendar overlay", "description": "Provide a way for users to fill in a date via a calendar overlay",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -40,10 +40,10 @@
"dependencies": { "dependencies": {
"@lion/calendar": "0.6.13", "@lion/calendar": "0.6.13",
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/input-date": "0.5.19", "@lion/input-date": "0.5.20",
"@lion/localize": "0.8.10", "@lion/localize": "0.8.10",
"@lion/overlays": "0.12.4", "@lion/overlays": "0.12.5",
"@lion/validate": "0.8.0", "@lion/validate": "0.8.0",
"@open-wc/scoped-elements": "^0.5.0" "@open-wc/scoped-elements": "^0.5.0"
}, },

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.6.4](https://github.com/ing-bank/lion/compare/@lion/input-email@0.6.3...@lion/input-email@0.6.4) (2020-03-19)
**Note:** Version bump only for package @lion/input-email
## [0.6.3](https://github.com/ing-bank/lion/compare/@lion/input-email@0.6.2...@lion/input-email@0.6.3) (2020-03-05) ## [0.6.3](https://github.com/ing-bank/lion/compare/@lion/input-email@0.6.2...@lion/input-email@0.6.3) (2020-03-05)
**Note:** Version bump only for package @lion/input-email **Note:** Version bump only for package @lion/input-email

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/input-email", "name": "@lion/input-email",
"version": "0.6.3", "version": "0.6.4",
"description": "Provide a way for users to fill in an email", "description": "Provide a way for users to fill in an email",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,8 +35,8 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/input": "0.5.18", "@lion/input": "0.5.19",
"@lion/localize": "0.8.10", "@lion/localize": "0.8.10",
"@lion/validate": "0.8.0" "@lion/validate": "0.8.0"
}, },

View file

@ -55,7 +55,7 @@ Use `loadDefaultFeedbackMessages` to get our default feedback messages displayed
</Story> </Story>
```js ```js
import { loadDefaultFeedbackMessages } from 'lion/validate'; import { loadDefaultFeedbackMessages } from '@lion/validate';
loadDefaultFeedbackMessages(); loadDefaultFeedbackMessages();
``` ```

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.6.4](https://github.com/ing-bank/lion/compare/@lion/input-iban@0.6.3...@lion/input-iban@0.6.4) (2020-03-19)
**Note:** Version bump only for package @lion/input-iban
## [0.6.3](https://github.com/ing-bank/lion/compare/@lion/input-iban@0.6.2...@lion/input-iban@0.6.3) (2020-03-05) ## [0.6.3](https://github.com/ing-bank/lion/compare/@lion/input-iban@0.6.2...@lion/input-iban@0.6.3) (2020-03-05)
**Note:** Version bump only for package @lion/input-iban **Note:** Version bump only for package @lion/input-iban

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/input-iban", "name": "@lion/input-iban",
"version": "0.6.3", "version": "0.6.4",
"description": "Provide a way for users to fill in an iban", "description": "Provide a way for users to fill in an iban",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,8 +35,8 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/input": "0.5.18", "@lion/input": "0.5.19",
"@lion/localize": "0.8.10", "@lion/localize": "0.8.10",
"@lion/validate": "0.8.0", "@lion/validate": "0.8.0",
"ibantools": "^2.2.0" "ibantools": "^2.2.0"

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.19](https://github.com/ing-bank/lion/compare/@lion/input-range@0.2.18...@lion/input-range@0.2.19) (2020-03-19)
**Note:** Version bump only for package @lion/input-range
## [0.2.18](https://github.com/ing-bank/lion/compare/@lion/input-range@0.2.17...@lion/input-range@0.2.18) (2020-03-05) ## [0.2.18](https://github.com/ing-bank/lion/compare/@lion/input-range@0.2.17...@lion/input-range@0.2.18) (2020-03-05)
**Note:** Version bump only for package @lion/input-range **Note:** Version bump only for package @lion/input-range

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/input-range", "name": "@lion/input-range",
"version": "0.2.18", "version": "0.2.19",
"description": "Provide a way for users to select one value from a range of values", "description": "Provide a way for users to select one value from a range of values",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -34,8 +34,8 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/input": "0.5.18", "@lion/input": "0.5.19",
"@lion/localize": "0.8.10" "@lion/localize": "0.8.10"
}, },
"devDependencies": { "devDependencies": {

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.5.19](https://github.com/ing-bank/lion/compare/@lion/input@0.5.18...@lion/input@0.5.19) (2020-03-19)
**Note:** Version bump only for package @lion/input
## [0.5.18](https://github.com/ing-bank/lion/compare/@lion/input@0.5.17...@lion/input@0.5.18) (2020-03-05) ## [0.5.18](https://github.com/ing-bank/lion/compare/@lion/input@0.5.17...@lion/input@0.5.18) (2020-03-05)
**Note:** Version bump only for package @lion/input **Note:** Version bump only for package @lion/input

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/input", "name": "@lion/input",
"version": "0.5.18", "version": "0.5.19",
"description": "It enhances the functionality of the native `<input>` element", "description": "It enhances the functionality of the native `<input>` element",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,7 +35,7 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3" "@lion/field": "0.11.4"
}, },
"devDependencies": { "devDependencies": {
"@lion/localize": "0.8.10", "@lion/localize": "0.8.10",

View file

@ -23,7 +23,7 @@ Further examples can be seen at [Features Overview Demo](?path=/docs/localize-fe
| --------------------------------------------------------------------- | --------------------------------------------- | | --------------------------------------------------------------------- | --------------------------------------------- |
| [Translate Text](?path=/docs/localize-translate-text--function-story) | Load and translate text in multiple languages | | [Translate Text](?path=/docs/localize-translate-text--function-story) | Load and translate text in multiple languages |
| [Format Numbers](?path=/docs/localize-numbers--formatting) | Format numbers in multiple languages | | [Format Numbers](?path=/docs/localize-numbers--formatting) | Format numbers in multiple languages |
| [Format Dates](?path=/docs/localize-dates--formatting)--formatting) | Format dates in multiple languages | | [Format Dates](?path=/docs/localize-dates--formatting) | Format dates in multiple languages |
## How to use ## How to use

View file

@ -277,7 +277,7 @@ If you want to optimize the page rendering and you can inline some of your local
```js ```js
// my-inlined-data.js // my-inlined-data.js
import { localize } from 'lion-localize/localize.js'; import { localize } from '@lion/localize';
localize.addData('en-GB', 'my-namespace', { localize.addData('en-GB', 'my-namespace', {
/* data */ /* data */
}); });

View file

@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.12.5](https://github.com/ing-bank/lion/compare/@lion/overlays@0.12.4...@lion/overlays@0.12.5) (2020-03-19)
### Bug Fixes
* normalization model-value-changed events ([1b6c3a4](https://github.com/ing-bank/lion/commit/1b6c3a44c820b9d61c26849b91bbb1bc8d6c772b))
## [0.12.4](https://github.com/ing-bank/lion/compare/@lion/overlays@0.12.3...@lion/overlays@0.12.4) (2020-03-05) ## [0.12.4](https://github.com/ing-bank/lion/compare/@lion/overlays@0.12.3...@lion/overlays@0.12.4) (2020-03-05)
**Note:** Version bump only for package @lion/overlays **Note:** Version bump only for package @lion/overlays

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/overlays", "name": "@lion/overlays",
"version": "0.12.4", "version": "0.12.5",
"description": "Overlays System using lit-html for rendering", "description": "Overlays System using lit-html for rendering",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",

View file

@ -1,7 +1,7 @@
export const withDropdownConfig = () => ({ export const withDropdownConfig = () => ({
placementMode: 'local', placementMode: 'local',
inheritsReferenceWidth: true, inheritsReferenceWidth: 'full',
hidesOnOutsideClick: true, hidesOnOutsideClick: true,
popperConfig: { popperConfig: {
placement: 'bottom-start', placement: 'bottom-start',

View file

@ -21,7 +21,7 @@ On top of this, the system was built having accessibility in mind.
For a detailed rationale, please consult [Rationale](?path=/docs/overlay-rationale--page). For a detailed rationale, please consult [Rationale](?path=/docs/overlay-rationale--page).
<Story name="default"> <Story name="Default">
{html` {html`
<demo-overlay-system> <demo-overlay-system>
<button slot="invoker">Click me to open the overlay!</button> <button slot="invoker">Click me to open the overlay!</button>
@ -312,7 +312,7 @@ Below is another demo where you can toggle between configurations using buttons.
</Story> </Story>
```js ```js
import { withModalDialogConfig, withBottomSheetConfig, withDropdownConfig } from 'lion/overlays'; import { withModalDialogConfig, withBottomSheetConfig, withDropdownConfig } from '@lion/overlays';
``` ```
```html ```html

View file

@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.8.5](https://github.com/ing-bank/lion/compare/@lion/radio-group@0.8.4...@lion/radio-group@0.8.5) (2020-03-19)
**Note:** Version bump only for package @lion/radio-group
## [0.8.4](https://github.com/ing-bank/lion/compare/@lion/radio-group@0.8.3...@lion/radio-group@0.8.4) (2020-03-12)
**Note:** Version bump only for package @lion/radio-group
## [0.8.3](https://github.com/ing-bank/lion/compare/@lion/radio-group@0.8.2...@lion/radio-group@0.8.3) (2020-03-05) ## [0.8.3](https://github.com/ing-bank/lion/compare/@lion/radio-group@0.8.2...@lion/radio-group@0.8.3) (2020-03-05)
**Note:** Version bump only for package @lion/radio-group **Note:** Version bump only for package @lion/radio-group

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/radio-group", "name": "@lion/radio-group",
"version": "0.8.3", "version": "0.8.5",
"description": "Manage a group of choices", "description": "Manage a group of choices",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -34,10 +34,10 @@
"*.js" "*.js"
], ],
"dependencies": { "dependencies": {
"@lion/choice-input": "0.7.5", "@lion/choice-input": "0.7.7",
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/fieldset": "0.9.3", "@lion/fieldset": "0.9.4",
"@lion/input": "0.5.18" "@lion/input": "0.5.19"
}, },
"devDependencies": { "devDependencies": {
"@lion/validate": "0.8.0", "@lion/validate": "0.8.0",

View file

@ -166,7 +166,7 @@ You can do the same thing for the entire group by setting the `disabled` attribu
</Story> </Story>
```js ```js
import { loadDefaultFeedbackMessages, Required } from 'lion/validate'; import { loadDefaultFeedbackMessages, Required } from '@lion/validate';
loadDefaultFeedbackMessages(); loadDefaultFeedbackMessages();
const validate = () => { const validate = () => {
const radioGroup = document.querySelector('#dinosGroup'); const radioGroup = document.querySelector('#dinosGroup');
@ -224,7 +224,7 @@ You can also create a validator that validates whether a certain option is check
</Story> </Story>
```js ```js
import { loadDefaultFeedbackMessages, Required, Validator } from 'lion/validate'; import { loadDefaultFeedbackMessages, Required, Validator } from '@lion/validate';
class IsBrontosaurus extends Validator { class IsBrontosaurus extends Validator {
static get validatorName() { static get validatorName() {

View file

@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.12.3](https://github.com/ing-bank/lion/compare/@lion/select-rich@0.12.2...@lion/select-rich@0.12.3) (2020-03-19)
**Note:** Version bump only for package @lion/select-rich
## [0.12.2](https://github.com/ing-bank/lion/compare/@lion/select-rich@0.12.1...@lion/select-rich@0.12.2) (2020-03-19)
### Bug Fixes
* normalization model-value-changed events ([1b6c3a4](https://github.com/ing-bank/lion/commit/1b6c3a44c820b9d61c26849b91bbb1bc8d6c772b))
## [0.12.1](https://github.com/ing-bank/lion/compare/@lion/select-rich@0.12.0...@lion/select-rich@0.12.1) (2020-03-12)
**Note:** Version bump only for package @lion/select-rich
# [0.12.0](https://github.com/ing-bank/lion/compare/@lion/select-rich@0.11.4...@lion/select-rich@0.12.0) (2020-03-05) # [0.12.0](https://github.com/ing-bank/lion/compare/@lion/select-rich@0.11.4...@lion/select-rich@0.12.0) (2020-03-05)

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/select-rich", "name": "@lion/select-rich",
"version": "0.12.0", "version": "0.12.3",
"description": "Provides a select with options that can contain html", "description": "Provides a select with options that can contain html",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -39,14 +39,14 @@
], ],
"dependencies": { "dependencies": {
"@lion/button": "0.5.9", "@lion/button": "0.5.9",
"@lion/choice-input": "0.7.5", "@lion/choice-input": "0.7.7",
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"@lion/overlays": "0.12.4", "@lion/overlays": "0.12.5",
"@lion/validate": "0.8.0" "@lion/validate": "0.8.0"
}, },
"devDependencies": { "devDependencies": {
"@lion/form": "0.4.18", "@lion/form": "0.4.20",
"@open-wc/demoing-storybook": "^1.10.4", "@open-wc/demoing-storybook": "^1.10.4",
"@open-wc/testing": "^2.5.0", "@open-wc/testing": "^2.5.0",
"sinon": "^7.2.2" "sinon": "^7.2.2"

View file

@ -148,7 +148,6 @@ export class LionSelectRich extends ScopedElementsMixin(
this.__cachedUserSetModelValue = value; this.__cachedUserSetModelValue = value;
} }
this.__syncInvokerElement();
this.requestUpdate('modelValue'); this.requestUpdate('modelValue');
} }
@ -199,8 +198,9 @@ export class LionSelectRich extends ScopedElementsMixin(
// for interaction states // for interaction states
this._listboxActiveDescendant = null; this._listboxActiveDescendant = null;
this.__hasInitialSelectedFormElement = false; this.__hasInitialSelectedFormElement = false;
this._repropagationRole = 'choice-group'; // configures FormControlMixin
this.__setupEventListeners(); this.__setupEventListeners();
this.__initInteractionStates();
} }
connectedCallback() { connectedCallback() {
@ -250,6 +250,15 @@ export class LionSelectRich extends ScopedElementsMixin(
} }
} }
async __initInteractionStates() {
await this.registrationComplete;
// This timeout is here, so that we know we handle after the initial model-value
// event (see firstUpdated method FormConrtolMixin) has fired.
setTimeout(() => {
this.initInteractionState();
});
}
get _inputNode() { get _inputNode() {
// In FormControl, we get direct child [slot="input"]. This doesn't work, because the overlay // In FormControl, we get direct child [slot="input"]. This doesn't work, because the overlay
// system wraps it in [slot="_overlay-shadow-outlet"] // system wraps it in [slot="_overlay-shadow-outlet"]
@ -298,6 +307,10 @@ export class LionSelectRich extends ScopedElementsMixin(
this._invokerNode.setAttribute('aria-invalid', this._hasFeedbackVisibleFor('error')); this._invokerNode.setAttribute('aria-invalid', this._hasFeedbackVisibleFor('error'));
} }
} }
if (changedProperties.has('modelValue')) {
this.__syncInvokerElement();
}
} }
toggle() { toggle() {
@ -345,24 +358,27 @@ export class LionSelectRich extends ScopedElementsMixin(
this.__setAttributeForAllFormElements('aria-setsize', this.formElements.length); this.__setAttributeForAllFormElements('aria-setsize', this.formElements.length);
child.setAttribute('aria-posinset', this.formElements.length); child.setAttribute('aria-posinset', this.formElements.length);
this.__onChildModelValueChanged({ target: child }); this.__proxyChildModelValueChanged({ target: child });
this.resetInteractionState(); this.resetInteractionState();
/* eslint-enable no-param-reassign */ /* eslint-enable no-param-reassign */
} }
__setupEventListeners() { __setupEventListeners() {
this.__onChildActiveChanged = this.__onChildActiveChanged.bind(this); this.__onChildActiveChanged = this.__onChildActiveChanged.bind(this);
this.__onChildModelValueChanged = this.__onChildModelValueChanged.bind(this); this.__proxyChildModelValueChanged = this.__proxyChildModelValueChanged.bind(this);
this.__onKeyUp = this.__onKeyUp.bind(this); this.__onKeyUp = this.__onKeyUp.bind(this);
this._listboxNode.addEventListener('active-changed', this.__onChildActiveChanged); this._listboxNode.addEventListener('active-changed', this.__onChildActiveChanged);
this._listboxNode.addEventListener('model-value-changed', this.__onChildModelValueChanged); this._listboxNode.addEventListener('model-value-changed', this.__proxyChildModelValueChanged);
this.addEventListener('keyup', this.__onKeyUp); this.addEventListener('keyup', this.__onKeyUp);
} }
__teardownEventListeners() { __teardownEventListeners() {
this._listboxNode.removeEventListener('active-changed', this.__onChildActiveChanged); this._listboxNode.removeEventListener('active-changed', this.__onChildActiveChanged);
this._listboxNode.removeEventListener('model-value-changed', this.__onChildModelValueChanged); this._listboxNode.removeEventListener(
'model-value-changed',
this.__proxyChildModelValueChanged,
);
this._listboxNode.removeEventListener('keyup', this.__onKeyUp); this._listboxNode.removeEventListener('keyup', this.__onKeyUp);
} }
@ -391,16 +407,14 @@ export class LionSelectRich extends ScopedElementsMixin(
}); });
} }
__onChildModelValueChanged({ target }) { __proxyChildModelValueChanged(ev) {
if (target.checked) { // We need to redispatch the model-value-changed event on 'this', so it will
this.formElements.forEach(formElement => { // align with FormControl.__repropagateChildrenValues method. Also, this makes
if (formElement !== target) { // it act like a portal, in case the listbox is put in a modal overlay on body level.
// eslint-disable-next-line no-param-reassign if (ev.stopPropagation) {
formElement.checked = false; ev.stopPropagation();
}
});
this.modelValue = target.value;
} }
this.dispatchEvent(new CustomEvent('model-value-changed', { detail: { element: ev.target } }));
} }
__syncInvokerElement() { __syncInvokerElement() {

View file

@ -1,5 +1,6 @@
import { Required } from '@lion/validate'; import { Required } from '@lion/validate';
import { expect, fixture, html, triggerBlurFor, triggerFocusFor } from '@open-wc/testing'; import { expect, html, triggerBlurFor, triggerFocusFor } from '@open-wc/testing';
import { formFixture as fixture } from '@lion/field/test-helpers.js';
import '../lion-option.js'; import '../lion-option.js';
import '../lion-options.js'; import '../lion-options.js';

View file

@ -1,15 +1,9 @@
import { LitElement } from '@lion/core'; import { LitElement } from '@lion/core';
import { OverlayController } from '@lion/overlays'; import { OverlayController } from '@lion/overlays';
import { Required } from '@lion/validate'; import { Required } from '@lion/validate';
import { import { aTimeout, defineCE, expect, html, nextFrame, unsafeStatic } from '@open-wc/testing';
aTimeout, import { formFixture as fixture } from '@lion/field/test-helpers.js';
defineCE,
expect,
fixture,
html,
nextFrame,
unsafeStatic,
} from '@open-wc/testing';
import { LionSelectRich } from '../index.js'; import { LionSelectRich } from '../index.js';
import '../lion-option.js'; import '../lion-option.js';
import '../lion-options.js'; import '../lion-options.js';
@ -246,6 +240,7 @@ describe('lion-select-rich', () => {
expect(el._invokerNode.selectedElement).dom.to.equal(options[1]); expect(el._invokerNode.selectedElement).dom.to.equal(options[1]);
el.checkedIndex = 0; el.checkedIndex = 0;
await el.updateComplete;
expect(el._invokerNode.selectedElement).dom.to.equal(options[0]); expect(el._invokerNode.selectedElement).dom.to.equal(options[0]);
}); });

View file

@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.5.19](https://github.com/ing-bank/lion/compare/@lion/select@0.5.18...@lion/select@0.5.19) (2020-03-19)
### Bug Fixes
* normalization model-value-changed events ([1b6c3a4](https://github.com/ing-bank/lion/commit/1b6c3a44c820b9d61c26849b91bbb1bc8d6c772b))
## [0.5.18](https://github.com/ing-bank/lion/compare/@lion/select@0.5.17...@lion/select@0.5.18) (2020-03-05) ## [0.5.18](https://github.com/ing-bank/lion/compare/@lion/select@0.5.17...@lion/select@0.5.18) (2020-03-05)
**Note:** Version bump only for package @lion/select **Note:** Version bump only for package @lion/select

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/select", "name": "@lion/select",
"version": "0.5.18", "version": "0.5.19",
"description": "Provide a set of options where you can select one", "description": "Provide a set of options where you can select one",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,7 +35,7 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3" "@lion/field": "0.11.4"
}, },
"devDependencies": { "devDependencies": {
"@lion/validate": "0.8.0", "@lion/validate": "0.8.0",

View file

@ -32,16 +32,16 @@ import { LionField } from '@lion/field';
export class LionSelect extends LionField { export class LionSelect extends LionField {
connectedCallback() { connectedCallback() {
super.connectedCallback(); super.connectedCallback();
this.addEventListener('change', this._proxyChangeEvent); this._inputNode.addEventListener('change', this._proxyChangeEvent);
} }
disconnectedCallback() { disconnectedCallback() {
super.disconnectedCallback(); super.disconnectedCallback();
this.removeEventListener('change', this._proxyChangeEvent); this._inputNode.removeEventListener('change', this._proxyChangeEvent);
} }
_proxyChangeEvent() { _proxyChangeEvent() {
this._inputNode.dispatchEvent( this.dispatchEvent(
new CustomEvent('user-input-changed', { new CustomEvent('user-input-changed', {
bubbles: true, bubbles: true,
composed: true, composed: true,

View file

@ -118,7 +118,7 @@ If you have an intermediate step loading data via AJAX request and then automati
If you need to be notified when transition between steps happens use `transition` event providing steps data: If you need to be notified when transition between steps happens use `transition` event providing steps data:
```html ```html
<lion-steps on-transition="onTransition"> <lion-steps @transition="${onTransition}">
<lion-step>Step 1</lion-step> <lion-step>Step 1</lion-step>
<lion-step>Step 2</lion-step> <lion-step>Step 2</lion-step>
<lion-step>Step 3</lion-step> <lion-step>Step 3</lion-step>
@ -140,9 +140,9 @@ For notifications about specific step status change you can use individual event
```html ```html
<lion-steps> <lion-steps>
<lion-step on-left="onLeft">Step 1</lion-step> <lion-step @leave="${onLeave}">Step 1</lion-step>
<lion-step on-skipped="onSkipped">Step 2</lion-step> <lion-step @skip="${onSkip}">Step 2</lion-step>
<lion-step on-entered="onEntered">Step 3</lion-step> <lion-step @enter="${onEnter}">Step 3</lion-step>
</lion-steps> </lion-steps>
``` ```

View file

@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.7.2](https://github.com/ing-bank/lion/compare/@lion/switch@0.7.1...@lion/switch@0.7.2) (2020-03-19)
**Note:** Version bump only for package @lion/switch
## [0.7.1](https://github.com/ing-bank/lion/compare/@lion/switch@0.7.0...@lion/switch@0.7.1) (2020-03-12)
**Note:** Version bump only for package @lion/switch
# [0.7.0](https://github.com/ing-bank/lion/compare/@lion/switch@0.6.3...@lion/switch@0.7.0) (2020-03-05) # [0.7.0](https://github.com/ing-bank/lion/compare/@lion/switch@0.6.3...@lion/switch@0.7.0) (2020-03-05)

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/switch", "name": "@lion/switch",
"version": "0.7.0", "version": "0.7.2",
"description": "A Switch is used for switching a property or feature on and off", "description": "A Switch is used for switching a property or feature on and off",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -34,9 +34,9 @@
"*.js" "*.js"
], ],
"dependencies": { "dependencies": {
"@lion/choice-input": "0.7.5", "@lion/choice-input": "0.7.7",
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3" "@lion/field": "0.11.4"
}, },
"devDependencies": { "devDependencies": {
"@lion/helpers": "0.3.3", "@lion/helpers": "0.3.3",

View file

@ -34,8 +34,6 @@ import '../lion-tabs.js';
npm i --save @lion/tabs; npm i --save @lion/tabs;
``` ```
### Usage
```js ```js
import '@lion/tabs/lion-tabs.js'; import '@lion/tabs/lion-tabs.js';
``` ```

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.5.20](https://github.com/ing-bank/lion/compare/@lion/textarea@0.5.19...@lion/textarea@0.5.20) (2020-03-19)
**Note:** Version bump only for package @lion/textarea
## [0.5.19](https://github.com/ing-bank/lion/compare/@lion/textarea@0.5.18...@lion/textarea@0.5.19) (2020-03-05) ## [0.5.19](https://github.com/ing-bank/lion/compare/@lion/textarea@0.5.18...@lion/textarea@0.5.19) (2020-03-05)
**Note:** Version bump only for package @lion/textarea **Note:** Version bump only for package @lion/textarea

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/textarea", "name": "@lion/textarea",
"version": "0.5.19", "version": "0.5.20",
"description": "Provide a way for users to write text that is multiple lines long", "description": "Provide a way for users to write text that is multiple lines long",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,7 +35,7 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/field": "0.11.3", "@lion/field": "0.11.4",
"autosize": "4.0.2" "autosize": "4.0.2"
}, },
"devDependencies": { "devDependencies": {

View file

@ -11,7 +11,7 @@ import '../lion-textarea.js';
Its purpose is to provide a way for users to write text that is multiple lines long. Its purpose is to provide a way for users to write text that is multiple lines long.
<Preview> <Preview>
<Story name="default"> <Story name="Default">
{html` {html`
<lion-textarea label="Stops growing after 4 rows" max-rows="4"></lion-textarea> <lion-textarea label="Stops growing after 4 rows" max-rows="4"></lion-textarea>
`} `}

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.8.5](https://github.com/ing-bank/lion/compare/@lion/tooltip@0.8.4...@lion/tooltip@0.8.5) (2020-03-19)
**Note:** Version bump only for package @lion/tooltip
## [0.8.4](https://github.com/ing-bank/lion/compare/@lion/tooltip@0.8.3...@lion/tooltip@0.8.4) (2020-03-05) ## [0.8.4](https://github.com/ing-bank/lion/compare/@lion/tooltip@0.8.3...@lion/tooltip@0.8.4) (2020-03-05)
**Note:** Version bump only for package @lion/tooltip **Note:** Version bump only for package @lion/tooltip

View file

@ -1,6 +1,6 @@
{ {
"name": "@lion/tooltip", "name": "@lion/tooltip",
"version": "0.8.4", "version": "0.8.5",
"description": "Show relative overlay content on hover", "description": "Show relative overlay content on hover",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
@ -35,7 +35,7 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.4.5", "@lion/core": "0.4.5",
"@lion/overlays": "0.12.4" "@lion/overlays": "0.12.5"
}, },
"devDependencies": { "devDependencies": {
"@open-wc/demoing-storybook": "^1.10.4", "@open-wc/demoing-storybook": "^1.10.4",