@ionic/core 8.7.17-dev.11769628168.11eca7cd → 8.7.17-dev.11770147425.1bfcd5e5

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/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-01-28T19:24:49",
2
+ "timestamp": "2026-02-03T19:39:04",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.38.0",
@@ -8401,6 +8401,10 @@
8401
8401
  "name": "slot",
8402
8402
  "text": "time-label - The label for the time selector in the datetime."
8403
8403
  },
8404
+ {
8405
+ "name": "part",
8406
+ "text": "wheel - The wheel container when using a wheel style layout, or in the month/year picker when using a grid style layout."
8407
+ },
8404
8408
  {
8405
8409
  "name": "part",
8406
8410
  "text": "wheel-item - The individual items when using a wheel style layout, or in the\nmonth/year picker when using a grid style layout."
@@ -9793,6 +9797,10 @@
9793
9797
  "name": "time-button active",
9794
9798
  "docs": "The time picker button when the picker is open."
9795
9799
  },
9800
+ {
9801
+ "name": "wheel",
9802
+ "docs": "The wheel container when using a wheel style layout, or in the month/year picker when using a grid style layout."
9803
+ },
9796
9804
  {
9797
9805
  "name": "wheel-item",
9798
9806
  "docs": "The individual items when using a wheel style layout, or in the\nmonth/year picker when using a grid style layout."
@@ -25540,6 +25548,10 @@
25540
25548
  "name": "slot",
25541
25549
  "text": "end - Content is placed to the right of the range slider in LTR, and to the left in RTL."
25542
25550
  },
25551
+ {
25552
+ "name": "part",
25553
+ "text": "label - The label text describing the range."
25554
+ },
25543
25555
  {
25544
25556
  "name": "part",
25545
25557
  "text": "tick - An inactive tick mark."
@@ -25548,25 +25560,85 @@
25548
25560
  "name": "part",
25549
25561
  "text": "tick-active - An active tick mark."
25550
25562
  },
25563
+ {
25564
+ "name": "part",
25565
+ "text": "bar - The inactive part of the bar."
25566
+ },
25567
+ {
25568
+ "name": "part",
25569
+ "text": "bar-active - The active part of the bar."
25570
+ },
25571
+ {
25572
+ "name": "part",
25573
+ "text": "knob-handle - The container element that wraps the knob and handles drag interactions."
25574
+ },
25575
+ {
25576
+ "name": "part",
25577
+ "text": "knob-handle-a - The container element for the first knob. Only available when `dualKnobs` is `true`."
25578
+ },
25579
+ {
25580
+ "name": "part",
25581
+ "text": "knob-handle-b - The container element for the second knob. Only available when `dualKnobs` is `true`."
25582
+ },
25583
+ {
25584
+ "name": "part",
25585
+ "text": "knob-handle-lower - The container element for the lower knob. Only available when `dualKnobs` is `true`."
25586
+ },
25587
+ {
25588
+ "name": "part",
25589
+ "text": "knob-handle-upper - The container element for the upper knob. Only available when `dualKnobs` is `true`."
25590
+ },
25551
25591
  {
25552
25592
  "name": "part",
25553
25593
  "text": "pin - The counter that appears above a knob."
25554
25594
  },
25555
25595
  {
25556
25596
  "name": "part",
25557
- "text": "knob - The handle that is used to drag the range."
25597
+ "text": "pin-a - The counter that appears above the first knob. Only available when `dualKnobs` is `true`."
25558
25598
  },
25559
25599
  {
25560
25600
  "name": "part",
25561
- "text": "bar - The inactive part of the bar."
25601
+ "text": "pin-b - The counter that appears above the second knob. Only available when `dualKnobs` is `true`."
25562
25602
  },
25563
25603
  {
25564
25604
  "name": "part",
25565
- "text": "bar-active - The active part of the bar."
25605
+ "text": "pin-lower - The counter that appears above the lower knob. Only available when `dualKnobs` is `true`."
25566
25606
  },
