Socket
Socket
Sign inDemoInstall

@lion/form-core

Package Overview
Dependencies
Maintainers
1
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.6.14 to 0.7.0

18

CHANGELOG.md
# Change Log
## 0.7.0
### Minor Changes
- a8cf4215: Added `isTriggeredByUser` meta data in `model-value-changed` event
Sometimes it can be helpful to detect whether a value change was caused by a user or via a programmatical change.
This feature acts as a normalization layer: since we use `model-value-changed` as a single source of truth event for all FormControls, there should be no use cases for (inconsistently implemented (cross browser)) events like `input`/`change`/`user-input-changed` etc.
### Patch Changes
- 5302ec89: Minimise dependencies by removing integration demos to form-integrations and form-core packages.
- 98f1bb7e: Ensure all lit imports are imported from @lion/core. Remove devDependencies in all subpackages and move to root package.json. Add demo dependencies as real dependencies for users that extend our docs/demos.
- Updated dependencies [a8cf4215]
- Updated dependencies [98f1bb7e]
- @lion/localize@0.15.4
- @lion/core@0.13.7
## 0.6.14

@@ -4,0 +22,0 @@

32

docs/validate/README.md

@@ -8,3 +8,3 @@ [//]: # 'AUTO INSERT HEADER PREPUBLISH'

import { LionInput } from '@lion/input';
import { Required, IsString, MaxLength, DefaultSuccess, Validator } from '@lion/form-core';
import { Required, IsString, MaxLength, DefaultSuccess, Validator } from '../../index.js';

@@ -16,4 +16,2 @@ import { loadDefaultFeedbackMessages } from '@lion/validate-messages';

};
loadDefaultFeedbackMessages();
```

@@ -114,1 +112,29 @@

```
## Default Validation Messages
Lion comes with a set of localized messages for default Validators.
Once the method `loadDefaultFeedbackMessages` is called, it will make sure that all validators provided in `@lion/form-core` will have a default error message.
It uses the `@lion/localize` system to provide these translations and has support for more than 15 locales.
```bash
npm i --save @lion/validate-messages
```
```js
import { loadDefaultFeedbackMessages } from '@lion/validate-messages';
```
```js preview-story
export const defaultValidationMessages = () => {
loadDefaultFeedbackMessages();
return html`
<lion-input
name="value"
label="Value"
.fieldName="${'value'}"
.validators="${[new Required()]}"
></lion-input>
`;
};
```

@@ -9,2 +9,3 @@ export { FocusMixin } from "./src/FocusMixin.js";

export { FormRegistrarPortalMixin } from "./src/registration/FormRegistrarPortalMixin.js";
export { NativeTextFieldMixin } from "./src/NativeTextFieldMixin.js";
export { FormControlsCollection } from "./src/registration/FormControlsCollection.js";

@@ -11,0 +12,0 @@ export { ValidateMixin } from "./src/validate/ValidateMixin.js";

@@ -9,2 +9,3 @@ export { FocusMixin } from './src/FocusMixin.js';

export { FormRegistrarPortalMixin } from './src/registration/FormRegistrarPortalMixin.js';
export { NativeTextFieldMixin } from './src/NativeTextFieldMixin.js';
export { FormControlsCollection } from './src/registration/FormControlsCollection.js';

@@ -11,0 +12,0 @@

6

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

@@ -37,4 +37,4 @@ "license": "MIT",

"dependencies": {
"@lion/core": "0.13.6",
"@lion/localize": "0.15.3"
"@lion/core": "0.13.7",
"@lion/localize": "0.15.4"
},

