@lion/ui 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/calendar/src/LionCalendar.js +1 -1
- package/components/calendar/test/lion-calendar.test.js +67 -47
- package/components/calendar/test-suites/LionCalendar.suite.js +79 -0
- package/components/form-core/src/choice-group/ChoiceInputMixin.js +1 -1
- package/components/input-amount-dropdown/src/LionInputAmountDropdown.js +6 -4
- package/components/input-amount-dropdown/test/LionInputAmountDropdown.test.js +20 -1
- package/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.js +24 -0
- package/components/input-datepicker/test/lion-input-datepicker.test.js +13 -4
- package/components/input-datepicker/test-suites/LionInputDatepicker.suite.js +35 -0
- package/components/input-email/src/LionInputEmail.js +2 -0
- package/components/input-email/test/lion-input-email.test.js +6 -0
- package/components/input-file/src/validators.js +31 -1
- package/components/input-file/test/FileValidators.test.js +31 -0
- package/components/input-file/translations/bg.js +1 -0
- package/components/input-file/translations/cs.js +1 -0
- package/components/input-file/translations/de.js +2 -0
- package/components/input-file/translations/en.js +1 -0
- package/components/input-file/translations/es.js +1 -0
- package/components/input-file/translations/fr.js +1 -0
- package/components/input-file/translations/hu.js +1 -0
- package/components/input-file/translations/id.js +1 -0
- package/components/input-file/translations/it.js +1 -0
- package/components/input-file/translations/nl.js +1 -0
- package/components/input-file/translations/pl.js +1 -0
- package/components/input-file/translations/ro.js +1 -0
- package/components/input-file/translations/ru.js +1 -0
- package/components/input-file/translations/sk.js +1 -0
- package/components/input-file/translations/uk.js +1 -0
- package/components/input-file/translations/zh.js +1 -0
- package/components/input-tel/src/LionInputTel.js +1 -1
- package/components/input-tel/test-suites/LionInputTel.suite.js +7 -0
- package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js +132 -26
- package/components/overlays/test/withHoverInteraction.test.js +118 -0
- package/components/switch/src/LionSwitch.js +1 -1
- package/components/switch/test/lion-switch.test.js +7 -0
- package/custom-elements.json +403 -62
- package/dist-types/components/calendar/test/lion-calendar.test.d.ts.map +1 -1
- package/dist-types/components/calendar/test-suites/LionCalendar.suite.d.ts +5 -0
- package/dist-types/components/calendar/test-suites/LionCalendar.suite.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/src/LionInputAmountDropdown.d.ts +0 -9
- package/dist-types/components/input-amount-dropdown/src/LionInputAmountDropdown.d.ts.map +1 -1
- package/dist-types/components/input-amount-dropdown/test/LionInputAmountDropdown.test.d.ts.map +1 -1
- package/dist-types/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/test/lion-input-datepicker.test.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/test-suites/LionInputDatepicker.suite.d.ts +7 -0
- package/dist-types/components/input-datepicker/test-suites/LionInputDatepicker.suite.d.ts.map +1 -0
- package/dist-types/components/input-email/src/LionInputEmail.d.ts.map +1 -1
- package/dist-types/components/input-file/src/validators.d.ts +11 -0
- package/dist-types/components/input-file/src/validators.d.ts.map +1 -1
- package/dist-types/components/input-file/translations/bg-BG.d.ts +1 -0
- package/dist-types/components/input-file/translations/bg.d.ts +1 -0
- package/dist-types/components/input-file/translations/cs-CZ.d.ts +1 -0
- package/dist-types/components/input-file/translations/cs.d.ts +1 -0
- package/dist-types/components/input-file/translations/de-DE.d.ts +1 -0
- package/dist-types/components/input-file/translations/de.d.ts +1 -0
- package/dist-types/components/input-file/translations/en-AU.d.ts +1 -0
- package/dist-types/components/input-file/translations/en-GB.d.ts +1 -0
- package/dist-types/components/input-file/translations/en-PH.d.ts +1 -0
- package/dist-types/components/input-file/translations/en-US.d.ts +1 -0
- package/dist-types/components/input-file/translations/en.d.ts +1 -0
- package/dist-types/components/input-file/translations/es-ES.d.ts +1 -0
- package/dist-types/components/input-file/translations/es.d.ts +1 -0
- package/dist-types/components/input-file/translations/fr-BE.d.ts +1 -0
- package/dist-types/components/input-file/translations/fr-FR.d.ts +1 -0
- package/dist-types/components/input-file/translations/fr.d.ts +1 -0
- package/dist-types/components/input-file/translations/hu-HU.d.ts +1 -0
- package/dist-types/components/input-file/translations/hu.d.ts +1 -0
- package/dist-types/components/input-file/translations/id-ID.d.ts +1 -0
- package/dist-types/components/input-file/translations/id.d.ts +1 -0
- package/dist-types/components/input-file/translations/it-IT.d.ts +1 -0
- package/dist-types/components/input-file/translations/it.d.ts +1 -0
- package/dist-types/components/input-file/translations/nl-BE.d.ts +1 -0
- package/dist-types/components/input-file/translations/nl-NL.d.ts +1 -0
- package/dist-types/components/input-file/translations/nl.d.ts +1 -0
- package/dist-types/components/input-file/translations/pl-PL.d.ts +1 -0
- package/dist-types/components/input-file/translations/pl.d.ts +1 -0
- package/dist-types/components/input-file/translations/ro-RO.d.ts +1 -0
- package/dist-types/components/input-file/translations/ro.d.ts +1 -0
- package/dist-types/components/input-file/translations/ru-RU.d.ts +1 -0
- package/dist-types/components/input-file/translations/ru.d.ts +1 -0
- package/dist-types/components/input-file/translations/sk-SK.d.ts +1 -0
- package/dist-types/components/input-file/translations/sk.d.ts +1 -0
- package/dist-types/components/input-file/translations/uk-UA.d.ts +1 -0
- package/dist-types/components/input-file/translations/uk.d.ts +1 -0
- package/dist-types/components/input-file/translations/zh-CN.d.ts +1 -0
- package/dist-types/components/input-file/translations/zh.d.ts +1 -0
- package/dist-types/components/input-tel/src/LionInputTel.d.ts.map +1 -1
- package/dist-types/components/input-tel/test-suites/LionInputTel.suite.d.ts.map +1 -1
- package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts +8 -2
- package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts.map +1 -1
- package/dist-types/components/overlays/test/withHoverInteraction.test.d.ts +2 -0
- package/dist-types/components/overlays/test/withHoverInteraction.test.d.ts.map +1 -0
- package/dist-types/exports/input-file.d.ts +1 -1
- 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/form/use-cases.md +2 -2
- package/docs/components/icon/use-cases.md +1 -1
- package/docs/components/input/overview.md +1 -1
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-amount-dropdown/api-table.md +1 -1
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-email/api-table.md +1 -1
- 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 +18 -0
- 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/api-table.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/api-table.md +1 -1
- package/docs/components/input-tel-dropdown/overview.md +1 -1
- package/docs/components/listbox/use-cases.md +1 -1
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.md +1 -1
- package/docs/components/select-rich/use-cases.md +2 -2
- package/docs/components/tabs/examples.md +1 -1
- package/docs/components/tooltip/use-cases.md +55 -0
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
- package/docs/fundamentals/rationales/accessibility.md +1 -1
- package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
- package/docs/fundamentals/systems/core/overview.md +1 -1
- package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
- package/docs/fundamentals/systems/form/model-value.md +1 -1
- package/docs/fundamentals/systems/form/overview.md +28 -28
- package/docs/fundamentals/systems/form/validate.md +2 -2
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/configuration.md +2 -2
- package/docs/fundamentals/systems/overlays/overview.md +5 -5
- package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
- package/docs/fundamentals/tools/helpers/overview.md +1 -1
- package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
- package/docs/guides/how-to/create-a-custom-field.md +5 -5
- package/docs/guides/how-to/create-a-form.md +4 -4
- package/docs/guides/how-to/extend-a-native-input.md +2 -2
- package/docs/guides/how-to/index.md +1 -1
- 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-file.js +5 -1
- package/input-file.js +5 -1
- package/package.json +2 -2
|
@@ -298,7 +298,7 @@ export class LionCalendar extends LocalizeMixin(LitElement) {
|
|
|
298
298
|
this.__contentWrapperElement.addEventListener('click', this.__boundClickDateDelegation);
|
|
299
299
|
this.__contentWrapperElement.addEventListener('focus', this.__boundFocusDateDelegation);
|
|
300
300
|
this.__contentWrapperElement.addEventListener('blur', this.__boundBlurDateDelegation);
|
|
301
|
-
this.__contentWrapperElement.addEventListener('
|
|
301
|
+
this.__contentWrapperElement.addEventListener('keyup', this.__boundKeyboardNavigationEvent);
|
|
302
302
|
this.__eventsAdded = true;
|
|
303
303
|
}
|
|
304
304
|
}
|
|
@@ -4,8 +4,10 @@ import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
|
|
|
4
4
|
import { expect, fixture as _fixture } from '@open-wc/testing';
|
|
5
5
|
import sinon from 'sinon';
|
|
6
6
|
import '@lion/ui/define/lion-calendar.js';
|
|
7
|
+
import { sendKeys } from '@web/test-runner-commands';
|
|
7
8
|
import { isSameDate } from '@lion/ui/calendar.js';
|
|
8
9
|
import { CalendarObject, DayObject } from '@lion/ui/calendar-test-helpers.js';
|
|
10
|
+
import { runCalendarSuite } from '../test-suites/LionCalendar.suite.js';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* @typedef {import('../src/LionCalendar.js').LionCalendar} LionCalendar
|
|
@@ -13,6 +15,16 @@ import { CalendarObject, DayObject } from '@lion/ui/calendar-test-helpers.js';
|
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
17
|
const fixture = /** @type {(arg: TemplateResult) => Promise<LionCalendar>} */ (_fixture);
|
|
18
|
+
/**
|
|
19
|
+
* @param {HTMLElement} el
|
|
20
|
+
* @returns {HTMLElement | null | undefined}
|
|
21
|
+
*/
|
|
22
|
+
const getSelectedDateEl = el => el?.shadowRoot?.querySelector('.calendar__day-button[selected]');
|
|
23
|
+
/**
|
|
24
|
+
* @param {HTMLElement} el
|
|
25
|
+
* @returns {void}
|
|
26
|
+
*/
|
|
27
|
+
const focusSelectedDate = el => getSelectedDateEl(el)?.focus();
|
|
16
28
|
|
|
17
29
|
describe('<lion-calendar>', () => {
|
|
18
30
|
const localizeManager = getLocalizeManager();
|
|
@@ -294,13 +306,14 @@ describe('<lion-calendar>', () => {
|
|
|
294
306
|
`);
|
|
295
307
|
const elObj = new CalendarObject(el);
|
|
296
308
|
|
|
297
|
-
el
|
|
309
|
+
focusSelectedDate(el);
|
|
310
|
+
await sendKeys({ press: 'ArrowLeft' });
|
|
298
311
|
await el.updateComplete;
|
|
299
312
|
expect(elObj.activeMonth).to.equal('October');
|
|
300
313
|
expect(elObj.activeYear).to.equal('2000');
|
|
301
314
|
expect(elObj.focusedDayObj?.monthday).to.equal(11);
|
|
302
315
|
|
|
303
|
-
|
|
316
|
+
await sendKeys({ press: 'Enter' });
|
|
304
317
|
await el.updateComplete;
|
|
305
318
|
expect(isSameDate(/** @type {Date} */ (el.selectedDate), new Date('2000/10/12'))).to.be.true;
|
|
306
319
|
expect(dateChangedSpy.called).to.equal(false);
|
|
@@ -1120,16 +1133,14 @@ describe('<lion-calendar>', () => {
|
|
|
1120
1133
|
expect(elObj.activeMonth).to.equal('January');
|
|
1121
1134
|
expect(elObj.activeYear).to.equal('2001');
|
|
1122
1135
|
|
|
1123
|
-
el
|
|
1124
|
-
|
|
1125
|
-
|
|
1136
|
+
focusSelectedDate(el);
|
|
1137
|
+
await sendKeys({ press: 'PageUp' });
|
|
1138
|
+
|
|
1126
1139
|
await el.updateComplete;
|
|
1127
1140
|
expect(elObj.activeMonth).to.equal('December');
|
|
1128
1141
|
expect(elObj.activeYear).to.equal('2000');
|
|
1129
1142
|
|
|
1130
|
-
|
|
1131
|
-
new KeyboardEvent('keydown', { key: 'PageDown' }),
|
|
1132
|
-
);
|
|
1143
|
+
await sendKeys({ press: 'PageDown' });
|
|
1133
1144
|
await el.updateComplete;
|
|
1134
1145
|
expect(elObj.activeMonth).to.equal('January');
|
|
1135
1146
|
expect(elObj.activeYear).to.equal('2001');
|
|
@@ -1139,20 +1150,36 @@ describe('<lion-calendar>', () => {
|
|
|
1139
1150
|
const el = await fixture(html`
|
|
1140
1151
|
<lion-calendar .selectedDate="${new Date('2001/01/02')}"></lion-calendar>
|
|
1141
1152
|
`);
|
|
1153
|
+
focusSelectedDate(el);
|
|
1154
|
+
|
|
1142
1155
|
const elObj = new CalendarObject(el);
|
|
1143
1156
|
expect(elObj.activeMonth).to.equal('January');
|
|
1144
1157
|
expect(elObj.activeYear).to.equal('2001');
|
|
1145
1158
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
);
|
|
1159
|
+
await sendKeys({
|
|
1160
|
+
down: 'Alt',
|
|
1161
|
+
});
|
|
1162
|
+
await sendKeys({
|
|
1163
|
+
press: 'PageDown',
|
|
1164
|
+
});
|
|
1165
|
+
await sendKeys({
|
|
1166
|
+
up: 'Alt',
|
|
1167
|
+
});
|
|
1168
|
+
|
|
1149
1169
|
await el.updateComplete;
|
|
1170
|
+
focusSelectedDate(el);
|
|
1150
1171
|
expect(elObj.activeMonth).to.equal('January');
|
|
1151
1172
|
expect(elObj.activeYear).to.equal('2002');
|
|
1152
1173
|
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
);
|
|
1174
|
+
await sendKeys({
|
|
1175
|
+
down: 'Alt',
|
|
1176
|
+
});
|
|
1177
|
+
await sendKeys({
|
|
1178
|
+
press: 'PageUp',
|
|
1179
|
+
});
|
|
1180
|
+
await sendKeys({
|
|
1181
|
+
up: 'Alt',
|
|
1182
|
+
});
|
|
1156
1183
|
await el.updateComplete;
|
|
1157
1184
|
expect(elObj.activeMonth).to.equal('January');
|
|
1158
1185
|
expect(elObj.activeYear).to.equal('2001');
|
|
@@ -1165,9 +1192,8 @@ describe('<lion-calendar>', () => {
|
|
|
1165
1192
|
`);
|
|
1166
1193
|
const elObj = new CalendarObject(el);
|
|
1167
1194
|
|
|
1168
|
-
el
|
|
1169
|
-
|
|
1170
|
-
);
|
|
1195
|
+
focusSelectedDate(el);
|
|
1196
|
+
await sendKeys({ press: 'ArrowDown' });
|
|
1171
1197
|
await el.updateComplete;
|
|
1172
1198
|
expect(elObj.focusedDayObj?.monthday).to.equal(2 + 7);
|
|
1173
1199
|
});
|
|
@@ -1178,9 +1204,8 @@ describe('<lion-calendar>', () => {
|
|
|
1178
1204
|
`);
|
|
1179
1205
|
const elObj = new CalendarObject(el);
|
|
1180
1206
|
|
|
1181
|
-
el
|
|
1182
|
-
|
|
1183
|
-
);
|
|
1207
|
+
focusSelectedDate(el);
|
|
1208
|
+
await sendKeys({ press: 'ArrowUp' });
|
|
1184
1209
|
await el.updateComplete;
|
|
1185
1210
|
expect(elObj.focusedDayObj?.monthday).to.equal(26); // of month before
|
|
1186
1211
|
});
|
|
@@ -1192,9 +1217,8 @@ describe('<lion-calendar>', () => {
|
|
|
1192
1217
|
`);
|
|
1193
1218
|
const elObj = new CalendarObject(el);
|
|
1194
1219
|
|
|
1195
|
-
el
|
|
1196
|
-
|
|
1197
|
-
);
|
|
1220
|
+
focusSelectedDate(el);
|
|
1221
|
+
await sendKeys({ press: 'ArrowLeft' });
|
|
1198
1222
|
await el.updateComplete;
|
|
1199
1223
|
expect(elObj.focusedDayObj?.monthday).to.equal(12 - 1);
|
|
1200
1224
|
});
|
|
@@ -1206,9 +1230,8 @@ describe('<lion-calendar>', () => {
|
|
|
1206
1230
|
`);
|
|
1207
1231
|
const elObj = new CalendarObject(el);
|
|
1208
1232
|
|
|
1209
|
-
el
|
|
1210
|
-
|
|
1211
|
-
);
|
|
1233
|
+
focusSelectedDate(el);
|
|
1234
|
+
await sendKeys({ press: 'ArrowRight' });
|
|
1212
1235
|
await el.updateComplete;
|
|
1213
1236
|
expect(elObj.focusedDayObj?.monthday).to.equal(12 + 1);
|
|
1214
1237
|
});
|
|
@@ -1224,9 +1247,8 @@ describe('<lion-calendar>', () => {
|
|
|
1224
1247
|
`);
|
|
1225
1248
|
const elObj = new CalendarObject(el);
|
|
1226
1249
|
|
|
1227
|
-
el
|
|
1228
|
-
|
|
1229
|
-
);
|
|
1250
|
+
focusSelectedDate(el);
|
|
1251
|
+
await sendKeys({ press: 'ArrowRight' });
|
|
1230
1252
|
await el.updateComplete;
|
|
1231
1253
|
expect(elObj.focusedDayObj?.monthday).to.equal(3);
|
|
1232
1254
|
});
|
|
@@ -1238,9 +1260,8 @@ describe('<lion-calendar>', () => {
|
|
|
1238
1260
|
const elObj = new CalendarObject(el);
|
|
1239
1261
|
expect(elObj.centralDayObj?.weekdayNameShort).to.equal('Sat');
|
|
1240
1262
|
|
|
1241
|
-
el
|
|
1242
|
-
|
|
1243
|
-
);
|
|
1263
|
+
focusSelectedDate(el);
|
|
1264
|
+
await sendKeys({ press: 'ArrowRight' });
|
|
1244
1265
|
await el.updateComplete;
|
|
1245
1266
|
expect(elObj.focusedDayObj?.monthday).to.equal(6);
|
|
1246
1267
|
expect(elObj.focusedDayObj?.weekdayNameShort).to.equal('Sun');
|
|
@@ -1253,9 +1274,8 @@ describe('<lion-calendar>', () => {
|
|
|
1253
1274
|
const elObj = new CalendarObject(el);
|
|
1254
1275
|
expect(elObj.centralDayObj?.weekdayNameShort).to.equal('Sun');
|
|
1255
1276
|
|
|
1256
|
-
el
|
|
1257
|
-
|
|
1258
|
-
);
|
|
1277
|
+
focusSelectedDate(el);
|
|
1278
|
+
await sendKeys({ press: 'ArrowLeft' });
|
|
1259
1279
|
await el.updateComplete;
|
|
1260
1280
|
expect(elObj.focusedDayObj?.monthday).to.equal(5);
|
|
1261
1281
|
expect(elObj.focusedDayObj?.weekdayNameShort).to.equal('Sat');
|
|
@@ -1269,9 +1289,8 @@ describe('<lion-calendar>', () => {
|
|
|
1269
1289
|
expect(elObj.activeMonth).to.equal('December');
|
|
1270
1290
|
expect(elObj.activeYear).to.equal('2000');
|
|
1271
1291
|
|
|
1272
|
-
el
|
|
1273
|
-
|
|
1274
|
-
);
|
|
1292
|
+
focusSelectedDate(el);
|
|
1293
|
+
await sendKeys({ press: 'ArrowRight' });
|
|
1275
1294
|
await el.updateComplete;
|
|
1276
1295
|
expect(elObj.activeMonth).to.equal('January');
|
|
1277
1296
|
expect(elObj.activeYear).to.equal('2001');
|
|
@@ -1286,9 +1305,8 @@ describe('<lion-calendar>', () => {
|
|
|
1286
1305
|
expect(elObj.activeMonth).to.equal('January');
|
|
1287
1306
|
expect(elObj.activeYear).to.equal('2001');
|
|
1288
1307
|
|
|
1289
|
-
el
|
|
1290
|
-
|
|
1291
|
-
);
|
|
1308
|
+
focusSelectedDate(el);
|
|
1309
|
+
await sendKeys({ press: 'ArrowLeft' });
|
|
1292
1310
|
await el.updateComplete;
|
|
1293
1311
|
expect(elObj.activeMonth).to.equal('December');
|
|
1294
1312
|
expect(elObj.activeYear).to.equal('2000');
|
|
@@ -1303,9 +1321,8 @@ describe('<lion-calendar>', () => {
|
|
|
1303
1321
|
expect(elObj.activeMonth).to.equal('December');
|
|
1304
1322
|
expect(elObj.activeYear).to.equal('2000');
|
|
1305
1323
|
|
|
1306
|
-
el
|
|
1307
|
-
|
|
1308
|
-
);
|
|
1324
|
+
focusSelectedDate(el);
|
|
1325
|
+
await sendKeys({ press: 'ArrowDown' });
|
|
1309
1326
|
await el.updateComplete;
|
|
1310
1327
|
expect(elObj.activeMonth).to.equal('January');
|
|
1311
1328
|
expect(elObj.activeYear).to.equal('2001');
|
|
@@ -1320,9 +1337,8 @@ describe('<lion-calendar>', () => {
|
|
|
1320
1337
|
expect(elObj.activeMonth).to.equal('January');
|
|
1321
1338
|
expect(elObj.activeYear).to.equal('2001');
|
|
1322
1339
|
|
|
1323
|
-
el
|
|
1324
|
-
|
|
1325
|
-
);
|
|
1340
|
+
focusSelectedDate(el);
|
|
1341
|
+
await sendKeys({ press: 'ArrowUp' });
|
|
1326
1342
|
await el.updateComplete;
|
|
1327
1343
|
expect(elObj.activeMonth).to.equal('December');
|
|
1328
1344
|
expect(elObj.activeYear).to.equal('2000');
|
|
@@ -1659,4 +1675,8 @@ describe('<lion-calendar>', () => {
|
|
|
1659
1675
|
expect(el).not.to.be.displayed;
|
|
1660
1676
|
});
|
|
1661
1677
|
});
|
|
1678
|
+
|
|
1679
|
+
describe('Run suite', () => {
|
|
1680
|
+
runCalendarSuite();
|
|
1681
|
+
});
|
|
1662
1682
|
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { LionCalendar } from '@lion/ui/calendar.js';
|
|
2
|
+
import { expect, html, fixture, waitUntil, unsafeStatic, defineCE } from '@open-wc/testing';
|
|
3
|
+
import sinon from 'sinon';
|
|
4
|
+
import '@lion/ui/define/lion-calendar.js';
|
|
5
|
+
import { sendKeys } from '@web/test-runner-commands';
|
|
6
|
+
|
|
7
|
+
export function runCalendarSuite({ klass = LionCalendar } = {}) {
|
|
8
|
+
const tagStringCalendar = defineCE(class extends klass {});
|
|
9
|
+
const tagCalendar = unsafeStatic(tagStringCalendar);
|
|
10
|
+
|
|
11
|
+
it('should fire keyboard press events on keyup and not on keydown', async () => {
|
|
12
|
+
/**
|
|
13
|
+
* This test covers a corner case where `keydown`, `keyup`, and `focus` events happen across different elements.
|
|
14
|
+
*
|
|
15
|
+
* Setup:
|
|
16
|
+
* - There is a dialog invoker button that has a keyup handler.
|
|
17
|
+
* - The dialog invoker button gets focused (important!) and then opens the dialog on click.
|
|
18
|
+
* - The dialog contains lion-calendar.
|
|
19
|
+
* - When a date is selected, the dialog closes.
|
|
20
|
+
*
|
|
21
|
+
* Expected behavior:
|
|
22
|
+
* - The dialog invoker button's `keyup` handler should not run when a date is selected in the calendar.
|
|
23
|
+
*
|
|
24
|
+
* The problem:
|
|
25
|
+
* - Pressing Enter on a date is handled by `keydown` inside `lion-calendar`.
|
|
26
|
+
* - The dialog then closes on `user-selected-date-changed` event.
|
|
27
|
+
* - The browser automatically returns focus to the previously focused element (the dialog invoker button).
|
|
28
|
+
* - The keyup event then fires on the now-focused dialog invoker button, triggering its keyup
|
|
29
|
+
* handler unexpectedly.
|
|
30
|
+
*
|
|
31
|
+
* Fix being verified:
|
|
32
|
+
* - Fire `user-selected-date-changed` on `keyup` instead of `keydown`.
|
|
33
|
+
* - This prevents the dialog invoker button from receiving and handling that `keyup` after the dialog closes.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** @type {HTMLElement} */
|
|
37
|
+
let el;
|
|
38
|
+
const keyUpSpy = sinon.spy();
|
|
39
|
+
const getDialogEl = () => el.querySelector('dialog');
|
|
40
|
+
const openDialogButtonClickHandler = () => getDialogEl()?.showModal();
|
|
41
|
+
const userSelectedDateChangedHandler = () => getDialogEl()?.close();
|
|
42
|
+
|
|
43
|
+
el = await fixture(html`
|
|
44
|
+
<div>
|
|
45
|
+
<button
|
|
46
|
+
@keyup="${keyUpSpy}"
|
|
47
|
+
@click="${openDialogButtonClickHandler}"
|
|
48
|
+
>
|
|
49
|
+
Open Dialog
|
|
50
|
+
</button>
|
|
51
|
+
<dialog>
|
|
52
|
+
<${tagCalendar}
|
|
53
|
+
.selectedDate="${new Date('2000/10/12')}"
|
|
54
|
+
@user-selected-date-changed="${userSelectedDateChangedHandler}"
|
|
55
|
+
>
|
|
56
|
+
</${tagCalendar}>
|
|
57
|
+
</dialog>
|
|
58
|
+
</div>
|
|
59
|
+
`);
|
|
60
|
+
|
|
61
|
+
const openDialogButton = el.querySelector('button');
|
|
62
|
+
const calendarEl = /** @type {LionCalendar} */ (el.querySelector(tagStringCalendar));
|
|
63
|
+
await calendarEl?.updateComplete;
|
|
64
|
+
|
|
65
|
+
openDialogButton?.focus();
|
|
66
|
+
openDialogButton?.click();
|
|
67
|
+
/**
|
|
68
|
+
* @returns {HTMLElement | null | undefined}
|
|
69
|
+
*/
|
|
70
|
+
const getSelectedDateEl = () =>
|
|
71
|
+
calendarEl?.shadowRoot?.querySelector('.calendar__day-button[selected]');
|
|
72
|
+
await waitUntil(getSelectedDateEl);
|
|
73
|
+
getSelectedDateEl()?.focus();
|
|
74
|
+
await sendKeys({ press: 'ArrowLeft' });
|
|
75
|
+
await sendKeys({ press: 'Enter' });
|
|
76
|
+
|
|
77
|
+
expect(keyUpSpy.called).to.equal(false);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -238,7 +238,7 @@ const ChoiceInputMixinImplementation = superclass =>
|
|
|
238
238
|
*/
|
|
239
239
|
// eslint-disable-next-line no-unused-vars
|
|
240
240
|
_toggleChecked(ev) {
|
|
241
|
-
if (this.disabled) {
|
|
241
|
+
if (this.disabled || this.readOnly) {
|
|
242
242
|
return;
|
|
243
243
|
}
|
|
244
244
|
this._isHandlingUserInput = true;
|
|
@@ -398,14 +398,16 @@ export class LionInputAmountDropdown extends LionInputAmount {
|
|
|
398
398
|
|
|
399
399
|
/**
|
|
400
400
|
* Used for Required validation and computation of interaction states.
|
|
401
|
-
* We
|
|
402
|
-
*
|
|
403
|
-
* @param {string} modelValue
|
|
401
|
+
* We only consider the amount part for emptiness checks.
|
|
402
|
+
* Missing, null, empty-string or NaN amount is considered empty.
|
|
404
403
|
* @return {boolean}
|
|
405
404
|
* @protected
|
|
406
405
|
*/
|
|
407
406
|
_isEmpty(modelValue = this.modelValue) {
|
|
408
|
-
|
|
407
|
+
const isNumberValue =
|
|
408
|
+
typeof modelValue?.amount === 'number' &&
|
|
409
|
+
(modelValue?.amount === 0 || Number.isNaN(modelValue?.amount));
|
|
410
|
+
return !modelValue?.amount && !isNumberValue;
|
|
409
411
|
}
|
|
410
412
|
|
|
411
413
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mimicUserChangingDropdown } from '@lion/ui/input-amount-dropdown-test-helpers.js';
|
|
2
2
|
import { runInputAmountDropdownSuite } from '@lion/ui/input-amount-dropdown-test-suites.js';
|
|
3
3
|
import { LionInputAmountDropdown } from '@lion/ui/input-amount-dropdown.js';
|
|
4
|
+
import { Required } from '@lion/ui/form-core.js';
|
|
4
5
|
import { aTimeout, expect, fixture } from '@open-wc/testing';
|
|
5
6
|
import { LionSelectRich } from '@lion/ui/select-rich.js';
|
|
6
7
|
import { repeat } from 'lit/directives/repeat.js';
|
|
@@ -194,7 +195,25 @@ describe('WithFormControlInputAmountDropdown', () => {
|
|
|
194
195
|
el.modelValue = { currency: 'EUR' };
|
|
195
196
|
await aTimeout(0);
|
|
196
197
|
el.modelValue = { currency: 'EUR', amount: '' };
|
|
197
|
-
expect(el.hasFeedbackFor).to.deep.equal([
|
|
198
|
+
expect(el.hasFeedbackFor).to.deep.equal([]);
|
|
198
199
|
});
|
|
199
200
|
});
|
|
201
|
+
|
|
202
|
+
it('includes error in showsFeedbackFor when required, empty, and touched & dirty', async () => {
|
|
203
|
+
const el = /** @type {LionInputAmountDropdown} */ (
|
|
204
|
+
await fixture(html`
|
|
205
|
+
<lion-input-amount-dropdown
|
|
206
|
+
.allowedCurrencies="${['GBP', 'EUR']}"
|
|
207
|
+
.validators="${[new Required()]}"
|
|
208
|
+
></lion-input-amount-dropdown>
|
|
209
|
+
`)
|
|
210
|
+
);
|
|
211
|
+
await el.updateComplete;
|
|
212
|
+
el.touched = true;
|
|
213
|
+
el.dirty = true;
|
|
214
|
+
await el.updateComplete;
|
|
215
|
+
await el.feedbackComplete;
|
|
216
|
+
expect(el.hasFeedbackFor).to.include('error', 'hasFeedbackFor');
|
|
217
|
+
expect(el.showsFeedbackFor).to.include('error', 'showsFeedbackFor');
|
|
218
|
+
});
|
|
200
219
|
});
|
|
@@ -317,5 +317,29 @@ export function runInputAmountDropdownSuite({ klass } = { klass: LionInputAmount
|
|
|
317
317
|
// @ts-ignore
|
|
318
318
|
expect(el._isEmpty(), 'empty').to.be.true;
|
|
319
319
|
});
|
|
320
|
+
|
|
321
|
+
it('only checks modelValue.amount', async () => {
|
|
322
|
+
const el = await fixture(html` <${tag}></${tag}> `);
|
|
323
|
+
|
|
324
|
+
el.modelValue = { currency: 'GBP', amount: 1 };
|
|
325
|
+
await el.updateComplete;
|
|
326
|
+
// @ts-ignore
|
|
327
|
+
expect(el._isEmpty(), 'filled amount').to.be.false;
|
|
328
|
+
|
|
329
|
+
el.modelValue = { currency: 'EUR', amount: '' };
|
|
330
|
+
await el.updateComplete;
|
|
331
|
+
// @ts-ignore
|
|
332
|
+
expect(el._isEmpty(), 'empty amount').to.be.true;
|
|
333
|
+
|
|
334
|
+
el.modelValue = { currency: 'EUR' };
|
|
335
|
+
await el.updateComplete;
|
|
336
|
+
// @ts-ignore
|
|
337
|
+
expect(el._isEmpty(), 'missing amount property').to.be.true;
|
|
338
|
+
|
|
339
|
+
el.modelValue = null;
|
|
340
|
+
await el.updateComplete;
|
|
341
|
+
// @ts-ignore
|
|
342
|
+
expect(el._isEmpty(), 'null modelValue').to.be.true;
|
|
343
|
+
});
|
|
320
344
|
});
|
|
321
345
|
}
|
|
@@ -4,11 +4,12 @@ import { IsDateDisabled, MaxDate, MinDate, MinMaxDate } from '@lion/ui/form-core
|
|
|
4
4
|
import { aTimeout, defineCE, expect, fixture as _fixture, nextFrame } from '@open-wc/testing';
|
|
5
5
|
import { mimicClick } from '@lion/ui/overlays-test-helpers.js';
|
|
6
6
|
import sinon from 'sinon';
|
|
7
|
-
import { setViewport } from '@web/test-runner-commands';
|
|
7
|
+
import { sendKeys, setViewport } from '@web/test-runner-commands';
|
|
8
8
|
import { DatepickerInputObject } from '@lion/ui/input-datepicker-test-helpers.js';
|
|
9
9
|
import { LionInputDatepicker } from '@lion/ui/input-datepicker.js';
|
|
10
10
|
|
|
11
11
|
import '@lion/ui/define/lion-input-datepicker.js';
|
|
12
|
+
import { runDatepickerSuite } from '../test-suites/LionInputDatepicker.suite.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* @typedef {import('lit').TemplateResult} TemplateResult
|
|
@@ -479,10 +480,14 @@ describe('<lion-input-datepicker>', () => {
|
|
|
479
480
|
// Open the calendar
|
|
480
481
|
await elObj.openCalendar();
|
|
481
482
|
|
|
483
|
+
const selectedDateEl = calendarEl?.shadowRoot?.querySelector(
|
|
484
|
+
'.calendar__day-button[selected]',
|
|
485
|
+
);
|
|
486
|
+
// @ts-ignore
|
|
487
|
+
selectedDateEl?.focus();
|
|
488
|
+
|
|
482
489
|
// Move focus to 18th of December
|
|
483
|
-
|
|
484
|
-
?.querySelector('#js-content-wrapper')
|
|
485
|
-
?.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }));
|
|
490
|
+
await sendKeys({ press: 'ArrowRight' });
|
|
486
491
|
|
|
487
492
|
expect(/** @type {Date} */ (calendarEl.focusedDate).getTime()).to.equal(
|
|
488
493
|
new Date('December 18, 2020 03:24:00 GMT+0000').getTime(),
|
|
@@ -834,4 +839,8 @@ describe('<lion-input-datepicker>', () => {
|
|
|
834
839
|
).to.be.true;
|
|
835
840
|
});
|
|
836
841
|
});
|
|
842
|
+
|
|
843
|
+
describe('Run suite', () => {
|
|
844
|
+
runDatepickerSuite();
|
|
845
|
+
});
|
|
837
846
|
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { expect, html, fixture, waitUntil, unsafeStatic } from '@open-wc/testing';
|
|
2
|
+
import { sendKeys } from '@web/test-runner-commands';
|
|
3
|
+
|
|
4
|
+
/** @typedef {import('@lion/ui/input-datepicker.js').LionInputDatepicker} LionInputDatepicker */
|
|
5
|
+
|
|
6
|
+
export function runDatepickerSuite({
|
|
7
|
+
datepickerTagName = 'lion-input-datepicker',
|
|
8
|
+
calendarTagName = 'lion-calendar',
|
|
9
|
+
} = {}) {
|
|
10
|
+
const tag = unsafeStatic(datepickerTagName);
|
|
11
|
+
|
|
12
|
+
it('should not reopen the datepicker popup when the date is selected by keyboard', async () => {
|
|
13
|
+
/** @type {LionInputDatepicker} */
|
|
14
|
+
const el = await fixture(html`<${tag} .modelValue="${new Date('2018/05/30')}"></${tag}>`);
|
|
15
|
+
await el.updateComplete;
|
|
16
|
+
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
const openDatepickerButton = el._invokerNode;
|
|
19
|
+
openDatepickerButton?.focus();
|
|
20
|
+
openDatepickerButton?.click();
|
|
21
|
+
/**
|
|
22
|
+
* @returns {HTMLElement | null | undefined}
|
|
23
|
+
*/
|
|
24
|
+
const getSelectedDateEl = () =>
|
|
25
|
+
el?.shadowRoot
|
|
26
|
+
?.querySelector(calendarTagName)
|
|
27
|
+
?.shadowRoot?.querySelector('.calendar__day-button[selected]');
|
|
28
|
+
await waitUntil(getSelectedDateEl);
|
|
29
|
+
getSelectedDateEl()?.focus();
|
|
30
|
+
await sendKeys({ press: 'ArrowLeft' });
|
|
31
|
+
await sendKeys({ press: 'Enter' });
|
|
32
|
+
|
|
33
|
+
expect(el.opened).to.be.false;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -10,6 +10,8 @@ import { LocalizeMixin } from '@lion/ui/localize-no-side-effects.js';
|
|
|
10
10
|
export class LionInputEmail extends LocalizeMixin(LionInput) {
|
|
11
11
|
constructor() {
|
|
12
12
|
super();
|
|
13
|
+
this.autocomplete = 'email';
|
|
14
|
+
|
|
13
15
|
// local-part@domain where the local part may be up to 64 characters long
|
|
14
16
|
// and the domain may have a maximum of 255 characters.
|
|
15
17
|
// @see https://www.wikiwand.com/en/Email_address
|
|
@@ -15,6 +15,12 @@ describe('<lion-input-email>', () => {
|
|
|
15
15
|
expect(_inputNode.type).to.equal('text');
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
+
it('sets autocomplete to "email"', async () => {
|
|
19
|
+
const el = await fixture(`<lion-input-email></lion-input-email>`);
|
|
20
|
+
// @ts-expect-error [allow-protected] inside tests
|
|
21
|
+
expect(el._inputNode.getAttribute('autocomplete')).to.equal('email');
|
|
22
|
+
});
|
|
23
|
+
|
|
18
24
|
it('has validator "IsEmail" applied by default', async () => {
|
|
19
25
|
// More elaborate tests can be found in lion-validate/test/StringValidators.test.js
|
|
20
26
|
const el = await fixture(`<lion-input-email></lion-input-email>`);
|
|
@@ -2,13 +2,14 @@ import { Validator } from '@lion/ui/form-core.js';
|
|
|
2
2
|
import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
+
* @typedef {import('../../form-core/types/validate/index.js').FeedbackMessageData} FeedbackMessageData
|
|
5
6
|
* @typedef {import('../../form-core/types/validate/validate.js').ValidatorConfig} ValidatorConfig
|
|
6
7
|
* @typedef {import('../../form-core/types/validate/validate.js').ValidatorParam} ValidatorParam
|
|
7
8
|
* @typedef {import('../../form-core/types/validate/validate.js').ValidatorOutcome} ValidatorOutcome
|
|
8
9
|
* @typedef {import('../types/input-file.js').InputFile} InputFile
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
|
-
/* eslint max-classes-per-file: ["error",
|
|
12
|
+
/* eslint max-classes-per-file: ["error", 3] */
|
|
12
13
|
export class IsAcceptedFile extends Validator {
|
|
13
14
|
static validatorName = 'IsAcceptedFile';
|
|
14
15
|
|
|
@@ -112,3 +113,32 @@ export class DuplicateFileNames extends Validator {
|
|
|
112
113
|
return localizeManager.msg('lion-input-file:uploadTextDuplicateFileName');
|
|
113
114
|
}
|
|
114
115
|
}
|
|
116
|
+
|
|
117
|
+
export class MaxFileCount extends Validator {
|
|
118
|
+
static get validatorName() {
|
|
119
|
+
return 'MaxFileCount';
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {Partial<FeedbackMessageData>} [data]
|
|
124
|
+
* @returns {Promise<string|Element>}
|
|
125
|
+
*/
|
|
126
|
+
static async getMessage(data) {
|
|
127
|
+
const localizeManager = getLocalizeManager();
|
|
128
|
+
if (!data?.params || typeof data.params !== 'number' || data.params <= 0) {
|
|
129
|
+
return 'Invalid MaxFileCount parameter. Please provide a valid number greater than 0.';
|
|
130
|
+
}
|
|
131
|
+
return localizeManager.msg('lion-input-file:maxFileCountExceeded', {
|
|
132
|
+
maxFileCount: data.params,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @param {File[]} value
|
|
138
|
+
* @param {number} maxFiles
|
|
139
|
+
* @returns {boolean}
|
|
140
|
+
*/
|
|
141
|
+
execute(value, maxFiles = this.param || 0) {
|
|
142
|
+
return maxFiles > 0 && value.length > maxFiles;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { expect } from '@open-wc/testing';
|
|
2
|
+
import { MaxFileCount } from '@lion/ui/input-file.js';
|
|
2
3
|
import { IsAcceptedFile } from '../src/validators.js';
|
|
3
4
|
|
|
4
5
|
describe('lion-input-file: IsAcceptedFile', () => {
|
|
@@ -167,4 +168,34 @@ describe('lion-input-file: IsAcceptedFile', () => {
|
|
|
167
168
|
expect(returnVal).to.be.true;
|
|
168
169
|
});
|
|
169
170
|
});
|
|
171
|
+
|
|
172
|
+
describe('Max File Count', () => {
|
|
173
|
+
/**
|
|
174
|
+
*
|
|
175
|
+
* @param {string} filename
|
|
176
|
+
* @returns {File}
|
|
177
|
+
*/
|
|
178
|
+
const newFile = filename => new File([], filename);
|
|
179
|
+
|
|
180
|
+
it('Allow up to 2 files', () => {
|
|
181
|
+
const validator = new MaxFileCount(2);
|
|
182
|
+
expect(MaxFileCount.validatorName).to.equal('MaxFileCount');
|
|
183
|
+
|
|
184
|
+
let isEnabled = validator.execute([newFile('file1.txt'), newFile('file2.txt')]);
|
|
185
|
+
expect(isEnabled).to.be.false;
|
|
186
|
+
|
|
187
|
+
isEnabled = validator.execute([
|
|
188
|
+
newFile('file1.txt'),
|
|
189
|
+
newFile('file2.txt'),
|
|
190
|
+
newFile('file3.txt'),
|
|
191
|
+
]);
|
|
192
|
+
expect(isEnabled).to.be.true;
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('Allow any number of files with empty param', () => {
|
|
196
|
+
const validator = new MaxFileCount();
|
|
197
|
+
const isEnabled = validator.execute([newFile('file1.txt'), newFile('file2.txt')]);
|
|
198
|
+
expect(isEnabled).to.be.false;
|
|
199
|
+
});
|
|
200
|
+
});
|
|
170
201
|
});
|
|
@@ -17,4 +17,5 @@ export default {
|
|
|
17
17
|
selectTextDuplicateFileName: 'Файл със същото име на файл вече е налице.',
|
|
18
18
|
selectTextMultipleFile: 'Избор на файлове',
|
|
19
19
|
selectTextSingleFile: 'Избор на файл',
|
|
20
|
+
maxFileCountExceeded: 'Броят на качените файлове не може да надвишава {maxFileCount}.',
|
|
20
21
|
};
|
|
@@ -18,4 +18,5 @@ export default {
|
|
|
18
18
|
selectTextDuplicateFileName: 'Soubor se stejným názvem byl již přítomen.',
|
|
19
19
|
selectTextMultipleFile: 'Vybrat soubory',
|
|
20
20
|
selectTextSingleFile: 'Vybrat soubor',
|
|
21
|
+
maxFileCountExceeded: 'Počet nahraných souborů nesmí překročit {maxFileCount}.',
|
|
21
22
|
};
|
|
@@ -17,4 +17,6 @@ export default {
|
|
|
17
17
|
selectTextDuplicateFileName: 'Eine Datei mit demselben Dateinamen war bereits vorhanden.',
|
|
18
18
|
selectTextMultipleFile: 'Dateien auswählen',
|
|
19
19
|
selectTextSingleFile: 'Datei auswählen',
|
|
20
|
+
maxFileCountExceeded:
|
|
21
|
+
'Die Anzahl der hochgeladenen Dateien darf {maxFileCount} nicht überschreiten.',
|
|
20
22
|
};
|
|
@@ -16,4 +16,5 @@ export default {
|
|
|
16
16
|
selectTextDuplicateFileName: 'A file with same filename was already present.',
|
|
17
17
|
selectTextMultipleFile: 'Select files',
|
|
18
18
|
selectTextSingleFile: 'Select file',
|
|
19
|
+
maxFileCountExceeded: 'The number of uploaded files must not exceed {maxFileCount}.',
|
|
19
20
|
};
|
|
@@ -17,4 +17,5 @@ export default {
|
|
|
17
17
|
selectTextDuplicateFileName: 'Ya había un archivo con el mismo nombre de archivo.',
|
|
18
18
|
selectTextMultipleFile: 'Seleccionar archivos',
|
|
19
19
|
selectTextSingleFile: 'Seleccionar archivo',
|
|
20
|
+
maxFileCountExceeded: 'El número de archivos cargados no puede superar {maxFileCount}.',
|
|
20
21
|
};
|