25567
25607
  {
25568
25608
  "name": "part",
25569
- "text": "label - The label text describing the range."
25609
+ "text": "pin-upper - The counter that appears above the upper knob. Only available when `dualKnobs` is `true`."
25610
+ },
25611
+ {
25612
+ "name": "part",
25613
+ "text": "knob - The visual knob element that appears on the range track."
25614
+ },
25615
+ {
25616
+ "name": "part",
25617
+ "text": "knob-a - The visual knob element for the first knob. Only available when `dualKnobs` is `true`."
25618
+ },
25619
+ {
25620
+ "name": "part",
25621
+ "text": "knob-b - The visual knob element for the second knob. Only available when `dualKnobs` is `true`."
25622
+ },
25623
+ {
25624
+ "name": "part",
25625
+ "text": "knob-lower - The visual knob element for the lower knob. Only available when `dualKnobs` is `true`."
25626
+ },
25627
+ {
25628
+ "name": "part",
25629
+ "text": "knob-upper - The visual knob element for the upper knob. Only available when `dualKnobs` is `true`."
25630
+ },
25631
+ {
25632
+ "name": "part",
25633
+ "text": "pressed - Added to the knob-handle, knob, and pin that is currently being pressed to drag. Only one set has this part at a time when `dualKnobs` is `true`."
25634
+ },
25635
+ {
25636
+ "name": "part",
25637
+ "text": "focused - Added to the knob-handle, knob, and pin that currently has focus. Only one set has this part at a time when `dualKnobs` is `true`."
25638
+ },
25639
+ {
25640
+ "name": "part",
25641
+ "text": "hover - Added to the knob-handle, knob, and pin when the knob has hover. Only one set has this part at a time."
25570
25642
  }
25571
25643
  ],
25572
25644
  "usage": {},
@@ -26386,9 +26458,53 @@
26386
26458
  "name": "bar-active",
26387
26459
  "docs": "The active part of the bar."
26388
26460
  },
26461
+ {
26462
+ "name": "focused",
26463
+ "docs": "Added to the knob-handle, knob, and pin that currently has focus. Only one set has this part at a time when `dualKnobs` is `true`."
26464
+ },
26465
+ {
26466
+ "name": "hover",
26467
+ "docs": "Added to the knob-handle, knob, and pin when the knob has hover. Only one set has this part at a time."
26468
+ },
26389
26469
  {
26390
26470
  "name": "knob",
26391
- "docs": "The handle that is used to drag the range."
26471
+ "docs": "The visual knob element that appears on the range track."
26472
+ },
26473
+ {
26474
+ "name": "knob-a",
26475
+ "docs": "The visual knob element for the first knob. Only available when `dualKnobs` is `true`."
26476
+ },
26477
+ {
26478
+ "name": "knob-b",
26479
+ "docs": "The visual knob element for the second knob. Only available when `dualKnobs` is `true`."
26480
+ },
26481
+ {
26482
+ "name": "knob-handle",
26483
+ "docs": "The container element that wraps the knob and handles drag interactions."
26484
+ },
26485
+ {
26486
+ "name": "knob-handle-a",
26487
+ "docs": "The container element for the first knob. Only available when `dualKnobs` is `true`."
26488
+ },
26489
+ {
26490
+ "name": "knob-handle-b",
26491
+ "docs": "The container element for the second knob. Only available when `dualKnobs` is `true`."
26492
+ },
26493
+ {
26494
+ "name": "knob-handle-lower",
26495
+ "docs": "The container element for the lower knob. Only available when `dualKnobs` is `true`."
26496
+ },
26497
+ {
26498
+ "name": "knob-handle-upper",
26499
+ "docs": "The container element for the upper knob. Only available when `dualKnobs` is `true`."
26500
+ },
26501
+ {
26502
+ "name": "knob-lower",
26503
+ "docs": "The visual knob element for the lower knob. Only available when `dualKnobs` is `true`."
26504
+ },
26505
+ {
26506
+ "name": "knob-upper",
26507
+ "docs": "The visual knob element for the upper knob. Only available when `dualKnobs` is `true`."
26392
26508
  },
26393
26509
  {
26394
26510
  "name": "label",
@@ -26398,6 +26514,26 @@
26398
26514
  "name": "pin",
26399
26515
  "docs": "The counter that appears above a knob."
26400
26516
  },
