@lion/ui 0.6.0-alpha.5 → 0.6.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/form-core/src/choice-group/ChoiceGroupMixin.js +10 -1
- package/components/form-core/src/validate/ValidateMixin.js +10 -0
- package/components/form-core/src/validate/Validator.js +6 -3
- package/components/form-core/test-suites/FormRegistrationMixins.suite.js +7 -7
- package/components/form-core/types/FormControlMixinTypes.ts +2 -0
- package/components/form-core/types/validate/ValidateMixinTypes.ts +2 -0
- package/components/form-core/types/validate/validate.ts +2 -2
- package/components/input-file/src/LionInputFile.js +7 -1
- package/components/input-tel-dropdown/src/LionInputTelDropdown.js +11 -3
- package/components/input-tel-dropdown/test/LionInputTelDropdown.test.js +110 -2
- package/components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.js +22 -0
- package/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js +1 -38
- package/components/localize/src/LocalizeMixin.js +2 -2
- package/components/overlays/src/OverlayController.js +1 -1
- package/components/select/src/LionSelect.js +5 -0
- package/components/validate-messages/src/getLocalizedMessage.js +12 -1
- package/components/validate-messages/test/loadDefaultFeedbackMessagesNoSideEffects.test.js +105 -0
- package/components/validate-messages/translations/bg.js +4 -0
- package/components/validate-messages/translations/cs.js +4 -0
- package/components/validate-messages/translations/de.js +4 -0
- package/components/validate-messages/translations/en.js +5 -1
- package/components/validate-messages/translations/es.js +4 -0
- package/components/validate-messages/translations/fr.js +4 -0
- package/components/validate-messages/translations/hu.js +4 -0
- package/components/validate-messages/translations/it.js +4 -0
- package/components/validate-messages/translations/nl.js +4 -0
- package/components/validate-messages/translations/pl.js +4 -0
- package/components/validate-messages/translations/ro.js +4 -0
- package/components/validate-messages/translations/ru.js +4 -0
- package/components/validate-messages/translations/sk.js +4 -0
- package/components/validate-messages/translations/uk.js +4 -0
- package/components/validate-messages/translations/zh.js +4 -0
- package/custom-elements.json +4375 -1693
- package/dist-types/components/form-core/src/choice-group/ChoiceGroupMixin.d.ts +1 -0
- package/dist-types/components/form-core/src/choice-group/ChoiceGroupMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/validate/ValidateMixin.d.ts +1 -0
- package/dist-types/components/form-core/src/validate/ValidateMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/validate/Validator.d.ts +5 -2
- package/dist-types/components/form-core/src/validate/Validator.d.ts.map +1 -1
- package/dist-types/components/form-core/types/FormControlMixinTypes.d.ts +1 -0
- package/dist-types/components/form-core/types/FormControlMixinTypes.d.ts.map +1 -1
- package/dist-types/components/form-core/types/validate/ValidateMixinTypes.d.ts +1 -0
- package/dist-types/components/form-core/types/validate/ValidateMixinTypes.d.ts.map +1 -1
- package/dist-types/components/form-core/types/validate/validate.d.ts +2 -2
- package/dist-types/components/input-file/src/LionInputFile.d.ts.map +1 -1
- package/dist-types/components/input-tel-dropdown/src/LionInputTelDropdown.d.ts.map +1 -1
- package/dist-types/components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.d.ts +12 -0
- package/dist-types/components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.d.ts.map +1 -0
- package/dist-types/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.d.ts.map +1 -1
- package/dist-types/components/select/src/LionSelect.d.ts.map +1 -1
- package/dist-types/components/validate-messages/src/getLocalizedMessage.d.ts.map +1 -1
- package/dist-types/components/validate-messages/test/loadDefaultFeedbackMessagesNoSideEffects.test.d.ts +4 -0
- package/dist-types/components/validate-messages/test/loadDefaultFeedbackMessagesNoSideEffects.test.d.ts.map +1 -0
- package/dist-types/components/validate-messages/translations/bg-BG.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/bg.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/cs-CZ.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/cs.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/de-DE.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/de.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/en-AU.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/en-GB.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/en-PH.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/en-US.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/en.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/es-ES.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/es.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/fr-BE.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/fr-FR.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/fr.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/hu-HU.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/hu.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/it-IT.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/it.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/nl-BE.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/nl-NL.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/nl.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/pl-PL.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/pl.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/ro-RO.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/ro.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/ru-RU.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/ru.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/sk-SK.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/sk.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/uk-UA.d.ts +4 -0
- package/dist-types/components/validate-messages/translations/uk.d.ts +6 -0
- package/dist-types/components/validate-messages/translations/zh.d.ts +6 -0
- package/dist-types/exports/input-tel-dropdown-test-helpers.d.ts +2 -0
- package/dist-types/exports/input-tel-dropdown-test-helpers.d.ts.map +1 -0
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/overview.md +1 -1
- 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/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-file/use-cases.md +8 -8
- 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 +90 -95
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.md +34 -33
- 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 +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/styling.md +34 -39
- package/docs/fundamentals/systems/form/validate.md +7 -4
- 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/ajax/overview.md +2 -1
- 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/exports/input-tel-dropdown-test-helpers.js +1 -0
- package/input-tel-dropdown-test-helpers.js +1 -0
- package/package.json +1 -1
- package/components/validate-messages/test/loadDefaultFeedbackMessagesNoSideEffects.js +0 -51
- package/dist-types/components/validate-messages/test/loadDefaultFeedbackMessagesNoSideEffects.d.ts +0 -2
- package/dist-types/components/validate-messages/test/loadDefaultFeedbackMessagesNoSideEffects.d.ts.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { dedupeMixin } from '@open-wc/dedupe-mixin';
|
|
2
2
|
import { FormRegistrarMixin } from '../registration/FormRegistrarMixin.js';
|
|
3
3
|
import { InteractionStateMixin } from '../InteractionStateMixin.js';
|
|
4
|
+
import { ValidateMixin } from '../validate/ValidateMixin.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @typedef {import('../../types/choice-group/ChoiceGroupMixinTypes.js').ChoiceGroupMixin} ChoiceGroupMixin
|
|
@@ -8,6 +9,7 @@ import { InteractionStateMixin } from '../InteractionStateMixin.js';
|
|
|
8
9
|
* @typedef {import('../../types/registration/FormRegistrarMixinTypes.js').ElementWithParentFormGroup} ElementWithParentFormGroup
|
|
9
10
|
* @typedef {import('../../types/form-group/FormGroupMixinTypes.js').FormControl} FormControl
|
|
10
11
|
* @typedef {import('../../types/choice-group/ChoiceInputMixinTypes.js').ChoiceInputHost} ChoiceInputHost
|
|
12
|
+
* @typedef {import('../validate/Validator.js').Validator} Validator
|
|
11
13
|
*/
|
|
12
14
|
|
|
13
15
|
/**
|
|
@@ -22,7 +24,9 @@ import { InteractionStateMixin } from '../InteractionStateMixin.js';
|
|
|
22
24
|
*/
|
|
23
25
|
const ChoiceGroupMixinImplementation = superclass =>
|
|
24
26
|
// @ts-ignore https://github.com/microsoft/TypeScript/issues/36821#issuecomment-588375051
|
|
25
|
-
class ChoiceGroupMixin extends FormRegistrarMixin(
|
|
27
|
+
class ChoiceGroupMixin extends FormRegistrarMixin(
|
|
28
|
+
ValidateMixin(InteractionStateMixin(superclass)),
|
|
29
|
+
) {
|
|
26
30
|
/** @type {any} */
|
|
27
31
|
static get properties() {
|
|
28
32
|
return {
|
|
@@ -123,6 +127,11 @@ const ChoiceGroupMixinImplementation = superclass =>
|
|
|
123
127
|
}
|
|
124
128
|
}
|
|
125
129
|
|
|
130
|
+
get operationMode() {
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
return this._repropagationRole === 'choice-group' ? 'select' : 'enter';
|
|
133
|
+
}
|
|
134
|
+
|
|
126
135
|
constructor() {
|
|
127
136
|
super();
|
|
128
137
|
|
|
@@ -20,6 +20,7 @@ import { FormControlMixin } from '../FormControlMixin.js';
|
|
|
20
20
|
* @typedef {import('../../types/validate/ValidateMixinTypes.js').ValidateMixin} ValidateMixin
|
|
21
21
|
* @typedef {import('../../types/validate/ValidateMixinTypes.js').ValidationType} ValidationType
|
|
22
22
|
* @typedef {import('../../types/validate/ValidateMixinTypes.js').ValidateHost} ValidateHost
|
|
23
|
+
* @typedef {import('../../types/validate/ValidateMixinTypes.js').OperationMode} OperationMode
|
|
23
24
|
* @typedef {import('../../types/validate/index.js').ValidatorOutcome} ValidatorOutcome
|
|
24
25
|
* @typedef {typeof import('../../types/validate/ValidateMixinTypes.js').ValidateHost} ValidateHostConstructor
|
|
25
26
|
* @typedef {{validator:Validator; outcome:boolean|string}} ValidationResultEntry
|
|
@@ -98,6 +99,15 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
98
99
|
return ['error'];
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Types of input interaction of the FormControl (for instance 'enter'|'select'|'upload')
|
|
104
|
+
* @overridable
|
|
105
|
+
* @type {OperationMode}
|
|
106
|
+
*/
|
|
107
|
+
get operationMode() {
|
|
108
|
+
return 'enter';
|
|
109
|
+
}
|
|
110
|
+
|
|
101
111
|
/**
|
|
102
112
|
* Adds "._feedbackNode" as described below
|
|
103
113
|
* @public
|
|
@@ -27,12 +27,15 @@ export class Validator extends EventTarget {
|
|
|
27
27
|
this.__param = param;
|
|
28
28
|
/** @type {ValidatorConfig} */
|
|
29
29
|
this.__config = config || {};
|
|
30
|
-
/**
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Default type supported by ValidateMixin
|
|
32
|
+
* @type {ValidationType}
|
|
33
|
+
*/
|
|
34
|
+
this.type = config?.type || 'error';
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
/**
|
|
35
|
-
* The name under which validation results get registered. For
|
|
38
|
+
* The name under which validation results get registered. For convenience and predictability, this
|
|
36
39
|
* should always be the same as the constructor name (since it will be obfuscated in js builds,
|
|
37
40
|
* we need to provide it separately).
|
|
38
41
|
* @type {ValidatorName}
|
|
@@ -163,20 +163,20 @@ export const runRegistrationSuite = customConfig => {
|
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
it('works for components that have a delayed render', async () => {
|
|
166
|
-
class
|
|
167
|
-
async
|
|
166
|
+
class ScheduleUpdate extends FormRegistrarMixin(LitElement) {
|
|
167
|
+
async scheduleUpdate() {
|
|
168
168
|
// eslint-disable-next-line no-promise-executor-return
|
|
169
169
|
await new Promise(resolve => setTimeout(() => resolve(undefined), 10));
|
|
170
|
-
await super.
|
|
170
|
+
await super.scheduleUpdate();
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
render() {
|
|
174
174
|
return html`<slot></slot>`;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
-
const tagWrapperString = defineCE(
|
|
177
|
+
const tagWrapperString = defineCE(ScheduleUpdate);
|
|
178
178
|
const tagWrapper = unsafeStatic(tagWrapperString);
|
|
179
|
-
const el = /** @type {
|
|
179
|
+
const el = /** @type {ScheduleUpdate} */ (
|
|
180
180
|
await fixture(html`
|
|
181
181
|
<${tagWrapper}>
|
|
182
182
|
<${childTag}></${childTag}>
|
|
@@ -359,10 +359,10 @@ export const runRegistrationSuite = customConfig => {
|
|
|
359
359
|
it('works for portals that have a delayed render', async () => {
|
|
360
360
|
const delayedPortalString = defineCE(
|
|
361
361
|
class extends FormRegistrarPortalMixin(LitElement) {
|
|
362
|
-
async
|
|
362
|
+
async scheduleUpdate() {
|
|
363
363
|
// eslint-disable-next-line no-promise-executor-return
|
|
364
364
|
await new Promise(resolve => setTimeout(() => resolve(undefined), 10));
|
|
365
|
-
await super.
|
|
365
|
+
await super.scheduleUpdate();
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
render() {
|
|
@@ -16,6 +16,8 @@ export type FeedbackMessage = {
|
|
|
16
16
|
|
|
17
17
|
export type ValidationType = 'error' | 'warning' | 'info' | 'success' | string;
|
|
18
18
|
|
|
19
|
+
export type OperationMode = 'enter' | 'select' | 'upload';
|
|
20
|
+
|
|
19
21
|
export declare class ValidateHost {
|
|
20
22
|
/**
|
|
21
23
|
* Used by Application Developers to add Validators to a FormControl.
|
|
@@ -2,7 +2,7 @@ import { FormControlHost } from '../../src/FormControlMixin.js';
|
|
|
2
2
|
import { ValidationType } from './ValidateMixinTypes.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* The name under which validation results get registered. For
|
|
5
|
+
* The name under which validation results get registered. For convenience and predictability, this
|
|
6
6
|
* should always be the same as the constructor name (since it will be obfuscated in js builds,
|
|
7
7
|
* we need to provide it separately).
|
|
8
8
|
* @example
|
|
@@ -34,7 +34,7 @@ export type ValidatorConfig = {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Output of the `execute` function that returns a validity outcome. When we need to
|
|
37
|
+
* Output of the `execute` function that returns a validity outcome. When we need to show feedback,
|
|
38
38
|
* it should return true, otherwise false. So when an error\info|warning|success message
|
|
39
39
|
* needs to be shown, return true.
|
|
40
40
|
* It's also possible to return an enum. Let's say that a phone number can have multiple
|
|
@@ -215,6 +215,11 @@ export class LionInputFile extends ScopedElementsMixin(LocalizeMixin(LionField))
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
// eslint-disable-next-line class-methods-use-this
|
|
219
|
+
get operationMode() {
|
|
220
|
+
return 'upload';
|
|
221
|
+
}
|
|
222
|
+
|
|
218
223
|
get _acceptCriteria() {
|
|
219
224
|
/** @type {string[]} */
|
|
220
225
|
let allowedFileTypes = [];
|
|
@@ -433,7 +438,8 @@ export class LionInputFile extends ScopedElementsMixin(LocalizeMixin(LionField))
|
|
|
433
438
|
];
|
|
434
439
|
}
|
|
435
440
|
});
|
|
436
|
-
//
|
|
441
|
+
// TODO: add a unit test for this
|
|
442
|
+
this._selectedFilesMetaData = [...this._selectedFilesMetaData];
|
|
437
443
|
}
|
|
438
444
|
});
|
|
439
445
|
}
|
|
@@ -324,7 +324,10 @@ export class LionInputTelDropdown extends LionInputTel {
|
|
|
324
324
|
*/
|
|
325
325
|
_onDropdownValueChange(event) {
|
|
326
326
|
const isInitializing = event.detail?.initialize || !this._phoneUtil;
|
|
327
|
-
const
|
|
327
|
+
const dropdownElement = event.target;
|
|
328
|
+
const dropdownValue = /** @type {RegionCode} */ (
|
|
329
|
+
dropdownElement.modelValue || dropdownElement.value
|
|
330
|
+
);
|
|
328
331
|
|
|
329
332
|
if (isInitializing || this.activeRegion === dropdownValue) {
|
|
330
333
|
return;
|
|
@@ -355,8 +358,13 @@ export class LionInputTelDropdown extends LionInputTel {
|
|
|
355
358
|
}
|
|
356
359
|
|
|
357
360
|
// Put focus on text box
|
|
358
|
-
|
|
359
|
-
|
|
361
|
+
//
|
|
362
|
+
// A LionSelectRich with interactionMode set on windows/linux
|
|
363
|
+
// will set each item on arrow key up/down to activeElement
|
|
364
|
+
// which causes the focus to jump every time to the inputNode
|
|
365
|
+
const overlayController = dropdownElement._overlayCtrl;
|
|
366
|
+
// @ts-ignore interactionMode only exists on LionSelectRich not on HTMLSelectElement
|
|
367
|
+
if (overlayController?.isShown && dropdownElement.interactionMode !== 'windows/linux') {
|
|
360
368
|
setTimeout(() => {
|
|
361
369
|
this._inputNode.focus();
|
|
362
370
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { runInputTelSuite } from '@lion/ui/input-tel-test-suites.js';
|
|
2
|
-
import { html } from 'lit';
|
|
3
2
|
import { repeat } from 'lit/directives/repeat.js';
|
|
4
3
|
import { ref } from 'lit/directives/ref.js';
|
|
5
|
-
|
|
4
|
+
import { aTimeout, expect, fixture, html } from '@open-wc/testing';
|
|
6
5
|
import { LionInputTelDropdown } from '@lion/ui/input-tel-dropdown.js';
|
|
7
6
|
import { LionOption } from '@lion/ui/listbox.js';
|
|
8
7
|
import { LionSelectRich } from '@lion/ui/select-rich.js';
|
|
9
8
|
import { runInputTelDropdownSuite } from '@lion/ui/input-tel-dropdown-test-suites.js';
|
|
9
|
+
import { mimicUserChangingDropdown } from '@lion/ui/input-tel-dropdown-test-helpers.js';
|
|
10
10
|
import { ScopedElementsMixin } from '../../core/src/ScopedElementsMixin.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -62,4 +62,112 @@ describe('WithFormControlInputTelDropdown', () => {
|
|
|
62
62
|
// @ts-expect-error
|
|
63
63
|
// Runs it for LionSelectRich, which uses .modelValue/@model-value-changed instead of .value/@change
|
|
64
64
|
runInputTelDropdownSuite({ klass: WithFormControlInputTelDropdown });
|
|
65
|
+
|
|
66
|
+
it('focuses the textbox right after selection if selected via opened dropdown if interaction-mode is mac', async () => {
|
|
67
|
+
class InputTelDropdownMac extends LionInputTelDropdown {
|
|
68
|
+
static templates = {
|
|
69
|
+
...(super.templates || {}),
|
|
70
|
+
/**
|
|
71
|
+
* @param {TemplateDataForDropdownInputTel} templateDataForDropdown
|
|
72
|
+
*/
|
|
73
|
+
dropdown: templateDataForDropdown => {
|
|
74
|
+
const { refs, data } = templateDataForDropdown;
|
|
75
|
+
// TODO: once spread directive available, use it per ref (like ref(refs?.dropdown?.ref))
|
|
76
|
+
return html`
|
|
77
|
+
<lion-select-rich
|
|
78
|
+
${ref(refs?.dropdown?.ref)}
|
|
79
|
+
label="${refs?.dropdown?.labels?.country}"
|
|
80
|
+
label-sr-only
|
|
81
|
+
@model-value-changed="${refs?.dropdown?.listeners['model-value-changed']}"
|
|
82
|
+
style="${refs?.dropdown?.props?.style}"
|
|
83
|
+
interaction-mode="mac"
|
|
84
|
+
>
|
|
85
|
+
${repeat(
|
|
86
|
+
data.regionMetaList,
|
|
87
|
+
regionMeta => regionMeta.regionCode,
|
|
88
|
+
regionMeta =>
|
|
89
|
+
html` <lion-option .choiceValue="${regionMeta.regionCode}"> </lion-option> `,
|
|
90
|
+
)}
|
|
91
|
+
</lion-select-rich>
|
|
92
|
+
`;
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
customElements.define('input-tel-dropdown-mac', InputTelDropdownMac);
|
|
97
|
+
const el = /** @type {LionInputTelDropdown} */ (
|
|
98
|
+
await fixture(
|
|
99
|
+
html`
|
|
100
|
+
<input-tel-dropdown-mac
|
|
101
|
+
.allowedRegions="${['NL', 'BE']}"
|
|
102
|
+
.modelValue="${'+31612345678'}"
|
|
103
|
+
></input-tel-dropdown-mac>
|
|
104
|
+
`,
|
|
105
|
+
)
|
|
106
|
+
);
|
|
107
|
+
const dropdownElement = el.refs.dropdown.value;
|
|
108
|
+
// @ts-expect-error [allow-protected-in-tests]
|
|
109
|
+
if (dropdownElement?._overlayCtrl) {
|
|
110
|
+
// @ts-expect-error [allow-protected-in-tests]
|
|
111
|
+
dropdownElement._overlayCtrl.show();
|
|
112
|
+
mimicUserChangingDropdown(dropdownElement, 'BE');
|
|
113
|
+
await el.updateComplete;
|
|
114
|
+
await aTimeout(0);
|
|
115
|
+
// @ts-expect-error [allow-protected-in-tests]
|
|
116
|
+
expect(el._inputNode).to.equal(document.activeElement);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('does not focus the textbox right after selection if selected via opened dropdown if interaction-mode is windows/linux', async () => {
|
|
121
|
+
class InputTelDropdownWindows extends LionInputTelDropdown {
|
|
122
|
+
static templates = {
|
|
123
|
+
...(super.templates || {}),
|
|
124
|
+
/**
|
|
125
|
+
* @param {TemplateDataForDropdownInputTel} templateDataForDropdown
|
|
126
|
+
*/
|
|
127
|
+
dropdown: templateDataForDropdown => {
|
|
128
|
+
const { refs, data } = templateDataForDropdown;
|
|
129
|
+
// TODO: once spread directive available, use it per ref (like ref(refs?.dropdown?.ref))
|
|
130
|
+
return html`
|
|
131
|
+
<lion-select-rich
|
|
132
|
+
${ref(refs?.dropdown?.ref)}
|
|
133
|
+
label="${refs?.dropdown?.labels?.country}"
|
|
134
|
+
label-sr-only
|
|
135
|
+
@model-value-changed="${refs?.dropdown?.listeners['model-value-changed']}"
|
|
136
|
+
style="${refs?.dropdown?.props?.style}"
|
|
137
|
+
interaction-mode="windows/linux"
|
|
138
|
+
>
|
|
139
|
+
${repeat(
|
|
140
|
+
data.regionMetaList,
|
|
141
|
+
regionMeta => regionMeta.regionCode,
|
|
142
|
+
regionMeta =>
|
|
143
|
+
html` <lion-option .choiceValue="${regionMeta.regionCode}"> </lion-option> `,
|
|
144
|
+
)}
|
|
145
|
+
</lion-select-rich>
|
|
146
|
+
`;
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
customElements.define('input-tel-dropdown-windows', InputTelDropdownWindows);
|
|
151
|
+
const el = /** @type {LionInputTelDropdown} */ (
|
|
152
|
+
await fixture(
|
|
153
|
+
html`
|
|
154
|
+
<input-tel-dropdown-windows
|
|
155
|
+
.allowedRegions="${['NL', 'BE']}"
|
|
156
|
+
.modelValue="${'+31612345678'}"
|
|
157
|
+
></input-tel-dropdown-windows>
|
|
158
|
+
`,
|
|
159
|
+
)
|
|
160
|
+
);
|
|
161
|
+
const dropdownElement = el.refs.dropdown.value;
|
|
162
|
+
// @ts-expect-error [allow-protected-in-tests]
|
|
163
|
+
if (dropdownElement?._overlayCtrl) {
|
|
164
|
+
// @ts-expect-error [allow-protected-in-tests]
|
|
165
|
+
dropdownElement._overlayCtrl.show();
|
|
166
|
+
mimicUserChangingDropdown(dropdownElement, 'BE');
|
|
167
|
+
await el.updateComplete;
|
|
168
|
+
await aTimeout(0);
|
|
169
|
+
// @ts-expect-error [allow-protected-in-tests]
|
|
170
|
+
expect(el._inputNode).to.not.equal(document.activeElement);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
65
173
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {HTMLSelectElement|HTMLElement & {modelValue:string}} DropdownElement
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {DropdownElement} dropdownEl
|
|
7
|
+
* @param {string} value
|
|
8
|
+
*/
|
|
9
|
+
export function mimicUserChangingDropdown(dropdownEl, value) {
|
|
10
|
+
if ('modelValue' in dropdownEl) {
|
|
11
|
+
// eslint-disable-next-line no-param-reassign
|
|
12
|
+
dropdownEl.modelValue = value;
|
|
13
|
+
dropdownEl.dispatchEvent(
|
|
14
|
+
new CustomEvent('model-value-changed', { detail: { isTriggeredByUser: true } }),
|
|
15
|
+
);
|
|
16
|
+
} else {
|
|
17
|
+
// eslint-disable-next-line no-param-reassign
|
|
18
|
+
dropdownEl.value = value;
|
|
19
|
+
dropdownEl.dispatchEvent(new Event('change'));
|
|
20
|
+
dropdownEl.dispatchEvent(new Event('input'));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from '@open-wc/testing';
|
|
12
12
|
import sinon from 'sinon';
|
|
13
13
|
import { LionInputTelDropdown } from '@lion/ui/input-tel-dropdown.js';
|
|
14
|
+
import { mimicUserChangingDropdown } from '@lion/ui/input-tel-dropdown-test-helpers.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* @typedef {import('lit').TemplateResult} TemplateResult
|
|
@@ -36,24 +37,6 @@ function getDropdownValue(dropdownEl) {
|
|
|
36
37
|
return dropdownEl.value;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
/**
|
|
40
|
-
* @param {DropdownElement} dropdownEl
|
|
41
|
-
* @param {string} value
|
|
42
|
-
*/
|
|
43
|
-
function mimicUserChangingDropdown(dropdownEl, value) {
|
|
44
|
-
if ('modelValue' in dropdownEl) {
|
|
45
|
-
// eslint-disable-next-line no-param-reassign
|
|
46
|
-
dropdownEl.modelValue = value;
|
|
47
|
-
dropdownEl.dispatchEvent(
|
|
48
|
-
new CustomEvent('model-value-changed', { detail: { isTriggeredByUser: true } }),
|
|
49
|
-
);
|
|
50
|
-
} else {
|
|
51
|
-
// eslint-disable-next-line no-param-reassign
|
|
52
|
-
dropdownEl.value = value;
|
|
53
|
-
dropdownEl.dispatchEvent(new Event('change'));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
40
|
/**
|
|
58
41
|
* @param {{ klass:LionInputTelDropdown }} config
|
|
59
42
|
*/
|
|
@@ -335,26 +318,6 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
|
|
|
335
318
|
expect(el.value).to.equal('+32');
|
|
336
319
|
});
|
|
337
320
|
|
|
338
|
-
it('focuses the textbox right after selection if selected via opened dropdown', async () => {
|
|
339
|
-
const el = await fixture(
|
|
340
|
-
html` <${tag} .allowedRegions="${[
|
|
341
|
-
'NL',
|
|
342
|
-
'BE',
|
|
343
|
-
]}" .modelValue="${'+31612345678'}"></${tag}> `,
|
|
344
|
-
);
|
|
345
|
-
const dropdownElement = el.refs.dropdown.value;
|
|
346
|
-
// @ts-expect-error [allow-protected-in-tests]
|
|
347
|
-
if (dropdownElement?._overlayCtrl) {
|
|
348
|
-
// @ts-expect-error [allow-protected-in-tests]
|
|
349
|
-
dropdownElement._overlayCtrl.show();
|
|
350
|
-
mimicUserChangingDropdown(dropdownElement, 'BE');
|
|
351
|
-
await el.updateComplete;
|
|
352
|
-
await aTimeout(0);
|
|
353
|
-
// @ts-expect-error [allow-protected-in-tests]
|
|
354
|
-
expect(el._inputNode).to.equal(document.activeElement);
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
|
|
358
321
|
it('keeps focus on dropdownElement after selection if selected via unopened dropdown', async () => {
|
|
359
322
|
const el = await fixture(
|
|
360
323
|
html` <${tag} .allowedRegions="${[
|
|
@@ -64,11 +64,11 @@ const LocalizeMixinImplementation = superclass =>
|
|
|
64
64
|
* hook into LitElement to only render once all translations are loaded
|
|
65
65
|
* @returns {Promise.<void>}
|
|
66
66
|
*/
|
|
67
|
-
async
|
|
67
|
+
async scheduleUpdate() {
|
|
68
68
|
if (Object.getPrototypeOf(this).constructor.waitForLocalizeNamespaces) {
|
|
69
69
|
await this.localizeNamespacesLoaded;
|
|
70
70
|
}
|
|
71
|
-
super.
|
|
71
|
+
super.scheduleUpdate();
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
connectedCallback() {
|
|
@@ -931,7 +931,7 @@ export class OverlayController extends EventTarget {
|
|
|
931
931
|
return;
|
|
932
932
|
}
|
|
933
933
|
|
|
934
|
-
if (this.elementToFocusAfterHide) {
|
|
934
|
+
if (this.elementToFocusAfterHide instanceof HTMLElement) {
|
|
935
935
|
this.elementToFocusAfterHide.focus();
|
|
936
936
|
this.elementToFocusAfterHide.scrollIntoView({ block: 'nearest' });
|
|
937
937
|
} else {
|
|
@@ -57,6 +57,11 @@ class LionFieldWithSelect extends LionField {
|
|
|
57
57
|
* @customElement lion-select
|
|
58
58
|
*/
|
|
59
59
|
export class LionSelect extends LionFieldWithSelect {
|
|
60
|
+
// eslint-disable-next-line class-methods-use-this
|
|
61
|
+
get operationMode() {
|
|
62
|
+
return 'select';
|
|
63
|
+
}
|
|
64
|
+
|
|
60
65
|
connectedCallback() {
|
|
61
66
|
super.connectedCallback();
|
|
62
67
|
this._inputNode.addEventListener('change', this._proxyChangeEvent);
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
/** @type {Promise<void | object>} */
|
|
7
7
|
let pendingPromise;
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} string
|
|
11
|
+
*/
|
|
12
|
+
const capitalize = string => (string && string[0].toUpperCase() + string.slice(1)) || '';
|
|
13
|
+
|
|
9
14
|
/**
|
|
10
15
|
* @param {{localize: LocalizeManager}} opts
|
|
11
16
|
*/
|
|
@@ -105,7 +110,13 @@ export async function loadValidateNamespace({ localize }) {
|
|
|
105
110
|
export const getLocalizedMessage = async ({ data, localize }) => {
|
|
106
111
|
await loadValidateNamespace({ localize });
|
|
107
112
|
if (data) {
|
|
108
|
-
|
|
113
|
+
const operationMode =
|
|
114
|
+
data.formControl?.operationMode !== 'enter' && data.name === 'Required'
|
|
115
|
+
? capitalize(data.formControl?.operationMode)
|
|
116
|
+
: undefined;
|
|
117
|
+
const validatorName = operationMode ? `_${data.name}${operationMode}` : data.name;
|
|
118
|
+
|
|
119
|
+
return localize.msg(`lion-validate:${data.type}.${validatorName}`, data);
|
|
109
120
|
}
|
|
110
121
|
return '';
|
|
111
122
|
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars, no-param-reassign */
|
|
2
|
+
import { expect } from '@open-wc/testing';
|
|
3
|
+
import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
|
|
4
|
+
import { MinDate, MinLength, Required } from '@lion/ui/form-core.js';
|
|
5
|
+
import { loadDefaultFeedbackMessagesNoSideEffects } from '@lion/ui/validate-messages-no-side-effects.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {import('../../form-core/src/validate/Validator.js').Validator} Validator
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {Validator} validatorEl
|
|
13
|
+
*/
|
|
14
|
+
function getProtectedMembers(validatorEl) {
|
|
15
|
+
// @ts-ignore protected members allowed in test
|
|
16
|
+
return {
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
getMessage: (...args) => validatorEl._getMessage(...args),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {import('@lion/ui/types/form-core.js').FormControlHost} FormControlHost
|
|
24
|
+
* @typedef {ArrayConstructor | ObjectConstructor | NumberConstructor | BooleanConstructor | StringConstructor | DateConstructor | 'iban' | 'email'} modelValueType
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
describe('loadDefaultFeedbackMessagesNoSideEffects', () => {
|
|
28
|
+
const localizeManager = getLocalizeManager();
|
|
29
|
+
|
|
30
|
+
it('will set default feedback message for Required', async () => {
|
|
31
|
+
const el = new Required();
|
|
32
|
+
const { getMessage } = getProtectedMembers(el);
|
|
33
|
+
expect(await getMessage()).to.equals(
|
|
34
|
+
'Please configure an error message for "Required" by overriding "static async getMessage()"',
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
loadDefaultFeedbackMessagesNoSideEffects({ localize: localizeManager });
|
|
38
|
+
expect(await getMessage({ fieldName: 'password' })).to.equal('Please enter a(n) password.');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('passes data to the feedback message', async () => {
|
|
42
|
+
const el = new MinLength(10);
|
|
43
|
+
const { getMessage } = getProtectedMembers(el);
|
|
44
|
+
|
|
45
|
+
loadDefaultFeedbackMessagesNoSideEffects({ localize: localizeManager });
|
|
46
|
+
expect(await getMessage({ fieldName: 'password' })).to.equal(
|
|
47
|
+
'Please enter a correct password (at least 10 characters).',
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const el2 = new MinDate(new Date('2024-01-29'));
|
|
51
|
+
// @ts-ignore protected members allowed in test
|
|
52
|
+
expect(await el2._getMessage({ fieldName: 'date' })).to.equal(
|
|
53
|
+
'Please enter a(n) date after or equal to 29/01/2024.',
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('will set select specific feedback message for Required when operationMode is set', async () => {
|
|
58
|
+
const el = new Required();
|
|
59
|
+
loadDefaultFeedbackMessagesNoSideEffects({ localize: localizeManager });
|
|
60
|
+
const { getMessage } = getProtectedMembers(el);
|
|
61
|
+
const formControl = { operationMode: 'select' };
|
|
62
|
+
expect(await getMessage({ fieldName: 'password', formControl })).to.equal(
|
|
63
|
+
'Please select a(n) password.',
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('will set upload specific feedback message for Required when operationMode is set', async () => {
|
|
68
|
+
const el = new Required();
|
|
69
|
+
const { getMessage } = getProtectedMembers(el);
|
|
70
|
+
|
|
71
|
+
loadDefaultFeedbackMessagesNoSideEffects({ localize: localizeManager });
|
|
72
|
+
const formControl = { operationMode: 'upload' };
|
|
73
|
+
expect(await getMessage({ fieldName: 'password', formControl })).to.equal(
|
|
74
|
+
'Please upload a(n) password.',
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('will set ignore the operationMode for any other validator then Required, e.g. MinLength', async () => {
|
|
79
|
+
const el = new MinLength(10);
|
|
80
|
+
const { getMessage } = getProtectedMembers(el);
|
|
81
|
+
|
|
82
|
+
loadDefaultFeedbackMessagesNoSideEffects({ localize: localizeManager });
|
|
83
|
+
const formControl = { operationMode: 'select' };
|
|
84
|
+
expect(await getMessage({ fieldName: 'password', formControl })).to.equal(
|
|
85
|
+
'Please enter a correct password (at least 10 characters).',
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('will await loading of translations when switching locale', async () => {
|
|
90
|
+
const el = new Required();
|
|
91
|
+
const { getMessage } = getProtectedMembers(el);
|
|
92
|
+
loadDefaultFeedbackMessagesNoSideEffects({ localize: localizeManager });
|
|
93
|
+
expect(await getMessage({ fieldName: 'password' })).to.equal('Please enter a(n) password.');
|
|
94
|
+
expect(await getMessage({ fieldName: 'user name' })).to.equal('Please enter a(n) user name.');
|
|
95
|
+
|
|
96
|
+
localizeManager.locale = 'de-DE';
|
|
97
|
+
await localizeManager.loadingComplete;
|
|
98
|
+
expect(await getMessage({ fieldName: 'Password' })).to.equal(
|
|
99
|
+
'Password muss ausgefüllt werden.',
|
|
100
|
+
);
|
|
101
|
+
expect(await getMessage({ fieldName: 'Benutzername' })).to.equal(
|
|
102
|
+
'Benutzername muss ausgefüllt werden.',
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
error: {
|
|
3
3
|
Required: 'Моля, въведете също {fieldName}.',
|
|
4
|
+
_RequiredUpload: 'Моля, качете {fieldName}.',
|
|
5
|
+
_RequiredSelect: 'Wählen Sie auch einen Wert für {fieldName} aus.',
|
|
4
6
|
EqualsLength: 'Моля, въведете правилно {fieldName} от точно {params} знака.',
|
|
5
7
|
MinLength: 'Моля, въведете правилен {fieldName} (поне {params}).',
|
|
6
8
|
MaxLength: 'Моля, въведете правилен {fieldName} (до {params} знака).',
|
|
@@ -22,6 +24,8 @@ export default {
|
|
|
22
24
|
},
|
|
23
25
|
warning: {
|
|
24
26
|
Required: 'Моля, въведете също {fieldName}.',
|
|
27
|
+
_RequiredUpload: 'Моля, качете {fieldName}.',
|
|
28
|
+
_RequiredSelect: 'Wählen Sie auch einen Wert für {fieldName} aus.',
|
|
25
29
|
EqualsLength: 'Моля, въведете правилно {fieldName} от точно {params} знака.',
|
|
26
30
|
MinLength: 'Моля, въведете правилен {fieldName} (поне {params}).',
|
|
27
31
|
MaxLength: 'Моля, въведете правилен {fieldName} (до {params} знака).',
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
error: {
|
|
3
3
|
Required: 'Zadejte rovněž {fieldName}.',
|
|
4
|
+
_RequiredUpload: 'Nahrajte {fieldname}.',
|
|
5
|
+
_RequiredSelect: 'Vyberte rovněž {fieldname}.',
|
|
4
6
|
EqualsLength: 'Zadejte správné {fieldName}, přesně {params} znaků.',
|
|
5
7
|
MinLength: 'Zadejte správné {fieldName} (alespoň {params}).',
|
|
6
8
|
MaxLength: 'Zadejte správné {fieldName} (až {params} znaků).',
|
|
@@ -21,6 +23,8 @@ export default {
|
|
|
21
23
|
},
|
|
22
24
|
warning: {
|
|
23
25
|
Required: 'Zadejte rovněž {fieldName}.',
|
|
26
|
+
_RequiredUpload: 'Nahrajte {fieldname}.',
|
|
27
|
+
_RequiredSelect: 'Vyberte rovněž {fieldname}.',
|
|
24
28
|
EqualsLength: 'Zadejte správné {fieldName}, přesně {params} znaků.',
|
|
25
29
|
MinLength: 'Zadejte správné {fieldName} (alespoň {params}).',
|
|
26
30
|
MaxLength: 'Zadejte správné {fieldName} (až {params} znaků).',
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
error: {
|
|
3
3
|
Required: '{fieldName} muss ausgefüllt werden.',
|
|
4
|
+
_RequiredUpload: 'Bitte laden Sie ein/e/n {fieldName} hoch.',
|
|
5
|
+
_RequiredSelect: 'Wählen Sie auch einen Wert für {fieldName} aus.',
|
|
4
6
|
EqualsLength: 'Geben Sie einen korrekten Wert für {fieldName} mit exakt {params} Zeichen ein.',
|
|
5
7
|
MinLength: 'Du musst mindestens {params} Zeichen eingeben.',
|
|
6
8
|
MaxLength: 'Du kannst maximal {params} Zeichen eingeben.',
|
|
@@ -23,6 +25,8 @@ export default {
|
|
|
23
25
|
},
|
|
24
26
|
warning: {
|
|
25
27
|
Required: '{fieldName} sollte ausgefüllt werden.',
|
|
28
|
+
_RequiredUpload: 'Bitte laden Sie ein/e/n {fieldName} hoch.',
|
|
29
|
+
_RequiredSelect: 'Wählen Sie auch einen Wert für {fieldName} aus.',
|
|
26
30
|
EqualsLength: 'Geben Sie einen korrekten Wert für {fieldName} mit exakt {params} Zeichen ein.',
|
|
27
31
|
MinLength: 'Du solltest mindestens {params} Zeichen eingeben.',
|
|
28
32
|
MaxLength: 'Du kannst maximal {params} Zeichen eingeben.',
|