@ionic/core 8.7.17-dev.11770147425.1bfcd5e5 → 8.7.17-dev.11770319814.172b4f50

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 (41) hide show
  1. package/components/ion-range.js +39 -97
  2. package/components/ion-refresher.js +32 -3
  3. package/components/ion-select.js +3 -2
  4. package/components/select-modal.js +6 -1
  5. package/dist/cjs/ion-range.cjs.entry.js +39 -95
  6. package/dist/cjs/ion-refresher_2.cjs.entry.js +32 -3
  7. package/dist/cjs/ion-select-modal.cjs.entry.js +5 -1
  8. package/dist/cjs/ion-select_3.cjs.entry.js +3 -2
  9. package/dist/cjs/ionic.cjs.js +1 -1
  10. package/dist/cjs/loader.cjs.js +1 -1
  11. package/dist/collection/components/range/range.js +42 -116
  12. package/dist/collection/components/refresher/refresher.js +70 -4
  13. package/dist/collection/components/select/select.js +3 -2
  14. package/dist/collection/components/select-modal/select-modal.js +25 -1
  15. package/dist/docs.json +83 -137
  16. package/dist/esm/ion-range.entry.js +39 -95
  17. package/dist/esm/ion-refresher_2.entry.js +32 -3
  18. package/dist/esm/ion-select-modal.entry.js +5 -1
  19. package/dist/esm/ion-select_3.entry.js +3 -2
  20. package/dist/esm/ionic.js +1 -1
  21. package/dist/esm/loader.js +1 -1
  22. package/dist/html.html-data.json +5 -1
  23. package/dist/ionic/ionic.esm.js +1 -1
  24. package/dist/ionic/p-012212e4.entry.js +4 -0
  25. package/dist/ionic/p-88367362.entry.js +4 -0
  26. package/dist/ionic/p-90f2d3ff.entry.js +4 -0
  27. package/dist/ionic/p-d2489bf2.entry.js +4 -0
  28. package/dist/types/components/range/range-interface.d.ts +0 -1
  29. package/dist/types/components/range/range.d.ts +4 -24
  30. package/dist/types/components/refresher/refresher-interface.d.ts +7 -0
  31. package/dist/types/components/refresher/refresher.d.ts +16 -3
  32. package/dist/types/components/select-modal/select-modal.d.ts +4 -0
  33. package/dist/types/components.d.ts +26 -5
  34. package/dist/types/interface.d.ts +1 -1
  35. package/hydrate/index.js +83 -122
  36. package/hydrate/index.mjs +83 -122
  37. package/package.json +1 -1
  38. package/dist/ionic/p-02d76786.entry.js +0 -4
  39. package/dist/ionic/p-639dd543.entry.js +0 -4
  40. package/dist/ionic/p-b0c2f1f1.entry.js +0 -4
  41. package/dist/ionic/p-eb024a5b.entry.js +0 -4
@@ -17,29 +17,13 @@ import { roundToMaxDecimalPlaces } from "../../utils/floating-point";
17
17
  * @slot start - Content is placed to the left of the range slider in LTR, and to the right in RTL.
18
18
  * @slot end - Content is placed to the right of the range slider in LTR, and to the left in RTL.
19
19
  *
20
- * @part label - The label text describing the range.
21
20
  * @part tick - An inactive tick mark.
22
21
  * @part tick-active - An active tick mark.
22
+ * @part pin - The counter that appears above a knob.
23
+ * @part knob - The handle that is used to drag the range.
23
24
  * @part bar - The inactive part of the bar.
24
25
  * @part bar-active - The active part of the bar.
25
- * @part knob-handle - The container element that wraps the knob and handles drag interactions.
26
- * @part knob-handle-a - The container element for the first knob. Only available when `dualKnobs` is `true`.
27
- * @part knob-handle-b - The container element for the second knob. Only available when `dualKnobs` is `true`.
28
- * @part knob-handle-lower - The container element for the lower knob. Only available when `dualKnobs` is `true`.
29
- * @part knob-handle-upper - The container element for the upper knob. Only available when `dualKnobs` is `true`.
30
- * @part pin - The counter that appears above a knob.
31
- * @part pin-a - The counter that appears above the first knob. Only available when `dualKnobs` is `true`.
32
- * @part pin-b - The counter that appears above the second knob. Only available when `dualKnobs` is `true`.
33
- * @part pin-lower - The counter that appears above the lower knob. Only available when `dualKnobs` is `true`.
34
- * @part pin-upper - The counter that appears above the upper knob. Only available when `dualKnobs` is `true`.
35
- * @part knob - The visual knob element that appears on the range track.
36
- * @part knob-a - The visual knob element for the first knob. Only available when `dualKnobs` is `true`.
37
- * @part knob-b - The visual knob element for the second knob. Only available when `dualKnobs` is `true`.
38
- * @part knob-lower - The visual knob element for the lower knob. Only available when `dualKnobs` is `true`.
39
- * @part knob-upper - The visual knob element for the upper knob. Only available when `dualKnobs` is `true`.
40
- * @part 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`.
41
- * @part 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`.
42
- * @part hover - Added to the knob-handle, knob, and pin when the knob has hover. Only one set has this part at a time.
26
+ * @part label - The label text describing the range.
43
27
  */