26517
+ {
26518
+ "name": "pin-a",
26519
+ "docs": "The counter that appears above the first knob. Only available when `dualKnobs` is `true`."
26520
+ },
26521
+ {
26522
+ "name": "pin-b",
26523
+ "docs": "The counter that appears above the second knob. Only available when `dualKnobs` is `true`."
26524
+ },
26525
+ {
26526
+ "name": "pin-lower",
26527
+ "docs": "The counter that appears above the lower knob. Only available when `dualKnobs` is `true`."
26528
+ },
26529
+ {
26530
+ "name": "pin-upper",
26531
+ "docs": "The counter that appears above the upper knob. Only available when `dualKnobs` is `true`."
26532
+ },
26533
+ {
26534
+ "name": "pressed",
26535
+ "docs": "Added to the knob-handle, knob, and pin that is currently being pressed to drag. Only one set has this part at a time when `dualKnobs` is `true`."
26536
+ },
26401
26537
  {
26402
26538
  "name": "tick",
26403
26539
  "docs": "An inactive tick mark."
@@ -1391,7 +1391,7 @@ const Datetime = class {
1391
1391
  const todayString = workingParts.day !== null
1392
1392
  ? `${workingParts.year}-${workingParts.month}-${workingParts.day}`
1393
1393
  : `${defaultParts.year}-${defaultParts.month}-${defaultParts.day}`;
1394
- return (h("ion-picker-column", { "aria-label": "Select a date", class: "date-column", color: this.color, disabled: disabled, value: todayString, onIonChange: (ev) => {
1394
+ return (h("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a date", class: "date-column", color: this.color, disabled: disabled, value: todayString, onIonChange: (ev) => {
1395
1395
  const { value } = ev.detail;
1396
1396
  const findPart = parts.find(({ month, day, year }) => value === `${year}-${month}-${day}`);
1397
1397
  this.setWorkingParts(Object.assign(Object.assign({}, workingParts), findPart));
@@ -1466,7 +1466,7 @@ const Datetime = class {
1466
1466
  const { disabled, workingParts } = this;
1467
1467
  const activePart = this.getActivePartsWithFallback();
1468
1468
  const pickerColumnValue = (_a = (workingParts.day !== null ? workingParts.day : this.defaultParts.day)) !== null && _a !== void 0 ? _a : undefined;
1469
- return (h("ion-picker-column", { "aria-label": "Select a day", class: "day-column", color: this.color, disabled: disabled, value: pickerColumnValue, onIonChange: (ev) => {
1469
+ return (h("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a day", class: "day-column", color: this.color, disabled: disabled, value: pickerColumnValue, onIonChange: (ev) => {
1470
1470
  this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { day: ev.detail.value }));
1471
1471
  this.setActiveParts(Object.assign(Object.assign({}, activePart), { day: ev.detail.value }));
1472
1472
  ev.stopPropagation();
@@ -1478,7 +1478,7 @@ const Datetime = class {
1478
1478
  }
1479
1479
  const { disabled, workingParts } = this;
1480
1480
  const activePart = this.getActivePartsWithFallback();
1481
- return (h("ion-picker-column", { "aria-label": "Select a month", class: "month-column", color: this.color, disabled: disabled, value: workingParts.month, onIonChange: (ev) => {
1481
+ return (h("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a month", class: "month-column", color: this.color, disabled: disabled, value: workingParts.month, onIonChange: (ev) => {
1482
1482
  this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { month: ev.detail.value }));
1483
1483
  this.setActiveParts(Object.assign(Object.assign({}, activePart), { month: ev.detail.value }));
1484
1484
  ev.stopPropagation();
@@ -1490,7 +1490,7 @@ const Datetime = class {
1490
1490
  }
1491
1491
  const { disabled, workingParts } = this;
1492
1492
  const activePart = this.getActivePartsWithFallback();
1493
- return (h("ion-picker-column", { "aria-label": "Select a year", class: "year-column", color: this.color, disabled: disabled, value: workingParts.year, onIonChange: (ev) => {
1493
+ return (h("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a year", class: "year-column", color: this.color, disabled: disabled, value: workingParts.year, onIonChange: (ev) => {
1494
1494
  this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { year: ev.detail.value }));
1495
1495
  this.setActiveParts(Object.assign(Object.assign({}, activePart), { year: ev.detail.value }));
1496
1496
  ev.stopPropagation();
@@ -1523,7 +1523,7 @@ const Datetime = class {
1523
1523
  if (hoursData.length === 0)
1524
1524
  return [];
1525
1525
  const activePart = this.getActivePartsWithFallback();
1526
- return (h("ion-picker-column", { "aria-label": "Select an hour", color: this.color, disabled: disabled, value: activePart.hour, numericInput: true, onIonChange: (ev) => {
1526
+ return (h("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select an hour", color: this.color, disabled: disabled, value: activePart.hour, numericInput: true, onIonChange: (ev) => {
1527
1527
  this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { hour: ev.detail.value }));
1528
1528
  this.setActiveParts(Object.assign(Object.assign({}, this.getActivePartsWithFallback()), { hour: ev.detail.value }));
1529
1529
  ev.stopPropagation();
@@ -1534,7 +1534,7 @@ const Datetime = class {
1534
1534
  if (minutesData.length === 0)
1535
1535
  return [];
1536
1536
  const activePart = this.getActivePartsWithFallback();
1537
- return (h("ion-picker-column", { "aria-label": "Select a minute", color: this.color, disabled: disabled, value: activePart.minute, numericInput: true, onIonChange: (ev) => {
1537
+ return (h("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a minute", color: this.color, disabled: disabled, value: activePart.minute, numericInput: true, onIonChange: (ev) => {
1538
1538
  this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { minute: ev.detail.value }));
1539
1539
  this.setActiveParts(Object.assign(Object.assign({}, this.getActivePartsWithFallback()), { minute: ev.detail.value }));
1540
1540
  ev.stopPropagation();
@@ -1547,7 +1547,7 @@ const Datetime = class {
1547
1547
  }
1548
1548
  const activePart = this.getActivePartsWithFallback();
1549
1549
  const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
1550
- return (h("ion-picker-column", { "aria-label": "Select a day period", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
1550
+ return (h("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a day period", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
1551
1551
  const hour = calculateHourFromAMPM(workingParts, ev.detail.value);
1552
1552
  this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { ampm: ev.detail.value, hour }));
1553
1553
  this.setActiveParts(Object.assign(Object.assign({}, this.getActivePartsWithFallback()), { ampm: ev.detail.value, hour }));
@@ -1889,7 +1889,7 @@ const Datetime = class {
1889
1889
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
1890
1890
  const hasWheelVariant = hasDatePresentation && preferWheel;
1891
1891
  renderHiddenInput(true, el, name, formatValue(value), disabled);
1892
- return (h(Host, { key: 'efdbc0922670a841bc667ceac392cdc1dedffd01', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1892
+ return (h(Host, { key: '19e20c9b6b5f9467e91a2567b6dc7d9d38b56cc3', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1893
1893
  [mode]: true,
1894
1894
  ['datetime-readonly']: readonly,
1895
1895
  ['datetime-disabled']: disabled,
@@ -1899,7 +1899,7 @@ const Datetime = class {
1899
1899
  [`datetime-size-${size}`]: true,
1900
1900
  [`datetime-prefer-wheel`]: hasWheelVariant,
1901
1901
  [`datetime-grid`]: isGridStyle,
1902
- })) }, h("div", { key: '3f8bb75fcb0baff55182ef3aa1b535eacc58d81f', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1902
+ })) }, h("div", { key: 'e31b5ef76cd6262dafd39f2d21980887880ec32e', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1903
1903
  }
1904
1904
  get el() { return getElement(this); }
1905
1905
  static get watchers() { return {
@@ -1919,6 +1919,7 @@ const Datetime = class {
1919
1919
  let datetimeIds = 0;
1920
1920
  const CANCEL_ROLE = 'datetime-cancel';
1921
1921
  const CONFIRM_ROLE = 'datetime-confirm';
1922
+ const WHEEL_PART = 'wheel';
1922
1923
  const WHEEL_ITEM_PART = 'wheel-item';
1923
1924
  const WHEEL_ITEM_ACTIVE_PART = `active`;
1924
1925
  Datetime.style = {
@@ -74,6 +74,7 @@ const Range = class {
74
74
  this.inheritedAttributes = {};
75
75
  this.contentEl = null;
76
76
  this.initialContentScrollY = true;
77
+ this.focusFromPointer = false;
77
78
  this.ratioA = 0;
78
79
  this.ratioB = 0;
79
80
  /**
@@ -205,6 +206,7 @@ const Range = class {
205
206
  this.onBlur = () => {
206
207
  if (this.hasFocus) {
207
208
  this.hasFocus = false;
209
+ this.focusedKnob = undefined;
208
210
  this.ionBlur.emit();
209
211
  }
210
212
  };
@@ -215,21 +217,20 @@ const Range = class {
215
217
  }
216
218
  };
217
219
  this.onKnobFocus = (knob) => {
220
+ // Clicking focuses the range which is needed for the keyboard,
221
+ // but we only want to add the ion-focused class when focused via Tab.
222
+ if (!this.focusFromPointer) {
223
+ this.focusedKnob = knob;
224
+ }
225
+ else {
226
+ this.focusFromPointer = false;
227
+ this.focusedKnob = undefined;
228
+ }
229
+ // If the knob was not already focused, emit the focus event
218
230
  if (!this.hasFocus) {
219
231
  this.hasFocus = true;
220
232
  this.ionFocus.emit();
221
233
  }
222
- // Manually manage ion-focused class for dual knobs
223
- if (this.dualKnobs && this.el.shadowRoot) {
224
- const knobA = this.el.shadowRoot.querySelector('.range-knob-a');
225
- const knobB = this.el.shadowRoot.querySelector('.range-knob-b');
226
- // Remove ion-focused from both knobs first
227
- knobA === null || knobA === void 0 ? void 0 : knobA.classList.remove('ion-focused');
228
- knobB === null || knobB === void 0 ? void 0 : knobB.classList.remove('ion-focused');
229
- // Add ion-focused only to the focused knob
230
- const focusedKnobEl = knob === 'A' ? knobA : knobB;
231
- focusedKnobEl === null || focusedKnobEl === void 0 ? void 0 : focusedKnobEl.classList.add('ion-focused');
232
- }
233
234
  };
234
235
  this.onKnobBlur = () => {
235
236
  // Check if focus is moving to another knob within the same range
@@ -241,18 +242,18 @@ const Range = class {
241
242
  if (!isStillFocusedOnKnob) {
242
243
  if (this.hasFocus) {
243
244
  this.hasFocus = false;
245
+ this.focusedKnob = undefined;
244
246
  this.ionBlur.emit();
245
247
  }
246
- // Remove ion-focused from both knobs when focus leaves the range
247
- if (this.dualKnobs && this.el.shadowRoot) {
248
- const knobA = this.el.shadowRoot.querySelector('.range-knob-a');
249
- const knobB = this.el.shadowRoot.querySelector('.range-knob-b');
250
- knobA === null || knobA === void 0 ? void 0 : knobA.classList.remove('ion-focused');
251
- knobB === null || knobB === void 0 ? void 0 : knobB.classList.remove('ion-focused');
252
- }
253
248
  }
254
249
  }, 0);
255
250
  };
251
+ this.onKnobMouseEnter = (knob) => {
252
+ this.hoveredKnob = knob;
253
+ };
254
+ this.onKnobMouseLeave = () => {
255
+ this.hoveredKnob = undefined;
256
+ };
256
257
  }
257
258
  debounceChanged() {
258
259
  const { ionInput, debounce, originalIonInput } = this;
@@ -506,7 +507,6 @@ const Range = class {
506
507
  ratio = 1 - ratio;
507
508
  }
508
509
  this.pressedKnob = !this.dualKnobs || Math.abs(this.ratioA - ratio) < Math.abs(this.ratioB - ratio) ? 'A' : 'B';
509
- this.setFocus(this.pressedKnob);
510
510
  }
511
511
  get valA() {
512
512
  return ratioToValue(this.ratioA, this.min, this.max, this.step);
@@ -533,9 +533,23 @@ const Range = class {
533
533
  updateRatio() {
534
534
  const value = this.getValue();
535
535
  const { min, max } = this;
536
+ /**
537
+ * For dual knobs, value gives lower/upper but not which is A vs B.
538
+ * Assign (lowerRatio, upperRatio) to (ratioA, ratioB) in the way that
539
+ * minimizes change from the current ratios so the knobs don't swap.
540
+ */
536
541
  if (this.dualKnobs) {
537
- this.ratioA = valueToRatio(value.lower, min, max);
538
- this.ratioB = valueToRatio(value.upper, min, max);
542
+ const lowerRatio = valueToRatio(value.lower, min, max);
543
+ const upperRatio = valueToRatio(value.upper, min, max);
544
+ if (Math.abs(this.ratioA - lowerRatio) + Math.abs(this.ratioB - upperRatio) <=
545
+ Math.abs(this.ratioA - upperRatio) + Math.abs(this.ratioB - lowerRatio)) {
546
+ this.ratioA = lowerRatio;
547
+ this.ratioB = upperRatio;
548
+ }
549
+ else {
550
+ this.ratioA = upperRatio;
551
+ this.ratioB = lowerRatio;
552
+ }
539
553
  }
540
554
  else {
541
555
  this.ratioA = valueToRatio(value, min, max);
@@ -552,14 +566,6 @@ const Range = class {
552
566
  };
553
567
  this.noUpdate = false;
554
568
  }
555
- setFocus(knob) {
556
- if (this.el.shadowRoot) {
557
- const knobEl = this.el.shadowRoot.querySelector(knob === 'A' ? '.range-knob-a' : '.range-knob-b');
558
- if (knobEl) {
559
- knobEl.focus();
560
- }
561
- }
562
- }
563
569
  /**
564
570
  * Returns true if content was passed to the "start" slot
565
571
  */
@@ -577,7 +583,7 @@ const Range = class {
577
583
  }
578
584
  renderRangeSlider() {
579
585
  var _a;
580
- const { min, max, step, handleKeyboard, pressedKnob, disabled, pin, ratioLower, ratioUpper, pinFormatter, inheritedAttributes, } = this;
586
+ const { min, max, step, handleKeyboard, focusedKnob, hoveredKnob, pressedKnob, disabled, pin, ratioLower, ratioUpper, pinFormatter, inheritedAttributes, } = this;
581
587
  let barStart = `${ratioLower * 100}%`;
582
588
  let barEnd = `${100 - ratioUpper * 100}%`;
583
589
  const rtl = isRTL(this.el);
@@ -637,7 +643,9 @@ const Range = class {
637
643
  ticks.push(tick);
638
644
  }
639
645
  }
640
- return (h("div", { class: "range-slider", ref: (rangeEl) => (this.rangeSlider = rangeEl),
646
+ return (h("div", { class: "range-slider", ref: (rangeEl) => (this.rangeSlider = rangeEl), onPointerDown: () => {
647
+ this.focusFromPointer = true;
648
+ },
641
649
  /**
642
650
  * Since the gesture has a threshold, the value
643
651
  * won't change until the user has dragged past
@@ -650,6 +658,7 @@ const Range = class {
650
658
  * we need to listen for the "pointerUp" event.
651
659
  */
652
660
  onPointerUp: (ev) => {
661
+ this.focusFromPointer = false;
653
662
  /**
654
663
  * If the user drags the knob on the web
655
664
  * version (does not occur on mobile),
@@ -675,6 +684,10 @@ const Range = class {
675
684
  'has-ticks': ticks.length > 0,
676
685
  }, role: "presentation", style: barStyle, part: "bar-active" })), renderKnob(rtl, {
677
686
  knob: 'A',
687
+ position: this.dualKnobs ? (this.ratioA <= this.ratioB ? 'lower' : 'upper') : 'lower',
688
+ dualKnobs: this.dualKnobs,
689
+ focused: focusedKnob === 'A',
690
+ hovered: hoveredKnob === 'A',
678
691
  pressed: pressedKnob === 'A',
679
692
  value: this.valA,
680
693
  ratio: this.ratioA,
@@ -687,9 +700,15 @@ const Range = class {
687
700
  inheritedAttributes,
688
701
  onKnobFocus: this.onKnobFocus,
689
702
  onKnobBlur: this.onKnobBlur,
703
+ onKnobMouseEnter: this.onKnobMouseEnter,
704
+ onKnobMouseLeave: this.onKnobMouseLeave,
690
705
  }), this.dualKnobs &&
691
706
  renderKnob(rtl, {
692
707
  knob: 'B',
708
+ position: this.ratioB <= this.ratioA ? 'lower' : 'upper',
709
+ dualKnobs: this.dualKnobs,
710
+ focused: focusedKnob === 'B',
711
+ hovered: hoveredKnob === 'B',
693
712
  pressed: pressedKnob === 'B',
694
713
  value: this.valB,
695
714
  ratio: this.ratioB,
@@ -702,6 +721,8 @@ const Range = class {
702
721
  inheritedAttributes,
703
722
  onKnobFocus: this.onKnobFocus,
704
723
  onKnobBlur: this.onKnobBlur,
724
+ onKnobMouseEnter: this.onKnobMouseEnter,
725
+ onKnobMouseLeave: this.onKnobMouseLeave,
705
726
  })));
706
727
  }
707
728
  render() {
@@ -727,10 +748,11 @@ const Range = class {
727
748
  const valueAtMin = dualKnobs ? this.valA === min || this.valB === min : this.valA === min;
728
749
  const valueAtMax = dualKnobs ? this.valA === max || this.valB === max : this.valA === max;
729
750
  renderHiddenInput(true, el, this.name, JSON.stringify(this.getValue()), disabled);
730
- return (h(Host, { key: 'ed646a42d51b8fe22012198c354cbcf5a389c108', onFocusin: this.onFocus, onFocusout: this.onBlur, id: rangeId, class: createColorClasses(this.color, {
751
+ return (h(Host, { key: '4a393e229cf599f3377b606acaebe5f090d41f6e', onFocusin: this.onFocus, onFocusout: this.onBlur, id: rangeId, class: createColorClasses(this.color, {
731
752
  [mode]: true,
732
753
  'in-item': inItem,
733
754
  'range-disabled': disabled,
755
+ 'range-dual-knobs': dualKnobs,
734
756
  'range-pressed': pressedKnob !== undefined,
735
757
  'range-has-pin': pin,
736
758
  [`range-label-placement-${labelPlacement}`]: true,
@@ -738,10 +760,10 @@ const Range = class {
738
760
  'range-item-end-adjustment': needsEndAdjustment,
739
761
  'range-value-min': valueAtMin,
740
762
  'range-value-max': valueAtMax,
741
- }) }, h("label", { key: '3083e4f2a624e3b268396acb4415f7c6ac44d851', class: "range-wrapper", id: "range-label" }, h("div", { key: '47b92f94d2a0381dd7c5cd3dda54ed2942096715', class: {
763
+ }) }, h("label", { key: 'd7f45882aa7f11bbac1cb783caa0053151efcc70', class: "range-wrapper", id: "range-label" }, h("div", { key: '537d3b1e7f9fed0c8380678551e31325b1ef1f85', class: {
742
764
  'label-text-wrapper': true,
743
765
  'label-text-wrapper-hidden': !hasLabel,
744
- }, part: "label" }, label !== undefined ? h("div", { class: "label-text" }, label) : h("slot", { name: "label" })), h("div", { key: '5341da8d19eb29091df680978a0e20cc8f2eec65', class: "native-wrapper" }, h("slot", { key: '09f1437078032676695442d8c827a16faa7dffe2', name: "start" }), this.renderRangeSlider(), h("slot", { key: '02b7781970ea4d44f10b5f4627a2ca36eca45f85', name: "end" })))));
766
+ }, part: "label" }, label !== undefined ? h("div", { class: "label-text" }, label) : h("slot", { name: "label" })), h("div", { key: 'cb50f07a3704d04af3554211ffad35f7d9fcc450', class: "native-wrapper" }, h("slot", { key: '09004eaa72688ca0f0536bd5f5d7160a23d16406', name: "start" }), this.renderRangeSlider(), h("slot", { key: 'a94da21d2ea7ed2feafcc0651c72da21d6de1e57', name: "end" })))));
745
767
  }
746
768
  get el() { return getElement(this); }
747
769
  static get watchers() { return {
@@ -754,7 +776,7 @@ const Range = class {
754
776
  "value": ["valueChanged"]
755
777
  }; }
756
778
  };
757
- const renderKnob = (rtl, { knob, value, ratio, min, max, disabled, pressed, pin, handleKeyboard, pinFormatter, inheritedAttributes, onKnobFocus, onKnobBlur, }) => {
779
+ const renderKnob = (rtl, { knob, position, dualKnobs, value, ratio, min, max, disabled, pressed, focused, hovered, pin, handleKeyboard, pinFormatter, inheritedAttributes, onKnobFocus, onKnobBlur, onKnobMouseEnter, onKnobMouseLeave, }) => {
758
780
  const start = rtl ? 'right' : 'left';
759
781
  const knobStyle = () => {
760
782
  const style = {};
@@ -775,16 +797,50 @@ const renderKnob = (rtl, { knob, value, ratio, min, max, disabled, pressed, pin,
775
797
  ev.preventDefault();
776
798
  ev.stopPropagation();
777
799
  }
778
- }, onFocus: () => onKnobFocus(knob), onBlur: onKnobBlur, class: {
800
+ }, onFocus: () => onKnobFocus(knob), onBlur: onKnobBlur, onMouseEnter: () => onKnobMouseEnter(knob), onMouseLeave: onKnobMouseLeave, class: {
779
801
  'range-knob-handle': true,
780
- 'range-knob-a': knob === 'A',
781
- 'range-knob-b': knob === 'B',
802
+ 'range-knob-handle-a': knob === 'A',
803
+ 'range-knob-handle-b': knob === 'B',
782
804
  'range-knob-pressed': pressed,
783
805
  'range-knob-min': value === min,
784
806
  'range-knob-max': value === max,
785
807
  'ion-activatable': true,
786
808
  'ion-focusable': true,
787
- }, style: knobStyle(), role: "slider", tabindex: disabled ? -1 : 0, "aria-label": ariaLabel !== undefined ? ariaLabel : null, "aria-labelledby": ariaLabel === undefined ? 'range-label' : null, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled ? 'true' : null, "aria-valuenow": value }, pin && (h("div", { class: "range-pin", role: "presentation", part: "pin" }, pinFormatter(value))), h("div", { class: "range-knob", role: "presentation", part: "knob" })));
809
+ 'ion-focused': focused,
810
+ }, part: [
811
+ 'knob-handle',
812
+ dualKnobs && knob === 'A' && 'knob-handle-a',
813
+ dualKnobs && knob === 'B' && 'knob-handle-b',
814
+ dualKnobs && position === 'lower' && 'knob-handle-lower',
815
+ dualKnobs && position === 'upper' && 'knob-handle-upper',
816
+ pressed && 'pressed',
817
+ focused && 'focused',
818
+ hovered && 'hover',
819
+ ]
820
+ .filter(Boolean)
821
+ .join(' '), style: knobStyle(), role: "slider", tabindex: disabled ? -1 : 0, "aria-label": ariaLabel !== undefined ? ariaLabel : null, "aria-labelledby": ariaLabel === undefined ? 'range-label' : null, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled ? 'true' : null, "aria-valuenow": value }, pin && (h("div", { class: "range-pin", role: "presentation", part: [
822
+ 'pin',
823
+ dualKnobs && knob === 'A' && 'pin-a',
824
+ dualKnobs && knob === 'B' && 'pin-b',
825
+ dualKnobs && position === 'lower' && 'pin-lower',
826
+ dualKnobs && position === 'upper' && 'pin-upper',
827
+ pressed && 'pressed',
828
+ focused && 'focused',
829
+ hovered && 'hover',
830
+ ]
831
+ .filter(Boolean)
832
+ .join(' ') }, pinFormatter(value))), h("div", { class: "range-knob", role: "presentation", part: [
833
+ 'knob',
834
+ dualKnobs && knob === 'A' && 'knob-a',
835
+ dualKnobs && knob === 'B' && 'knob-b',
836
+ dualKnobs && position === 'lower' && 'knob-lower',
837
+ dualKnobs && position === 'upper' && 'knob-upper',
838
+ pressed && 'pressed',
839
+ focused && 'focused',
840
+ hovered && 'hover',
841
+ ]
842
+ .filter(Boolean)
843
+ .join(' ') })));
788
844
  };
789
845
  const ratioToValue = (ratio, min, max, step) => {
790
846
  let value = (max - min) * ratio;