@lion/ui 0.4.2 → 0.5.0
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/calendar/src/LionCalendar.js +1 -1
- package/components/calendar/test-helpers/DayObject.js +2 -2
- package/components/combobox/src/LionCombobox.js +79 -28
- package/components/combobox/test/lion-combobox-integrations.test.js +5 -0
- package/components/combobox/test/lion-combobox.test.js +290 -23
- package/components/combobox/test-helpers/combobox-helpers.js +5 -2
- package/components/drawer/src/LionDrawer.js +1 -0
- package/components/form-core/src/FocusMixin.js +2 -0
- package/components/form-core/src/FormControlMixin.js +1 -1
- package/components/form-core/src/choice-group/ChoiceGroupMixin.js +1 -0
- package/components/form-core/src/choice-group/CustomChoiceGroupMixin.js +173 -0
- package/components/form-core/src/utils/getAriaElementsInRightDomOrder.js +7 -14
- package/components/form-core/src/validate/validators/Required.js +2 -2
- package/components/form-core/test/choice-group/CustomChoiceGroupMixin.integrations.test.js +55 -0
- package/components/form-core/test/choice-group/CustomChoiceGroupMixin.test.js +16 -0
- package/components/form-core/test/utils/getAriaElementsInRightDomOrder.test.js +0 -25
- package/components/form-core/test/validate/StringValidators.test.js +1 -1
- package/components/form-core/test-helpers/ExampleValidators.js +1 -3
- package/components/form-core/test-suites/FormRegistrationMixins.suite.js +2 -0
- package/components/form-core/test-suites/NativeTextFieldMixin.suite.js +4 -4
- package/components/form-core/test-suites/ValidateMixin.suite.js +27 -0
- package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +11 -2
- package/components/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.js +1 -0
- package/components/form-core/test-suites/choice-group/CustomChoiceGroupMixin.suite.js +265 -0
- package/components/form-core/types/choice-group/ChoiceGroupMixinTypes.ts +1 -1
- package/components/form-core/types/choice-group/CustomChoiceGroupMixinTypes.ts +30 -0
- package/components/form-core/types/choice-group/index.ts +1 -0
- package/components/helpers/src/SbActionLogger.js +1 -0
- package/components/icon/src/LionIcon.js +1 -9
- package/components/icon/test/lion-icon.test.js +2 -0
- package/components/input-range/test/lion-input-range.test.js +12 -6
- package/components/listbox/src/LionOptions.js +5 -5
- package/components/listbox/src/ListboxMixin.js +1 -16
- package/components/listbox/test/lion-options.test.js +1 -1
- package/components/listbox/test-suites/ListboxMixin.suite.js +1 -1
- package/components/localize/src/date/getMonthNames.js +3 -0
- package/components/localize/src/date/utils/forceDotsForNlnl.js +11 -0
- package/components/localize/src/number/utils/normalize-format-number-to-parts/forceAddGroupSeparators.js +3 -1
- package/components/localize/src/number/utils/normalize-format-number-to-parts/forceSymbols.js +2 -0
- package/components/localize/src/number/utils/normalize-format-number-to-parts/normalizeIntl.js +1 -0
- package/components/localize/test/date/getMonthNames.test.js +1 -0
- package/components/localize/test-helpers/fake-imports.js +1 -0
- package/components/radio-group/src/LionRadioGroup.js +1 -1
- package/components/radio-group/test/lion-radio-group.test.js +29 -0
- package/components/select/test/lion-select.test.js +1 -1
- package/components/switch/src/LionSwitchButton.js +1 -5
- package/components/tabs/src/LionTabs.js +7 -7
- package/components/textarea/src/LionTextarea.js +1 -1
- package/custom-elements.json +102923 -61581
- package/dist-types/components/combobox/src/LionCombobox.d.ts +13 -8
- package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
- package/dist-types/components/combobox/test-helpers/combobox-helpers.d.ts.map +1 -1
- package/dist-types/components/drawer/src/LionDrawer.d.ts.map +1 -1
- package/dist-types/components/form-core/src/FocusMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/choice-group/ChoiceGroupMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/choice-group/CustomChoiceGroupMixin.d.ts +4 -0
- package/dist-types/components/form-core/src/choice-group/CustomChoiceGroupMixin.d.ts.map +1 -0
- package/dist-types/components/form-core/src/utils/getAriaElementsInRightDomOrder.d.ts +5 -5
- package/dist-types/components/form-core/src/utils/getAriaElementsInRightDomOrder.d.ts.map +1 -1
- package/dist-types/components/form-core/test/choice-group/CustomChoiceGroupMixin.integrations.test.d.ts +2 -0
- package/dist-types/components/form-core/test/choice-group/CustomChoiceGroupMixin.integrations.test.d.ts.map +1 -0
- package/dist-types/components/form-core/test/choice-group/CustomChoiceGroupMixin.test.d.ts +6 -0
- package/dist-types/components/form-core/test/choice-group/CustomChoiceGroupMixin.test.d.ts.map +1 -0
- package/dist-types/components/form-core/test-helpers/ExampleValidators.d.ts +0 -1
- package/dist-types/components/form-core/test-helpers/ExampleValidators.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/FormRegistrationMixins.suite.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixin.suite.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/test-suites/choice-group/ChoiceGroupMixin.suite.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/choice-group/CustomChoiceGroupMixin.suite.d.ts +14 -0
- package/dist-types/components/form-core/test-suites/choice-group/CustomChoiceGroupMixin.suite.d.ts.map +1 -0
- package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts +1 -1
- package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts.map +1 -1
- package/dist-types/components/form-core/types/choice-group/CustomChoiceGroupMixinTypes.d.ts +18 -0
- package/dist-types/components/form-core/types/choice-group/CustomChoiceGroupMixinTypes.d.ts.map +1 -0
- package/dist-types/components/form-core/types/choice-group/index.d.ts +1 -0
- package/dist-types/components/form-core/types/choice-group/index.d.ts.map +1 -1
- package/dist-types/components/helpers/src/SbActionLogger.d.ts.map +1 -1
- package/dist-types/components/icon/src/LionIcon.d.ts +0 -9
- package/dist-types/components/icon/src/LionIcon.d.ts.map +1 -1
- package/dist-types/components/listbox/src/LionOptions.d.ts +0 -5
- package/dist-types/components/listbox/src/LionOptions.d.ts.map +1 -1
- package/dist-types/components/listbox/src/ListboxMixin.d.ts.map +1 -1
- package/dist-types/components/localize/src/date/getMonthNames.d.ts.map +1 -1
- package/dist-types/components/localize/src/date/utils/forceDotsForNlnl.d.ts +5 -0
- package/dist-types/components/localize/src/date/utils/forceDotsForNlnl.d.ts.map +1 -0
- package/dist-types/components/localize/src/number/utils/normalize-format-number-to-parts/forceAddGroupSeparators.d.ts.map +1 -1
- package/dist-types/components/localize/src/number/utils/normalize-format-number-to-parts/forceSymbols.d.ts.map +1 -1
- package/dist-types/components/localize/src/number/utils/normalize-format-number-to-parts/normalizeIntl.d.ts.map +1 -1
- package/dist-types/components/localize/test-helpers/fake-imports.d.ts.map +1 -1
- package/dist-types/components/switch/src/LionSwitchButton.d.ts +0 -5
- package/dist-types/components/switch/src/LionSwitchButton.d.ts.map +1 -1
- package/dist-types/components/tabs/src/LionTabs.d.ts.map +1 -1
- package/dist-types/exports/types/form-core.d.ts +1 -1
- package/dist-types/exports/types/form-core.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/assets/CustomCollapsible.js +4 -0
- package/docs/components/collapsible/overview.md +1 -1
- package/docs/components/combobox/overview.md +1 -1
- package/docs/components/combobox/src/demo-selection-display.js +8 -35
- package/docs/components/combobox/use-cases.md +24 -1
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- 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/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/radio-group/overview.md +3 -3
- package/docs/components/select-rich/use-cases.md +1 -1
- package/docs/components/tabs/examples.md +1 -1
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
- 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 +3 -3
- 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 +18 -2
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/configuration.md +3 -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/example-complex/overlayCompatibility.js +1 -2
- 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/exports/types/form-core.ts +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { dedupeMixin } from '@open-wc/dedupe-mixin';
|
|
2
|
+
import { ChoiceGroupMixin } from './ChoiceGroupMixin.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('../../types/choice-group/CustomChoiceGroupMixinTypes.js').CustomChoiceGroupMixin} CustomChoiceGroupMixin
|
|
6
|
+
* @typedef {import('../../types/choice-group/CustomChoiceGroupMixinTypes.js').CustomChoiceGroupHost} CustomChoiceGroupHost
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {any|any[]} value
|
|
11
|
+
* @returns {any[]}
|
|
12
|
+
*/
|
|
13
|
+
function ensureArray(value) {
|
|
14
|
+
return Array.isArray(value) ? value : [value];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Extends the ChoiceGroupMixin to add optional support for custom user choices without altering the initial choice list.
|
|
19
|
+
*
|
|
20
|
+
* @type {CustomChoiceGroupMixin}
|
|
21
|
+
* @param {import('@open-wc/dedupe-mixin').Constructor<import('lit').LitElement>} superclass
|
|
22
|
+
*/
|
|
23
|
+
const CustomChoiceGroupMixinImplementation = superclass =>
|
|
24
|
+
// @ts-ignore https://github.com/microsoft/TypeScript/issues/36821#issuecomment-588375051
|
|
25
|
+
class CustomChoiceGroupMixin extends ChoiceGroupMixin(superclass) {
|
|
26
|
+
static get properties() {
|
|
27
|
+
return {
|
|
28
|
+
allowCustomChoice: {
|
|
29
|
+
type: Boolean,
|
|
30
|
+
attribute: 'allow-custom-choice',
|
|
31
|
+
},
|
|
32
|
+
modelValue: { type: Object },
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
get modelValue() {
|
|
38
|
+
return this.__getChoicesFrom(super.modelValue);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
set modelValue(value) {
|
|
42
|
+
super.modelValue = value;
|
|
43
|
+
|
|
44
|
+
if (value === null || value === undefined || value === '') {
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
this._customChoices = new Set();
|
|
47
|
+
} else if (this.allowCustomChoice) {
|
|
48
|
+
const old = this.modelValue;
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
this._customChoices = new Set(ensureArray(value));
|
|
51
|
+
this.requestUpdate('modelValue', old);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
get formattedValue() {
|
|
57
|
+
return this.__getChoicesFrom(super.formattedValue);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
set formattedValue(value) {
|
|
61
|
+
super.formattedValue = value;
|
|
62
|
+
|
|
63
|
+
if (value === null || value === undefined) {
|
|
64
|
+
this._customChoices = new Set();
|
|
65
|
+
} else if (this.allowCustomChoice) {
|
|
66
|
+
const old = this.modelValue;
|
|
67
|
+
// Convert formattedValue to modelValue to store as custom choices, or fall back to the input value
|
|
68
|
+
this._customChoices = new Set(
|
|
69
|
+
ensureArray(value).map(
|
|
70
|
+
val => this.formElements.find(el => el.formattedValue === val)?.modelValue || val,
|
|
71
|
+
),
|
|
72
|
+
);
|
|
73
|
+
this.requestUpdate('modelValue', old);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// @ts-ignore
|
|
78
|
+
get serializedValue() {
|
|
79
|
+
return this.__getChoicesFrom(super.serializedValue);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
set serializedValue(value) {
|
|
83
|
+
super.serializedValue = value;
|
|
84
|
+
|
|
85
|
+
if (value === null || value === undefined) {
|
|
86
|
+
this._customChoices = new Set();
|
|
87
|
+
} else if (this.allowCustomChoice) {
|
|
88
|
+
const old = this.modelValue;
|
|
89
|
+
// Convert serializedValue to modelValue to store as custom choices, or fall back to the input value
|
|
90
|
+
this._customChoices = new Set(
|
|
91
|
+
ensureArray(value).map(
|
|
92
|
+
val => this.formElements.find(el => el.serializedValue === val)?.modelValue || val,
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
this.requestUpdate('modelValue', old);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Custom elements are all missing elements that have no corresponding element, independent if enabled or not.
|
|
101
|
+
*/
|
|
102
|
+
// @ts-ignore
|
|
103
|
+
get customChoices() {
|
|
104
|
+
if (!this.allowCustomChoice) {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const elems = this._getCheckedElements();
|
|
109
|
+
|
|
110
|
+
return Array.from(this._customChoices).filter(
|
|
111
|
+
choice => !elems.some(elem => elem.choiceValue === choice),
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
constructor() {
|
|
116
|
+
super();
|
|
117
|
+
|
|
118
|
+
this.allowCustomChoice = false;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @type {Set<unknown>}
|
|
122
|
+
* @protected
|
|
123
|
+
*/
|
|
124
|
+
this._customChoices = new Set();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
__getChoicesFrom(input) {
|
|
132
|
+
const values = input;
|
|
133
|
+
if (!this.allowCustomChoice) {
|
|
134
|
+
return values;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (this.multipleChoice) {
|
|
138
|
+
return [...ensureArray(values), ...this.customChoices];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (values === '') {
|
|
142
|
+
return this._customChoices.values().next().value || '';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return values;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @protected
|
|
150
|
+
*/
|
|
151
|
+
_isEmpty() {
|
|
152
|
+
return super._isEmpty() && this._customChoices.size === 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
clear() {
|
|
156
|
+
this._customChoices = new Set();
|
|
157
|
+
super.clear();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @param {string|string[]} value
|
|
162
|
+
* @returns {*}
|
|
163
|
+
*/
|
|
164
|
+
parser(value) {
|
|
165
|
+
if (this.allowCustomChoice && Array.isArray(value)) {
|
|
166
|
+
return value.filter(v => v.trim() !== '');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export const CustomChoiceGroupMixin = dedupeMixin(CustomChoiceGroupMixinImplementation);
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
/* eslint-disable no-bitwise */
|
|
2
|
-
import { browserDetection } from '@lion/ui/core.js';
|
|
3
|
-
|
|
4
2
|
const moveDownConditions = [
|
|
5
3
|
Node.DOCUMENT_POSITION_PRECEDING,
|
|
6
4
|
Node.DOCUMENT_POSITION_CONTAINS,
|
|
@@ -8,30 +6,25 @@ const moveDownConditions = [
|
|
|
8
6
|
];
|
|
9
7
|
|
|
10
8
|
/**
|
|
11
|
-
*
|
|
9
|
+
* Let the order of adding ids to aria element by DOM order, so that the screen reader
|
|
12
10
|
* respects visual order when reading:
|
|
13
11
|
* https://developers.google.com/web/fundamentals/accessibility/focus/dom-order-matters
|
|
14
|
-
* @param {
|
|
12
|
+
* @param {Element[]} descriptionElements - holds references to description or label elements whose
|
|
15
13
|
* id should be returned
|
|
16
14
|
* @param {Object} opts
|
|
17
15
|
* @param {boolean} [opts.reverse]
|
|
18
|
-
* @returns {
|
|
16
|
+
* @returns {Element[]} sorted set of elements based on dom order
|
|
19
17
|
*/
|
|
20
18
|
export function getAriaElementsInRightDomOrder(descriptionElements, { reverse } = {}) {
|
|
21
19
|
/**
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {
|
|
24
|
-
* @
|
|
20
|
+
* @param {Node} a
|
|
21
|
+
* @param {Node} b
|
|
22
|
+
* @returns {-1|1}
|
|
25
23
|
*/
|
|
26
24
|
const putPrecedingSiblingsAndLocalParentsFirst = (a, b) => {
|
|
27
25
|
// https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
|
|
28
26
|
const pos = a.compareDocumentPosition(b);
|
|
29
|
-
|
|
30
|
-
// Unfortunately, for IE, we have to switch the order (?)
|
|
31
|
-
if (moveDownConditions.includes(pos)) {
|
|
32
|
-
return browserDetection.isIE11 ? -1 : 1;
|
|
33
|
-
}
|
|
34
|
-
return browserDetection.isIE11 ? 1 : -1;
|
|
27
|
+
return moveDownConditions.includes(pos) ? 1 : -1;
|
|
35
28
|
};
|
|
36
29
|
|
|
37
30
|
const descriptionEls = descriptionElements.filter(el => el); // filter out null references
|
|
@@ -45,7 +45,7 @@ export class Required extends Validator {
|
|
|
45
45
|
/**
|
|
46
46
|
* @param {FormControlHost & HTMLElement} formControl
|
|
47
47
|
*/
|
|
48
|
-
// @ts-ignore [allow-protected] we are allowed to know FormControl
|
|
48
|
+
// @ts-ignore [allow-protected] we are allowed to know FormControl protected props in form-core
|
|
49
49
|
// eslint-disable-next-line class-methods-use-this
|
|
50
50
|
onFormControlConnect({ _inputNode: inputNode }) {
|
|
51
51
|
if (inputNode) {
|
|
@@ -61,7 +61,7 @@ export class Required extends Validator {
|
|
|
61
61
|
/**
|
|
62
62
|
* @param {FormControlHost & HTMLElement} formControl
|
|
63
63
|
*/
|
|
64
|
-
// @ts-ignore [allow-protected] we are allowed to know FormControl
|
|
64
|
+
// @ts-ignore [allow-protected] we are allowed to know FormControl protected props in form-core
|
|
65
65
|
// eslint-disable-next-line class-methods-use-this
|
|
66
66
|
onFormControlDisconnect({ _inputNode: inputNode }) {
|
|
67
67
|
if (inputNode) {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { runChoiceGroupMixinSuite } from '@lion/ui/form-core-test-suites.js';
|
|
2
|
+
import { LitElement } from 'lit';
|
|
3
|
+
import '@lion/ui/define/lion-fieldset.js';
|
|
4
|
+
import '@lion/ui/define/lion-checkbox-group.js';
|
|
5
|
+
import '@lion/ui/define/lion-checkbox.js';
|
|
6
|
+
import { FormGroupMixin, ChoiceInputMixin } from '@lion/ui/form-core.js';
|
|
7
|
+
import { LionInput } from '@lion/ui/input.js';
|
|
8
|
+
import { CustomChoiceGroupMixin } from '../../src/choice-group/CustomChoiceGroupMixin.js';
|
|
9
|
+
|
|
10
|
+
class CustomChoiceGroup extends CustomChoiceGroupMixin(FormGroupMixin(LitElement)) {}
|
|
11
|
+
customElements.define('custom-choice-input-group', CustomChoiceGroup);
|
|
12
|
+
|
|
13
|
+
class ChoiceInput extends ChoiceInputMixin(LionInput) {}
|
|
14
|
+
customElements.define('custom-choice-input', ChoiceInput);
|
|
15
|
+
|
|
16
|
+
class CustomChoiceGroupAllowCustom extends CustomChoiceGroupMixin(FormGroupMixin(LitElement)) {
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
this.allowCustomChoice = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
customElements.define('allow-custom-choice-input-group', CustomChoiceGroupAllowCustom);
|
|
23
|
+
|
|
24
|
+
class MultipleCustomChoiceGroup extends CustomChoiceGroupMixin(FormGroupMixin(LitElement)) {
|
|
25
|
+
constructor() {
|
|
26
|
+
super();
|
|
27
|
+
this.multipleChoice = true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
customElements.define('multiple-custom-choice-input-group', MultipleCustomChoiceGroup);
|
|
31
|
+
|
|
32
|
+
class MultipleCustomChoiceGroupAllowCustom extends CustomChoiceGroupMixin(
|
|
33
|
+
FormGroupMixin(LitElement),
|
|
34
|
+
) {
|
|
35
|
+
constructor() {
|
|
36
|
+
super();
|
|
37
|
+
this.multipleChoice = true;
|
|
38
|
+
this.allowCustomChoice = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
customElements.define(
|
|
42
|
+
'multiple-allow-custom-choice-input-group',
|
|
43
|
+
MultipleCustomChoiceGroupAllowCustom,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
runChoiceGroupMixinSuite({ parentTagString: 'custom-choice-input-group' });
|
|
47
|
+
runChoiceGroupMixinSuite({
|
|
48
|
+
parentTagString: 'multiple-custom-choice-input-group',
|
|
49
|
+
choiceType: 'multiple',
|
|
50
|
+
});
|
|
51
|
+
runChoiceGroupMixinSuite({ parentTagString: 'allow-custom-choice-input-group' });
|
|
52
|
+
runChoiceGroupMixinSuite({
|
|
53
|
+
parentTagString: 'multiple-allow-custom-choice-input-group',
|
|
54
|
+
choiceType: 'multiple',
|
|
55
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ChoiceInputMixin, FormGroupMixin } from '@lion/ui/form-core.js';
|
|
2
|
+
import { LionInput } from '@lion/ui/input.js';
|
|
3
|
+
import { LitElement } from 'lit';
|
|
4
|
+
import '@lion/ui/define/lion-fieldset.js';
|
|
5
|
+
import '@lion/ui/define/lion-checkbox-group.js';
|
|
6
|
+
import '@lion/ui/define/lion-checkbox.js';
|
|
7
|
+
import { CustomChoiceGroupMixin } from '../../src/choice-group/CustomChoiceGroupMixin.js';
|
|
8
|
+
import { runCustomChoiceGroupMixinSuite } from '../../test-suites/choice-group/CustomChoiceGroupMixin.suite.js';
|
|
9
|
+
|
|
10
|
+
export class CustomChoiceGroup extends CustomChoiceGroupMixin(FormGroupMixin(LitElement)) {}
|
|
11
|
+
customElements.define('custom-choice-input-group', CustomChoiceGroup);
|
|
12
|
+
|
|
13
|
+
class ChoiceInput extends ChoiceInputMixin(LionInput) {}
|
|
14
|
+
customElements.define('custom-choice-input', ChoiceInput);
|
|
15
|
+
|
|
16
|
+
runCustomChoiceGroupMixinSuite();
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { expect, fixture } from '@open-wc/testing';
|
|
2
2
|
import { html } from 'lit/static-html.js';
|
|
3
|
-
import sinon from 'sinon';
|
|
4
|
-
import { browserDetection } from '@lion/ui/core.js';
|
|
5
3
|
import { getAriaElementsInRightDomOrder } from '../../src/utils/getAriaElementsInRightDomOrder.js';
|
|
6
4
|
|
|
7
5
|
describe('getAriaElementsInRightDomOrder', () => {
|
|
@@ -47,27 +45,4 @@ describe('getAriaElementsInRightDomOrder', () => {
|
|
|
47
45
|
const result = getAriaElementsInRightDomOrder(unorderedNodes, { reverse: true });
|
|
48
46
|
expect(result).to.eql([c, bChild, b, a]);
|
|
49
47
|
});
|
|
50
|
-
|
|
51
|
-
it('orders in reverse for IE11', async () => {
|
|
52
|
-
const browserDetectionStub = sinon.stub(browserDetection, 'isIE11').value(true);
|
|
53
|
-
const el = await fixture(html`
|
|
54
|
-
<div>
|
|
55
|
-
<div id="a"></div>
|
|
56
|
-
<div></div>
|
|
57
|
-
<div id="b">
|
|
58
|
-
<div></div>
|
|
59
|
-
<div id="b-child"></div>
|
|
60
|
-
</div>
|
|
61
|
-
<div></div>
|
|
62
|
-
<div id="c"></div>
|
|
63
|
-
<div></div>
|
|
64
|
-
</div>
|
|
65
|
-
`);
|
|
66
|
-
// eslint-disable-next-line no-unused-vars
|
|
67
|
-
const [a, _1, b, _2, bChild, _3, c, _4] = Array.from(el.querySelectorAll('div'));
|
|
68
|
-
const unorderedNodes = [bChild, c, a, b];
|
|
69
|
-
const result = getAriaElementsInRightDomOrder(unorderedNodes);
|
|
70
|
-
expect(result).to.eql([c, bChild, b, a]);
|
|
71
|
-
browserDetectionStub.restore();
|
|
72
|
-
});
|
|
73
48
|
});
|
|
@@ -124,7 +124,7 @@ describe('String Validation', () => {
|
|
|
124
124
|
isEnabled = validator.execute('#LionRests');
|
|
125
125
|
expect(isEnabled).to.be.true;
|
|
126
126
|
|
|
127
|
-
validator = new Pattern(
|
|
127
|
+
validator = new Pattern(/#LionRocks/);
|
|
128
128
|
isEnabled = validator.execute('Some string #LionRocks');
|
|
129
129
|
expect(isEnabled).to.be.false;
|
|
130
130
|
|
|
@@ -165,6 +165,7 @@ export const runRegistrationSuite = customConfig => {
|
|
|
165
165
|
it('works for components that have a delayed render', async () => {
|
|
166
166
|
class PerformUpdate extends FormRegistrarMixin(LitElement) {
|
|
167
167
|
async performUpdate() {
|
|
168
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
168
169
|
await new Promise(resolve => setTimeout(() => resolve(undefined), 10));
|
|
169
170
|
await super.performUpdate();
|
|
170
171
|
}
|
|
@@ -359,6 +360,7 @@ export const runRegistrationSuite = customConfig => {
|
|
|
359
360
|
const delayedPortalString = defineCE(
|
|
360
361
|
class extends FormRegistrarPortalMixin(LitElement) {
|
|
361
362
|
async performUpdate() {
|
|
363
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
362
364
|
await new Promise(resolve => setTimeout(() => resolve(undefined), 10));
|
|
363
365
|
await super.performUpdate();
|
|
364
366
|
}
|
|
@@ -5,9 +5,9 @@ import { sendKeys } from '@web/test-runner-commands';
|
|
|
5
5
|
import { spy } from 'sinon';
|
|
6
6
|
import { NativeTextFieldMixin } from '@lion/ui/form-core.js';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const isSafari = (() => {
|
|
9
9
|
const ua = navigator.userAgent.toLowerCase();
|
|
10
|
-
return ua.indexOf('
|
|
10
|
+
return ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1;
|
|
11
11
|
})();
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -54,8 +54,8 @@ export function runNativeTextFieldMixinSuite(customConfig) {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it('move focus to a next focusable element after writing some text', async () => {
|
|
57
|
-
if (
|
|
58
|
-
// TODO: This test is broken on
|
|
57
|
+
if (isSafari) {
|
|
58
|
+
// TODO: This test is broken on Safari, to be fixed later
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
const el = /** @type {NativeTextFieldClass} */ (await fixture(html`<${tag}></${tag}>`));
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from '@lion/ui/form-core-test-helpers.js';
|
|
10
10
|
import sinon from 'sinon';
|
|
11
11
|
import {
|
|
12
|
+
EqualsLength,
|
|
12
13
|
MaxLength,
|
|
13
14
|
MinLength,
|
|
14
15
|
Required,
|
|
@@ -779,6 +780,32 @@ export function runValidateMixinSuite(customConfig) {
|
|
|
779
780
|
});
|
|
780
781
|
});
|
|
781
782
|
|
|
783
|
+
describe('getMessages with custom HTML', () => {
|
|
784
|
+
it('will render HTML for lion-validation-feedback', async () => {
|
|
785
|
+
const messageHtmlId = 'test123';
|
|
786
|
+
const messageHtml = `<div id="test123">test</div>`;
|
|
787
|
+
const el = /** @type {ValidateElement} */ (
|
|
788
|
+
await fixture(html`
|
|
789
|
+
<${tag}
|
|
790
|
+
.validators="${[
|
|
791
|
+
new EqualsLength(4, { getMessage: () => html`<div id="test123">test</div>` }),
|
|
792
|
+
]}" })]}"
|
|
793
|
+
.modelValue="${'123'}"
|
|
794
|
+
label="Custom message for validator instance"
|
|
795
|
+
></${tag}>
|
|
796
|
+
`)
|
|
797
|
+
);
|
|
798
|
+
expect(el.validationStates.error.EqualsLength).to.be.true;
|
|
799
|
+
expect(el.hasFeedbackFor).to.deep.equal(['error']);
|
|
800
|
+
const { _feedbackNode } = getFormControlMembers(el);
|
|
801
|
+
await el.updateComplete;
|
|
802
|
+
await el.updateComplete;
|
|
803
|
+
const messageHtmlNode = _feedbackNode.shadowRoot?.querySelector(`#${messageHtmlId}`);
|
|
804
|
+
expect(messageHtmlNode?.outerHTML).to.equal(messageHtml);
|
|
805
|
+
expect(messageHtmlNode?.tagName).to.equal('DIV');
|
|
806
|
+
});
|
|
807
|
+
});
|
|
808
|
+
|
|
782
809
|
describe('Required Validator integration', () => {
|
|
783
810
|
it('will result in erroneous state when form control is empty', async () => {
|
|
784
811
|
const el = /** @type {ValidateElement} */ (
|
|
@@ -517,7 +517,11 @@ export function runValidateMixinFeedbackPart() {
|
|
|
517
517
|
.submitted=${true}
|
|
518
518
|
.validators=${[constructorValidator]}
|
|
519
519
|
.modelValue=${'cat'}
|
|
520
|
-
.fieldName=${new Promise(
|
|
520
|
+
.fieldName=${new Promise(
|
|
521
|
+
(
|
|
522
|
+
resolve, // eslint-disable-next-line no-promise-executor-return
|
|
523
|
+
) => resolve('myField'),
|
|
524
|
+
)}
|
|
521
525
|
>${lightDom}</${tag}>
|
|
522
526
|
`)
|
|
523
527
|
);
|
|
@@ -537,6 +541,7 @@ export function runValidateMixinFeedbackPart() {
|
|
|
537
541
|
|
|
538
542
|
it('".getMessage()" gets .fieldName defined on Validator config', async () => {
|
|
539
543
|
const constructorValidator = new MinLength(4, {
|
|
544
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
540
545
|
fieldName: new Promise(resolve => resolve('myFieldViaCfg')),
|
|
541
546
|
});
|
|
542
547
|
const ctorValidator = /** @type {typeof MinLength} */ (constructorValidator.constructor);
|
|
@@ -548,7 +553,11 @@ export function runValidateMixinFeedbackPart() {
|
|
|
548
553
|
.submitted=${true}
|
|
549
554
|
.validators=${[constructorValidator]}
|
|
550
555
|
.modelValue=${'cat'}
|
|
551
|
-
.fieldName=${new Promise(
|
|
556
|
+
.fieldName=${new Promise(
|
|
557
|
+
(
|
|
558
|
+
resolve, // eslint-disable-next-line no-promise-executor-return
|
|
559
|
+
) => resolve('myField'),
|
|
560
|
+
)}
|
|
552
561
|
>${lightDom}</${tag}>
|
|
553
562
|
`)
|
|
554
563
|
);
|