@@ -41,0 +41,0 @@ "keywords": [

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

/** @param {import('lit-element').PropertyValues} changedProperties */
/** @param {import('@lion/core').PropertyValues} changedProperties */
updated(changedProperties) {

@@ -167,0 +167,0 @@ super.updated(changedProperties);

@@ -95,3 +95,3 @@ /* eslint-disable class-methods-use-this */

/**
* @param {import('lit-element').PropertyValues } changedProperties
* @param {import('@lion/core').PropertyValues } changedProperties
*/

@@ -108,3 +108,3 @@ firstUpdated(changedProperties) {

/**
* @param {import('lit-element').PropertyValues } changedProperties
* @param {import('@lion/core').PropertyValues } changedProperties
*/

@@ -180,2 +180,3 @@ updated(changedProperties) {

</small>
${this._afterTemplate()}
`;

@@ -188,2 +189,6 @@ }

_afterTemplate() {
return nothing;
}
connectedCallback() {

@@ -203,3 +208,5 @@ super.connectedCallback();

}
this.__isHandlingUserInput = true;
this.checked = !this.checked;
this.__isHandlingUserInput = false;
}

@@ -206,0 +213,0 @@

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

import { dedupeMixin, html, SlotMixin } from '@lion/core';
import { DisabledMixin } from '@lion/core/src/DisabledMixin.js';
import { dedupeMixin, html, SlotMixin, DisabledMixin } from '@lion/core';
import { FormControlMixin } from '../FormControlMixin.js';

@@ -210,3 +209,3 @@ import { FormControlsCollection } from '../registration/FormControlsCollection.js';

/**
* @param {import('lit-element').PropertyValues } changedProperties
* @param {import('@lion/core').PropertyValues } changedProperties
*/

@@ -213,0 +212,0 @@ updated(changedProperties) {

export type FormatMixin = typeof import("../types/FormatMixinTypes.js").FormatImplementation;
export const FormatMixin: typeof import("../types/FormatMixinTypes.js").FormatImplementation;
export type FormatOptions = import("@lion/localize/types/LocalizeMixinTypes").FormatNumberOptions;
export type ModelValueEventDetails = {
formPath: HTMLElement[];
isTriggeredByUser: boolean;
initialize?: boolean | undefined;
};

@@ -11,2 +11,3 @@ /* eslint-disable class-methods-use-this */

* @typedef {import('@lion/localize/types/LocalizeMixinTypes').FormatNumberOptions} FormatOptions
* @typedef {import('../types/FormControlMixinTypes.js').ModelValueEventDetails} ModelValueEventDetails
*/

@@ -320,3 +321,6 @@

bubbles: true,
detail: { formPath: [this] },
detail: /** @type { ModelValueEventDetails } */ ({
formPath: [this],
isTriggeredByUser: Boolean(this.__isHandlingUserInput),
}),
}),

@@ -323,0 +327,0 @@ );

@@ -1,43 +0,14 @@

/**
* #FormControlMixin :
*
* This Mixin is a shared fundament for all form components, it's applied on:
* - LionField (which is extended to LionInput, LionTextarea, LionSelect etc. etc.)
* - LionFieldset (which is extended to LionRadioGroup, LionCheckboxGroup, LionForm)
*/
export type FormControlMixin = typeof import("../types/FormControlMixinTypes.js").FormControlImplementation;
export const FormControlMixin: typeof import("../types/FormControlMixinTypes.js").FormControlImplementation;
/**
* #FormControlMixin :
*
* This Mixin is a shared fundament for all form components, it's applied on:
* - LionField (which is extended to LionInput, LionTextarea, LionSelect etc. etc.)
* - LionFieldset (which is extended to LionRadioGroup, LionCheckboxGroup, LionForm)
*/
export type TemplateResult = import("lit-element").TemplateResult;
/**
* #FormControlMixin :
*
* This Mixin is a shared fundament for all form components, it's applied on:
* - LionField (which is extended to LionInput, LionTextarea, LionSelect etc. etc.)
* - LionFieldset (which is extended to LionRadioGroup, LionCheckboxGroup, LionForm)
*/
export type CSSResult = import("lit-element").CSSResult;
/**
* #FormControlMixin :
*
* This Mixin is a shared fundament for all form components, it's applied on:
* - LionField (which is extended to LionInput, LionTextarea, LionSelect etc. etc.)
* - LionFieldset (which is extended to LionRadioGroup, LionCheckboxGroup, LionForm)
*/
export type TemplateResult = import("@lion/core").TemplateResult;
export type CSSResult = import("@lion/core").CSSResult;
export type nothing = any;
/**
* #FormControlMixin :
*
* This Mixin is a shared fundament for all form components, it's applied on:
* - LionField (which is extended to LionInput, LionTextarea, LionSelect etc. etc.)
* - LionFieldset (which is extended to LionRadioGroup, LionCheckboxGroup, LionForm)
*/
export type SlotsMap = {
[key: string]: typeof import("@lion/core/types/SlotMixinTypes").slotFunction;
};
export type FormControlHost = import("../types/FormControlMixinTypes.js").FormControlHost;
export type ModelValueEventDetails = {
formPath: HTMLElement[];
isTriggeredByUser: boolean;
initialize?: boolean | undefined;
};

@@ -8,2 +8,12 @@ import { css, dedupeMixin, html, nothing, SlotMixin } from '@lion/core';

/**
* @typedef {import('@lion/core').TemplateResult} TemplateResult
* @typedef {import('@lion/core').CSSResult} CSSResult
* @typedef {import('@lion/core').nothing} nothing
* @typedef {import('@lion/core/types/SlotMixinTypes').SlotsMap} SlotsMap
* @typedef {import('../types/FormControlMixinTypes.js').FormControlHost} FormControlHost
* @typedef {import('../types/FormControlMixinTypes.js').FormControlMixin} FormControlMixin
* @typedef {import('../types/FormControlMixinTypes.js').ModelValueEventDetails} ModelValueEventDetails
*/
/**
* Generates random unique identifier (for dom elements)

@@ -22,7 +32,2 @@ * @param {string} prefix

* - LionFieldset (which is extended to LionRadioGroup, LionCheckboxGroup, LionForm)
* @typedef {import('@lion/core').TemplateResult} TemplateResult
* @typedef {import('@lion/core').CSSResult} CSSResult
* @typedef {import('@lion/core').nothing} nothing
* @typedef {import('@lion/core/types/SlotMixinTypes').SlotsMap} SlotsMap
* @typedef {import('../types/FormControlMixinTypes.js').FormControlMixin} FormControlMixin
* @param {import('@open-wc/dedupe-mixin').Constructor<import('@lion/core').LitElement>} superclass

@@ -236,3 +241,3 @@ * @type {FormControlMixin}

/** @param {import('lit-element').PropertyValues } changedProperties */
/** @param {import('@lion/core').PropertyValues } changedProperties */
updated(changedProperties) {

@@ -756,3 +761,7 @@ super.updated(changedProperties);

bubbles: true,
detail: { formPath: [this], initialize: true },
detail: /** @type {ModelValueEventDetails} */ ({
formPath: [this],
initialize: true,
isTriggeredByUser: false,
}),
}),

@@ -829,3 +838,9 @@ );

this.dispatchEvent(
new CustomEvent('model-value-changed', { bubbles: true, detail: { formPath } }),
new CustomEvent('model-value-changed', {
bubbles: true,
detail: /** @type {ModelValueEventDetails} */ ({
formPath,
isTriggeredByUser: Boolean(ev.detail?.isTriggeredByUser),
}),
}),
);

@@ -832,0 +847,0 @@ }

@@ -49,3 +49,3 @@ import { LitElement, SlotMixin } from '@lion/core';

/**
* @param {import('lit-element').PropertyValues } changedProperties
* @param {import('@lion/core').PropertyValues } changedProperties
*/

@@ -52,0 +52,0 @@ firstUpdated(changedProperties) {

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

/** @param {import('lit-element').PropertyValues } changedProperties */
/** @param {import('@lion/core').PropertyValues } changedProperties */
firstUpdated(changedProperties) {

@@ -40,0 +40,0 @@ super.firstUpdated(changedProperties);

@@ -30,3 +30,3 @@ /**

validator: Validator;
}): string | Node | import("lit-element").TemplateResult;
}): string | Node | import("@lion/core").TemplateResult;
currentType: string | undefined;

@@ -38,3 +38,3 @@ removeMessage: number | undefined;

export type Validator = import("./Validator").Validator;
export type TemplateResult = import("lit-element").TemplateResult;
export type TemplateResult = import("@lion/core").TemplateResult;
export type messageMap = {

@@ -41,0 +41,0 @@ message: string | Node;

@@ -36,3 +36,3 @@ import { html, LitElement } from '@lion/core';

/**
* @param {import('lit-element').PropertyValues } changedProperties
* @param {import('@lion/core').PropertyValues } changedProperties
*/

@@ -39,0 +39,0 @@ updated(changedProperties) {

@@ -174,3 +174,3 @@ /* eslint-disable class-methods-use-this, camelcase, no-param-reassign, max-classes-per-file */

/**
* @param {import('lit-element').PropertyValues} changedProperties
* @param {import('@lion/core').PropertyValues} changedProperties
*/

@@ -474,3 +474,3 @@ firstUpdated(changedProperties) {

const errorType = Array.isArray(v) ? 'array' : typeof v;
const errorMessage = `Validators array only accepts class instances of Validator. Type "${errorType}" found.`;
const errorMessage = `Validators array only accepts class instances of Validator. Type "${errorType}" found. This may be caused by having multiple installations of @lion/form-core.`;
// eslint-disable-next-line no-console

@@ -612,3 +612,3 @@ console.error(errorMessage, this);

/** @param {import('lit-element').PropertyValues} changedProperties */
/** @param {import('@lion/core').PropertyValues} changedProperties */
updated(changedProperties) {

@@ -615,0 +615,0 @@ super.updated(changedProperties);

@@ -241,2 +241,3 @@ import { expect, html, defineCE, unsafeStatic, fixture } from '@open-wc/testing';

expect(fieldsetEv.detail.formPath).to.eql([fieldsetEl]);
expect(fieldsetEv.detail.initialize).to.be.true;

@@ -247,5 +248,9 @@ expect(formSpy.callCount).to.equal(1);

expect(formEv.detail.formPath).to.eql([formEl]);
expect(formEv.detail.initialize).to.be.true;
});
});
/**
* After initialization means: events triggered programmatically or by user actions
*/
describe('After initialization', () => {

@@ -315,2 +320,3 @@ it('redispatches one event from host and keeps formPath history', async () => {

expect(choiceGroupEv.detail.formPath).to.eql([choiceGroupEl]);
expect(choiceGroupEv.detail.isTriggeredByUser).to.be.false;

@@ -321,5 +327,38 @@ expect(formSpy.callCount).to.equal(1);

expect(formEv.detail.formPath).to.eql([choiceGroupEl, formEl]);
expect(formEv.detail.isTriggeredByUser).to.be.false;
});
it('sets "isTriggeredByUser" event detail when event triggered by user', 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 CustomEvent('model-value-changed', {
bubbles: true,
detail: { isTriggeredByUser: true },
}),
);
const fieldsetEv = fieldsetSpy.firstCall.args[0];
expect(fieldsetEv.detail.isTriggeredByUser).to.be.true;
const formEv = formSpy.firstCall.args[0];
expect(formEv.detail.isTriggeredByUser).to.be.true;
});
});
});
});

@@ -29,3 +29,3 @@ import { LitElement } from '@lion/core';

/** @param {import('lit-element').PropertyValues } changedProperties */
/** @param {import('@lion/core').PropertyValues } changedProperties */
firstUpdated(changedProperties) {

@@ -32,0 +32,0 @@ super.firstUpdated(changedProperties);

import { Constructor } from '@open-wc/dedupe-mixin';
import { LitElement, TemplateResult } from '@lion/core';
import { CSSResultArray } from 'lit-element';
import { CSSResultArray } from '@lion/core';
import { FormatHost } from '../FormatMixinTypes';

@@ -38,2 +38,3 @@

_choiceGraphicTemplate(): TemplateResult;
_afterTemplate(): TemplateResult;

@@ -51,2 +52,4 @@ connectedCallback(): void;

__isHandlingUserInput: boolean;
_proxyInputEvent(): void;

@@ -53,0 +56,0 @@

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

import { CSSResultArray } from 'lit-element';
import { LitElement, nothing, TemplateResult } from '@lion/core';
import { LitElement, nothing, TemplateResult, CSSResultArray } from '@lion/core';
import { SlotsMap, SlotHost } from '@lion/core/types/SlotMixinTypes';

@@ -10,2 +9,27 @@ import { Constructor } from '@open-wc/dedupe-mixin';

export type ModelValueEventDetails = {
/**
* A list that represents the path of FormControls the model-value-changed event
* 'traveled through'.
* (every FormControl stops propagation of its child and sends a new event, hereby adding
* itself to the beginning of formPath)
*/
formPath: HTMLElement[];
/**
* Sometimes it can be helpful to detect whether a value change was caused by a user or
* via a programmatical change.
* This feature acts as a normalization layer: since we use `model-value-changed` as a single
* source of truth event for all FormControls, there should be no use cases for
* (inconsistently implemented (cross browser)) events
* like 'input'/'change'/'user-input-changed' etc.)
*/
isTriggeredByUser: boolean;
/**
* Whether it is the first event sent on initialization of the form (other
* model-value-changed events are triggered imperatively or via user input (in the latter
* case `isTriggeredByUser` is true))
*/
initialize?: boolean;
};
declare interface HTMLElementWithValue extends HTMLElement {

@@ -45,8 +69,8 @@ value: string;

*/
readOnly: boolean;
public readOnly: boolean;
/**
* The name the element will be registered on to the .formElements collection
* The name the element will be registered with to the .formElements collection
* of the parent.
*/
name: string;
public name: string;
/**

@@ -64,3 +88,3 @@ * The model value is the result of the parser function(when available).

*/
modelValue: unknown;
public modelValue: unknown;
/**

@@ -70,4 +94,4 @@ * The label text for the input node.

*/
get label(): string;
set label(arg: string);
public get label(): string;
public set label(arg: string);
__label: string | undefined;

@@ -78,9 +102,9 @@ /**

*/
get helpText(): string;
set helpText(arg: string);
public get helpText(): string;
public set helpText(arg: string);
__helpText: string | undefined;
set fieldName(arg: string);
get fieldName(): string;
public set fieldName(arg: string);
public get fieldName(): string;
__fieldName: string | undefined;
get slots(): SlotsMap;
public get slots(): SlotsMap;
get _inputNode(): HTMLElementWithValue;

@@ -110,3 +134,3 @@ get _labelNode(): HTMLElement;

connectedCallback(): void;
updated(changedProperties: import('lit-element').PropertyValues): void;
updated(changedProperties: import('@lion/core').PropertyValues): void;

@@ -133,3 +157,3 @@ render(): TemplateResult;

_getAriaDescriptionElements(): HTMLElement[];
addToAriaLabelledBy(
public addToAriaLabelledBy(
element: HTMLElement,

@@ -142,3 +166,3 @@ customConfig?: {

__reorderAriaLabelledNodes: boolean | undefined;
addToAriaDescribedBy(
public addToAriaDescribedBy(
element: HTMLElement,

@@ -145,0 +169,0 @@ customConfig?: {

import { LitElement } from '@lion/core';
import { Constructor } from '@open-wc/dedupe-mixin';
import { PropertyValues } from 'lit-element';
import { PropertyValues } from '@lion/core';

@@ -5,0 +5,0 @@ export declare interface SyncUpdatableNamespace {

@@ -44,5 +44,5 @@ import { LitElement } from '@lion/core';

disconnectedCallback(): void;
firstUpdated(changedProperties: import('lit-element').PropertyValues): void;
firstUpdated(changedProperties: import('@lion/core').PropertyValues): void;
updateSync(name: string, oldValue: unknown): void;
updated(changedProperties: import('lit-element').PropertyValues): void;
updated(changedProperties: import('@lion/core').PropertyValues): void;

@@ -49,0 +49,0 @@ validate(opts?: { clearCurrentResult?: boolean }): void;

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc