Socket
Socket
Sign inDemoInstall

@lion/form-core

Package Overview
Dependencies
2
Maintainers
1
Versions
73
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.6 to 0.3.0

11

CHANGELOG.md

@@ -6,2 +6,13 @@ # Change Log

# [0.3.0](https://github.com/ing-bank/lion/compare/@lion/form-core@0.2.6...@lion/form-core@0.3.0) (2020-07-27)
### Features
* synchronous form registration system ([8698f73](https://github.com/ing-bank/lion/commit/8698f734186eb88c4669bbadf8d5ae461f1c27f5))
## [0.2.6](https://github.com/ing-bank/lion/compare/@lion/form-core@0.2.5...@lion/form-core@0.2.6) (2020-07-16)

@@ -8,0 +19,0 @@

4

package.json
{
"name": "@lion/form-core",
"version": "0.2.6",
"version": "0.3.0",
"description": "Form-core contains all essential building blocks for creating form fields and fieldsets",

@@ -46,3 +46,3 @@ "license": "MIT",

},
"gitHead": "48b145fc22a4a4206a40e657bd4f729c541d0270"
"gitHead": "bb4190d5212d570c0572c77a5946db250ad402da"
}

@@ -33,3 +33,10 @@ import { dedupeMixin } from '@lion/core';

set modelValue(value) {
this._setCheckedElements(value, (el, val) => el.modelValue.value === val);
if (this.__isInitialModelValue) {
this.__isInitialModelValue = false;
this.registrationComplete.then(() => {
this._setCheckedElements(value, (el, val) => el.modelValue.value === val);
});
} else {
this._setCheckedElements(value, (el, val) => el.modelValue.value === val);
}
}

@@ -54,3 +61,10 @@

set serializedValue(value) {
this._setCheckedElements(value, (el, val) => el.serializedValue.value === val);
if (this.__isInitialSerializedValue) {
this.__isInitialSerializedValue = false;
this.registrationComplete.then(() => {
this._setCheckedElements(value, (el, val) => el.serializedValue.value === val);
});
} else {
this._setCheckedElements(value, (el, val) => el.serializedValue.value === val);
}
}

@@ -62,4 +76,47 @@

this._repropagationRole = 'choice-group'; // configures event propagation logic of FormControlMixin
this.__isInitialModelValue = true;
this.__isInitialSerializedValue = true;
this.registrationComplete = new Promise((resolve, reject) => {
this.__resolveRegistrationComplete = resolve;
this.__rejectRegistrationComplete = reject;
});
this.registrationComplete.done = false;
this.registrationComplete.then(
() => {
this.registrationComplete.done = true;
},
() => {
this.registrationComplete.done = true;
throw new Error(
'Registration could not finish. Please use await el.registrationComplete;',
);
},
);
}
connectedCallback() {
super.connectedCallback();
this.__registrationCompleteTimer = setTimeout(() => {
this.__resolveRegistrationComplete();
});
this.registrationComplete.then(() => {
this.__isInitialModelValue = false;
this.__isInitialSerializedValue = false;
});
}
disconnectedCallback() {
if (super.disconnectedCallback) {
super.disconnectedCallback();
}
clearTimeout(this.__registrationCompleteTimer);
if (this.registrationComplete.done === false) {
this.__rejectRegistrationComplete();
}
}
/**

@@ -75,2 +132,11 @@ * @override from FormRegistrarMixin

/**
* @override from FormControlMixin
*/
_triggerInitialModelValueChangedEvent() {
this.registrationComplete.then(() => {
this.__dispatchInitialModelValueChangedEvent();
});
}
/**
* @override

@@ -136,7 +202,3 @@ */

