@lion/ui 0.4.1 → 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 +5 -3
- package/components/calendar/test-helpers/DayObject.js +2 -2
- package/components/combobox/src/LionCombobox.js +82 -29
- package/components/combobox/test/lion-combobox-integrations.test.js +5 -0
- package/components/combobox/test/lion-combobox.test.js +318 -23
- package/components/combobox/test-helpers/combobox-helpers.js +19 -22
- 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-amount/src/LionInputAmount.js +5 -2
- package/components/input-amount/test/lion-input-amount.test.js +21 -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/overlays/src/utils/adopt-styles.js +1 -1
- 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 +103314 -61972
- package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
- 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/input-amount/src/LionInputAmount.d.ts +2 -2
- package/dist-types/components/input-amount/src/LionInputAmount.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/steps/overview.md +2 -4
- 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,265 @@
|
|
|
1
|
+
import '@lion/ui/define/lion-fieldset.js';
|
|
2
|
+
import '@lion/ui/define/lion-checkbox-group.js';
|
|
3
|
+
import '@lion/ui/define/lion-checkbox.js';
|
|
4
|
+
import { expect, fixture, fixtureSync, html, unsafeStatic } from '@open-wc/testing';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @typedef {import('../../test/choice-group/CustomChoiceGroupMixin.test.js').CustomChoiceGroup} CustomChoiceGroup
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {{ parentTagString?:string, childTagString?: string, choiceType?: string}} config
|
|
13
|
+
*/
|
|
14
|
+
export function runCustomChoiceGroupMixinSuite({
|
|
15
|
+
parentTagString,
|
|
16
|
+
childTagString,
|
|
17
|
+
choiceType,
|
|
18
|
+
} = {}) {
|
|
19
|
+
const cfg = {
|
|
20
|
+
parentTagString: parentTagString || 'custom-choice-input-group',
|
|
21
|
+
childTagString: childTagString || 'custom-choice-input',
|
|
22
|
+
choiceType: choiceType || 'single',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const parentTag = unsafeStatic(cfg.parentTagString);
|
|
26
|
+
const childTag = unsafeStatic(cfg.childTagString);
|
|
27
|
+
|
|
28
|
+
describe(`CustomChoiceGroupMixin: ${cfg.parentTagString}`, () => {
|
|
29
|
+
if (cfg.choiceType === 'single') {
|
|
30
|
+
it('has a single modelValue representing a custom value', async () => {
|
|
31
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
32
|
+
await fixture(html`
|
|
33
|
+
<${parentTag} allow-custom-choice name="gender[]">
|
|
34
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
35
|
+
<${childTag} checked .choiceValue=${'female'}></${childTag}>
|
|
36
|
+
</${parentTag}>
|
|
37
|
+
`)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
await el.registrationComplete;
|
|
41
|
+
|
|
42
|
+
expect(el.modelValue).to.equal('female');
|
|
43
|
+
el.modelValue = 'male';
|
|
44
|
+
expect(el.modelValue).to.equal('male');
|
|
45
|
+
|
|
46
|
+
el.modelValue = 'other';
|
|
47
|
+
expect(el.modelValue).to.equal('other');
|
|
48
|
+
|
|
49
|
+
expect(el.formElements[0].checked).to.be.false;
|
|
50
|
+
expect(el.formElements[1].checked).to.be.false;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('has a single formattedValue representing a custom value', async () => {
|
|
54
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
55
|
+
await fixture(html`
|
|
56
|
+
<${parentTag} allow-custom-choice name="gender">
|
|
57
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
58
|
+
<${childTag} .choiceValue=${'female'} checked></${childTag}>
|
|
59
|
+
</${parentTag}>
|
|
60
|
+
`)
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
el.modelValue = 'other';
|
|
64
|
+
expect(el.formattedValue).to.equal('other');
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
it('can set initial custom modelValue on creation', async () => {
|
|
69
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
70
|
+
await fixture(html`
|
|
71
|
+
<${parentTag} allow-custom-choice name="gender[]" .modelValue=${'other'}>
|
|
72
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
73
|
+
<${childTag} .choiceValue=${'female'}></${childTag}>
|
|
74
|
+
</${parentTag}>
|
|
75
|
+
`)
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (cfg.choiceType === 'single') {
|
|
79
|
+
expect(el.modelValue).to.equal('other');
|
|
80
|
+
} else {
|
|
81
|
+
expect(el.modelValue).to.deep.equal(['other']);
|
|
82
|
+
}
|
|
83
|
+
expect(el.formElements[0].checked).to.be.false;
|
|
84
|
+
expect(el.formElements[1].checked).to.be.false;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('can set initial custom serializedValue on creation', async () => {
|
|
88
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
89
|
+
await fixture(html`
|
|
90
|
+
<${parentTag} allow-custom-choice name="gender[]" .serializedValue=${'other'}>
|
|
91
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
92
|
+
<${childTag} .choiceValue=${'female'}></${childTag}>
|
|
93
|
+
</${parentTag}>
|
|
94
|
+
`)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (cfg.choiceType === 'single') {
|
|
98
|
+
expect(el.serializedValue).to.equal('other');
|
|
99
|
+
} else {
|
|
100
|
+
expect(el.serializedValue).to.deep.equal(['other']);
|
|
101
|
+
}
|
|
102
|
+
expect(el.formElements[0].checked).to.be.false;
|
|
103
|
+
expect(el.formElements[1].checked).to.be.false;
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('can set initial custom formattedValue on creation', async () => {
|
|
107
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
108
|
+
await fixture(html`
|
|
109
|
+
<${parentTag} allow-custom-choice name="gender[]" .formattedValue=${'other'}>
|
|
110
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
111
|
+
<${childTag} .choiceValue=${'female'}></${childTag}>
|
|
112
|
+
</${parentTag}>
|
|
113
|
+
`)
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
if (cfg.choiceType === 'single') {
|
|
117
|
+
expect(el.formattedValue).to.equal('other');
|
|
118
|
+
} else {
|
|
119
|
+
expect(el.formattedValue).to.deep.equal(['other']);
|
|
120
|
+
}
|
|
121
|
+
expect(el.formElements[0].checked).to.be.false;
|
|
122
|
+
expect(el.formElements[1].checked).to.be.false;
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('correctly handles custom modelValue being set before registrationComplete', async () => {
|
|
126
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
127
|
+
fixtureSync(html`
|
|
128
|
+
<${parentTag} allow-custom-choice name="gender[]" .modelValue=${null}>
|
|
129
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
130
|
+
<${childTag} .choiceValue=${'female'}></${childTag}>
|
|
131
|
+
</${parentTag}>
|
|
132
|
+
`)
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
if (cfg.choiceType === 'single') {
|
|
136
|
+
el.modelValue = 'other';
|
|
137
|
+
await el.registrationComplete;
|
|
138
|
+
expect(el.modelValue).to.equal('other');
|
|
139
|
+
} else {
|
|
140
|
+
el.modelValue = ['other'];
|
|
141
|
+
await el.registrationComplete;
|
|
142
|
+
expect(el.modelValue).to.deep.equal(['other']);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('correctly handles custom serializedValue being set before registrationComplete', async () => {
|
|
147
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
148
|
+
fixtureSync(html`
|
|
149
|
+
<${parentTag} allow-custom-choice name="gender[]" .serializedValue=${null}>
|
|
150
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
151
|
+
<${childTag} .choiceValue=${'female'}></${childTag}>
|
|
152
|
+
</${parentTag}>
|
|
153
|
+
`)
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
if (cfg.choiceType === 'single') {
|
|
157
|
+
// @ts-expect-error
|
|
158
|
+
el.serializedValue = 'other';
|
|
159
|
+
await el.registrationComplete;
|
|
160
|
+
expect(el.serializedValue).to.equal('other');
|
|
161
|
+
} else {
|
|
162
|
+
// @ts-expect-error
|
|
163
|
+
el.serializedValue = ['other'];
|
|
164
|
+
await el.registrationComplete;
|
|
165
|
+
expect(el.serializedValue).to.deep.equal(['other']);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('can be cleared, even when a custom value is selected', async () => {
|
|
170
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
171
|
+
await fixture(html`
|
|
172
|
+
<${parentTag} allow-custom-choice name="gender[]">
|
|
173
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
174
|
+
<${childTag} .choiceValue=${'female'}></${childTag}>
|
|
175
|
+
</${parentTag}>
|
|
176
|
+
`)
|
|
177
|
+
);
|
|
178
|
+
if (cfg.choiceType === 'single') {
|
|
179
|
+
el.modelValue = 'other';
|
|
180
|
+
} else {
|
|
181
|
+
el.modelValue = ['other'];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
el.clear();
|
|
185
|
+
|
|
186
|
+
if (cfg.choiceType === 'single') {
|
|
187
|
+
expect(el.serializedValue).to.deep.equal('');
|
|
188
|
+
} else {
|
|
189
|
+
expect(el.serializedValue).to.deep.equal([]);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('multipleChoice', () => {
|
|
194
|
+
it('has a single modelValue representing all currently checked values, including custom values', async () => {
|
|
195
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
196
|
+
await fixture(html`
|
|
197
|
+
<${parentTag} allow-custom-choice multiple-choice name="gender[]">
|
|
198
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
199
|
+
<${childTag} .choiceValue=${'female'} checked></${childTag}>
|
|
200
|
+
</${parentTag}>
|
|
201
|
+
`)
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
expect(el.modelValue).to.eql(['female']);
|
|
205
|
+
|
|
206
|
+
el.modelValue = ['female', 'male'];
|
|
207
|
+
expect(el.modelValue).to.eql(['male', 'female']);
|
|
208
|
+
|
|
209
|
+
el.modelValue = ['female', 'male', 'other'];
|
|
210
|
+
expect(el.modelValue).to.eql(['male', 'female', 'other']);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('has a single serializedValue representing all currently checked values, including custom values', async () => {
|
|
214
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
215
|
+
await fixture(html`
|
|
216
|
+
<${parentTag} allow-custom-choice multiple-choice name="gender[]">
|
|
217
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
218
|
+
<${childTag} .choiceValue=${'female'} checked></${childTag}>
|
|
219
|
+
</${parentTag}>
|
|
220
|
+
`)
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
expect(el.serializedValue).to.eql(['female']);
|
|
224
|
+
|
|
225
|
+
el.modelValue = ['female', 'male', 'other'];
|
|
226
|
+
expect(el.serializedValue).to.eql(['male', 'female', 'other']);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('has a single formattedValue representing all currently checked values', async () => {
|
|
230
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
231
|
+
await fixture(html`
|
|
232
|
+
<${parentTag} allow-custom-choice multiple-choice name="gender[]">
|
|
233
|
+
<${childTag} .choiceValue=${'male'}></${childTag}>
|
|
234
|
+
<${childTag} .choiceValue=${'female'} checked></${childTag}>
|
|
235
|
+
</${parentTag}>
|
|
236
|
+
`)
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
expect(el.formattedValue).to.eql(['female']);
|
|
240
|
+
|
|
241
|
+
el.modelValue = ['female', 'male', 'other'];
|
|
242
|
+
expect(el.formattedValue).to.eql(['male', 'female', 'other']);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('unchecks non-matching checkboxes when setting the modelValue', async () => {
|
|
246
|
+
const el = /** @type {CustomChoiceGroup} */ (
|
|
247
|
+
await fixture(html`
|
|
248
|
+
<${parentTag} allow-custom-choice multiple-choice name="gender[]">
|
|
249
|
+
<${childTag} .choiceValue=${'male'} checked></${childTag}>
|
|
250
|
+
<${childTag} .choiceValue=${'female'} checked></${childTag}>
|
|
251
|
+
</${parentTag}>
|
|
252
|
+
`)
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
expect(el.modelValue).to.eql(['male', 'female']);
|
|
256
|
+
expect(el.formElements[0].checked).to.be.true;
|
|
257
|
+
expect(el.formElements[1].checked).to.be.true;
|
|
258
|
+
|
|
259
|
+
el.modelValue = ['other'];
|
|
260
|
+
expect(el.formElements[0].checked).to.be.false;
|
|
261
|
+
expect(el.formElements[1].checked).to.be.false;
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
}
|
|
@@ -25,7 +25,7 @@ export declare class ChoiceGroupHost {
|
|
|
25
25
|
filterFn?: (el: FormControl, property?: string) => boolean,
|
|
26
26
|
): void;
|
|
27
27
|
protected _throwWhenInvalidChildModelValue(child: FormControlHost): void;
|
|
28
|
-
protected _isEmpty():
|
|
28
|
+
protected _isEmpty(): boolean;
|
|
29
29
|
protected _checkSingleChoiceElements(ev: Event): void;
|
|
30
30
|
protected _getCheckedElements(): ChoiceInputHost[];
|
|
31
31
|
protected _setCheckedElements(value: any, check: boolean): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Constructor } from '@open-wc/dedupe-mixin';
|
|
2
|
+
import { LitElement } from 'lit';
|
|
3
|
+
|
|
4
|
+
import { ChoiceGroupHost } from './ChoiceGroupMixinTypes.js';
|
|
5
|
+
|
|
6
|
+
export declare class CustomChoiceGroupHost {
|
|
7
|
+
allowCustomChoice: boolean;
|
|
8
|
+
get modelValue(): any;
|
|
9
|
+
set modelValue(value: any);
|
|
10
|
+
get serializedValue(): string;
|
|
11
|
+
set serializedValue(value: string);
|
|
12
|
+
get formattedValue(): string;
|
|
13
|
+
set formattedValue(value: string);
|
|
14
|
+
|
|
15
|
+
clear(): void;
|
|
16
|
+
parser(value: string | string[]): string | string[];
|
|
17
|
+
|
|
18
|
+
protected _isEmpty(): boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export declare function CustomChoiceGroupImplementation<T extends Constructor<LitElement>>(
|
|
22
|
+
superclass: T,
|
|
23
|
+
): T &
|
|
24
|
+
Constructor<CustomChoiceGroupHost> &
|
|
25
|
+
Pick<typeof CustomChoiceGroupHost, keyof typeof CustomChoiceGroupHost> &
|
|
26
|
+
Constructor<ChoiceGroupHost> &
|
|
27
|
+
Pick<typeof ChoiceGroupHost, keyof typeof ChoiceGroupHost> &
|
|
28
|
+
Pick<typeof LitElement, keyof typeof LitElement>;
|
|
29
|
+
|
|
30
|
+
export type CustomChoiceGroupMixin = typeof CustomChoiceGroupImplementation;
|
|
@@ -5,6 +5,7 @@ import { css, html, LitElement, render } from 'lit';
|
|
|
5
5
|
export class SbActionLogger extends LitElement {
|
|
6
6
|
static get properties() {
|
|
7
7
|
return {
|
|
8
|
+
// eslint-disable-next-line lit/no-native-attributes
|
|
8
9
|
title: { type: String, reflect: true },
|
|
9
10
|
simple: { type: Boolean, reflect: true },
|
|
10
11
|
__logCounter: { type: Number },
|
|
@@ -57,14 +57,6 @@ export class LionIcon extends LitElement {
|
|
|
57
57
|
type: String,
|
|
58
58
|
attribute: 'icon-id',
|
|
59
59
|
},
|
|
60
|
-
/**
|
|
61
|
-
* @private
|
|
62
|
-
*/
|
|
63
|
-
role: {
|
|
64
|
-
type: String,
|
|
65
|
-
attribute: 'role',
|
|
66
|
-
reflect: true,
|
|
67
|
-
},
|
|
68
60
|
};
|
|
69
61
|
}
|
|
70
62
|
|
|
@@ -101,7 +93,6 @@ export class LionIcon extends LitElement {
|
|
|
101
93
|
|
|
102
94
|
constructor() {
|
|
103
95
|
super();
|
|
104
|
-
this.role = 'img';
|
|
105
96
|
this.ariaLabel = '';
|
|
106
97
|
this.iconId = '';
|
|
107
98
|
/**
|
|
@@ -131,6 +122,7 @@ export class LionIcon extends LitElement {
|
|
|
131
122
|
// ensures that aria-hidden is set if there is no aria-label attribute
|
|
132
123
|
this._onLabelChanged();
|
|
133
124
|
super.connectedCallback();
|
|
125
|
+
this.setAttribute('role', 'img');
|
|
134
126
|
}
|
|
135
127
|
|
|
136
128
|
/**
|
|
@@ -185,10 +185,12 @@ describe('lion-icon', () => {
|
|
|
185
185
|
try {
|
|
186
186
|
icons.addIconResolver(
|
|
187
187
|
'foo',
|
|
188
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
188
189
|
() => new Promise(resolve => setTimeout(() => resolve(heartSvg), 10)),
|
|
189
190
|
);
|
|
190
191
|
icons.addIconResolver(
|
|
191
192
|
'bar',
|
|
193
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
192
194
|
() => new Promise(resolve => setTimeout(() => resolve(hammerSvg), 4)),
|
|
193
195
|
);
|
|
194
196
|
const el = await fixture(html`<lion-icon icon-id="foo:lorem:ipsum"></lion-icon>`);
|
|
@@ -159,6 +159,9 @@ export class LionInputAmount extends LocalizeMixin(LionInput) {
|
|
|
159
159
|
if (currency) {
|
|
160
160
|
if (!this.__currencyDisplayNodeIsConnected) {
|
|
161
161
|
this.appendChild(this.__currencyDisplayNode);
|
|
162
|
+
this.addToAriaLabelledBy(this.__currencyDisplayNode, {
|
|
163
|
+
idPrefix: this._currencyDisplayNodeSlot,
|
|
164
|
+
});
|
|
162
165
|
this.__currencyDisplayNodeIsConnected = true;
|
|
163
166
|
}
|
|
164
167
|
this.__currencyDisplayNode.textContent = this.__currencyLabel;
|
|
@@ -182,11 +185,11 @@ export class LionInputAmount extends LocalizeMixin(LionInput) {
|
|
|
182
185
|
}
|
|
183
186
|
|
|
184
187
|
/**
|
|
185
|
-
* @returns the current currency display node
|
|
188
|
+
* @returns {HTMLElement | undefined} the current currency display node
|
|
186
189
|
* @private
|
|
187
190
|
*/
|
|
188
191
|
get __currencyDisplayNode() {
|
|
189
|
-
const node = Array.from(this.children).find(
|
|
192
|
+
const node = /** @type {HTMLElement[]} */ (Array.from(this.children)).find(
|
|
190
193
|
child => child.slot === this._currencyDisplayNodeSlot,
|
|
191
194
|
);
|
|
192
195
|
if (node) {
|
|
@@ -308,6 +308,27 @@ describe('<lion-input-amount>', () => {
|
|
|
308
308
|
expect(_inputNode.getAttribute('aria-labelledby')).to.contain(label?.id);
|
|
309
309
|
});
|
|
310
310
|
|
|
311
|
+
it('adds currency id to aria-labelledby of input when currency switches from undefined', async () => {
|
|
312
|
+
const el = /** @type {LionInputAmount} */ (
|
|
313
|
+
await fixture(`<lion-input-amount></lion-input-amount>`)
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
el.currency = 'EUR';
|
|
317
|
+
|
|
318
|
+
let resolved = await el.updateComplete;
|
|
319
|
+
while (!resolved) {
|
|
320
|
+
resolved = await el.updateComplete;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const label = /** @type {HTMLElement[]} */ (Array.from(el.children)).find(
|
|
324
|
+
child => child.slot === 'after',
|
|
325
|
+
);
|
|
326
|
+
const { _inputNode } = getInputMembers(/** @type {* & LionInput} */ (el));
|
|
327
|
+
|
|
328
|
+
expect(label?.id).not.equal('');
|
|
329
|
+
expect(_inputNode.getAttribute('aria-labelledby')).to.contain(label?.id);
|
|
330
|
+
});
|
|
331
|
+
|
|
311
332
|
it('adds an aria-label to currency slot', async () => {
|
|
312
333
|
const el = /** @type {LionInputAmount} */ (
|
|
313
334
|
await fixture(`<lion-input-amount currency="EUR"></lion-input-amount>`)
|
|
@@ -19,10 +19,14 @@ describe('<lion-input-range>', () => {
|
|
|
19
19
|
<lion-input-range .modelValue=${75} unit="${`%`}"></lion-input-range>
|
|
20
20
|
`);
|
|
21
21
|
expect(
|
|
22
|
-
/** @type {HTMLElement} */ (
|
|
22
|
+
/** @type {HTMLElement} */ (
|
|
23
|
+
/** @type {ShadowRoot} */ (el.shadowRoot).querySelector('.input-range__value')
|
|
24
|
+
).innerText,
|
|
23
25
|
).to.equal('75');
|
|
24
26
|
expect(
|
|
25
|
-
/** @type {HTMLElement} */ (
|
|
27
|
+
/** @type {HTMLElement} */ (
|
|
28
|
+
/** @type {ShadowRoot} */ (el.shadowRoot).querySelector('.input-range__unit')
|
|
29
|
+
).innerText,
|
|
26
30
|
).to.equal('%');
|
|
27
31
|
});
|
|
28
32
|
|
|
@@ -30,12 +34,14 @@ describe('<lion-input-range>', () => {
|
|
|
30
34
|
const el = await fixture(`<lion-input-range min="100" max="200"></lion-input-range>`);
|
|
31
35
|
expect(el.shadowRoot?.querySelectorAll('.input-range__limits span').length).to.equal(2);
|
|
32
36
|
expect(
|
|
33
|
-
/** @type {HTMLElement} */ (
|
|
34
|
-
.
|
|
37
|
+
/** @type {HTMLElement} */ (
|
|
38
|
+
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('.input-range__limits span')[0]
|
|
39
|
+
).innerText,
|
|
35
40
|
).to.equal(el.min.toString());
|
|
36
41
|
expect(
|
|
37
|
-
/** @type {HTMLElement} */ (
|
|
38
|
-
.
|
|
42
|
+
/** @type {HTMLElement} */ (
|
|
43
|
+
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('.input-range__limits span')[1]
|
|
44
|
+
).innerText,
|
|
39
45
|
).to.equal(el.max.toString());
|
|
40
46
|
});
|
|
41
47
|
|
|
@@ -7,10 +7,6 @@ import { FormRegistrarPortalMixin } from '@lion/ui/form-core.js';
|
|
|
7
7
|
export class LionOptions extends FormRegistrarPortalMixin(LitElement) {
|
|
8
8
|
static get properties() {
|
|
9
9
|
return {
|
|
10
|
-
role: {
|
|
11
|
-
type: String,
|
|
12
|
-
reflect: true,
|
|
13
|
-
},
|
|
14
10
|
tabIndex: {
|
|
15
11
|
type: Number,
|
|
16
12
|
reflect: true,
|
|
@@ -21,10 +17,14 @@ export class LionOptions extends FormRegistrarPortalMixin(LitElement) {
|
|
|
21
17
|
|
|
22
18
|
constructor() {
|
|
23
19
|
super();
|
|
24
|
-
this.role = 'listbox';
|
|
25
20
|
this.tabIndex = 0;
|
|
26
21
|
}
|
|
27
22
|
|
|
23
|
+
connectedCallback() {
|
|
24
|
+
super.connectedCallback();
|
|
25
|
+
this.setAttribute('role', 'listbox');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
28
|
createRenderRoot() {
|
|
29
29
|
return this;
|
|
30
30
|
}
|
|
@@ -196,22 +196,6 @@ const ListboxMixinImplementation = superclass =>
|
|
|
196
196
|
return this._listboxNode;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
/**
|
|
200
|
-
* @override ChoiceGroupMixin
|
|
201
|
-
*/
|
|
202
|
-
get serializedValue() {
|
|
203
|
-
return this.modelValue;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Duplicating from FormGroupMixin, because you cannot independently inherit/override getter + setter.
|
|
207
|
-
// If you override one, gotta override the other, they go in pairs.
|
|
208
|
-
/**
|
|
209
|
-
* @override ChoiceGroupMixin
|
|
210
|
-
*/
|
|
211
|
-
set serializedValue(value) {
|
|
212
|
-
super.serializedValue = value;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
199
|
get activeIndex() {
|
|
216
200
|
return this.formElements.findIndex(el => el.active === true);
|
|
217
201
|
}
|
|
@@ -473,6 +457,7 @@ const ListboxMixinImplementation = superclass =>
|
|
|
473
457
|
}
|
|
474
458
|
|
|
475
459
|
clear() {
|
|
460
|
+
super.clear();
|
|
476
461
|
this.setCheckedIndex(-1);
|
|
477
462
|
this.resetInteractionState();
|
|
478
463
|
}
|
|
@@ -163,7 +163,7 @@ export function runListboxMixinSuite(customConfig = {}) {
|
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
it('requests update for modelValue when checkedIndex changes', async () => {
|
|
166
|
-
const el = await fixture(html`
|
|
166
|
+
const el = /** @type {LionListbox} */ await fixture(html`
|
|
167
167
|
<${tag} name="gender" .modelValue=${'other'}>
|
|
168
168
|
<${optionTag} .choiceValue=${'male'}></${optionTag}>
|
|
169
169
|
<${optionTag} .choiceValue=${'female'}></${optionTag}>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { normalizeIntlDate } from './utils/normalizeIntlDate.js';
|
|
2
2
|
import { forceShortMonthNamesForEnGb } from './utils/forceShortMonthNamesForEnGb.js';
|
|
3
|
+
import { forceDotsForNlnl } from './utils/forceDotsForNlnl.js';
|
|
3
4
|
|
|
4
5
|
/** @type {Object.<string, Object.<string,string[]>>} */
|
|
5
6
|
const monthsLocaleCache = {};
|
|
@@ -29,6 +30,8 @@ export function getMonthNames({ locale = 'en-GB', style = 'long' } = {}) {
|
|
|
29
30
|
}
|
|
30
31
|
if (locale === 'en-GB' && style === 'short') {
|
|
31
32
|
months = forceShortMonthNamesForEnGb(months);
|
|
33
|
+
} else if (locale === 'nl-NL' && style === 'short') {
|
|
34
|
+
months = forceDotsForNlnl(months);
|
|
32
35
|
}
|
|
33
36
|
monthsLocaleCache[locale] = monthsLocaleCache[locale] || {};
|
|
34
37
|
monthsLocaleCache[locale][style] = months;
|
|
@@ -13,7 +13,7 @@ export function forceAddGroupSeparators(formattedParts, groupSeparator) {
|
|
|
13
13
|
let integerPart;
|
|
14
14
|
|
|
15
15
|
for (let i = 0; i < formattedParts.length; i += 1) {
|
|
16
|
-
if (formattedParts[i].type === 'integer') {
|
|
16
|
+
if (formattedParts[i].type === 'integer' && formattedParts[i].value.length > 3) {
|
|
17
17
|
firstPart = formattedParts.splice(0, i);
|
|
18
18
|
integerPart = formattedParts.splice(0, 1);
|
|
19
19
|
}
|
|
@@ -66,6 +66,8 @@ export function forceAddGroupSeparators(formattedParts, groupSeparator) {
|
|
|
66
66
|
if (firstPart) {
|
|
67
67
|
concatArray = firstPart.concat(numberArray, formattedParts);
|
|
68
68
|
}
|
|
69
|
+
} else {
|
|
70
|
+
return formattedParts;
|
|
69
71
|
}
|
|
70
72
|
return concatArray;
|
|
71
73
|
}
|
package/components/localize/src/number/utils/normalize-format-number-to-parts/forceSymbols.js
CHANGED
|
@@ -17,6 +17,7 @@ const CURRENCY_CODE_SYMBOL_MAP = {
|
|
|
17
17
|
* @param {string[]} currencyScope
|
|
18
18
|
* @returns {FormatNumberPart[]}
|
|
19
19
|
*/
|
|
20
|
+
// eslint-disable-next-line default-param-last
|
|
20
21
|
export function forceSymbols(formattedParts, { currency, currencyDisplay } = {}, currencyScope) {
|
|
21
22
|
const result = formattedParts;
|
|
22
23
|
if (
|
|
@@ -44,6 +45,7 @@ export function forceSymbols(formattedParts, { currency, currencyDisplay } = {},
|
|
|
44
45
|
*/
|
|
45
46
|
export function forceFRBESymbols(
|
|
46
47
|
formattedParts,
|
|
48
|
+
// eslint-disable-next-line default-param-last
|
|
47
49
|
{ currency, currencyDisplay } = {},
|
|
48
50
|
currencyScope,
|
|
49
51
|
) {
|
package/components/localize/src/number/utils/normalize-format-number-to-parts/normalizeIntl.js
CHANGED
|
@@ -17,6 +17,7 @@ import { forceFRBESymbols, forceSymbols } from './forceSymbols.js';
|
|
|
17
17
|
* @param {string} _locale
|
|
18
18
|
* @returns {FormatNumberPart[]}
|
|
19
19
|
*/
|
|
20
|
+
// eslint-disable-next-line default-param-last
|
|
20
21
|
export function normalizeIntl(formattedParts, options = {}, _locale) {
|
|
21
22
|
let normalize = forceNormalSpaces(formattedParts);
|
|
22
23
|
// Dutch and Belgian currency must be moved to end of number
|
|
@@ -25,6 +25,7 @@ describe('getMonthNames', () => {
|
|
|
25
25
|
// expect(getMonthNames({ locale: 'en-GB', style: 'short' })).to.deep.equal(
|
|
26
26
|
// s`Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec`,
|
|
27
27
|
// );
|
|
28
|
+
// Chromium default is leading
|
|
28
29
|
expect(getMonthNames({ locale: 'nl-NL', style: 'short' })).to.deep.equal(
|
|
29
30
|
s`jan. feb. mrt. apr. mei jun. jul. aug. sep. okt. nov. dec.`,
|
|
30
31
|
);
|
|
@@ -56,5 +56,6 @@ export async function fakeImport(path, ms = 0) {
|
|
|
56
56
|
setTimeout(() => resolveOrReject(result, resolve, reject), ms);
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
59
60
|
return new Promise((resolve, reject) => resolveOrReject(result, resolve, reject));
|
|
60
61
|
}
|
|
@@ -119,7 +119,7 @@ export function adoptStyle(renderRoot, style, { teardown = false } = {}) {
|
|
|
119
119
|
if (!teardown) {
|
|
120
120
|
// @ts-ignore
|
|
121
121
|
// eslint-disable-next-line no-param-reassign
|
|
122
|
-
renderRoot.adoptedStyleSheets.
|
|
122
|
+
renderRoot.adoptedStyleSheets = [...renderRoot.adoptedStyleSheets, sheet];
|
|
123
123
|
} else if (renderRoot.adoptedStyleSheets.includes(sheet)) {
|
|
124
124
|
renderRoot.adoptedStyleSheets.splice(renderRoot.adoptedStyleSheets.indexOf(sheet), 1);
|
|
125
125
|
}
|