@lion/ui 0.13.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/accordion/src/LionAccordion.js +3 -2
- package/components/button/src/LionButton.js +6 -10
- package/components/button/src/LionButtonReset.js +2 -0
- package/components/button/src/LionButtonSubmit.js +2 -0
- package/components/button/test-suites/LionButton.suite.js +0 -14
- package/components/checkbox-group/src/LionCheckbox.js +3 -0
- package/components/checkbox-group/src/LionCheckboxGroup.js +2 -0
- package/components/checkbox-group/src/LionCheckboxIndeterminate.js +3 -0
- package/components/collapsible/src/LionCollapsible.js +4 -1
- package/components/combobox/src/LionCombobox.js +5 -0
- package/components/dialog/src/LionDialog.js +3 -0
- package/components/drawer/src/LionDrawer.js +9 -0
- package/components/fieldset/src/LionFieldset.js +1 -1
- package/components/form/src/LionForm.js +0 -1
- package/components/form-core/src/FormControlMixin.js +10 -0
- package/components/form-core/src/FormatMixin.js +1 -1
- package/components/form-core/src/validate/LionValidationFeedback.js +8 -10
- package/components/form-core/src/validate/ValidateMixin.js +23 -3
- package/components/form-core/test/validate/lion-validation-feedback.test.js +0 -22
- package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +119 -0
- package/components/form-core/types/validate/validate.ts +1 -0
- package/components/icon/src/LionIcon.js +2 -0
- package/components/input-file/src/LionInputFile.js +9 -0
- package/components/input-tel/src/LionInputTel.js +3 -0
- package/components/input-tel-dropdown/src/LionInputTelDropdown.js +2 -0
- package/components/listbox/src/LionListbox.js +2 -0
- package/components/overlays/src/OverlayMixin.js +4 -0
- package/components/progress-indicator/src/LionProgressIndicator.js +4 -0
- package/components/radio-group/src/LionRadioGroup.js +3 -1
- package/components/select/src/LionSelect.js +4 -0
- package/components/select-rich/src/LionSelectInvoker.js +2 -0
- package/components/select-rich/src/LionSelectRich.js +2 -0
- package/components/steps/src/LionStep.js +0 -1
- package/components/steps/src/LionSteps.js +0 -1
- package/components/switch/src/LionSwitch.js +3 -0
- package/components/switch/src/LionSwitchButton.js +5 -0
- package/components/tabs/src/LionTabs.js +8 -0
- package/custom-elements.json +127 -79
- package/dist-types/components/accordion/src/LionAccordion.d.ts +3 -2
- package/dist-types/components/accordion/src/LionAccordion.d.ts.map +1 -1
- package/dist-types/components/button/src/LionButton.d.ts +2 -1
- package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
- package/dist-types/components/button/src/LionButtonReset.d.ts +2 -0
- package/dist-types/components/button/src/LionButtonReset.d.ts.map +1 -1
- package/dist-types/components/button/src/LionButtonSubmit.d.ts +2 -0
- package/dist-types/components/button/src/LionButtonSubmit.d.ts.map +1 -1
- package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
- package/dist-types/components/checkbox-group/src/LionCheckbox.d.ts +3 -0
- package/dist-types/components/checkbox-group/src/LionCheckbox.d.ts.map +1 -1
- package/dist-types/components/checkbox-group/src/LionCheckboxGroup.d.ts +2 -0
- package/dist-types/components/checkbox-group/src/LionCheckboxGroup.d.ts.map +1 -1
- package/dist-types/components/checkbox-group/src/LionCheckboxIndeterminate.d.ts +3 -0
- package/dist-types/components/checkbox-group/src/LionCheckboxIndeterminate.d.ts.map +1 -1
- package/dist-types/components/collapsible/src/LionCollapsible.d.ts +3 -1
- package/dist-types/components/collapsible/src/LionCollapsible.d.ts.map +1 -1
- package/dist-types/components/combobox/src/LionCombobox.d.ts +5 -0
- package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts +3 -0
- package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
- package/dist-types/components/drawer/src/LionDrawer.d.ts +9 -0
- package/dist-types/components/drawer/src/LionDrawer.d.ts.map +1 -1
- package/dist-types/components/fieldset/src/LionFieldset.d.ts +1 -1
- package/dist-types/components/form/src/LionForm.d.ts.map +1 -1
- package/dist-types/components/form-core/src/FormControlMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/validate/LionValidationFeedback.d.ts +4 -3
- package/dist-types/components/form-core/src/validate/LionValidationFeedback.d.ts.map +1 -1
- package/dist-types/components/form-core/src/validate/ValidateMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
- package/dist-types/components/form-core/types/validate/validate.d.ts +1 -0
- package/dist-types/components/form-core/types/validate/validate.d.ts.map +1 -1
- package/dist-types/components/icon/src/LionIcon.d.ts +2 -0
- package/dist-types/components/icon/src/LionIcon.d.ts.map +1 -1
- package/dist-types/components/input-file/src/LionInputFile.d.ts +9 -0
- package/dist-types/components/input-file/src/LionInputFile.d.ts.map +1 -1
- package/dist-types/components/input-tel/src/LionInputTel.d.ts +3 -0
- package/dist-types/components/input-tel/src/LionInputTel.d.ts.map +1 -1
- package/dist-types/components/input-tel-dropdown/src/LionInputTelDropdown.d.ts +2 -0
- package/dist-types/components/input-tel-dropdown/src/LionInputTelDropdown.d.ts.map +1 -1
- package/dist-types/components/listbox/src/LionListbox.d.ts +2 -0
- package/dist-types/components/listbox/src/LionListbox.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayMixin.d.ts +4 -0
- package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
- package/dist-types/components/progress-indicator/src/LionProgressIndicator.d.ts +3 -0
- package/dist-types/components/progress-indicator/src/LionProgressIndicator.d.ts.map +1 -1
- package/dist-types/components/radio-group/src/LionRadioGroup.d.ts +3 -1
- package/dist-types/components/radio-group/src/LionRadioGroup.d.ts.map +1 -1
- package/dist-types/components/select/src/LionSelect.d.ts +3 -0
- package/dist-types/components/select/src/LionSelect.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts +2 -0
- package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +3 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/components/steps/src/LionStep.d.ts +0 -1
- package/dist-types/components/steps/src/LionStep.d.ts.map +1 -1
- package/dist-types/components/steps/src/LionSteps.d.ts +0 -1
- package/dist-types/components/steps/src/LionSteps.d.ts.map +1 -1
- package/dist-types/components/switch/src/LionSwitch.d.ts +3 -0
- package/dist-types/components/switch/src/LionSwitch.d.ts.map +1 -1
- package/dist-types/components/switch/src/LionSwitchButton.d.ts +5 -0
- package/dist-types/components/switch/src/LionSwitchButton.d.ts.map +1 -1
- package/dist-types/components/tabs/src/LionTabs.d.ts +8 -0
- package/dist-types/components/tabs/src/LionTabs.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/accordion/api-table.md +8 -0
- package/docs/components/button/api-table.md +0 -3
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/api-table.md +7 -0
- package/docs/components/collapsible/overview.md +1 -1
- package/docs/components/combobox/api-table.md +7 -0
- package/docs/components/combobox/overview.md +1 -1
- package/docs/components/combobox/use-cases.md +1 -1
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/drawer/api-table.md +8 -0
- package/docs/components/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- package/docs/components/form/use-cases.md +2 -2
- package/docs/components/icon/use-cases.md +1 -1
- package/docs/components/input/overview.md +1 -1
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-email/overview.md +2 -2
- package/docs/components/input-file/api-table.md +7 -0
- package/docs/components/input-file/overview.md +1 -1
- package/docs/components/input-iban/overview.md +2 -2
- package/docs/components/input-range/overview.md +2 -2
- package/docs/components/input-stepper/overview.md +1 -1
- package/docs/components/input-tel/overview.md +1 -1
- package/docs/components/input-tel/use-cases.md +6 -6
- package/docs/components/input-tel-dropdown/overview.md +1 -1
- package/docs/components/listbox/use-cases.md +1 -1
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.md +1 -1
- package/docs/components/select-rich/api-table.md +0 -1
- package/docs/components/select-rich/use-cases.md +1 -1
- package/docs/components/tabs/api-table.md +7 -0
- package/docs/components/tabs/examples.md +1 -1
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
- package/docs/fundamentals/rationales/accessibility.md +1 -1
- package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
- package/docs/fundamentals/systems/core/overview.md +1 -1
- package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
- package/docs/fundamentals/systems/form/model-value.md +1 -1
- package/docs/fundamentals/systems/form/overview.md +28 -28
- package/docs/fundamentals/systems/form/validate.md +19 -3
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/configuration.md +2 -2
- package/docs/fundamentals/systems/overlays/overview.md +5 -5
- package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
- package/docs/fundamentals/tools/helpers/overview.md +1 -1
- package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
- package/docs/guides/how-to/create-a-custom-field.md +5 -5
- package/docs/guides/how-to/create-a-form.md +4 -4
- package/docs/guides/how-to/extend-a-native-input.md +2 -2
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/styling.md +1 -1
- package/package.json +1 -1
|
@@ -14,10 +14,11 @@ import { uuid } from '@lion/ui/core.js';
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* @slot invoker - The invoker element for the accordion
|
|
18
|
+
* @slot content - The content element for the accordion
|
|
19
|
+
* @slot _accordion - The slot for the accordion, used to rearrange invokers and content
|
|
18
20
|
*
|
|
19
21
|
* @customElement lion-accordion
|
|
20
|
-
* @extends LitElement
|
|
21
22
|
*/
|
|
22
23
|
export class LionAccordion extends LitElement {
|
|
23
24
|
static get properties() {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { html, LitElement, css } from 'lit';
|
|
2
|
-
import {
|
|
2
|
+
import { DisabledWithTabIndexMixin } from '@lion/ui/core.js';
|
|
3
3
|
|
|
4
4
|
const isKeyboardClickEvent = (/** @type {KeyboardEvent} */ e) => e.key === ' ' || e.key === 'Enter';
|
|
5
5
|
const isSpaceKeyboardClickEvent = (/** @type {KeyboardEvent} */ e) => e.key === ' ';
|
|
6
6
|
|
|
7
|
+
// TODO: simplify html structure, as we got rid of the wrapper element for IE11
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* @typedef {import('lit').TemplateResult} TemplateResult
|
|
9
11
|
*/
|
|
@@ -25,6 +27,8 @@ const isSpaceKeyboardClickEvent = (/** @type {KeyboardEvent} */ e) => e.key ===
|
|
|
25
27
|
* `<form>` support is needed:
|
|
26
28
|
* - When type="reset|submit" should be supported, use LionButtonReset.
|
|
27
29
|
* - When implicit form submission should be supported on top, use LionButtonSubmit.
|
|
30
|
+
*
|
|
31
|
+
* @customElement lion-button
|
|
28
32
|
*/
|
|
29
33
|
export class LionButton extends DisabledWithTabIndexMixin(LitElement) {
|
|
30
34
|
static get properties() {
|
|
@@ -35,7 +39,7 @@ export class LionButton extends DisabledWithTabIndexMixin(LitElement) {
|
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
render() {
|
|
38
|
-
return html` <div class="button-content"
|
|
42
|
+
return html` <div class="button-content"><slot></slot></div> `;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
static get styles() {
|
|
@@ -124,14 +128,6 @@ export class LionButton extends DisabledWithTabIndexMixin(LitElement) {
|
|
|
124
128
|
this.type = 'button';
|
|
125
129
|
this.active = false;
|
|
126
130
|
|
|
127
|
-
this._buttonId = uuid('button');
|
|
128
|
-
if (browserDetection.isIE11) {
|
|
129
|
-
this.updateComplete.then(() => {
|
|
130
|
-
if (!this.hasAttribute('aria-labelledby')) {
|
|
131
|
-
this.setAttribute('aria-labelledby', this._buttonId);
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
131
|
this.__setupEvents();
|
|
136
132
|
}
|
|
137
133
|
|
|
@@ -17,6 +17,8 @@ import { LionButton } from './LionButton.js';
|
|
|
17
17
|
* implicit form submission logic), but LionButtonReset is an easier to grasp name for
|
|
18
18
|
* Application Developers: for reset buttons, always use LionButtonReset, for submit
|
|
19
19
|
* buttons always use LionButtonSubmit.
|
|
20
|
+
*
|
|
21
|
+
* @customElement lion-button-reset
|
|
20
22
|
*/
|
|
21
23
|
export class LionButtonReset extends LionButton {
|
|
22
24
|
constructor() {
|
|
@@ -39,6 +39,8 @@ function createImplicitSubmitHelperButton() {
|
|
|
39
39
|
* - the Application Developer should be able to switch types between 'submit'|'reset'|'button'
|
|
40
40
|
* (this is similar to how native HTMLButtonElement works)
|
|
41
41
|
* - a submit button with native form support is needed
|
|
42
|
+
*
|
|
43
|
+
* @customElement lion-button-submit
|
|
42
44
|
*/
|
|
43
45
|
export class LionButtonSubmit extends LionButtonReset {
|
|
44
46
|
/**
|
|
@@ -203,20 +203,6 @@ export function LionButtonSuite({ klass = LionButton } = {}) {
|
|
|
203
203
|
expect(el.getAttribute('tabindex')).to.equal('5');
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
-
it('has an aria-labelledby and wrapper element in IE11', async () => {
|
|
207
|
-
const browserDetectionStub = sinon.stub(browserDetection, 'isIE11').value(true);
|
|
208
|
-
const el = /** @type {LionButton} */ (
|
|
209
|
-
await fixture(html`<${tagButton}>foo</${tagButton}>`)
|
|
210
|
-
);
|
|
211
|
-
expect(el.hasAttribute('aria-labelledby')).to.be.true;
|
|
212
|
-
const wrapperId = el.getAttribute('aria-labelledby');
|
|
213
|
-
expect(/** @type {ShadowRoot} */ (el.shadowRoot).querySelector(`#${wrapperId}`)).to.exist;
|
|
214
|
-
expect(
|
|
215
|
-
/** @type {ShadowRoot} */ (el.shadowRoot).querySelector(`#${wrapperId}`),
|
|
216
|
-
).dom.to.equal(`<div class="button-content" id="${wrapperId}"><slot></slot></div>`);
|
|
217
|
-
browserDetectionStub.restore();
|
|
218
|
-
});
|
|
219
|
-
|
|
220
206
|
it('does not override aria-labelledby when provided by user', async () => {
|
|
221
207
|
const browserDetectionStub = sinon.stub(browserDetection, 'isIE11').value(true);
|
|
222
208
|
const el = /** @type {LionButton} */ (
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { LionInput } from '@lion/ui/input.js';
|
|
2
2
|
import { ChoiceInputMixin } from '@lion/ui/form-core.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @customElement lion-checkbox
|
|
6
|
+
*/
|
|
4
7
|
export class LionCheckbox extends ChoiceInputMixin(LionInput) {
|
|
5
8
|
connectedCallback() {
|
|
6
9
|
super.connectedCallback();
|
|
@@ -3,6 +3,8 @@ import { ChoiceGroupMixin, FormGroupMixin } from '@lion/ui/form-core.js';
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A wrapper around multiple checkboxes
|
|
6
|
+
*
|
|
7
|
+
* @customElement lion-checkbox-group
|
|
6
8
|
*/
|
|
7
9
|
export class LionCheckboxGroup extends ChoiceGroupMixin(FormGroupMixin(LitElement)) {
|
|
8
10
|
constructor() {
|
|
@@ -5,6 +5,9 @@ import { LionCheckbox } from './LionCheckbox.js';
|
|
|
5
5
|
* @typedef {import('./LionCheckboxGroup.js').LionCheckboxGroup} LionCheckboxGroup
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @customElement lion-checkbox-indeterminate
|
|
10
|
+
*/
|
|
8
11
|
export class LionCheckboxIndeterminate extends LionCheckbox {
|
|
9
12
|
static get styles() {
|
|
10
13
|
return [
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit';
|
|
2
2
|
import { uuid } from '@lion/ui/core.js';
|
|
3
|
+
|
|
3
4
|
/**
|
|
4
5
|
* `LionCollapsible` is a class for custom collapsible element (`<lion-collapsible>` web component).
|
|
5
6
|
*
|
|
7
|
+
* @slot invoker - The invoker element for the collapsible
|
|
8
|
+
* @slot content - The content element for the collapsible
|
|
9
|
+
*
|
|
6
10
|
* @customElement lion-collapsible
|
|
7
|
-
* @extends LitElement
|
|
8
11
|
*/
|
|
9
12
|
export class LionCollapsible extends LitElement {
|
|
10
13
|
static get styles() {
|
|
@@ -28,6 +28,11 @@ const matchA11ySpanReverseFns = new WeakMap();
|
|
|
28
28
|
/**
|
|
29
29
|
* LionCombobox: implements the wai-aria combobox design pattern and integrates it as a Lion
|
|
30
30
|
* FormControl
|
|
31
|
+
*
|
|
32
|
+
* @slot listbox - The listbox element for the combobox, e.g. <lion-options>
|
|
33
|
+
* @slot selection-display - The selection display element for the combobox, e.g. <lion-selection-display>
|
|
34
|
+
*
|
|
35
|
+
* @customElement lion-combobox
|
|
31
36
|
*/
|
|
32
37
|
export class LionCombobox extends LocalizeMixin(OverlayMixin(CustomChoiceGroupMixin(LionListbox))) {
|
|
33
38
|
/** @type {any} */
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { html, LitElement } from 'lit';
|
|
2
2
|
import { OverlayMixin, withModalDialogConfig } from '@lion/ui/overlays.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @customElement lion-dialog
|
|
6
|
+
*/
|
|
4
7
|
export class LionDialog extends OverlayMixin(LitElement) {
|
|
5
8
|
/** @type {any} */
|
|
6
9
|
static get properties() {
|
|
@@ -7,6 +7,15 @@ const EVENT = {
|
|
|
7
7
|
TRANSITION_START: 'transitionstart',
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* LionDrawer: extension of lion-collapsible with drawer specific styles and animations
|
|
12
|
+
*
|
|
13
|
+
* @slot invoker - The invoker element for the drawer
|
|
14
|
+
* @slot content - The content element for the drawer
|
|
15
|
+
* @slot headline - The headline element for the drawer
|
|
16
|
+
*
|
|
17
|
+
* @customElement lion-drawer
|
|
18
|
+
*/
|
|
10
19
|
export class LionDrawer extends LionCollapsible {
|
|
11
20
|
static get properties() {
|
|
12
21
|
return {
|
|
@@ -2,7 +2,7 @@ import { LitElement } from 'lit';
|
|
|
2
2
|
import { FormGroupMixin } from '@lion/ui/form-core.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* LionFieldset is basically a 'sub form' and can have its own nested sub forms.
|
|
6
6
|
* It mimics the native <fieldset> element in this sense, but has all the functionality of
|
|
7
7
|
* a FormControl (advanced styling, validation, interaction states etc.) Also see
|
|
8
8
|
* FormGroupMixin it depends on.
|
|
@@ -24,6 +24,16 @@ import { FormRegisteringMixin } from './registration/FormRegisteringMixin.js';
|
|
|
24
24
|
* This Mixin is a shared fundament for all form components, it's applied on:
|
|
25
25
|
* - LionField (which is extended to LionInput, LionTextarea, LionSelect etc. etc.)
|
|
26
26
|
* - LionFieldset (which is extended to LionRadioGroup, LionCheckboxGroup, LionForm)
|
|
27
|
+
*
|
|
28
|
+
* @slot label - The label for the form control
|
|
29
|
+
* @slot help-text - The help text for the form control
|
|
30
|
+
* @slot input - The input element for the form control, e.g. <input>, <textarea>, <select>
|
|
31
|
+
* @slot feedback - The validation feedback for the form control
|
|
32
|
+
* @slot prefix - The prefix for the form control, e.g. currency symbol
|
|
33
|
+
* @slot suffix - The suffix for the form control, e.g. currency symbol
|
|
34
|
+
* @slot before - The before element for the form control, e.g. a label
|
|
35
|
+
* @slot after - The after element for the form control, e.g. a label
|
|
36
|
+
*
|
|
27
37
|
* @param {import('@open-wc/dedupe-mixin').Constructor<import('lit').LitElement>} superclass
|
|
28
38
|
* @type {FormControlMixin}
|
|
29
39
|
*/
|
|
@@ -25,7 +25,7 @@ import { Unparseable } from './validate/Unparseable.js';
|
|
|
25
25
|
// formattedValue condition needs to be evaluated right before syncing back to the view
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Designed to be applied on top of a LionField.
|
|
29
29
|
* To understand all concepts within the Mixin, please consult the flow diagram in the
|
|
30
30
|
* documentation.
|
|
31
31
|
*
|
|
@@ -48,6 +48,14 @@ export class LionValidationFeedback extends LocalizeMixin(LitElement) {
|
|
|
48
48
|
];
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
constructor() {
|
|
52
|
+
super();
|
|
53
|
+
/**
|
|
54
|
+
* @type {FeedbackMessage[] | undefined}
|
|
55
|
+
*/
|
|
56
|
+
this.feedbackData = undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
/**
|
|
52
60
|
* @overridable
|
|
53
61
|
* @param {Object} opts
|
|
@@ -69,16 +77,6 @@ export class LionValidationFeedback extends LocalizeMixin(LitElement) {
|
|
|
69
77
|
if (this.feedbackData && this.feedbackData[0]) {
|
|
70
78
|
this.setAttribute('type', this.feedbackData[0].type);
|
|
71
79
|
this.currentType = this.feedbackData[0].type;
|
|
72
|
-
window.clearTimeout(this.removeMessage);
|
|
73
|
-
// TODO: this logic should be in ValidateMixin, so that [show-feedback-for] is in sync,
|
|
74
|
-
// plus duration should be configurable
|
|
75
|
-
if (this.currentType === 'success') {
|
|
76
|
-
this.removeMessage = window.setTimeout(() => {
|
|
77
|
-
this.removeAttribute('type');
|
|
78
|
-
/** @type {FeedbackMessage[]} */
|
|
79
|
-
this.feedbackData = [];
|
|
80
|
-
}, 3000);
|
|
81
|
-
}
|
|
82
80
|
} else if (this.currentType !== 'success') {
|
|
83
81
|
this.removeAttribute('type');
|
|
84
82
|
}
|
|
@@ -590,7 +590,7 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
590
590
|
return [];
|
|
591
591
|
}
|
|
592
592
|
|
|
593
|
-
// If empty, do not show the
|
|
593
|
+
// If empty, do not show the ResultValidation message (e.g. Correct!)
|
|
594
594
|
if (this._isEmpty(this.modelValue)) {
|
|
595
595
|
this.__prevShownValidationResult = [];
|
|
596
596
|
return [];
|
|
@@ -619,7 +619,7 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
619
619
|
* - on sync validation
|
|
620
620
|
* - on async validation (can depend on server response)
|
|
621
621
|
*
|
|
622
|
-
* This method
|
|
622
|
+
* This method finishes a pass by adding the properties to the instance:
|
|
623
623
|
* - validationStates
|
|
624
624
|
* - hasFeedbackFor
|
|
625
625
|
*
|
|
@@ -763,6 +763,7 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
763
763
|
* @property {string} type will be 'error' for messages from default Validators. Could be
|
|
764
764
|
* 'warning', 'info' etc. for Validators with custom types. Needed as a directive for
|
|
765
765
|
* feedbackNode how to render a message of a certain type
|
|
766
|
+
* @property {number} visibilityDuration duration in ms for how long the message should be shown
|
|
766
767
|
* @property {Validator} [validator] when the message is directly coupled to a Validator
|
|
767
768
|
* (in most cases), this property is filled. When a message is not coupled to a Validator
|
|
768
769
|
* (in case of success feedback which is based on a diff or current and previous validation
|
|
@@ -788,7 +789,12 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
788
789
|
fieldName,
|
|
789
790
|
outcome,
|
|
790
791
|
});
|
|
791
|
-
return {
|
|
792
|
+
return {
|
|
793
|
+
message,
|
|
794
|
+
type: validator.type,
|
|
795
|
+
validator,
|
|
796
|
+
visibilityDuration: validator.config?.visibilityDuration || 3000,
|
|
797
|
+
};
|
|
792
798
|
}),
|
|
793
799
|
);
|
|
794
800
|
}
|
|
@@ -809,6 +815,8 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
809
815
|
* @protected
|
|
810
816
|
*/
|
|
811
817
|
_updateFeedbackComponent() {
|
|
818
|
+
window.clearTimeout(this.removeMessage);
|
|
819
|
+
|
|
812
820
|
const { _feedbackNode } = this;
|
|
813
821
|
if (!_feedbackNode) {
|
|
814
822
|
return;
|
|
@@ -840,6 +848,18 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
840
848
|
|
|
841
849
|
const messageMap = await this.__getFeedbackMessages(this.__prioritizedResult);
|
|
842
850
|
_feedbackNode.feedbackData = messageMap || [];
|
|
851
|
+
|
|
852
|
+
if (
|
|
853
|
+
messageMap?.[0] &&
|
|
854
|
+
messageMap[0].type === 'success' &&
|
|
855
|
+
messageMap[0].visibilityDuration !== Infinity
|
|
856
|
+
) {
|
|
857
|
+
this.removeMessage = window.setTimeout(() => {
|
|
858
|
+
_feedbackNode.removeAttribute('type');
|
|
859
|
+
/** @type {FeedbackMessage[]} */
|
|
860
|
+
_feedbackNode.feedbackData = [];
|
|
861
|
+
}, messageMap[0].visibilityDuration);
|
|
862
|
+
}
|
|
843
863
|
});
|
|
844
864
|
} else {
|
|
845
865
|
this.__feedbackQueue.add(async () => {
|
|
@@ -33,28 +33,6 @@ describe('lion-validation-feedback', () => {
|
|
|
33
33
|
expect(el.getAttribute('type')).to.equal('warning');
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it('success message clears after 3s', async () => {
|
|
37
|
-
const el = /** @type {LionValidationFeedback} */ (
|
|
38
|
-
await fixture(html`<lion-validation-feedback></lion-validation-feedback>`)
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
const clock = sinon.useFakeTimers();
|
|
42
|
-
|
|
43
|
-
el.feedbackData = [{ message: 'hello', type: 'success', validator: new AlwaysValid() }];
|
|
44
|
-
await el.updateComplete;
|
|
45
|
-
expect(el.getAttribute('type')).to.equal('success');
|
|
46
|
-
|
|
47
|
-
clock.tick(2900);
|
|
48
|
-
|
|
49
|
-
expect(el.getAttribute('type')).to.equal('success');
|
|
50
|
-
|
|
51
|
-
clock.tick(200);
|
|
52
|
-
|
|
53
|
-
expect(el).to.not.have.attribute('type');
|
|
54
|
-
|
|
55
|
-
clock.restore();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
36
|
it('does not clear error messages', async () => {
|
|
59
37
|
const el = /** @type {LionValidationFeedback} */ (
|
|
60
38
|
await fixture(html`<lion-validation-feedback></lion-validation-feedback>`)
|
|
@@ -349,6 +349,125 @@ export function runValidateMixinFeedbackPart() {
|
|
|
349
349
|
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Nachricht für MinLength');
|
|
350
350
|
});
|
|
351
351
|
|
|
352
|
+
it('shows success message and clears after 3s', async () => {
|
|
353
|
+
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
|
354
|
+
static get validationTypes() {
|
|
355
|
+
return ['error', 'success'];
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const clock = sinon.useFakeTimers();
|
|
359
|
+
const elTagString = defineCE(ValidateElementCustomTypes);
|
|
360
|
+
const elTag = unsafeStatic(elTagString);
|
|
361
|
+
const el = /** @type {ValidateElementCustomTypes} */ (
|
|
362
|
+
await fixture(html`
|
|
363
|
+
<${elTag}
|
|
364
|
+
.submitted=${true}
|
|
365
|
+
.validators=${[
|
|
366
|
+
new MinLength(3),
|
|
367
|
+
new DefaultSuccess(null, { getMessage: () => 'This is a success message' }),
|
|
368
|
+
]}
|
|
369
|
+
>${lightDom}</${elTag}>
|
|
370
|
+
`)
|
|
371
|
+
);
|
|
372
|
+
const { _feedbackNode } = getFormControlMembers(el);
|
|
373
|
+
|
|
374
|
+
el.modelValue = 'a';
|
|
375
|
+
await el.updateComplete;
|
|
376
|
+
await el.feedbackComplete;
|
|
377
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Message for MinLength');
|
|
378
|
+
|
|
379
|
+
el.modelValue = 'abcd';
|
|
380
|
+
await el.updateComplete;
|
|
381
|
+
await el.feedbackComplete;
|
|
382
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
383
|
+
clock.tick(2900);
|
|
384
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
385
|
+
clock.tick(200);
|
|
386
|
+
expect(_feedbackNode.feedbackData).to.be.empty;
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('shows success message and clears after configured time', async () => {
|
|
390
|
+
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
|
391
|
+
static get validationTypes() {
|
|
392
|
+
return ['error', 'success'];
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
const clock = sinon.useFakeTimers();
|
|
396
|
+
const elTagString = defineCE(ValidateElementCustomTypes);
|
|
397
|
+
const elTag = unsafeStatic(elTagString);
|
|
398
|
+
const el = /** @type {ValidateElementCustomTypes} */ (
|
|
399
|
+
await fixture(html`
|
|
400
|
+
<${elTag}
|
|
401
|
+
.submitted=${true}
|
|
402
|
+
.validators=${[
|
|
403
|
+
new MinLength(3),
|
|
404
|
+
new DefaultSuccess(null, {
|
|
405
|
+
getMessage: () => 'This is a success message',
|
|
406
|
+
visibilityDuration: 6000,
|
|
407
|
+
}),
|
|
408
|
+
]}
|
|
409
|
+
>${lightDom}</${elTag}>
|
|
410
|
+
`)
|
|
411
|
+
);
|
|
412
|
+
const { _feedbackNode } = getFormControlMembers(el);
|
|
413
|
+
|
|
414
|
+
el.modelValue = 'a';
|
|
415
|
+
await el.updateComplete;
|
|
416
|
+
await el.feedbackComplete;
|
|
417
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Message for MinLength');
|
|
418
|
+
|
|
419
|
+
el.modelValue = 'abcd';
|
|
420
|
+
await el.updateComplete;
|
|
421
|
+
await el.feedbackComplete;
|
|
422
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
423
|
+
clock.tick(5900);
|
|
424
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
425
|
+
clock.tick(200);
|
|
426
|
+
expect(_feedbackNode.feedbackData).to.be.empty;
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('shows success message and stays persistent', async () => {
|
|
430
|
+
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
|
431
|
+
static get validationTypes() {
|
|
432
|
+
return ['error', 'success'];
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const clock = sinon.useFakeTimers();
|
|
436
|
+
const elTagString = defineCE(ValidateElementCustomTypes);
|
|
437
|
+
const elTag = unsafeStatic(elTagString);
|
|
438
|
+
const el = /** @type {ValidateElementCustomTypes} */ (
|
|
439
|
+
await fixture(html`
|
|
440
|
+
<${elTag}
|
|
441
|
+
.submitted=${true}
|
|
442
|
+
.validators=${[
|
|
443
|
+
new MinLength(3),
|
|
444
|
+
new DefaultSuccess(null, {
|
|
445
|
+
getMessage: () => 'This is a success message',
|
|
446
|
+
visibilityDuration: Infinity,
|
|
447
|
+
}),
|
|
448
|
+
]}
|
|
449
|
+
>${lightDom}</${elTag}>
|
|
450
|
+
`)
|
|
451
|
+
);
|
|
452
|
+
const { _feedbackNode } = getFormControlMembers(el);
|
|
453
|
+
|
|
454
|
+
el.modelValue = 'a';
|
|
455
|
+
await el.updateComplete;
|
|
456
|
+
await el.feedbackComplete;
|
|
457
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Message for MinLength');
|
|
458
|
+
|
|
459
|
+
el.modelValue = 'abcd';
|
|
460
|
+
await el.updateComplete;
|
|
461
|
+
await el.feedbackComplete;
|
|
462
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
463
|
+
clock.tick(2900);
|
|
464
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
465
|
+
clock.tick(200);
|
|
466
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
467
|
+
clock.tick(20000);
|
|
468
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
469
|
+
});
|
|
470
|
+
|
|
352
471
|
it('shows success message after fixing an error', async () => {
|
|
353
472
|
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
|
354
473
|
static get validationTypes() {
|
|
@@ -31,6 +31,15 @@ function formatBytes(bytes, decimals = 2) {
|
|
|
31
31
|
return `${parseFloat((bytes / k ** i).toFixed(dm))}${sizes[i]}`;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* LionInputFile: A file input component
|
|
36
|
+
* This component allows users to select files, displays selected files, and handles file uploads.
|
|
37
|
+
*
|
|
38
|
+
* @slot file-select-button - [private] The button to open the file dialog
|
|
39
|
+
* @slot selected-file-list - [private] The list of selected files
|
|
40
|
+
*
|
|
41
|
+
* @customElement lion-input-file
|
|
42
|
+
*/
|
|
34
43
|
export class LionInputFile extends ScopedElementsMixin(LocalizeMixin(LionField)) {
|
|
35
44
|
static get scopedElements() {
|
|
36
45
|
return {
|
|
@@ -18,6 +18,9 @@ import { localizeNamespaceLoader } from './localizeNamespaceLoader.js';
|
|
|
18
18
|
* @typedef {FormatOptions & {regionCode: RegionCode; formatStrategy: PhoneNumberFormat; formatCountryCodeStyle: string;}} FormatOptionsTel
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @customElement lion-input-tel
|
|
23
|
+
*/
|
|
21
24
|
export class LionInputTel extends LocalizeMixin(LionInput) {
|
|
22
25
|
/**
|
|
23
26
|
* @configure LitElement
|
|
@@ -40,6 +40,8 @@ import { regionCodeToLocale } from './regionCodeToLocale.js';
|
|
|
40
40
|
* possible. Also, it doesn't need to be a `FormControl`, because it's purely a helper element
|
|
41
41
|
* to provide better UX: the modelValue (the text field) contains all needed info, since it's in
|
|
42
42
|
* `e164` format that contains all info (both region code and national phone number).
|
|
43
|
+
*
|
|
44
|
+
* @customElement lion-input-tel-dropdown
|
|
43
45
|
*/
|
|
44
46
|
export class LionInputTelDropdown extends LionInputTel {
|
|
45
47
|
refs = {
|
|
@@ -7,6 +7,8 @@ import { ListboxMixin } from './ListboxMixin.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* LionListbox: implements the wai-aria listbox design pattern and integrates it as a Lion
|
|
9
9
|
* FormControl
|
|
10
|
+
*
|
|
11
|
+
* @customElement lion-listbox
|
|
10
12
|
*/
|
|
11
13
|
export class LionListbox extends ListboxMixin(
|
|
12
14
|
FocusMixin(InteractionStateMixin(ValidateMixin(LitElement))),
|
|
@@ -9,6 +9,10 @@ import { isEqualConfig } from './utils/is-equal-config.js';
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
+
* @slot backdrop - The backdrop element for the overlay
|
|
13
|
+
* @slot content - The content element for the overlay
|
|
14
|
+
* @slot invoker - The invoker element for the overlay
|
|
15
|
+
*
|
|
12
16
|
* @type {OverlayMixin}
|
|
13
17
|
* @param {import('@open-wc/dedupe-mixin').Constructor<import('lit').LitElement>} superclass
|
|
14
18
|
*/
|
|
@@ -5,6 +5,10 @@ import { getLocalizeManager, LocalizeMixin } from '@lion/ui/localize-no-side-eff
|
|
|
5
5
|
/**
|
|
6
6
|
* @typedef {import('lit').TemplateResult} TemplateResult
|
|
7
7
|
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @customElement lion-progress-indicator
|
|
11
|
+
*/
|
|
8
12
|
export class LionProgressIndicator extends LocalizeMixin(LitElement) {
|
|
9
13
|
static get properties() {
|
|
10
14
|
return {
|
|
@@ -2,7 +2,9 @@ import { LitElement } from 'lit';
|
|
|
2
2
|
import { ChoiceGroupMixin, FormGroupMixin } from '@lion/ui/form-core.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* A wrapper around multiple radios.
|
|
5
|
+
* LionRadioGroup: A wrapper around multiple radios.
|
|
6
|
+
*
|
|
7
|
+
* @customElement lion-radio-group
|
|
6
8
|
*/
|
|
7
9
|
export class LionRadioGroup extends ChoiceGroupMixin(FormGroupMixin(LitElement)) {
|
|
8
10
|
connectedCallback() {
|
|
@@ -4,6 +4,10 @@ import { LionField } from '@lion/ui/form-core.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {import('../../localize/types/LocalizeMixinTypes.js').FormatNumberOptions} FormatOptions
|
|
6
6
|
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @customElement lion-field-with-select
|
|
10
|
+
*/
|
|
7
11
|
class LionFieldWithSelect extends LionField {
|
|
8
12
|
/** @type {any} */
|
|
9
13
|
static get properties() {
|
|
@@ -11,6 +11,8 @@ import { SlotMixin } from '@lion/ui/core.js';
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* LionSelectInvoker: invoker button consuming a selected element
|
|
14
|
+
*
|
|
15
|
+
* @customElement lion-select-invoker
|
|
14
16
|
*/
|
|
15
17
|
export class LionSelectInvoker extends SlotMixin(LionButton) {
|
|
16
18
|
static get styles() {
|
|
@@ -22,6 +22,8 @@ function detectInteractionMode() {
|
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* LionSelectRich: wraps the <lion-listbox> element
|
|
25
|
+
*
|
|
26
|
+
* @customElement lion-field-with-select
|
|
25
27
|
*/
|
|
26
28
|
export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(LionListbox))) {
|
|
27
29
|
static get scopedElements() {
|
|
@@ -3,6 +3,9 @@ import { ChoiceInputMixin, LionField } from '@lion/ui/form-core.js';
|
|
|
3
3
|
import { ScopedElementsMixin } from '../../core/src/ScopedElementsMixin.js';
|
|
4
4
|
import { LionSwitchButton } from './LionSwitchButton.js';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @customElement lion-switch
|
|
8
|
+
*/
|
|
6
9
|
export class LionSwitch extends ScopedElementsMixin(ChoiceInputMixin(LionField)) {
|
|
7
10
|
static get styles() {
|
|
8
11
|
return [
|