44
28
  export class Range {
45
29
  constructor() {
@@ -50,7 +34,6 @@ export class Range {
50
34
  this.inheritedAttributes = {};
51
35
  this.contentEl = null;
52
36
  this.initialContentScrollY = true;
53
- this.focusFromPointer = false;
54
37
  this.ratioA = 0;
55
38
  this.ratioB = 0;
56
39
  /**
@@ -182,7 +165,6 @@ export class Range {
182
165
  this.onBlur = () => {
183
166
  if (this.hasFocus) {
184
167
  this.hasFocus = false;
185
- this.focusedKnob = undefined;
186
168
  this.ionBlur.emit();
187
169
  }
188
170
  };
@@ -193,20 +175,21 @@ export class Range {
193
175
  }
194
176
  };
195
177
  this.onKnobFocus = (knob) => {
196
- // Clicking focuses the range which is needed for the keyboard,
197
- // but we only want to add the ion-focused class when focused via Tab.
198
- if (!this.focusFromPointer) {
199
- this.focusedKnob = knob;
200
- }
201
- else {
202
- this.focusFromPointer = false;
203
- this.focusedKnob = undefined;
204
- }
205
- // If the knob was not already focused, emit the focus event
206
178
  if (!this.hasFocus) {
207
179
  this.hasFocus = true;
208
180
  this.ionFocus.emit();
209
181
  }
182
+ // Manually manage ion-focused class for dual knobs
183
+ if (this.dualKnobs && this.el.shadowRoot) {
184
+ const knobA = this.el.shadowRoot.querySelector('.range-knob-a');
185
+ const knobB = this.el.shadowRoot.querySelector('.range-knob-b');
186
+ // Remove ion-focused from both knobs first
187
+ knobA === null || knobA === void 0 ? void 0 : knobA.classList.remove('ion-focused');
188
+ knobB === null || knobB === void 0 ? void 0 : knobB.classList.remove('ion-focused');
189
+ // Add ion-focused only to the focused knob
190
+ const focusedKnobEl = knob === 'A' ? knobA : knobB;
191
+ focusedKnobEl === null || focusedKnobEl === void 0 ? void 0 : focusedKnobEl.classList.add('ion-focused');
192
+ }
210
193
  };
211
194
  this.onKnobBlur = () => {
212
195
  // Check if focus is moving to another knob within the same range
@@ -218,18 +201,18 @@ export class Range {
218
201
  if (!isStillFocusedOnKnob) {
219
202
  if (this.hasFocus) {
220
203
  this.hasFocus = false;
221
- this.focusedKnob = undefined;
222
204
  this.ionBlur.emit();
223
205
  }
206
+ // Remove ion-focused from both knobs when focus leaves the range
207
+ if (this.dualKnobs && this.el.shadowRoot) {
208
+ const knobA = this.el.shadowRoot.querySelector('.range-knob-a');
209
+ const knobB = this.el.shadowRoot.querySelector('.range-knob-b');
210
+ knobA === null || knobA === void 0 ? void 0 : knobA.classList.remove('ion-focused');
211
+ knobB === null || knobB === void 0 ? void 0 : knobB.classList.remove('ion-focused');
212
+ }
224
213
  }
225
214
  }, 0);
226
215
  };
227
- this.onKnobMouseEnter = (knob) => {
228
- this.hoveredKnob = knob;
229
- };
230
- this.onKnobMouseLeave = () => {
231
- this.hoveredKnob = undefined;
232
- };
233
216
  }
234
217
  debounceChanged() {
235
218
  const { ionInput, debounce, originalIonInput } = this;
@@ -483,6 +466,7 @@ export class Range {
483
466
  ratio = 1 - ratio;
484
467
  }
485
468
  this.pressedKnob = !this.dualKnobs || Math.abs(this.ratioA - ratio) < Math.abs(this.ratioB - ratio) ? 'A' : 'B';
469
+ this.setFocus(this.pressedKnob);
486
470
  }
487
471
  get valA() {
488
472
  return ratioToValue(this.ratioA, this.min, this.max, this.step);
@@ -509,23 +493,9 @@ export class Range {
509
493
  updateRatio() {
510
494
  const value = this.getValue();
511
495
  const { min, max } = this;
512
- /**
513
- * For dual knobs, value gives lower/upper but not which is A vs B.
514
- * Assign (lowerRatio, upperRatio) to (ratioA, ratioB) in the way that
515
- * minimizes change from the current ratios so the knobs don't swap.
516
- */
517
496
  if (this.dualKnobs) {
518
- const lowerRatio = valueToRatio(value.lower, min, max);
519
- const upperRatio = valueToRatio(value.upper, min, max);
520
- if (Math.abs(this.ratioA - lowerRatio) + Math.abs(this.ratioB - upperRatio) <=
521
- Math.abs(this.ratioA - upperRatio) + Math.abs(this.ratioB - lowerRatio)) {
522
- this.ratioA = lowerRatio;
523
- this.ratioB = upperRatio;
524
- }
525
- else {
526
- this.ratioA = upperRatio;
527
- this.ratioB = lowerRatio;
528
- }
497
+ this.ratioA = valueToRatio(value.lower, min, max);
498
+ this.ratioB = valueToRatio(value.upper, min, max);
529
499
  }
530
500
  else {
531
501
  this.ratioA = valueToRatio(value, min, max);
@@ -542,6 +512,14 @@ export class Range {
542
512
  };
543
513
  this.noUpdate = false;
544
514
  }
515
+ setFocus(knob) {
516
+ if (this.el.shadowRoot) {
517
+ const knobEl = this.el.shadowRoot.querySelector(knob === 'A' ? '.range-knob-a' : '.range-knob-b');
518
+ if (knobEl) {
519
+ knobEl.focus();
520
+ }
521
+ }
522
+ }
545
523
  /**
546
524
  * Returns true if content was passed to the "start" slot
547
525
  */
@@ -559,7 +537,7 @@ export class Range {
559
537
  }
560
538
  renderRangeSlider() {
561
539
  var _a;
562
- const { min, max, step, handleKeyboard, focusedKnob, hoveredKnob, pressedKnob, disabled, pin, ratioLower, ratioUpper, pinFormatter, inheritedAttributes, } = this;
540
+ const { min, max, step, handleKeyboard, pressedKnob, disabled, pin, ratioLower, ratioUpper, pinFormatter, inheritedAttributes, } = this;
563
541
  let barStart = `${ratioLower * 100}%`;
564
542
  let barEnd = `${100 - ratioUpper * 100}%`;
565
543
  const rtl = isRTL(this.el);
@@ -619,9 +597,7 @@ export class Range {
619
597
  ticks.push(tick);
620
598
  }
621
599
  }
622
- return (h("div", { class: "range-slider", ref: (rangeEl) => (this.rangeSlider = rangeEl), onPointerDown: () => {
623
- this.focusFromPointer = true;
624
- },
600
+ return (h("div", { class: "range-slider", ref: (rangeEl) => (this.rangeSlider = rangeEl),
625
601
  /**
626
602
  * Since the gesture has a threshold, the value
627
603
  * won't change until the user has dragged past
@@ -634,7 +610,6 @@ export class Range {
634
610
  * we need to listen for the "pointerUp" event.
635
611
  */
636
612
  onPointerUp: (ev) => {
637
- this.focusFromPointer = false;
638
613
  /**
639
614
  * If the user drags the knob on the web
640
615
  * version (does not occur on mobile),
@@ -660,10 +635,6 @@ export class Range {
660
635
  'has-ticks': ticks.length > 0,
661
636
  }, role: "presentation", style: barStyle, part: "bar-active" })), renderKnob(rtl, {
662
637
  knob: 'A',
663
- position: this.dualKnobs ? (this.ratioA <= this.ratioB ? 'lower' : 'upper') : 'lower',
664
- dualKnobs: this.dualKnobs,
665
- focused: focusedKnob === 'A',
666
- hovered: hoveredKnob === 'A',
667
638
  pressed: pressedKnob === 'A',
668
639
  value: this.valA,
669
640
  ratio: this.ratioA,
@@ -676,15 +647,9 @@ export class Range {
676
647
  inheritedAttributes,
677
648
  onKnobFocus: this.onKnobFocus,
678
649
  onKnobBlur: this.onKnobBlur,
679
- onKnobMouseEnter: this.onKnobMouseEnter,
680
- onKnobMouseLeave: this.onKnobMouseLeave,
681
650
  }), this.dualKnobs &&
682
651
  renderKnob(rtl, {
683
652
  knob: 'B',
684
- position: this.ratioB <= this.ratioA ? 'lower' : 'upper',
685
- dualKnobs: this.dualKnobs,
686
- focused: focusedKnob === 'B',
687
- hovered: hoveredKnob === 'B',
688
653
  pressed: pressedKnob === 'B',
689
654
  value: this.valB,
690
655
  ratio: this.ratioB,
@@ -697,8 +662,6 @@ export class Range {
697
662
  inheritedAttributes,
698
663
  onKnobFocus: this.onKnobFocus,
699
664
  onKnobBlur: this.onKnobBlur,
700
- onKnobMouseEnter: this.onKnobMouseEnter,
701
- onKnobMouseLeave: this.onKnobMouseLeave,
702
665
  })));
703
666
  }
704
667
  render() {
@@ -724,11 +687,10 @@ export class Range {
724
687
  const valueAtMin = dualKnobs ? this.valA === min || this.valB === min : this.valA === min;
725
688
  const valueAtMax = dualKnobs ? this.valA === max || this.valB === max : this.valA === max;
726
689
  renderHiddenInput(true, el, this.name, JSON.stringify(this.getValue()), disabled);
727
- return (h(Host, { key: '4a393e229cf599f3377b606acaebe5f090d41f6e', onFocusin: this.onFocus, onFocusout: this.onBlur, id: rangeId, class: createColorClasses(this.color, {
690
+ return (h(Host, { key: 'ed646a42d51b8fe22012198c354cbcf5a389c108', onFocusin: this.onFocus, onFocusout: this.onBlur, id: rangeId, class: createColorClasses(this.color, {
728
691
  [mode]: true,
729
692
  'in-item': inItem,
730
693
  'range-disabled': disabled,
731
- 'range-dual-knobs': dualKnobs,
732
694
  'range-pressed': pressedKnob !== undefined,
733
695
  'range-has-pin': pin,
734
696
  [`range-label-placement-${labelPlacement}`]: true,
@@ -736,10 +698,10 @@ export class Range {
736
698
  'range-item-end-adjustment': needsEndAdjustment,
737
699
  'range-value-min': valueAtMin,
738
700
  'range-value-max': valueAtMax,
739
- }) }, h("label", { key: 'd7f45882aa7f11bbac1cb783caa0053151efcc70', class: "range-wrapper", id: "range-label" }, h("div", { key: '537d3b1e7f9fed0c8380678551e31325b1ef1f85', class: {
701
+ }) }, h("label", { key: '3083e4f2a624e3b268396acb4415f7c6ac44d851', class: "range-wrapper", id: "range-label" }, h("div", { key: '47b92f94d2a0381dd7c5cd3dda54ed2942096715', class: {
740
702
  'label-text-wrapper': true,
741
703
  'label-text-wrapper-hidden': !hasLabel,
742
- }, 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" })))));
704
+ }, 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" })))));
743
705
  }
744
706
  static get is() { return "ion-range"; }
745
707
  static get encapsulation() { return "shadow"; }
@@ -1095,8 +1057,6 @@ export class Range {
1095
1057
  return {
1096
1058
  "ratioA": {},
1097
1059
  "ratioB": {},
1098
- "focusedKnob": {},
1099
- "hoveredKnob": {},
1100
1060
  "pressedKnob": {}
1101
1061
  };
1102
1062
  }
@@ -1243,7 +1203,7 @@ export class Range {
1243
1203
  }];
1244
1204
  }
1245
1205
  }
1246
- const renderKnob = (rtl, { knob, position, dualKnobs, value, ratio, min, max, disabled, pressed, focused, hovered, pin, handleKeyboard, pinFormatter, inheritedAttributes, onKnobFocus, onKnobBlur, onKnobMouseEnter, onKnobMouseLeave, }) => {
1206
+ const renderKnob = (rtl, { knob, value, ratio, min, max, disabled, pressed, pin, handleKeyboard, pinFormatter, inheritedAttributes, onKnobFocus, onKnobBlur, }) => {
1247
1207
  const start = rtl ? 'right' : 'left';
1248
1208
  const knobStyle = () => {
1249
1209
  const style = {};
@@ -1264,50 +1224,16 @@ const renderKnob = (rtl, { knob, position, dualKnobs, value, ratio, min, max, di
1264
1224
  ev.preventDefault();
1265
1225
  ev.stopPropagation();
1266
1226
  }
1267
- }, onFocus: () => onKnobFocus(knob), onBlur: onKnobBlur, onMouseEnter: () => onKnobMouseEnter(knob), onMouseLeave: onKnobMouseLeave, class: {
1227
+ }, onFocus: () => onKnobFocus(knob), onBlur: onKnobBlur, class: {
1268
1228
  'range-knob-handle': true,
1269
- 'range-knob-handle-a': knob === 'A',
1270
- 'range-knob-handle-b': knob === 'B',
1229
+ 'range-knob-a': knob === 'A',
1230
+ 'range-knob-b': knob === 'B',
1271
1231
  'range-knob-pressed': pressed,
1272
1232
  'range-knob-min': value === min,
1273
1233
  'range-knob-max': value === max,
1274
1234
  'ion-activatable': true,
1275
1235
  'ion-focusable': true,
1276
- 'ion-focused': focused,
1277
- }, part: [
1278
- 'knob-handle',
1279
- dualKnobs && knob === 'A' && 'knob-handle-a',
1280
- dualKnobs && knob === 'B' && 'knob-handle-b',
1281
- dualKnobs && position === 'lower' && 'knob-handle-lower',
1282
- dualKnobs && position === 'upper' && 'knob-handle-upper',
1283
- pressed && 'pressed',
1284
- focused && 'focused',
1285
- hovered && 'hover',
1286
- ]
1287
- .filter(Boolean)
1288
- .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: [
1289
- 'pin',
1290
- dualKnobs && knob === 'A' && 'pin-a',
1291
- dualKnobs && knob === 'B' && 'pin-b',
1292
- dualKnobs && position === 'lower' && 'pin-lower',
1293
- dualKnobs && position === 'upper' && 'pin-upper',
1294
- pressed && 'pressed',
1295
- focused && 'focused',
1296
- hovered && 'hover',
1297
- ]
1298
- .filter(Boolean)
1299
- .join(' ') }, pinFormatter(value))), h("div", { class: "range-knob", role: "presentation", part: [
1300
- 'knob',
1301
- dualKnobs && knob === 'A' && 'knob-a',
1302
- dualKnobs && knob === 'B' && 'knob-b',
1303
- dualKnobs && position === 'lower' && 'knob-lower',
1304
- dualKnobs && position === 'upper' && 'knob-upper',
1305
- pressed && 'pressed',
1306
- focused && 'focused',
1307
- hovered && 'hover',
1308
- ]
1309
- .filter(Boolean)
1310
- .join(' ') })));
1236
+ }, 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" })));
1311
1237
  };
1312
1238
  const ratioToValue = (ratio, min, max, step) => {
1313
1239
  let value = (max - min) * ratio;
@@ -68,8 +68,8 @@ export class Refresher {
68
68
  * than `1`. The default value is `1` which is equal to the speed of the cursor.
69
69
  * If a negative value is passed in, the factor will be `1` instead.
70
70
  *
71
- * For example: If the value passed is `1.2` and the content is dragged by
72
- * `10` pixels, instead of `10` pixels the content will be pulled by `12` pixels
71
+ * For example, If the value passed is `1.2` and the content is dragged by
72
+ * `10` pixels, instead of `10` pixels, the content will be pulled by `12` pixels
73
73
  * (an increase of 20 percent). If the value passed is `0.8`, the dragged amount
74
74
  * will be `8` pixels, less than the amount the cursor has moved.
75
75
  *
@@ -119,6 +119,9 @@ export class Refresher {
119
119
  this.animations = [];
120
120
  this.progress = 0;
121
121
  this.state = 1 /* RefresherState.Inactive */;
122
+ this.ionPullEnd.emit({
123
+ reason: state === 32 /* RefresherState.Completing */ ? 'complete' : 'cancel',
124
+ });
122
125
  }
123
126
  async setupiOSNativeRefresher(pullingSpinner, refreshingSpinner) {
124
127
  this.elementToTransform = this.scrollEl;
@@ -151,6 +154,7 @@ export class Refresher {
151
154
  if (!this.didStart) {
152
155
  this.didStart = true;
153
156
  this.ionStart.emit();
157
+ this.ionPullStart.emit();
154
158
  }
155
159
  // emit "pulling" on every move
156
160
  if (this.pointerDown) {
@@ -226,6 +230,7 @@ export class Refresher {
226
230
  this.lastVelocityY = ev.velocityY;
227
231
  },
228
232
  onEnd: () => {
233
+ const hadStarted = this.didStart;
229
234
  this.pointerDown = false;
230
235
  this.didStart = false;
231
236
  if (this.needsCompletion) {
@@ -235,6 +240,13 @@ export class Refresher {
235
240
  else if (this.didRefresh) {
236
241
  readTask(() => translateElement(this.elementToTransform, `${this.el.clientHeight}px`));
237
242
  }
243
+ else if (hadStarted) {
244
+ /**
245
+ * User started pulling but released before reaching the refresh threshold.
246
+ * Emit ionPullEnd to complete the event pair.
247
+ */
248
+ this.ionPullEnd.emit({ reason: 'cancel' });
249
+ }
238
250
  },
239
251
  });
240
252
  this.disabledChanged();
@@ -281,6 +293,7 @@ export class Refresher {
281
293
  ev.data.animation = animation;
282
294
  animation.progressStart(false, 0);
283
295
  this.ionStart.emit();
296
+ this.ionPullStart.emit();
284
297
  this.animations.push(animation);
285
298
  return;
286
299
  }
@@ -303,6 +316,7 @@ export class Refresher {
303
316
  this.animations = [];
304
317
  this.gesture.enable(true);
305
318
  this.state = 1 /* RefresherState.Inactive */;
319
+ this.ionPullEnd.emit({ reason: 'cancel' });
306
320
  });
307
321
  return;
308
322
  }
@@ -547,6 +561,7 @@ export class Refresher {
547
561
  if (!this.didStart) {
548
562
  this.didStart = true;
549
563
  this.ionStart.emit();
564
+ this.ionPullStart.emit();
550
565
  }
551
566
  // emit "pulling" on every move
552
567
  this.ionPull.emit();
@@ -590,6 +605,15 @@ export class Refresher {
590
605
  * available right away.
591
606
  */
592
607
  this.restoreOverflowStyle();
608
+ /**
609
+ * If ionPullStart was emitted, we need to emit ionPullEnd
610
+ * even though the gesture was aborted before reaching the
611
+ * pulling threshold.
612
+ */
613
+ if (this.didStart) {
614
+ this.didStart = false;
615
+ this.ionPullEnd.emit({ reason: 'cancel' });
616
+ }
593
617
  }
594
618
  }
595
619
  beginRefresh() {
@@ -636,6 +660,9 @@ export class Refresher {
636
660
  if (this.contentFullscreen && this.backgroundContentEl) {
637
661
  (_a = this.backgroundContentEl) === null || _a === void 0 ? void 0 : _a.style.removeProperty('--offset-top');
638
662
  }
663
+ this.ionPullEnd.emit({
664
+ reason: state === 32 /* RefresherState.Completing */ ? 'complete' : 'cancel',
665
+ });
639
666
  }, 600);
640
667
  // reset the styles on the scroll element
641
668
  // set that the refresh is actively cancelling/completing
@@ -689,7 +716,7 @@ export class Refresher {
689
716
  }
690
717
  render() {
691
718
  const mode = getIonMode(this);
692
- return (h(Host, { key: '2d1bd880877b698604542ab2d602d38b9504d975', slot: "fixed", class: {
719
+ return (h(Host, { key: 'bed0c2f44c32ecac24b7d8326ac7c7ef1d12c44f', slot: "fixed", class: {
693
720
  [mode]: true,
694
721
  // Used internally for styling
695
722
  [`refresher-${mode}`]: true,
@@ -809,7 +836,7 @@ export class Refresher {
809
836
  "optional": false,
810
837
  "docs": {
811
838
  "tags": [],
812
- "text": "How much to multiply the pull speed by. To slow the pull animation down,\npass a number less than `1`. To speed up the pull, pass a number greater\nthan `1`. The default value is `1` which is equal to the speed of the cursor.\nIf a negative value is passed in, the factor will be `1` instead.\n\nFor example: If the value passed is `1.2` and the content is dragged by\n`10` pixels, instead of `10` pixels the content will be pulled by `12` pixels\n(an increase of 20 percent). If the value passed is `0.8`, the dragged amount\nwill be `8` pixels, less than the amount the cursor has moved.\n\nDoes not apply when the refresher content uses a spinner,\nenabling the native refresher."
839
+ "text": "How much to multiply the pull speed by. To slow the pull animation down,\npass a number less than `1`. To speed up the pull, pass a number greater\nthan `1`. The default value is `1` which is equal to the speed of the cursor.\nIf a negative value is passed in, the factor will be `1` instead.\n\nFor example, If the value passed is `1.2` and the content is dragged by\n`10` pixels, instead of `10` pixels, the content will be pulled by `12` pixels\n(an increase of 20 percent). If the value passed is `0.8`, the dragged amount\nwill be `8` pixels, less than the amount the cursor has moved.\n\nDoes not apply when the refresher content uses a spinner,\nenabling the native refresher."
813
840
  },
814
841
  "getter": false,
815
842
  "setter": false,
@@ -888,6 +915,24 @@ export class Refresher {
888
915
  "bubbles": true,
889
916
  "cancelable": true,
890
917
  "composed": true,
918
+ "docs": {
919
+ "tags": [{
920
+ "name": "deprecated",
921
+ "text": "Use `ionPullStart` instead."
922
+ }],
923
+ "text": "Emitted when the user begins to start pulling down.\nTODO(FW-7044): Remove this in a major release"
924
+ },
925
+ "complexType": {
926
+ "original": "void",
927
+ "resolved": "void",
928
+ "references": {}
929
+ }
930
+ }, {
931
+ "method": "ionPullStart",
932
+ "name": "ionPullStart",
933
+ "bubbles": true,
934
+ "cancelable": true,
935
+ "composed": true,
891
936
  "docs": {
892
937
  "tags": [],
893
938
  "text": "Emitted when the user begins to start pulling down."
@@ -897,6 +942,27 @@ export class Refresher {
897
942
  "resolved": "void",
898
943
  "references": {}
899
944
  }
945
+ }, {
946
+ "method": "ionPullEnd",
947
+ "name": "ionPullEnd",
948
+ "bubbles": true,
949
+ "cancelable": true,
950
+ "composed": true,
951
+ "docs": {
952
+ "tags": [],
953
+ "text": "Emitted when the refresher has returned to the inactive state\nafter a pull gesture. This fires whether the refresh completed\nsuccessfully or was canceled."
954
+ },
955
+ "complexType": {
956
+ "original": "RefresherPullEndEventDetail",
957
+ "resolved": "RefresherPullEndEventDetail",
958
+ "references": {
959
+ "RefresherPullEndEventDetail": {
960
+ "location": "import",
961
+ "path": "./refresher-interface",
962
+ "id": "src/components/refresher/refresher-interface.ts::RefresherPullEndEventDetail"
963
+ }
964
+ }
965
+ }
900
966
  }];
901
967
  }
902
968
  static get methods() {
@@ -572,6 +572,7 @@ export class Select {
572
572
  const mode = getIonMode(this);
573
573
  const modalOpts = Object.assign(Object.assign({}, interfaceOptions), { mode, cssClass: ['select-modal', interfaceOptions.cssClass], component: 'ion-select-modal', componentProps: {
574
574
  header: interfaceOptions.header,
575
+ cancelText: this.cancelText,
575
576
  multiple,
576
577
  value,
577
578
  options: this.createOverlaySelectOptions(this.childOpts, value),
@@ -833,7 +834,7 @@ export class Select {
833
834
  * TODO(FW-5592): Remove hasStartEndSlots condition
834
835
  */
835
836
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || isExpanded || hasStartEndSlots));
836
- return (h(Host, { key: 'd8026835993d0e6dce747098f741a06ae4e4f54d', onClick: this.onClick, class: createColorClasses(this.color, {
837
+ return (h(Host, { key: 'b7fa907f8fbc54fd63e2d07a9bb5156d94fd5057', onClick: this.onClick, class: createColorClasses(this.color, {
837
838
  [mode]: true,
838
839
  'in-item': inItem,
839
840
  'in-item-color': hostContext('ion-item.ion-color', el),
@@ -851,7 +852,7 @@ export class Select {
851
852
  [`select-justify-${justify}`]: justifyEnabled,
852
853
  [`select-shape-${shape}`]: shape !== undefined,
853
854
  [`select-label-placement-${labelPlacement}`]: true,
854
- }) }, h("label", { key: 'fcfb40209d6d07d49c7fdca4884b31abf6ac2567', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: 'f191664f2290c3890bde1156157c83a6ff17dbe2', class: "select-wrapper-inner" }, h("slot", { key: '317a28d1115b4214f291e228ce0fe6fc782e57d5', name: "start" }), h("div", { key: 'db68e18abd5ca3a1023d7c7b58bf89893ae18073', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), h("slot", { key: '4274e042267c2234a198b0f65c89477898d08130', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && h("div", { key: '2e2eb1ee2b2791e0683d9afb186fde6e938ca59c', class: "select-highlight" })), this.renderBottomContent()));
855
+ }) }, h("label", { key: '11137e6a8b0374e93923ddb5a4629972ded5f43c', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '99e3c09b5e6c2e7be493ed5834f991fffe45cfff', class: "select-wrapper-inner" }, h("slot", { key: '740f0e5a913cb0209d5acae31c33a6ed8f672dfc', name: "start" }), h("div", { key: 'b20e33c8b60915a5194948fcf8e22d7789f0b050', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), h("slot", { key: '0199f338185d5fa2cdd977bb20516746bd9ddad5', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && h("div", { key: '3b54de893cc8fc66df8588cee22e30d6f10850b3', class: "select-highlight" })), this.renderBottomContent()));
855
856
  }
856
857
  static get is() { return "ion-select"; }
857
858
  static get encapsulation() { return "shadow"; }
@@ -7,6 +7,10 @@ import { safeCall } from "../../utils/overlays";
7
7
  import { getClassMap } from "../../utils/theme";
8
8
  export class SelectModal {
9
9
  constructor() {
10
+ /**
11
+ * The text to display on the cancel button.
12
+ */
13
+ this.cancelText = 'Close';
10
14
  this.options = [];
11
15
  }
12
16
  closeModal() {
@@ -75,7 +79,7 @@ export class SelectModal {
75
79
  } }, option.text))));
76
80
  }
77
81
  render() {
78
- return (h(Host, { key: 'b6c0dec240b2e41985b15fdf4e5a6d3a145c1567', class: getIonMode(this) }, h("ion-header", { key: 'cd177e85ee0f62a60a3a708342d6ab6eb19a44dc' }, h("ion-toolbar", { key: 'aee8222a5a4daa540ad202b2e4cac1ef93d9558c' }, this.header !== undefined && h("ion-title", { key: '5f8fecc764d97bf840d3d4cfddeeccd118ab4436' }, this.header), h("ion-buttons", { key: '919033950d7c2b0101f96a9c9698219de9f568ea', slot: "end" }, h("ion-button", { key: '34b571cab6dced4bde555a077a21e91800829931', onClick: () => this.closeModal() }, "Close")))), h("ion-content", { key: '3c9153d26ba7a5a03d3b20fcd628d0c3031661a7' }, h("ion-list", { key: 'e00b222c071bc97c82ad1bba4db95a8a5c43ed6d' }, this.multiple === true ? this.renderCheckboxOptions() : this.renderRadioOptions()))));
82
+ return (h(Host, { key: '59ba79ffdbb69befe8e13745450c1071a1fe8c6c', class: getIonMode(this) }, h("ion-header", { key: 'fa4d08ee43eec4b9add09d9ffabcba9ed13dd4af' }, h("ion-toolbar", { key: 'b5e26cf092297c51c1dba3ce7963e7b03420393b' }, this.header !== undefined && h("ion-title", { key: 'a8a93cdea4d119d3a17d8cef3878b8a1daa86e26' }, this.header), h("ion-buttons", { key: 'bbc656713b41ef09099ed466f93a9cfbdaceecc1', slot: "end" }, h("ion-button", { key: '80b8751fe4c96e06b620a0b9d17b2d9b3da2faa5', onClick: () => this.closeModal() }, this.cancelText)))), h("ion-content", { key: 'a251fc00ae4cc7e6b3abe13caa10d95bb515558e' }, h("ion-list", { key: 'bcaf38d6d91accfabb4a9d26783bc0e4801abe3c' }, this.multiple === true ? this.renderCheckboxOptions() : this.renderRadioOptions()))));
79
83
  }
80
84
  static get is() { return "ion-select-modal"; }
81
85
  static get encapsulation() { return "scoped"; }
@@ -114,6 +118,26 @@ export class SelectModal {
114
118
  "reflect": false,
115
119
  "attribute": "header"
116
120
  },
121
+ "cancelText": {
122
+ "type": "string",
123
+ "mutable": false,
124
+ "complexType": {
125
+ "original": "string",
126
+ "resolved": "string",
127
+ "references": {}
128
+ },
129
+ "required": false,
130
+ "optional": false,
131
+ "docs": {
132
+ "tags": [],
133
+ "text": "The text to display on the cancel button."
134
+ },
135
+ "getter": false,
136
+ "setter": false,
137
+ "reflect": false,
138
+ "attribute": "cancel-text",
139
+ "defaultValue": "'Close'"
140
+ },
117
141
  "multiple": {
118
142
  "type": "boolean",
119
143
  "mutable": false,