@lion/ui 0.15.2 → 0.15.3

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.
Files changed (85) hide show
  1. package/README.md +44 -9
  2. package/components/form-core/src/validate/LionValidationFeedback.js +2 -2
  3. package/components/form-core/src/validate/ValidateMixin.js +3 -3
  4. package/components/form-core/test/validate/lion-validation-feedback.test.js +2 -2
  5. package/components/form-core/test-suites/ValidateMixin.suite.js +23 -11
  6. package/components/form-core/translations/bg.js +4 -4
  7. package/components/form-core/translations/cs.js +4 -4
  8. package/components/form-core/translations/de.js +4 -4
  9. package/components/form-core/translations/en.js +4 -4
  10. package/components/form-core/translations/es.js +4 -4
  11. package/components/form-core/translations/fr.js +4 -4
  12. package/components/form-core/translations/hu.js +4 -4
  13. package/components/form-core/translations/it.js +4 -4
  14. package/components/form-core/translations/nl.js +4 -4
  15. package/components/form-core/translations/pl.js +4 -4
  16. package/components/form-core/translations/ro.js +4 -4
  17. package/components/form-core/translations/ru.js +4 -4
  18. package/components/form-core/translations/sk.js +4 -4
  19. package/components/form-core/translations/uk.js +4 -4
  20. package/components/form-core/translations/zh.js +4 -4
  21. package/components/input-stepper/src/LionInputStepper.js +48 -52
  22. package/components/input-stepper/test/lion-input-stepper.test.js +253 -41
  23. package/components/pagination/src/LionPagination.js +2 -1
  24. package/components/pagination/test/lion-pagination.test.js +41 -0
  25. package/components/validate-messages/translations/it.js +2 -2
  26. package/custom-elements.json +148 -170
  27. package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
  28. package/dist-types/components/input-stepper/src/LionInputStepper.d.ts +4 -20
  29. package/dist-types/components/input-stepper/src/LionInputStepper.d.ts.map +1 -1
  30. package/dist-types/components/input-stepper/test/lion-input-stepper.test.d.ts.map +1 -1
  31. package/dist-types/components/pagination/src/LionPagination.d.ts.map +1 -1
  32. package/dist-types/tsconfig.tsbuildinfo +1 -1
  33. package/docs/components/checkbox-group/overview.md +2 -2
  34. package/docs/components/checkbox-group/use-cases.md +3 -9
  35. package/docs/components/collapsible/overview.md +1 -1
  36. package/docs/components/combobox/overview.md +1 -1
  37. package/docs/components/combobox/use-cases.md +1 -1
  38. package/docs/components/dialog/overview.md +1 -1
  39. package/docs/components/fieldset/overview.md +5 -5
  40. package/docs/components/form/overview.md +3 -3
  41. package/docs/components/form/use-cases.md +2 -2
  42. package/docs/components/icon/use-cases.md +1 -1
  43. package/docs/components/input/overview.md +1 -1
  44. package/docs/components/input-amount/overview.md +3 -3
  45. package/docs/components/input-date/overview.md +3 -3
  46. package/docs/components/input-datepicker/overview.md +5 -5
  47. package/docs/components/input-email/overview.md +2 -2
  48. package/docs/components/input-file/overview.md +1 -1
  49. package/docs/components/input-iban/overview.md +2 -2
  50. package/docs/components/input-range/overview.md +2 -2
  51. package/docs/components/input-stepper/api-table.md +2 -3
  52. package/docs/components/input-stepper/overview.md +1 -1
  53. package/docs/components/input-tel/overview.md +1 -1
  54. package/docs/components/input-tel/use-cases.md +6 -6
  55. package/docs/components/input-tel-dropdown/overview.md +1 -1
  56. package/docs/components/listbox/use-cases.md +1 -1
  57. package/docs/components/radio-group/overview.md +3 -3
  58. package/docs/components/radio-group/use-cases.md +3 -9
  59. package/docs/components/select/overview.md +1 -1
  60. package/docs/components/select/use-cases.md +6 -6
  61. package/docs/components/select-rich/use-cases.md +2 -2
  62. package/docs/components/tabs/examples.md +1 -1
  63. package/docs/fundamentals/index.md +4 -4
  64. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  65. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  66. package/docs/fundamentals/rationales/accessibility.md +1 -1
  67. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  68. package/docs/fundamentals/systems/core/overview.md +1 -1
  69. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  70. package/docs/fundamentals/systems/form/model-value.md +1 -1
  71. package/docs/fundamentals/systems/form/overview.md +28 -28
  72. package/docs/fundamentals/systems/form/validate.md +2 -2
  73. package/docs/fundamentals/systems/localize/overview.md +4 -4
  74. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  75. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  76. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  77. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  78. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  79. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  80. package/docs/guides/how-to/create-a-form.md +4 -4
  81. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  82. package/docs/guides/index.md +8 -8
  83. package/docs/guides/principles/index.md +5 -5
  84. package/docs/guides/principles/styling.md +1 -1
  85. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { expect, fixture as _fixture, nextFrame } from '@open-wc/testing';
2
+ import { nothing } from 'lit';
2
3
  import { html } from 'lit/static-html.js';
3
4
  import sinon from 'sinon';
4
5
  import { formatNumber } from '@lion/ui/localize-no-side-effects.js';
@@ -17,6 +18,7 @@ const inputStepperWithAttrs = html`<lion-input-stepper
17
18
  step="10"
18
19
  min="100"
19
20
  max="200"
21
+ label="Label"
20
22
  ></lion-input-stepper>`;
21
23
 
22
24
  describe('<lion-input-stepper>', () => {
@@ -177,31 +179,6 @@ describe('<lion-input-stepper>', () => {
177
179
  expect(counter).to.equal(1);
178
180
  });
179
181
 
180
- it('fires a leave event ("blur") on button clicks', async () => {
181
- const blurSpy = sinon.spy();
182
- const el = await fixture(html`
183
- <lion-input-stepper @blur=${blurSpy} name="year" label="Years"></lion-input-stepper>
184
- `);
185
-
186
- expect(el.value).to.equal('');
187
- const decrementButton = el.querySelector('[slot=prefix]');
188
- decrementButton?.dispatchEvent(new Event('focus'));
189
- decrementButton?.dispatchEvent(new Event('click'));
190
- decrementButton?.dispatchEvent(new Event('blur'));
191
- expect(el.value).to.equal('−1');
192
- expect(blurSpy.calledOnce).to.be.true;
193
- expect(el.touched).to.be.true;
194
-
195
- el.touched = false;
196
- const incrementButton = el.querySelector('[slot=suffix]');
197
- incrementButton?.dispatchEvent(new Event('focus'));
198
- incrementButton?.dispatchEvent(new Event('click'));
199
- incrementButton?.dispatchEvent(new Event('blur'));
200
- expect(el.value).to.equal('0');
201
- expect(blurSpy.calledTwice).to.be.true;
202
- expect(el.touched).to.be.true;
203
- });
204
-
205
182
  it('should update min and max attributes when min and max property change', async () => {
206
183
  const el = await fixture(inputStepperWithAttrs);
207
184
  el.min = 100;
@@ -358,6 +335,251 @@ describe('<lion-input-stepper>', () => {
358
335
  await el.updateComplete;
359
336
  expect(el.modelValue).to.equal(-13, 'Fail - : (-23 > 100 by 10; val 55)'); // -23 > -13 > -3 > 7
360
337
  });
338
+
339
+ it('handles decimal step values correctly', async () => {
340
+ // Test with decimal step 0.1
341
+ let el = await fixture(
342
+ html`<lion-input-stepper step="0.1" min="0" max="9" value="5.55"></lion-input-stepper>`,
343
+ );
344
+
345
+ // Test increment with decimal step
346
+ let incrementButton = el.querySelector('[slot=suffix]');
347
+ incrementButton?.dispatchEvent(new Event('click'));
348
+ await el.updateComplete;
349
+ expect(el.modelValue).to.equal(5.6, 'Fail + : (0 > 9 by 0.1; val 5.55)');
350
+
351
+ // Test decrement with decimal step
352
+ let decrementButton = el.querySelector('[slot=prefix]');
353
+ decrementButton?.dispatchEvent(new Event('click'));
354
+ await el.updateComplete;
355
+ expect(el.modelValue).to.equal(5.5, 'Fail - : (0 > 9 by 0.1; val 5.6)');
356
+
357
+ // Test with value that needs alignment
358
+ el = await fixture(
359
+ html`<lion-input-stepper step="0.1" min="0" max="9" value="3.27"></lion-input-stepper>`,
360
+ );
361
+
362
+ // Should align to next step when incrementing
363
+ incrementButton = el.querySelector('[slot=suffix]');
364
+ incrementButton?.dispatchEvent(new Event('click'));
365
+ await el.updateComplete;
366
+ expect(el.modelValue).to.equal(3.3, 'Fail + alignment: (0 > 9 by 0.1; val 3.27)');
367
+
368
+ // Reset and test decrement alignment
369
+ el = await fixture(
370
+ html`<lion-input-stepper step="0.1" min="0" max="9" value="3.27"></lion-input-stepper>`,
371
+ );
372
+
373
+ // Should align to previous step when decrementing
374
+ decrementButton = el.querySelector('[slot=prefix]');
375
+ decrementButton?.dispatchEvent(new Event('click'));
376
+ await el.updateComplete;
377
+ expect(el.modelValue).to.equal(3.2, 'Fail - alignment: (0 > 9 by 0.1; val 3.27)');
378
+ });
379
+ });
380
+ });
381
+
382
+ describe('_destroyOutputContent method', () => {
383
+ beforeEach(() => {
384
+ // Ensure clean state for each test
385
+ sinon.restore();
386
+ });
387
+
388
+ it('should clear existing timer before setting a new one', async () => {
389
+ const el = await fixture(defaultInputStepper);
390
+ const clearTimeoutSpy = sinon.spy(window, 'clearTimeout');
391
+
392
+ // Set an initial timer
393
+ el.timer = setTimeout(() => {}, 1000);
394
+ const initialTimer = el.timer;
395
+
396
+ // Call _destroyOutputContent
397
+ el._destroyOutputContent();
398
+
399
+ expect(clearTimeoutSpy.calledWith(initialTimer)).to.be.true;
400
+ clearTimeoutSpy.restore();
401
+ });
402
+
403
+ it('should set __valueText to nothing and request update after timeout', async () => {
404
+ const el = await fixture(defaultInputStepper);
405
+ const requestUpdateSpy = sinon.spy(el, 'requestUpdate');
406
+ const clock = sinon.useFakeTimers();
407
+
408
+ // Set initial value text
409
+ el.__valueText = 'test value';
410
+
411
+ // Call _destroyOutputContent
412
+ el._destroyOutputContent();
413
+
414
+ // Fast forward time by 2000ms (default timeout)
415
+ clock.tick(2000);
416
+
417
+ await expect(el.__valueText).to.equal(nothing);
418
+ expect(requestUpdateSpy.calledOnce).to.be.true;
419
+
420
+ clock.restore();
421
+ requestUpdateSpy.restore();
422
+ });
423
+
424
+ it('should use custom timeout from data-self-destruct attribute', async () => {
425
+ const el = await fixture(html`
426
+ <lion-input-stepper name="test" label="Test"> </lion-input-stepper>
427
+ `);
428
+
429
+ await el.updateComplete;
430
+
431
+ // Get the output element and set custom self-destruct value
432
+ const outputElement = /** @type {HTMLElement} */ (
433
+ el.shadowRoot?.querySelector('.input-stepper__value')
434
+ );
435
+ if (outputElement) {
436
+ outputElement.dataset.selfDestruct = '5000';
437
+ }
438
+
439
+ const clock = sinon.useFakeTimers();
440
+ const requestUpdateSpy = sinon.spy(el, 'requestUpdate');
441
+
442
+ el.__valueText = 'test value';
443
+ el._destroyOutputContent();
444
+
445
+ // Should not trigger after default 2000ms
446
+ clock.tick(2000);
447
+ await expect(el.__valueText).to.equal('test value');
448
+ expect(requestUpdateSpy.called).to.be.false;
449
+
450
+ // Should trigger after custom 5000ms
451
+ clock.tick(3000); // Total 5000ms
452
+ await expect(el.__valueText).to.equal(nothing);
453
+ expect(requestUpdateSpy.calledOnce).to.be.true;
454
+
455
+ clock.restore();
456
+ requestUpdateSpy.restore();
457
+ });
458
+
459
+ it('should handle invalid data-self-destruct value by using default timeout', async () => {
460
+ const el = await fixture(html`
461
+ <lion-input-stepper name="test" label="Test"> </lion-input-stepper>
462
+ `);
463
+
464
+ await el.updateComplete;
465
+
466
+ // Get the output element and set invalid self-destruct value
467
+ const outputElement = /** @type {HTMLElement} */ (
468
+ el.shadowRoot?.querySelector('.input-stepper__value')
469
+ );
470
+ if (outputElement) {
471
+ outputElement.dataset.selfDestruct = 'invalid';
472
+ }
473
+
474
+ const clock = sinon.useFakeTimers();
475
+ const requestUpdateSpy = sinon.spy(el, 'requestUpdate');
476
+
477
+ el.__valueText = 'test value';
478
+ el._destroyOutputContent();
479
+
480
+ // Should use default 2000ms when invalid value is provided
481
+ clock.tick(2000);
482
+ await expect(el.__valueText).to.equal(nothing);
483
+ expect(requestUpdateSpy.calledOnce).to.be.true;
484
+
485
+ clock.restore();
486
+ requestUpdateSpy.restore();
487
+ });
488
+
489
+ it('should not set timeout if output element does not exist', async () => {
490
+ const el = await fixture(defaultInputStepper);
491
+ const setTimeoutSpy = sinon.spy(window, 'setTimeout');
492
+
493
+ // Mock shadowRoot to return null for querySelector
494
+ const originalQuerySelector = el.shadowRoot?.querySelector;
495
+ if (el.shadowRoot) {
496
+ el.shadowRoot.querySelector = () => null;
497
+ }
498
+
499
+ el._destroyOutputContent();
500
+
501
+ expect(setTimeoutSpy.called).to.be.false;
502
+
503
+ // Restore original querySelector
504
+ if (el.shadowRoot && originalQuerySelector) {
505
+ el.shadowRoot.querySelector = originalQuerySelector;
506
+ }
507
+ setTimeoutSpy.restore();
508
+ });
509
+
510
+ it('should only execute timeout callback if output element still has parent', async () => {
511
+ const el = await fixture(defaultInputStepper);
512
+ const clock = sinon.useFakeTimers();
513
+ const requestUpdateSpy = sinon.spy(el, 'requestUpdate');
514
+
515
+ el.__valueText = 'test value';
516
+ el._destroyOutputContent();
517
+
518
+ // Remove the output element from DOM before timeout
519
+ const outputElement = el.shadowRoot?.querySelector('.input-stepper__value');
520
+ if (outputElement && outputElement.parentNode) {
521
+ outputElement.parentNode.removeChild(outputElement);
522
+ }
523
+
524
+ // Fast forward time
525
+ clock.tick(2000);
526
+
527
+ // Should not have updated since element was removed
528
+ expect(requestUpdateSpy.called).to.be.false;
529
+ expect(el.__valueText).to.equal('test value');
530
+
531
+ clock.restore();
532
+ requestUpdateSpy.restore();
533
+ });
534
+
535
+ it('should be called when increment button is clicked', async () => {
536
+ const el = await fixture(defaultInputStepper);
537
+ const destroyOutputSpy = sinon.spy(el, '_destroyOutputContent');
538
+
539
+ const incrementButton = el.querySelector('[slot=suffix]');
540
+ incrementButton?.dispatchEvent(new Event('click'));
541
+
542
+ expect(destroyOutputSpy.calledOnce).to.be.true;
543
+ destroyOutputSpy.restore();
544
+ });
545
+
546
+ it('should be called when decrement button is clicked', async () => {
547
+ const el = await fixture(defaultInputStepper);
548
+ const destroyOutputSpy = sinon.spy(el, '_destroyOutputContent');
549
+
550
+ const decrementButton = el.querySelector('[slot=prefix]');
551
+ decrementButton?.dispatchEvent(new Event('click'));
552
+
553
+ expect(destroyOutputSpy.calledOnce).to.be.true;
554
+ destroyOutputSpy.restore();
555
+ });
556
+
557
+ it('should handle multiple rapid calls by clearing previous timers', async () => {
558
+ const el = await fixture(defaultInputStepper);
559
+ const clock = sinon.useFakeTimers();
560
+ const requestUpdateSpy = sinon.spy(el, 'requestUpdate');
561
+
562
+ el.__valueText = 'test value';
563
+
564
+ // Call _destroyOutputContent multiple times rapidly
565
+ el._destroyOutputContent();
566
+ clock.tick(1000); // 1 second
567
+
568
+ el._destroyOutputContent(); // This should clear the previous timer
569
+ clock.tick(1000); // Total 2 seconds from first call, 1 second from second call
570
+
571
+ // Should not have triggered yet since second call reset the timer
572
+ expect(el.__valueText).to.equal('test value');
573
+ expect(requestUpdateSpy.called).to.be.false;
574
+
575
+ clock.tick(1000); // Total 2 seconds from second call
576
+
577
+ // Should trigger now
578
+ await expect(el.__valueText).to.equal(nothing);
579
+ expect(requestUpdateSpy.calledOnce).to.be.true;
580
+
581
+ clock.restore();
582
+ requestUpdateSpy.restore();
361
583
  });
362
584
  });
363
585
 
@@ -448,30 +670,20 @@ describe('<lion-input-stepper>', () => {
448
670
  expect(el._inputNode.getAttribute('aria-valuemax')).to.equal('1000');
449
671
  });
450
672
 
451
- it('when decrease button gets focus, it sets aria-live to input-stepper__value', async () => {
673
+ it('decrease button should have aria-label with the component label', async () => {
452
674
  const el = await fixture(inputStepperWithAttrs);
453
- const stepperValue = el.shadowRoot?.querySelector('.input-stepper__value');
454
675
  const decrementButton = el.querySelector('[slot=prefix]');
455
676
 
456
- decrementButton?.dispatchEvent(new Event('focus'));
457
- expect(stepperValue?.hasAttribute('aria-live')).to.be.true;
458
- expect(stepperValue?.getAttribute('aria-live')).to.equal('assertive');
459
-
460
- decrementButton?.dispatchEvent(new Event('blur'));
461
- expect(stepperValue?.hasAttribute('aria-live')).to.be.false;
677
+ expect(decrementButton?.hasAttribute('aria-label')).to.be.true;
678
+ expect(decrementButton?.getAttribute('aria-label')).to.equal('Decrease Label');
462
679
  });
463
680
 
464
- it('when increase button gets focus, it sets aria-live to input-stepper__value', async () => {
681
+ it('increase button should have aria-label with the component label', async () => {
465
682
  const el = await fixture(inputStepperWithAttrs);
466
- const stepperValue = el.shadowRoot?.querySelector('.input-stepper__value');
467
683
  const incrementButton = el.querySelector('[slot=suffix]');
468
684
 
469
- incrementButton?.dispatchEvent(new Event('focus'));
470
- expect(stepperValue?.hasAttribute('aria-live')).to.be.true;
471
- expect(stepperValue?.getAttribute('aria-live')).to.equal('assertive');
472
-
473
- incrementButton?.dispatchEvent(new Event('blur'));
474
- expect(stepperValue?.hasAttribute('aria-live')).to.be.false;
685
+ expect(incrementButton?.hasAttribute('aria-label')).to.be.true;
686
+ expect(incrementButton?.getAttribute('aria-label')).to.equal('Increase Label');
475
687
  });
476
688
  });
477
689
  });