async _setCheckedElements(value, check) {
if (!this.__readyForRegistration) {
await this.registrationReady;
}
_setCheckedElements(value, check) {
for (let i = 0; i < this.formElements.length; i += 1) {

@@ -143,0 +205,0 @@ if (this.multipleChoice) {

@@ -79,3 +79,10 @@ import { dedupeMixin, html, SlotMixin } from '@lion/core';

set modelValue(values) {
this._setValueMapForAllFormElements('modelValue', values);
if (this.__isInitialModelValue) {
this.__isInitialModelValue = false;
this.registrationComplete.then(() => {
this._setValueMapForAllFormElements('modelValue', values);
});
} else {
this._setValueMapForAllFormElements('modelValue', values);
}
}

@@ -88,3 +95,10 @@

set serializedValue(values) {
this._setValueMapForAllFormElements('serializedValue', values);
if (this.__isInitialSerializedValue) {
this.__isInitialSerializedValue = false;
this.registrationComplete.then(() => {
this._setValueMapForAllFormElements('serializedValue', values);
});
} else {
this._setValueMapForAllFormElements('serializedValue', values);
}
}

@@ -112,2 +126,4 @@

this.__addedSubValidators = false;
this.__isInitialModelValue = true;
this.__isInitialSerializedValue = true;

@@ -122,13 +138,40 @@ this._checkForOutsideClick = this._checkForOutsideClick.bind(this);

this.defaultValidators = [new FormElementsHaveNoError()];
this.registrationComplete = new Promise((resolve, reject) => {
this.__resolveRegistrationComplete = resolve;
this.__rejectRegistrationComplete = reject;
});
this.registrationComplete.done = false;
this.registrationComplete.then(
() => {
this.registrationComplete.done = true;
},
() => {
this.registrationComplete.done = true;
throw new Error(
'Registration could not finish. Please use await el.registrationComplete;',
);
},
);
}
connectedCallback() {
// eslint-disable-next-line wc/guard-super-call
super.connectedCallback();
this.setAttribute('role', 'group');
this.__initInteractionStates();
this.__registrationCompleteTimer = setTimeout(() => {
this.__resolveRegistrationComplete();
});
this.registrationComplete.then(() => {
this.__isInitialModelValue = false;
this.__isInitialSerializedValue = false;
this.__initInteractionStates();
});
}
disconnectedCallback() {
super.disconnectedCallback(); // eslint-disable-line wc/guard-super-call
if (super.disconnectedCallback) {
super.disconnectedCallback();
}

@@ -139,8 +182,9 @@ if (this.__hasActiveOutsideClickHandling) {

}
clearTimeout(this.__registrationCompleteTimer);
if (this.registrationComplete.done === false) {
this.__rejectRegistrationComplete();
}
}
async __initInteractionStates() {
if (!this.registrationHasCompleted) {
await this.registrationComplete;
}
__initInteractionStates() {
this.formElements.forEach(el => {

@@ -153,2 +197,11 @@ if (typeof el.initInteractionState === 'function') {

/**
* @override from FormControlMixin
*/
_triggerInitialModelValueChangedEvent() {
this.registrationComplete.then(() => {
this.__dispatchInitialModelValueChangedEvent();
});
}
updated(changedProperties) {

@@ -278,6 +331,3 @@ super.updated(changedProperties);

async _setValueForAllFormElements(property, value) {
if (!this.__readyForRegistration) {
await this.registrationReady;
}
_setValueForAllFormElements(property, value) {
this.formElements.forEach(el => {

@@ -288,7 +338,3 @@ el[property] = value; // eslint-disable-line no-param-reassign

async _setValueMapForAllFormElements(property, values) {
if (!this.__readyForRegistration) {
await this.registrationReady;
}
_setValueMapForAllFormElements(property, values) {
if (values && typeof values === 'object') {

@@ -295,0 +341,0 @@ Object.keys(values).forEach(name => {

@@ -177,4 +177,9 @@ import { css, dedupeMixin, html, nothing, SlotMixin } from '@lion/core';

this._enhanceLightDomA11y();
this._triggerInitialModelValueChangedEvent();
}
_triggerInitialModelValueChangedEvent() {
this.__dispatchInitialModelValueChangedEvent();
}
_enhanceLightDomClasses() {

@@ -594,8 +599,3 @@ if (this._inputNode) {

firstUpdated(changedProperties) {
super.firstUpdated(changedProperties);
this.__dispatchInitialModelValueChangedEvent();
}
async __dispatchInitialModelValueChangedEvent() {
__dispatchInitialModelValueChangedEvent() {
// When we are not a fieldset / choice-group, we don't need to wait for our children

@@ -607,3 +607,2 @@ // to send a unified event

await this.registrationComplete;
// Initially we don't repropagate model-value-changed events coming

@@ -610,0 +609,0 @@ // from children. On firstUpdated we re-dispatch this event to maintain

import { dedupeMixin } from '@lion/core';
import { formRegistrarManager } from './formRegistrarManager.js';

@@ -16,7 +15,2 @@ /**

class FormRegisteringMixin extends superclass {
constructor() {
super();
this.__boundDispatchRegistration = this._dispatchRegistration.bind(this);
}
connectedCallback() {

@@ -26,24 +20,2 @@ if (super.connectedCallback) {

}
this.__setupRegistrationHook();
}
disconnectedCallback() {
if (super.disconnectedCallback) {
super.disconnectedCallback();
}
this._unregisterFormElement();
}
__setupRegistrationHook() {
if (formRegistrarManager.ready) {
this._dispatchRegistration();
} else {
formRegistrarManager.addEventListener(
'all-forms-open-for-registration',
this.__boundDispatchRegistration,
);
}
}
_dispatchRegistration() {
this.dispatchEvent(

@@ -55,9 +27,8 @@ new CustomEvent('form-element-register', {

);
formRegistrarManager.removeEventListener(
'all-forms-open-for-registration',
this.__boundDispatchRegistration,
);
}
_unregisterFormElement() {
disconnectedCallback() {
if (super.disconnectedCallback) {
super.disconnectedCallback();
}
if (this.__parentFormGroup) {

@@ -64,0 +35,0 @@ this.__parentFormGroup.removeFormElement(this);

// eslint-disable-next-line max-classes-per-file
import { dedupeMixin } from '@lion/core';
import { FormRegisteringMixin } from './FormRegisteringMixin.js';
import { formRegistrarManager } from './formRegistrarManager.js';
import { FormControlsCollection } from './FormControlsCollection.js';

@@ -34,3 +33,3 @@

*/
_isFormOrFieldset: Boolean,
_isFormOrFieldset: { type: Boolean },
};

@@ -45,11 +44,2 @@ }

this.__readyForRegistration = false;
this.__hasBeenRendered = false;
this.registrationReady = new Promise(resolve => {
this.__resolveRegistrationReady = resolve;
});
this.registrationComplete = new Promise(resolve => {
this.__resolveRegistrationComplete = resolve;
});
this._onRequestToAddFormElement = this._onRequestToAddFormElement.bind(this);

@@ -59,19 +49,2 @@ this.addEventListener('form-element-register', this._onRequestToAddFormElement);

connectedCallback() {
if (super.connectedCallback) {
super.connectedCallback();
}
formRegistrarManager.add(this);
if (this.__hasBeenRendered) {
formRegistrarManager.becomesReady();
}
}
disconnectedCallback() {
if (super.disconnectedCallback) {
super.disconnectedCallback();
}
formRegistrarManager.remove(this);
}
isRegisteredFormElement(el) {

@@ -81,20 +54,2 @@ return this.formElements.some(exitingEl => exitingEl === el);

firstUpdated(changedProperties) {
super.firstUpdated(changedProperties);
this.__resolveRegistrationReady();
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();
this.__hasBeenRendered = true;
}
addFormElement(child, indexToInsertAt) {

@@ -101,0 +56,0 @@ // This is a way to let the child element (a lion-fieldset or lion-field) know, about its parent

import { dedupeMixin } from '@lion/core';
import { formRegistrarManager } from './formRegistrarManager.js';

@@ -22,30 +21,6 @@ /**

super();
this.formElements = [];
this.registrationTarget = undefined;
this.__hasBeenRendered = false;
this.__readyForRegistration = false;
this.registrationReady = new Promise(resolve => {
this.__resolveRegistrationReady = resolve;
});
}
connectedCallback() {
if (super.connectedCallback) {
super.connectedCallback();
}
formRegistrarManager.add(this);
if (this.__hasBeenRendered) {
formRegistrarManager.becomesReady();
}
this.__redispatchEventForFormRegistrarPortalMixin = ev => {
ev.stopPropagation();
this.registrationTarget.dispatchEvent(
new CustomEvent('form-element-register', {
detail: { element: ev.detail.element },
bubbles: true,
}),
);
};
this.__redispatchEventForFormRegistrarPortalMixin = this.__redispatchEventForFormRegistrarPortalMixin.bind(
this,
);
this.addEventListener(

@@ -57,28 +32,15 @@ 'form-element-register',

disconnectedCallback() {
if (super.disconnectedCallback) {
super.disconnectedCallback();
}
formRegistrarManager.remove(this);
this.removeEventListener(
'form-element-register',
this.__redispatchEventForFormRegistrarPortalMixin,
);
}
firstUpdated(changedProperties) {
this.__checkRegistrationTarget();
super.firstUpdated(changedProperties);
this.__resolveRegistrationReady();
this.__readyForRegistration = true;
formRegistrarManager.becomesReady(this);
this.__hasBeenRendered = true;
}
__checkRegistrationTarget() {
__redispatchEventForFormRegistrarPortalMixin(ev) {
ev.stopPropagation();
if (!this.registrationTarget) {
throw new Error('A FormRegistrarPortal element requires a .registrationTarget');
}
this.registrationTarget.dispatchEvent(
new CustomEvent('form-element-register', {
detail: { element: ev.detail.element },
bubbles: true,
}),
);
}
},
);

@@ -1,2 +0,1 @@

export { formFixture } from './test-helpers/formFixture.js';
export {

@@ -3,0 +2,0 @@ AlwaysInvalid,

import { html, LitElement } from '@lion/core';
import { formFixture as fixture } from '@lion/form-core/test-helpers.js';
import '@lion/fieldset/lion-fieldset.js';
import { LionInput } from '@lion/input';
import { FormGroupMixin, Required } from '@lion/form-core';
import { expect, nextFrame } from '@open-wc/testing';
import { expect, fixture } from '@open-wc/testing';
import { ChoiceGroupMixin } from '../../src/choice-group/ChoiceGroupMixin.js';

@@ -35,3 +34,2 @@ import { ChoiceInputMixin } from '../../src/choice-group/ChoiceInputMixin.js';

`);
await nextFrame();
expect(el.modelValue).to.equal('female');

@@ -52,3 +50,2 @@ el.formElements[0].checked = true;

`);
await nextFrame();
const invalidChild = await fixture(html`

@@ -72,3 +69,3 @@ <choice-group-input .modelValue=${'Lara'}></choice-group-input>

`);
await nextFrame();
await el.registrationComplete;

@@ -93,3 +90,3 @@ expect(el.formElements[0].name).to.equal('gender');

`);
await nextFrame();
const invalidChild = await fixture(html`

@@ -114,7 +111,4 @@ <choice-group-input name="foo" .choiceValue=${'male'}></choice-group-input>

`);
await el.registrationComplete;
await nextFrame();
await el.registrationReady;
await el.updateComplete;
expect(el.modelValue).to.equal('other');

@@ -132,4 +126,6 @@ expect(el.formElements[2].checked).to.be.true;

`);
await el.registrationComplete;
expect(el.serializedValue).to.equal('other');
expect(el.formElements[2].checked).to.be.true;
});

@@ -146,3 +142,2 @@

`);
await nextFrame();

@@ -161,3 +156,2 @@ expect(el.modelValue).to.equal(date);

`);
await nextFrame();

@@ -181,3 +175,4 @@ expect(el.modelValue).to.equal(0);

`);
await nextFrame();
await el.registrationComplete;
expect(el.modelValue).to.equal('female');

@@ -202,3 +197,4 @@ el.modelValue = 'other';

`);
await nextFrame();
await el.registrationComplete;
counter = 0; // reset after setup which may result in different results

@@ -266,3 +262,2 @@

`);
await nextFrame();

@@ -281,3 +276,3 @@ expect(el.serializedValue).to.deep.equal('');

`);
await nextFrame();
expect(el.modelValue).to.eql(['female']);

@@ -299,5 +294,3 @@ el.formElements[0].checked = true;

await nextFrame();
await el.registrationReady;
await el.updateComplete;
await el.registrationComplete;
el.modelValue = ['male', 'other'];

@@ -318,5 +311,3 @@ expect(el.modelValue).to.eql(['male', 'other']);

await nextFrame();
await el.registrationReady;
await el.updateComplete;
await el.registrationComplete;
expect(el.modelValue).to.eql(['male', 'other']);

@@ -345,4 +336,2 @@ expect(el.formElements[0].checked).to.be.true;

await nextFrame();
await el.registrationReady;
await el.updateComplete;

@@ -349,0 +338,0 @@ expect(el.serializedValue).to.eql({

@@ -1,5 +0,4 @@

import { expect, html, defineCE, unsafeStatic } from '@open-wc/testing';
import { expect, html, defineCE, unsafeStatic, fixture } from '@open-wc/testing';
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';

@@ -222,2 +221,4 @@ import { FormRegistrarMixin } from '../src/registration/FormRegistrarMixin.js';

const fieldsetEl = formEl.querySelector('[name=fieldset]');
await formEl.registrationComplete;
await fieldsetEl.registrationComplete;

@@ -224,0 +225,0 @@ expect(fieldsetSpy.callCount).to.equal(1);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc