@ionic/core 9.0.11-dev.11793719937.1e883321 → 9.0.11-dev.11793727726.19b906b5

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 (89) hide show
  1. package/components/ion-action-sheet.js +1 -1
  2. package/components/ion-alert.js +1 -1
  3. package/components/ion-content.js +1 -1
  4. package/components/ion-datetime-button.js +1 -1
  5. package/components/ion-datetime.js +1 -1
  6. package/components/ion-modal.js +1 -1
  7. package/components/ion-popover.js +1 -1
  8. package/components/ion-select-modal.js +1 -1
  9. package/components/ion-select.js +1 -1
  10. package/components/ion-toast.js +1 -1
  11. package/components/{p-DtZimz8H.js → p-1HReh-CB.js} +1 -1
  12. package/components/{p-BCQSEpww.js → p-B7ExaLVL.js} +1 -1
  13. package/components/{p-CseHeZbU.js → p-BCYVFy50.js} +1 -1
  14. package/components/p-ByE0slik.js +4 -0
  15. package/components/p-DgNvIX46.js +4 -0
  16. package/components/p-DmyvpOqm.js +4 -0
  17. package/components/p-mG85e2ek.js +4 -0
  18. package/css/ionic/bundle.ionic.css +1 -1
  19. package/css/ionic/bundle.ionic.css.map +1 -1
  20. package/css/ionic/core.ionic.css +1 -1
  21. package/css/ionic/core.ionic.css.map +1 -1
  22. package/css/ionic/global.bundle.ionic.css.map +1 -1
  23. package/css/ionic/link.ionic.css.map +1 -1
  24. package/css/ionic/typography.ionic.css.map +1 -1
  25. package/dist/cjs/ion-action-sheet.cjs.entry.js +1 -1
  26. package/dist/cjs/ion-alert.cjs.entry.js +1 -1
  27. package/dist/cjs/ion-app_8.cjs.entry.js +5 -13
  28. package/dist/cjs/ion-datetime-button.cjs.entry.js +33 -6
  29. package/dist/cjs/ion-datetime.cjs.entry.js +353 -36
  30. package/dist/cjs/ion-modal.cjs.entry.js +1 -1
  31. package/dist/cjs/ion-popover.cjs.entry.js +1 -1
  32. package/dist/cjs/ion-toast.cjs.entry.js +1 -1
  33. package/dist/cjs/ionic.cjs.js +1 -1
  34. package/dist/cjs/loader.cjs.js +1 -1
  35. package/dist/collection/components/action-sheet/action-sheet.ionic.css +1 -1
  36. package/dist/collection/components/alert/alert.ionic.css +1 -1
  37. package/dist/collection/components/content/{content.ios.css → content.css} +41 -65
  38. package/dist/collection/components/content/content.js +5 -9
  39. package/dist/collection/components/datetime/datetime.ionic.css +179 -5
  40. package/dist/collection/components/datetime/datetime.ios.css +134 -2
  41. package/dist/collection/components/datetime/datetime.js +406 -33
  42. package/dist/collection/components/datetime/datetime.md.css +120 -0
  43. package/dist/collection/components/datetime/utils/state.js +18 -1
  44. package/dist/collection/components/datetime-button/datetime-button.js +34 -6
  45. package/dist/collection/components/modal/modal.ionic.css +2 -2
  46. package/dist/collection/components/popover/popover.ionic.css +1 -2
  47. package/dist/collection/components/toast/toast.ionic.css +1 -1
  48. package/dist/docs.json +160 -127
  49. package/dist/esm/{format-NT7iHsbA.js → format-DUHrIiJq.js} +1 -1
  50. package/dist/esm/ion-action-sheet.entry.js +1 -1
  51. package/dist/esm/ion-alert.entry.js +1 -1
  52. package/dist/esm/ion-app_8.entry.js +5 -13
  53. package/dist/esm/ion-datetime-button.entry.js +34 -7
  54. package/dist/esm/ion-datetime.entry.js +354 -37
  55. package/dist/esm/ion-modal.entry.js +1 -1
  56. package/dist/esm/ion-popover.entry.js +1 -1
  57. package/dist/esm/ion-toast.entry.js +1 -1
  58. package/dist/esm/ionic.js +1 -1
  59. package/dist/esm/loader.js +1 -1
  60. package/dist/html.html-data.json +20 -0
  61. package/dist/ionic/ionic.esm.js +1 -1
  62. package/dist/ionic/{p-b076511a.entry.js → p-3674a7de.entry.js} +1 -1
  63. package/dist/ionic/p-56d77e95.entry.js +4 -0
  64. package/dist/ionic/{p-3ddd32cc.entry.js → p-5a024b02.entry.js} +1 -1
  65. package/dist/ionic/p-9cce1ed5.entry.js +4 -0
  66. package/dist/ionic/{p-BtccSO5J.js → p-CaOPF8Xt.js} +1 -1
  67. package/dist/ionic/p-b30b468d.entry.js +4 -0
  68. package/dist/ionic/p-ceca04fb.entry.js +4 -0
  69. package/dist/ionic/p-d7da66b1.entry.js +4 -0
  70. package/dist/ionic/p-f02c29cd.entry.js +4 -0
  71. package/dist/types/components/datetime/datetime-interface.d.ts +4 -0
  72. package/dist/types/components/datetime/datetime.d.ts +71 -2
  73. package/dist/types/components/datetime/utils/state.d.ts +5 -2
  74. package/dist/types/components.d.ts +33 -0
  75. package/hydrate/index.js +405 -61
  76. package/hydrate/index.mjs +405 -61
  77. package/package.json +2 -2
  78. package/components/p-Da8LCPwo.js +0 -4
  79. package/components/p-DibGn4gb.js +0 -4
  80. package/components/p-NZGZhPF5.js +0 -4
  81. package/components/p-PFwuhbqg.js +0 -4
  82. package/dist/collection/components/content/content.ionic.css +0 -352
  83. package/dist/collection/components/content/content.md.css +0 -347
  84. package/dist/ionic/p-0743a26a.entry.js +0 -4
  85. package/dist/ionic/p-1d87b153.entry.js +0 -4
  86. package/dist/ionic/p-39e3be74.entry.js +0 -4
  87. package/dist/ionic/p-a1555032.entry.js +0 -4
  88. package/dist/ionic/p-ad46d2fd.entry.js +0 -4
  89. package/dist/ionic/p-dbf53341.entry.js +0 -4
@@ -1,3 +1,42 @@
1
+ /**
2
+ * Convert a pixels given value into rem
3
+ *
4
+ * @param pixels - Value in pixels to be converted (i.e. px)
5
+ * @param context (optional) - Baseline value
6
+ */
7
+ /**
8
+ * Convert a font size to a dynamic font size.
9
+ * Fonts that participate in Dynamic Type should use
10
+ * dynamic font sizes.
11
+ * @param size - The initial font size including the unit (i.e. px or pt)
12
+ * @param unit (optional) - The unit to convert to. Use this if you want to
13
+ * convert to a unit other than $baselineUnit.
14
+ */
15
+ /**
16
+ * Convert a font size to a dynamic font size but impose
17
+ * a maximum font size.
18
+ * @param size - The initial font size including the unit (i.e. px or pt)
19
+ * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
20
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
21
+ * convert to a unit other than $baselineUnit.
22
+ */
23
+ /**
24
+ * Convert a font size to a dynamic font size but impose
25
+ * a minimum font size.
26
+ * @param size - The initial font size including the unit (i.e. px or pt)
27
+ * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
28
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
29
+ * convert to a unit other than $baselineUnit.
30
+ */
31
+ /**
32
+ * Convert a font size to a dynamic font size but impose
33
+ * maximum and minimum font sizes.
34
+ * @param size - The initial font size including the unit (i.e. px or pt)
35
+ * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
36
+ * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
37
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
38
+ * convert to a unit other than $baselineUnit.
39
+ */
1
40
  /**
2
41
  * A heuristic that applies CSS to tablet
3
42
  * viewports.
@@ -36,6 +75,8 @@
36
75
  * @prop --offset-top: Offset top of the content
37
76
  * @prop --offset-bottom: Offset bottom of the content
38
77
  */
78
+ --background: var(--ion-background-color, #fff);
79
+ --color: var(--ion-text-color, #000);
39
80
  --padding-top: 0px;
40
81
  --padding-bottom: 0px;
41
82
  --padding-start: 0px;
@@ -279,69 +320,4 @@
279
320
  :host(.content-tab-bar-hide-scroll-partner:not(.content-fullscreen).content-tab-bar-hide-scroll-hidden) .inner-scroll {
280
321
  transition: none;
281
322
  }
282
- }
283
- /**
284
- * Convert a pixels given value into rem
285
- *
286
- * @param pixels - Value in pixels to be converted (i.e. px)
287
- * @param context (optional) - Baseline value
288
- */
289
- /**
290
- * Convert a font size to a dynamic font size.
291
- * Fonts that participate in Dynamic Type should use
292
- * dynamic font sizes.
293
- * @param size - The initial font size including the unit (i.e. px or pt)
294
- * @param unit (optional) - The unit to convert to. Use this if you want to
295
- * convert to a unit other than $baselineUnit.
296
- */
297
- /**
298
- * Convert a font size to a dynamic font size but impose
299
- * a maximum font size.
300
- * @param size - The initial font size including the unit (i.e. px or pt)
301
- * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
302
- * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
303
- * convert to a unit other than $baselineUnit.
304
- */
305
- /**
306
- * Convert a font size to a dynamic font size but impose
307
- * a minimum font size.
308
- * @param size - The initial font size including the unit (i.e. px or pt)
309
- * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
310
- * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
311
- * convert to a unit other than $baselineUnit.
312
- */
313
- /**
314
- * Convert a font size to a dynamic font size but impose
315
- * maximum and minimum font sizes.
316
- * @param size - The initial font size including the unit (i.e. px or pt)
317
- * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
318
- * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
319
- * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
320
- * convert to a unit other than $baselineUnit.
321
- */
322
- /**
323
- * A heuristic that applies CSS to tablet
324
- * viewports.
325
- *
326
- * Usage:
327
- * @include tablet-viewport() {
328
- * :host {
329
- * background-color: green;
330
- * }
331
- * }
332
- */
333
- /**
334
- * A heuristic that applies CSS to mobile
335
- * viewports (i.e. phones, not tablets).
336
- *
337
- * Usage:
338
- * @include mobile-viewport() {
339
- * :host {
340
- * background-color: blue;
341
- * }
342
- * }
343
- */
344
- :host {
345
- --background: var(--ion-background-color, #fff);
346
- --color: var(--ion-text-color, #000);
347
323
  }
@@ -471,7 +471,7 @@ export class Content {
471
471
  const forceOverscroll = this.shouldForceOverscroll(mode);
472
472
  const transitionShadow = theme === 'ios';
473
473
  this.resize();
474
- return (h(Host, { key: '6cdef99e2396f9b451240ee739800b6d4a0df9fa', role: isMainContent ? 'main' : undefined, class: createColorClasses(this.color, {
474
+ return (h(Host, { key: '7e283337732b709e43fe89b08f6852c499b964ff', role: isMainContent ? 'main' : undefined, class: createColorClasses(this.color, {
475
475
  [theme]: true,
476
476
  'content-fullscreen': this.fullscreen,
477
477
  'content-sizing': this.sizeToContent,
@@ -480,27 +480,23 @@ export class Content {
480
480
  }), style: {
481
481
  '--offset-top': `${this.cTop}px`,
482
482
  '--offset-bottom': `${this.cBottom}px`,
483
- }, ...inheritedAttributes }, h("div", { key: 'bbd9b4bf3fc97404cd42bb7824fc20e031f77922', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? h("slot", { name: "fixed" }) : null, h("div", { key: '4d4747e2495645da20a0718275a77f44fdbdd82d', class: {
483
+ }, ...inheritedAttributes }, h("div", { key: '0dcbe4f4fe2d0f85b8c36bc656fc619afdc89cfe', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? h("slot", { name: "fixed" }) : null, h("div", { key: 'cbe91794c2fc53a59f8994968571a677a2e8346b', class: {
484
484
  'inner-scroll': true,
485
485
  'scroll-x': scrollX,
486
486
  'scroll-y': scrollY,
487
487
  overscroll: (scrollX || scrollY) && forceOverscroll,
488
- }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: 'fbafdcfd579732945a3f375fb6cc9777651f41f5' })), transitionShadow ? (h("div", { class: "transition-effect" }, h("div", { class: "transition-cover" }), h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? h("slot", { name: "fixed" }) : null));
488
+ }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '1a6b9bf25051eee41003185e1b519e4c4af2c001' })), transitionShadow ? (h("div", { class: "transition-effect" }, h("div", { class: "transition-cover" }), h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? h("slot", { name: "fixed" }) : null));
489
489
  }
490
490
  static get is() { return "ion-content"; }
491
491
  static get encapsulation() { return "shadow"; }
492
492
  static get originalStyleUrls() {
493
493
  return {
494
- "ios": ["content.ios.scss"],
495
- "md": ["content.md.scss"],
496
- "ionic": ["content.ionic.scss"]
494
+ "$": ["content.scss"]
497
495
  };
498
496
  }
499
497
  static get styleUrls() {
500
498
  return {
501
- "ios": ["content.ios.css"],
502
- "md": ["content.md.css"],
503
- "ionic": ["content.ionic.css"]
499
+ "$": ["content.css"]
504
500
  };
505
501
  }
506
502
  static get properties() {
@@ -346,11 +346,108 @@
346
346
 
347
347
  :host .calendar-day-wrapper {
348
348
  display: flex;
349
+ position: relative;
349
350
  align-items: center;
350
351
  justify-content: center;
351
352
  min-width: 0;
352
353
  min-height: 0;
353
354
  overflow: visible;
355
+ /**
356
+ * Create a stacking context so the range track
357
+ * (::before with z-index: -1) stays behind the
358
+ * day button but above the host background.
359
+ */
360
+ z-index: 0;
361
+ }
362
+
363
+ /**
364
+ * Each day in the range draws its own piece of the track with a
365
+ * ::before. In-range days fill the cell, while the start and end
366
+ * caps cover the half between the pill center and the next day.
367
+ *
368
+ * Grid columns are `1fr`, so cell edges land on fractional pixels
369
+ * and a cell's track can fall a hairline short of its neighbor's.
370
+ * Each day therefore extends 1px toward the next day in the range,
371
+ * which the next day paints over except inside such a gap.
372
+ *
373
+ * @prop --range-background: The background color of the range selection track.
374
+ */
375
+ :host .calendar-day-wrapper-in-range::before,
376
+ :host .calendar-day-wrapper-range-start::before,
377
+ :host .calendar-day-wrapper-range-end::before {
378
+ position: absolute;
379
+ top: 50%;
380
+ inset-inline-start: 0;
381
+ inset-inline-end: 0;
382
+ height: var(--range-track-height);
383
+ transform: translateY(-50%);
384
+ /**
385
+ * `--range-background` is translucent by default, so it is layered
386
+ * over the datetime background to paint an opaque track. Where two
387
+ * days overlap, the color stays the same instead of doubling up
388
+ * into a darker line.
389
+ */
390
+ background: linear-gradient(var(--range-background), var(--range-background)), linear-gradient(var(--background), var(--background));
391
+ content: "";
392
+ z-index: -1;
393
+ }
394
+
395
+ :host .calendar-day-wrapper-range-start::before {
396
+ inset-inline-start: 50%;
397
+ }
398
+
399
+ :host .calendar-day-wrapper-range-end::before {
400
+ inset-inline-end: 50%;
401
+ }
402
+
403
+ /**
404
+ * Only extend toward a day that draws the track as well. The last
405
+ * day of a week is followed by the next row, and the next day is
406
+ * unpainted when it ends the selection or is disabled inside the
407
+ * range, so extending there would leave a 1px nub.
408
+ */
409
+ :host .calendar-day-wrapper-in-range:not(:nth-child(7n)):has(+ .calendar-day-wrapper-in-range)::before,
410
+ :host .calendar-day-wrapper-in-range:not(:nth-child(7n)):has(+ .calendar-day-wrapper-range-end)::before,
411
+ :host .calendar-day-wrapper-range-start:not(:nth-child(7n)):has(+ .calendar-day-wrapper-in-range)::before,
412
+ :host .calendar-day-wrapper-range-start:not(:nth-child(7n)):has(+ .calendar-day-wrapper-range-end)::before {
413
+ inset-inline-end: -1px;
414
+ }
415
+
416
+ /**
417
+ * A range that continues onto the next week runs the track
418
+ * through the grid padding to the edge of the calendar.
419
+ */
420
+ :host .calendar-day-wrapper-in-range:nth-child(7n)::before,
421
+ :host .calendar-day-wrapper-range-start:nth-child(7n)::before {
422
+ inset-inline-end: calc(var(--range-track-edge-overflow, 0px) * -1);
423
+ }
424
+
425
+ :host .calendar-day-wrapper-in-range:nth-child(7n+1)::before,
426
+ :host .calendar-day-wrapper-range-end:nth-child(7n+1)::before {
427
+ inset-inline-start: calc(var(--range-track-edge-overflow, 0px) * -1);
428
+ }
429
+
430
+ /**
431
+ * When a single day is both the start and end of the range,
432
+ * do not show a track since there is nothing to connect.
433
+ */
434
+ :host .calendar-day-wrapper-range-start.calendar-day-wrapper-range-end::before {
435
+ display: none;
436
+ }
437
+
438
+ /**
439
+ * When the component is disabled, fade the whole grid once instead of
440
+ * fading each day. Fading a day makes it its own compositing group, so
441
+ * the 1px that each day extends toward the next would be painted twice
442
+ * and read as a darker seam. The day buttons drop their own disabled
443
+ * opacity so the grid is the only thing applying it.
444
+ */
445
+ :host(.datetime-disabled.datetime-range) .calendar-month-grid {
446
+ opacity: 0.4;
447
+ }
448
+
449
+ :host(.datetime-disabled.datetime-range) .calendar-month-grid .calendar-day[disabled] {
450
+ opacity: 1;
354
451
  }
355
452
 
356
453
  /**
@@ -451,7 +548,7 @@
451
548
  */
452
549
  --background: var(--token-bg-surface-default, var(--token-primitives-base-white, #ffffff));
453
550
  --focus-ring-color: var(--token-border-focus-default, var(--token-semantics-primary-400, var(--token-primitives-blue-400, #b5c0f7)));
454
- --focus-ring-width: var(--token-border-radius-025, var(--token-scale-050, 2px));
551
+ --focus-ring-width: var(--token-border-size-050, var(--token-scale-050, 2px));
455
552
  /**
456
553
  * TODO(FW-6931): Remove these variables upon solving the root cause
457
554
  */
@@ -601,16 +698,16 @@
601
698
  }
602
699
 
603
700
  .calendar-day[disabled]:not(.calendar-day-constrained) {
604
- color: var(--token-primitives-neutral-500, #9fa5ad);
701
+ color: var(--token-text-disabled, var(--token-primitives-neutral-500, #9fa5ad));
605
702
  }
606
703
 
607
704
  .calendar-day.calendar-day-today {
608
- color: var(--token-semantics-primary-base, var(--token-semantics-primary-700, var(--token-primitives-blue-700, #105cef)));
705
+ color: var(--token-text-select, var(--token-semantics-primary-700, var(--token-primitives-blue-700, #105cef)));
609
706
  }
610
707
 
611
708
  .calendar-day.calendar-day-active,
612
709
  .calendar-day.calendar-day-active.calendar-day-adjacent-day {
613
- background: var(--token-semantics-primary-100, var(--token-primitives-blue-100, #f0f2ff));
710
+ background: var(--token-bg-primary-subtle-default, var(--token-semantics-primary-100, var(--token-primitives-blue-100, #f0f2ff)));
614
711
  }
615
712
 
616
713
  .calendar-day:focus-visible {
@@ -618,7 +715,7 @@
618
715
  }
619
716
 
620
717
  @media (any-hover: hover) {
621
- .calendar-day:not([disabled]):not(:active):hover {
718
+ .calendar-day:not([disabled]):not(:active):not(.calendar-day-in-range):hover {
622
719
  background: var(--token-semantics-primary-200, var(--token-primitives-blue-200, #e4e8ff));
623
720
  }
624
721
  }
@@ -635,6 +732,83 @@
635
732
  color: var(--token-text-default, var(--token-primitives-neutral-1200, #242528));
636
733
  }
637
734
 
735
+ :host {
736
+ --range-background: var(--token-bg-primary-subtle-default, var(--token-semantics-primary-100, var(--token-primitives-blue-100, #f0f2ff)));
737
+ --range-track-height: var(--token-scale-1200, 48px);
738
+ }
739
+
740
+ :host .calendar-day.calendar-day-range-start,
741
+ :host .calendar-day.calendar-day-range-end {
742
+ border-radius: var(--token-border-radius-full, 999px);
743
+ background: var(--token-bg-primary-base-default, var(--token-semantics-primary-base, var(--token-semantics-primary-700, var(--token-primitives-blue-700, #105cef))));
744
+ color: var(--token-text-inverse, var(--token-primitives-base-white, #ffffff));
745
+ }
746
+
747
+ .calendar-day.calendar-day-in-range {
748
+ border-radius: 0;
749
+ background: none;
750
+ color: var(--token-text-default, var(--token-primitives-neutral-1200, #242528));
751
+ }
752
+
753
+ .calendar-day.calendar-day-today.calendar-day-in-range {
754
+ color: var(--token-text-select, var(--token-semantics-primary-700, var(--token-primitives-blue-700, #105cef)));
755
+ }
756
+
757
+ :host .calendar-day.calendar-day-today.calendar-day-range-start,
758
+ :host .calendar-day.calendar-day-today.calendar-day-range-end {
759
+ color: var(--token-text-inverse, var(--token-primitives-base-white, #ffffff));
760
+ }
761
+
762
+ @media (any-hover: hover) {
763
+ .calendar-day.calendar-day-range-start:not([disabled]):not(:active):hover,
764
+ .calendar-day.calendar-day-range-end:not([disabled]):not(:active):hover {
765
+ background: var(--token-bg-primary-base-press, var(--token-semantics-primary-900, var(--token-primitives-blue-900, #0d4bc3)));
766
+ }
767
+ }
768
+ .calendar-day.calendar-day-range-start:active,
769
+ .calendar-day.calendar-day-range-end:active {
770
+ background: var(--token-bg-primary-base-press, var(--token-semantics-primary-900, var(--token-primitives-blue-900, #0d4bc3)));
771
+ }
772
+
773
+ .calendar-day.calendar-day-in-range:active {
774
+ background: var(--token-bg-primary-subtle-press, var(--token-semantics-primary-300, var(--token-primitives-blue-300, #d0d7fa)));
775
+ }
776
+
777
+ :host(.datetime-disabled.datetime-range) .calendar-day[disabled]:not(.calendar-day-constrained) {
778
+ color: var(--token-text-default, var(--token-primitives-neutral-1200, #242528));
779
+ }
780
+
781
+ :host(.datetime-disabled.datetime-range) .calendar-day.calendar-day-adjacent-day[disabled] {
782
+ color: var(--token-text-subtlest, var(--token-primitives-neutral-800, #6c727a));
783
+ }
784
+
785
+ :host(.datetime-disabled.datetime-range) .calendar-day.calendar-day-today[disabled] {
786
+ color: var(--token-text-select, var(--token-semantics-primary-700, var(--token-primitives-blue-700, #105cef)));
787
+ }
788
+
789
+ :host(.datetime-disabled.datetime-range) .calendar-day.calendar-day-range-start[disabled],
790
+ :host(.datetime-disabled.datetime-range) .calendar-day.calendar-day-range-end[disabled] {
791
+ color: var(--token-text-inverse, var(--token-primitives-base-white, #ffffff));
792
+ }
793
+
794
+ :host(.datetime-readonly) .calendar-day.calendar-day-range-start[disabled],
795
+ :host(.datetime-readonly) .calendar-day.calendar-day-range-end[disabled] {
796
+ color: var(--token-text-inverse, var(--token-primitives-base-white, #ffffff));
797
+ }
798
+
799
+ :host(.datetime-readonly) .calendar-day.calendar-day-in-range[disabled] {
800
+ color: var(--token-text-default, var(--token-primitives-neutral-1200, #242528));
801
+ }
802
+
803
+ :host(.datetime-readonly) .calendar-day.calendar-day-today.calendar-day-in-range[disabled] {
804
+ color: var(--token-text-select, var(--token-semantics-primary-700, var(--token-primitives-blue-700, #105cef)));
805
+ }
806
+
807
+ :host(.datetime-readonly) .calendar-day.calendar-day-today.calendar-day-range-start[disabled],
808
+ :host(.datetime-readonly) .calendar-day.calendar-day-today.calendar-day-range-end[disabled] {
809
+ color: var(--token-text-inverse, var(--token-primitives-base-white, #ffffff));
810
+ }
811
+
638
812
  :host .datetime-time {
639
813
  -webkit-padding-start: var(--token-space-400, var(--token-scale-400, 16px));
640
814
  padding-inline-start: var(--token-space-400, var(--token-scale-400, 16px));
@@ -349,11 +349,108 @@
349
349
 
350
350
  :host .calendar-day-wrapper {
351
351
  display: flex;
352
+ position: relative;
352
353
  align-items: center;
353
354
  justify-content: center;
354
355
  min-width: 0;
355
356
  min-height: 0;
356
357
  overflow: visible;
358
+ /**
359
+ * Create a stacking context so the range track
360
+ * (::before with z-index: -1) stays behind the
361
+ * day button but above the host background.
362
+ */
363
+ z-index: 0;
364
+ }
365
+
366
+ /**
367
+ * Each day in the range draws its own piece of the track with a
368
+ * ::before. In-range days fill the cell, while the start and end
369
+ * caps cover the half between the pill center and the next day.
370
+ *
371
+ * Grid columns are `1fr`, so cell edges land on fractional pixels
372
+ * and a cell's track can fall a hairline short of its neighbor's.
373
+ * Each day therefore extends 1px toward the next day in the range,
374
+ * which the next day paints over except inside such a gap.
375
+ *
376
+ * @prop --range-background: The background color of the range selection track.
377
+ */
378
+ :host .calendar-day-wrapper-in-range::before,
379
+ :host .calendar-day-wrapper-range-start::before,
380
+ :host .calendar-day-wrapper-range-end::before {
381
+ position: absolute;
382
+ top: 50%;
383
+ inset-inline-start: 0;
384
+ inset-inline-end: 0;
385
+ height: var(--range-track-height);
386
+ transform: translateY(-50%);
387
+ /**
388
+ * `--range-background` is translucent by default, so it is layered
389
+ * over the datetime background to paint an opaque track. Where two
390
+ * days overlap, the color stays the same instead of doubling up
391
+ * into a darker line.
392
+ */
393
+ background: linear-gradient(var(--range-background), var(--range-background)), linear-gradient(var(--background), var(--background));
394
+ content: "";
395
+ z-index: -1;
396
+ }
397
+
398
+ :host .calendar-day-wrapper-range-start::before {
399
+ inset-inline-start: 50%;
400
+ }
401
+
402
+ :host .calendar-day-wrapper-range-end::before {
403
+ inset-inline-end: 50%;
404
+ }
405
+
406
+ /**
407
+ * Only extend toward a day that draws the track as well. The last
408
+ * day of a week is followed by the next row, and the next day is
409
+ * unpainted when it ends the selection or is disabled inside the
410
+ * range, so extending there would leave a 1px nub.
411
+ */
412
+ :host .calendar-day-wrapper-in-range:not(:nth-child(7n)):has(+ .calendar-day-wrapper-in-range)::before,
413
+ :host .calendar-day-wrapper-in-range:not(:nth-child(7n)):has(+ .calendar-day-wrapper-range-end)::before,
414
+ :host .calendar-day-wrapper-range-start:not(:nth-child(7n)):has(+ .calendar-day-wrapper-in-range)::before,
415
+ :host .calendar-day-wrapper-range-start:not(:nth-child(7n)):has(+ .calendar-day-wrapper-range-end)::before {
416
+ inset-inline-end: -1px;
417
+ }
418
+
419
+ /**
420
+ * A range that continues onto the next week runs the track
421
+ * through the grid padding to the edge of the calendar.
422
+ */
423
+ :host .calendar-day-wrapper-in-range:nth-child(7n)::before,
424
+ :host .calendar-day-wrapper-range-start:nth-child(7n)::before {
425
+ inset-inline-end: calc(var(--range-track-edge-overflow, 0px) * -1);
426
+ }
427
+
428
+ :host .calendar-day-wrapper-in-range:nth-child(7n+1)::before,
429
+ :host .calendar-day-wrapper-range-end:nth-child(7n+1)::before {
430
+ inset-inline-start: calc(var(--range-track-edge-overflow, 0px) * -1);
431
+ }
432
+
433
+ /**
434
+ * When a single day is both the start and end of the range,
435
+ * do not show a track since there is nothing to connect.
436
+ */
437
+ :host .calendar-day-wrapper-range-start.calendar-day-wrapper-range-end::before {
438
+ display: none;
439
+ }
440
+
441
+ /**
442
+ * When the component is disabled, fade the whole grid once instead of
443
+ * fading each day. Fading a day makes it its own compositing group, so
444
+ * the 1px that each day extends toward the next would be painted twice
445
+ * and read as a darker seam. The day buttons drop their own disabled
446
+ * opacity so the grid is the only thing applying it.
447
+ */
448
+ :host(.datetime-disabled.datetime-range) .calendar-month-grid {
449
+ opacity: 0.4;
450
+ }
451
+
452
+ :host(.datetime-disabled.datetime-range) .calendar-month-grid .calendar-day[disabled] {
453
+ opacity: 1;
357
454
  }
358
455
 
359
456
  /**
@@ -980,12 +1077,12 @@ ion-picker {
980
1077
  }
981
1078
 
982
1079
  .calendar-day.calendar-day-active {
983
- background: rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.2);
1080
+ background: rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.12);
984
1081
  font-size: min(1.375rem, 35.2px);
985
1082
  }
986
1083
 
987
1084
  :host(.ion-color) .calendar-day.calendar-day-active {
988
- background: rgba(var(--ion-color-base-rgb), 0.2);
1085
+ background: rgba(var(--ion-color-base-rgb), 0.12);
989
1086
  }
990
1087
 
991
1088
  /**
@@ -1035,6 +1132,41 @@ ion-picker {
1035
1132
  color: var(--ion-color-step-300, var(--ion-text-color-step-700, #b3b3b3));
1036
1133
  }
1037
1134
 
1135
+ :host {
1136
+ --range-background: rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.12);
1137
+ --range-track-height: 40px;
1138
+ --range-track-edge-overflow: 8px;
1139
+ }
1140
+
1141
+ :host(.ion-color) {
1142
+ --range-background: rgba(var(--ion-color-base-rgb), 0.12);
1143
+ }
1144
+
1145
+ /**
1146
+ * The wrapper has `height: 0`, which makes `top: 50%` on the range
1147
+ * track resolve to 0 and pins the track to the top of the cell.
1148
+ * Override to `auto` so the track stays vertically centered. Apply
1149
+ * it to every wrapper in range mode so range rows are not taller
1150
+ * than the other rows.
1151
+ */
1152
+ :host(.datetime-range) .calendar-day-wrapper {
1153
+ height: auto;
1154
+ }
1155
+
1156
+ :host .calendar-day.calendar-day-range-start,
1157
+ :host .calendar-day.calendar-day-range-end {
1158
+ border-radius: 50%;
1159
+ background: var(--ion-color-primary, #0054e9);
1160
+ color: var(--ion-color-primary-contrast, #fff);
1161
+ font-weight: 600;
1162
+ }
1163
+
1164
+ :host(.ion-color) .calendar-day.calendar-day-range-start,
1165
+ :host(.ion-color) .calendar-day.calendar-day-range-end {
1166
+ background: var(--ion-color-base);
1167
+ color: var(--ion-color-contrast);
1168
+ }
1169
+
1038
1170
  :host .datetime-time {
1039
1171
  -webkit-padding-start: 16px;
1040
1172
  padding-inline-start: 16px;