@@ -196,7 +196,8 @@ export class LionPagination extends LocalizeMixin(LitElement) {
196
196
  const finish = this.count;
197
197
  // If there are more pages then we want to display we have to redo the list each time
198
198
  // Else we can just return the same list every time.
199
- if (this.count > this.__visiblePages) {
199
+ // Allow up to 2 extra pages without ellipsis (e.g., count=6 or count=7 when visiblePages=5)
200
+ if (this.count > this.__visiblePages + 2) {
200
201
  // Calculate left side of current page and right side
201
202
  const pos3 = this.current - 1;
202
203
  const pos4 = this.current;
@@ -164,4 +164,45 @@ describe('Pagination', () => {
164
164
  expect(buttons[3].getAttribute('aria-current')).to.equal('false');
165
165
  });
166
166
  });
167
+
168
+ describe('Ellipsis display', () => {
169
+ it('should not show ellipsis when count is visiblePages + 1 (count=6, visiblePages=5)', async () => {
170
+ const el = await fixture(html` <lion-pagination count="6" current="1"></lion-pagination> `);
171
+ const navItems = Array.from(/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('li'));
172
+ // Check that no ellipsis is rendered (no <span> elements with '...')
173
+ const spans = Array.from(
174
+ /** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('li span'),
175
+ );
176
+ expect(spans.length).to.equal(0);
177
+
178
+ // There should be 8 nav items: previous button + 6 page buttons + next button
179
+ expect(navItems.length).to.equal(8);
180
+ });
181
+
182
+ it('should not show ellipsis when count is visiblePages + 2 (count=7, visiblePages=5)', async () => {
183
+ const el = await fixture(html` <lion-pagination count="7" current="1"></lion-pagination> `);
184
+ // Check that no ellipsis is rendered (no <span> elements with '...')
185
+ const spans = Array.from(
186
+ /** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('li span'),
187
+ );
188
+ expect(spans.length).to.equal(0);
189
+
190
+ // There should be 9 nav items: previous button + 7 page buttons + next button
191
+ const navItems = Array.from(/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('li'));
192
+ expect(navItems.length).to.equal(9);
193
+ });
194
+
195
+ it('should show ellipsis when count is visiblePages + 3 (count=8, visiblePages=5)', async () => {
196
+ const el = await fixture(html` <lion-pagination count="8" current="1"></lion-pagination> `);
197
+ // Check that ellipsis is rendered (should have <span> elements with '...')
198
+ const spans = Array.from(
199
+ /** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('li span'),
200
+ );
201
+ expect(spans.length).to.be.greaterThan(0);
202
+
203
+ // Verify the ellipsis contains '...'
204
+ const ellipsisText = Array.from(spans).map(span => span.textContent);
205
+ expect(ellipsisText).to.include('...');
206
+ });
207
+ });
167
208
  });
@@ -18,7 +18,7 @@ export default {
18
18
  MaxDate: 'Inserire un(a) {fieldName} prima di {params, date, YYYYMMDD}.',
19
19
  MinMaxDate:
20
20
  'Inserire un(a) {fieldName} tra {params.min, date, YYYYMMDD} e {params.max, date, YYYYMMDD}.',
21
- IsDateDisabled: "ТQuesta data non è disponibile, sceglierne un'altra.",
21
+ IsDateDisabled: "Questa data non è disponibile, sceglierne un'altra.",
22
22
  IsEmail: 'Inserire un valore valido per {fieldName} nel formato "name@example.com".',
23
23
  MatchesOption:
24
24
  'Nessun risultato corrispondente. Provare con una parola chiave o una categoria diversa.',
@@ -41,7 +41,7 @@ export default {
41
41
  MaxDate: 'Inserire un(a) {fieldName} prima di {params, date, YYYYMMDD}.',
42
42
  MinMaxDate:
43
43
  'Inserire un(a) {fieldName} tra {params.min, date, YYYYMMDD} e {params.max, date, YYYYMMDD}.',
44
- IsDateDisabled: "ТQuesta data non è disponibile, sceglierne un'altra.",
44
+ IsDateDisabled: "Questa data non è disponibile, sceglierne un'altra.",
45
45
  IsEmail: 'Inserire un valore valido per {fieldName} nel formato "name@example.com".',
46
46
  MatchesOption:
47
47
  'Nessun risultato corrispondente. Provare con una parola chiave o una categoria diversa.',