@ionic/core 9.0.1-nightly.20260820 → 9.0.1-nightly.20260821

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 (73) hide show
  1. package/components/index.js +1 -1
  2. package/components/ion-action-sheet.js +1 -1
  3. package/components/ion-alert.js +1 -1
  4. package/components/ion-infinite-scroll-content.js +1 -1
  5. package/components/ion-item-sliding.js +1 -1
  6. package/components/ion-loading.js +1 -1
  7. package/components/ion-refresher-content.js +1 -1
  8. package/components/ion-refresher.js +1 -1
  9. package/components/ion-segment-button.js +1 -1
  10. package/components/ion-select-modal.js +1 -1
  11. package/components/ion-select-popover.js +1 -1
  12. package/components/ion-select.js +1 -1
  13. package/components/ion-toast.js +1 -1
  14. package/{dist/ionic/p-DgUL3JbO.js → components/p-BE48ZNam.js} +1 -1
  15. package/components/{p-CaiZOhfC.js → p-C3QTG7as.js} +1 -1
  16. package/components/{p-B6x5_b9w.js → p-CmpstNYe.js} +1 -1
  17. package/components/{p-DqAI6tg7.js → p-CrzR7nZk.js} +1 -1
  18. package/components/{p-Bnc0m4SW.js → p-DGwySvgi.js} +1 -1
  19. package/components/{p-eFI3mtEX.js → p-e8f0KKOJ.js} +1 -1
  20. package/dist/cjs/{index-EJLjthTK.js → index-D4T0SA6Q.js} +1 -0
  21. package/dist/cjs/index.cjs.js +1 -1
  22. package/dist/cjs/ion-action-sheet.cjs.entry.js +2 -2
  23. package/dist/cjs/ion-alert.cjs.entry.js +2 -2
  24. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +1 -1
  25. package/dist/cjs/ion-item-option_3.cjs.entry.js +9 -11
  26. package/dist/cjs/ion-loading.cjs.entry.js +1 -1
  27. package/dist/cjs/ion-refresher_2.cjs.entry.js +11 -4
  28. package/dist/cjs/ion-segment_2.cjs.entry.js +11 -7
  29. package/dist/cjs/ion-select-modal.cjs.entry.js +2 -2
  30. package/dist/cjs/ion-select_3.cjs.entry.js +50 -40
  31. package/dist/cjs/ion-toast.cjs.entry.js +1 -1
  32. package/dist/cjs/{select-option-render-7m1WdFzF.js → select-option-render-CgnqHkpg.js} +1 -1
  33. package/dist/collection/components/item-sliding/item-sliding.js +10 -12
  34. package/dist/collection/components/refresher/refresher.js +10 -3
  35. package/dist/collection/components/segment-button/segment-button.js +11 -7
  36. package/dist/collection/components/select/select.js +49 -39
  37. package/dist/collection/utils/test/late-props/late-props.js +69 -0
  38. package/dist/docs.json +1 -1
  39. package/dist/esm/{index-elneMH8y.js → index-D3o-MD4_.js} +1 -1
  40. package/dist/esm/index.js +1 -1
  41. package/dist/esm/ion-action-sheet.entry.js +2 -2
  42. package/dist/esm/ion-alert.entry.js +2 -2
  43. package/dist/esm/ion-infinite-scroll_2.entry.js +1 -1
  44. package/dist/esm/ion-item-option_3.entry.js +10 -12
  45. package/dist/esm/ion-loading.entry.js +1 -1
  46. package/dist/esm/ion-refresher_2.entry.js +11 -4
  47. package/dist/esm/ion-segment_2.entry.js +11 -7
  48. package/dist/esm/ion-select-modal.entry.js +2 -2
  49. package/dist/esm/ion-select_3.entry.js +50 -40
  50. package/dist/esm/ion-toast.entry.js +1 -1
  51. package/dist/esm/{select-option-render-lIuu64EV.js → select-option-render-Dv7KImop.js} +1 -1
  52. package/dist/ionic/index.esm.js +1 -1
  53. package/dist/ionic/ionic.esm.js +1 -1
  54. package/dist/ionic/{p-68507e70.entry.js → p-0a9d2de8.entry.js} +1 -1
  55. package/dist/ionic/{p-873a315a.entry.js → p-29970df5.entry.js} +1 -1
  56. package/dist/ionic/p-5b906fd6.entry.js +4 -0
  57. package/dist/ionic/{p-886d9e66.entry.js → p-8edf9c85.entry.js} +1 -1
  58. package/{components/p-CqyGR9Aq.js → dist/ionic/p-BfiwBb5h.js} +1 -1
  59. package/dist/ionic/p-a389f473.entry.js +4 -0
  60. package/dist/ionic/p-bdb4c7e5.entry.js +4 -0
  61. package/dist/ionic/{p-34b9379b.entry.js → p-c075e3e4.entry.js} +1 -1
  62. package/dist/ionic/{p-05800a02.entry.js → p-c91501b7.entry.js} +1 -1
  63. package/dist/ionic/{p-959df5f8.entry.js → p-eeabd236.entry.js} +1 -1
  64. package/dist/ionic/p-f7dd1ed9.entry.js +4 -0
  65. package/dist/ionic/{p-BZVE25Gu.js → p-fVT-pm3r.js} +1 -1
  66. package/dist/types/components/refresher/refresher.d.ts +7 -0
  67. package/hydrate/index.js +78 -59
  68. package/hydrate/index.mjs +78 -59
  69. package/package.json +1 -1
  70. package/dist/ionic/p-1d694d39.entry.js +0 -4
  71. package/dist/ionic/p-4437015c.entry.js +0 -4
  72. package/dist/ionic/p-8f464a8f.entry.js +0 -4
  73. package/dist/ionic/p-f521b13c.entry.js +0 -4
package/hydrate/index.js CHANGED
@@ -22330,19 +22330,17 @@ class ItemSliding {
22330
22330
  }
22331
22331
  }
22332
22332
  async updateOptions() {
22333
- const options = this.el.querySelectorAll('ion-item-options');
22333
+ const options = Array.from(this.el.querySelectorAll('ion-item-options'));
22334
+ /**
22335
+ * Frameworks that assign element props after inserting the element haven't set
22336
+ * `side` while `connectedCallback` runs, so reading it any earlier reports every
22337
+ * option as `end`.
22338
+ */
22339
+ await Promise.all(options.map((option) => new Promise((resolve) => componentOnReady(option, resolve))));
22334
22340
  let sides = 0;
22335
22341
  // Reset left and right options in case they were removed
22336
22342
  this.leftOptions = this.rightOptions = undefined;
22337
- for (let i = 0; i < options.length; i++) {
22338
- const item = options.item(i);
22339
- /**
22340
- * We cannot use the componentOnReady helper
22341
- * util here since we need to wait for all of these items
22342
- * to be ready before we set `this.sides` and `this.optsDirty`.
22343
- */
22344
- // eslint-disable-next-line custom-rules/no-component-on-ready-method
22345
- const option = item.componentOnReady !== undefined ? await item.componentOnReady() : item;
22343
+ for (const option of options) {
22346
22344
  const side = isEndSide(option.side ?? option.getAttribute('side')) ? 'end' : 'start';
22347
22345
  if (side === 'start') {
22348
22346
  this.leftOptions = option;
@@ -22541,7 +22539,7 @@ class ItemSliding {
22541
22539
  }
22542
22540
  render() {
22543
22541
  const mode = getIonMode$1(this);
22544
- return (hAsync(Host, { key: '15f6a98f8c888e86c29827cdf55d98ace08699dd', class: {
22542
+ return (hAsync(Host, { key: '02174ca963753d3a51a4249068f3d436f8acb03d', class: {
22545
22543
  [mode]: true,
22546
22544
  'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
22547
22545
  'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
@@ -33648,11 +33646,18 @@ class Refresher {
33648
33646
  componentDidUpdate() {
33649
33647
  this.checkNativeRefresher();
33650
33648
  }
33651
- async connectedCallback() {
33649
+ /**
33650
+ * Validate the slot attribute before rendering, while the host still reflects the
33651
+ * developer's original markup. `connectedCallback` is too early: in the custom
33652
+ * elements build it runs during insertion, before frameworks such as React assign
33653
+ * the slot.
33654
+ */
33655
+ componentWillLoad() {
33652
33656
  if (this.el.getAttribute('slot') !== 'fixed') {
33653
33657
  printIonError('[ion-refresher] - Make sure you use: <ion-refresher slot="fixed">');
33654
- return;
33655
33658
  }
33659
+ }
33660
+ async connectedCallback() {
33656
33661
  const contentEl = this.el.closest(ION_CONTENT_ELEMENT_SELECTOR);
33657
33662
  if (!contentEl) {
33658
33663
  printIonContentErrorMsg(this.el);
@@ -34012,7 +34017,7 @@ class Refresher {
34012
34017
  }
34013
34018
  render() {
34014
34019
  const mode = getIonMode$1(this);
34015
- return (hAsync(Host, { key: 'b76e9fb79121799717063137135e448a3c784d82', slot: "fixed", class: {
34020
+ return (hAsync(Host, { key: 'fd9c8e51155d56f12148e8eb547e45c05807b4b5', slot: "fixed", class: {
34016
34021
  [mode]: true,
34017
34022
  // Used internally for styling
34018
34023
  [`refresher-${mode}`]: true,
@@ -37268,11 +37273,6 @@ class SegmentButton {
37268
37273
  addEventListener$1(segmentEl, 'ionSelect', this.updateState);
37269
37274
  addEventListener$1(segmentEl, 'ionStyle', this.updateStyle);
37270
37275
  }
37271
- // Prevent buttons from being disabled when associated with segment content
37272
- if (this.contentId && this.disabled) {
37273
- printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
37274
- this.disabled = false;
37275
- }
37276
37276
  }
37277
37277
  disconnectedCallback() {
37278
37278
  const segmentEl = this.segmentEl;
@@ -37289,6 +37289,15 @@ class SegmentButton {
37289
37289
  // Return if there is no contentId defined
37290
37290
  if (!this.contentId)
37291
37291
  return;
37292
+ /**
37293
+ * Checked here rather than in `connectedCallback` so frameworks that assign element
37294
+ * props after inserting the element have set `disabled` by now. A disabled ion-segment
37295
+ * pushes that onto its buttons too, which this guard should not undo.
37296
+ */
37297
+ if (this.disabled && this.segmentEl?.disabled !== true) {
37298
+ printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
37299
+ this.disabled = false;
37300
+ }
37292
37301
  // Attempt to find the Segment Content by its contentId
37293
37302
  const segmentContent = document.getElementById(this.contentId);
37294
37303
  // If no associated Segment Content exists, log an error and return
@@ -37323,7 +37332,7 @@ class SegmentButton {
37323
37332
  const { checked, type, disabled, hasIcon, hasLabel, layout, segmentEl } = this;
37324
37333
  const mode = getIonMode$1(this);
37325
37334
  const hasSegmentColor = () => segmentEl?.color !== undefined;
37326
- return (hAsync(Host, { key: '2b4b7ad8b981d2ee39aba5b9c734de8a5bd045ba', class: {
37335
+ return (hAsync(Host, { key: 'd8acc71d87e26b32f20b2d0f9a6acc9f0dab0dee', class: {
37327
37336
  [mode]: true,
37328
37337
  'in-toolbar': hostContext('ion-toolbar', this.el),
37329
37338
  'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
@@ -37339,7 +37348,7 @@ class SegmentButton {
37339
37348
  'ion-activatable': true,
37340
37349
  'ion-activatable-instant': true,
37341
37350
  'ion-focusable': true,
37342
- } }, hAsync("button", { key: '9cc58cfbe70844a0f5e1a307002e0d04e044be99', "aria-selected": checked ? 'true' : 'false', role: "tab", ref: (el) => (this.nativeEl = el), type: type, class: "button-native", part: "native", disabled: disabled, ...this.inheritedAttributes }, hAsync("span", { key: '6443551951ce589efdb2d0e1fd1a14e35b82ed19', class: "button-inner" }, hAsync("slot", { key: 'c3548b469ae6e5477d8372cb28bc70dff3a24d18' })), mode === 'md' && hAsync("ion-ripple-effect", { key: 'fb176415ca1702766c4d7a5964ec0bb467bdcb55' })), hAsync("div", { key: 'aa22b4752f8336d0e232a1e0894e87023b284a08', part: "indicator", class: "segment-button-indicator segment-button-indicator-animated" }, hAsync("div", { key: '61e29ea52048fa0583fce6c20c81614a4d0199cb', part: "indicator-background", class: "segment-button-indicator-background" }))));
37351
+ } }, hAsync("button", { key: 'ce65da07b1a012bce353b3c6c24eecfbd4071d54', "aria-selected": checked ? 'true' : 'false', role: "tab", ref: (el) => (this.nativeEl = el), type: type, class: "button-native", part: "native", disabled: disabled, ...this.inheritedAttributes }, hAsync("span", { key: '6c4b4dcd20e407e5dc31674bea23633d8a09187a', class: "button-inner" }, hAsync("slot", { key: '817145ae77a3c5ada88ab95723d881f1bde96b2a' })), mode === 'md' && hAsync("ion-ripple-effect", { key: '054d7e5e2a13013914fac6bbde8efdb28d9b459e' })), hAsync("div", { key: 'c48074881a302510ad4752eeb9383222cd3a54cb', part: "indicator", class: "segment-button-indicator segment-button-indicator-animated" }, hAsync("div", { key: '7672a6b10ee18ad026b798fbd8207dc3cd5683f9', part: "indicator-background", class: "segment-button-indicator-background" }))));
37343
37352
  }
37344
37353
  get el() { return getElement(this); }
37345
37354
  static get watchers() { return {
@@ -38383,7 +38392,7 @@ class Select {
38383
38392
  const hasOutlineFill = mode === 'md' && fill === 'outline';
38384
38393
  renderHiddenInput(true, el, name, parseValue(value), disabled);
38385
38394
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
38386
- return (hAsync(Host, { key: '5d1e5bf46d0f204efdcb55cc42cfde52e6db304b', onClick: this.onClick, class: createColorClasses$1(this.color, {
38395
+ return (hAsync(Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: createColorClasses$1(this.color, {
38387
38396
  [mode]: true,
38388
38397
  'in-item': inItem,
38389
38398
  'in-item-color': hostContext('ion-item.ion-color', el),
@@ -38401,7 +38410,7 @@ class Select {
38401
38410
  [`select-justify-${justify}`]: justifyEnabled,
38402
38411
  [`select-shape-${shape}`]: shape !== undefined,
38403
38412
  [`select-label-placement-${labelPlacement}`]: true,
38404
- }) }, hAsync("label", { key: '15fd1f8e06510ae8472c621cf8cf90e51172e0be', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), hAsync("div", { key: '7964e3d9351671899793b117896acdda25ec24c4', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, hAsync("slot", { key: 'aa309ef155c4025acfd7ed5739b5221c85097b36', name: "start" })), hAsync("div", { key: '23d5a9dfea64a9d81b0b36d9426b15bed98901b9', class: "select-control", part: "control" }, this.renderLabel(), hAsync("div", { key: '810da9fbfa8771e09b5fb768d64e5f04858b5833', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), hAsync("div", { key: 'bf1c04704326ecfa14cf2e49bb76d3fb45beb08d', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), hAsync("slot", { key: '76a8bcaeefdcaa908aebd820d93171b08165cee3', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '55a9c417a82323a44e16328fd62a634d9d7c558b', class: "select-highlight" })), this.renderBottomContent()));
38413
+ }) }, hAsync("label", { key: '944a2eb468154a21260d181fdaf67828a71eb902', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), hAsync("div", { key: '927200c53548b1bb4f52d6a167605b724a7b7d0d', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, hAsync("slot", { key: '6e14b95e9b95c116b16744d630600e90977782bc', name: "start" })), hAsync("div", { key: '8451ed4300ac005963075be36a04ea8763bc0fdd', class: "select-control", part: "control" }, this.renderLabel(), hAsync("div", { key: '207e7b63f3224a4870579365ac992da6784fb31f', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), hAsync("div", { key: '5c17367d488db4d570f31b25e33560efa9011500', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), hAsync("slot", { key: '21fd8c0d9bee8cffef9ef6984cacd31e8f38211c', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '1fff767db9a1ec07b274ef65ff7ae8fb976e6ad2', class: "select-highlight" })), this.renderBottomContent()));
38405
38414
  }
38406
38415
  get el() { return getElement(this); }
38407
38416
  static get watchers() { return {
@@ -38510,29 +38519,14 @@ const textForValue = (opts, value, compareWith, useHTML = false) => {
38510
38519
  return getOptionContent(selectOpt, undefined, true);
38511
38520
  }
38512
38521
  /**
38513
- * When custom HTML is enabled, extract only the default slot content.
38514
- * This ensures aria-label and other text-only contexts read only
38515
- * the relevant option text.
38522
+ * Every text-only context reads only the default slot, so the start
38523
+ * and end slots stay out of the `aria-label` and the overlay labels.
38524
+ * Both config paths derive that text through the same helper, so they
38525
+ * cannot disagree about what an option's text is. `null` marks an
38526
+ * option with no text, which is dropped from the joined text of a
38527
+ * `multiple` select rather than joined in as an empty entry.
38516
38528
  */
38517
- if (customHTMLEnabled) {
38518
- const content = getOptionContent(selectOpt);
38519
- if (typeof content === 'string') {
38520
- return content;
38521
- }
38522
- /**
38523
- * Elements were found in the default slot, extract and concatenate
38524
- * their text content while trimming whitespace.
38525
- */
38526
- if (content) {
38527
- const texts = Array.from(content.childNodes)
38528
- .map((n) => n.textContent?.trim())
38529
- .filter((t) => t);
38530
- return texts.join(' ') || null;
38531
- }
38532
- // Empty option
38533
- return null;
38534
- }
38535
- return getDefaultSlotPlainText(selectOpt);
38529
+ return getDefaultSlotPlainText(selectOpt) || null;
38536
38530
  };
38537
38531
  /**
38538
38532
  * Trims whitespace from all text nodes within a DOM tree.
@@ -38588,9 +38582,13 @@ const getOptionContent = (option, slotName, useHTML = false) => {
38588
38582
  if (nodes.length === 0) {
38589
38583
  return null;
38590
38584
  }
38591
- // Return plain text if no elements are found
38585
+ /**
38586
+ * Return plain text if no elements are found. This reads the option the
38587
+ * same way the non-custom-HTML path does, so the two do not disagree
38588
+ * about what an option's text is.
38589
+ */
38592
38590
  if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
38593
- return nodes.map((n) => n.textContent?.trim()).join(' ') || null;
38591
+ return getDefaultSlotPlainText(option) || null;
38594
38592
  }
38595
38593
  /**
38596
38594
  * Mirror known custom-element properties (e.g. ion-icon's `icon`)
@@ -38646,22 +38644,43 @@ const getOptionDefaultSlot = (option) => {
38646
38644
  }
38647
38645
  return defaultSlotNodes;
38648
38646
  };
38647
+ /**
38648
+ * Concatenates the text a node renders, skipping the subtrees of tags
38649
+ * whose contents the browser never paints (`script`, `style`, and the
38650
+ * rest of `blockedTags`). `textContent` includes those, so reading it
38651
+ * directly would put stylesheet or script source into the select text
38652
+ * and the `aria-label`.
38653
+ *
38654
+ * @param node - The node to read text from.
38655
+ * @returns The node's rendered text.
38656
+ */
38657
+ const getRenderedTextContent = (node) => {
38658
+ if (node.nodeType === Node.TEXT_NODE) {
38659
+ return node.textContent ?? '';
38660
+ }
38661
+ if (node.nodeType !== Node.ELEMENT_NODE) {
38662
+ return '';
38663
+ }
38664
+ if (blockedTags.includes(node.tagName.toLowerCase())) {
38665
+ return '';
38666
+ }
38667
+ return Array.from(node.childNodes)
38668
+ .map((child) => getRenderedTextContent(child))
38669
+ .join('');
38670
+ };
38649
38671
  /**
38650
38672
  * Extracts plain text from only the default slot of an option,
38651
- * excluding content assigned to named slots (start/end).
38673
+ * excluding content assigned to named slots (start/end). Text is
38674
+ * concatenated with no separator and collapsible whitespace is
38675
+ * collapsed, approximating how the browser renders the option.
38676
+ * NBSP is not collapsible, so it is preserved.
38677
+ *
38678
+ * @param option - The `ion-select-option` element to read text from.
38679
+ * @returns The option's default slot text.
38652
38680
  */
38653
38681
  const getDefaultSlotPlainText = (option) => {
38654
- const texts = Array.from(option.childNodes)
38655
- .filter((node) => {
38656
- if (node.nodeType === Node.ELEMENT_NODE) {
38657
- return !node.hasAttribute('slot');
38658
- }
38659
- return node.nodeType === Node.TEXT_NODE;
38660
- })
38661
- .filter((node) => node.nodeType === Node.TEXT_NODE)
38662
- .map((n) => n.textContent?.trim())
38663
- .filter((t) => t);
38664
- return texts.join(' ');
38682
+ const text = (getOptionDefaultSlot(option) ?? []).map((node) => getRenderedTextContent(node)).join('');
38683
+ return text.replace(/[ \t\n\r\f]+/g, ' ').replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, '');
38665
38684
  };
38666
38685
  /**
38667
38686
  * Extracts the rich content from an `ion-select-option`.
package/hydrate/index.mjs CHANGED
@@ -22328,19 +22328,17 @@ class ItemSliding {
22328
22328
  }
22329
22329
  }
22330
22330
  async updateOptions() {
22331
- const options = this.el.querySelectorAll('ion-item-options');
22331
+ const options = Array.from(this.el.querySelectorAll('ion-item-options'));
22332
+ /**
22333
+ * Frameworks that assign element props after inserting the element haven't set
22334
+ * `side` while `connectedCallback` runs, so reading it any earlier reports every
22335
+ * option as `end`.
22336
+ */
22337
+ await Promise.all(options.map((option) => new Promise((resolve) => componentOnReady(option, resolve))));
22332
22338
  let sides = 0;
22333
22339
  // Reset left and right options in case they were removed
22334
22340
  this.leftOptions = this.rightOptions = undefined;
22335
- for (let i = 0; i < options.length; i++) {
22336
- const item = options.item(i);
22337
- /**
22338
- * We cannot use the componentOnReady helper
22339
- * util here since we need to wait for all of these items
22340
- * to be ready before we set `this.sides` and `this.optsDirty`.
22341
- */
22342
- // eslint-disable-next-line custom-rules/no-component-on-ready-method
22343
- const option = item.componentOnReady !== undefined ? await item.componentOnReady() : item;
22341
+ for (const option of options) {
22344
22342
  const side = isEndSide(option.side ?? option.getAttribute('side')) ? 'end' : 'start';
22345
22343
  if (side === 'start') {
22346
22344
  this.leftOptions = option;
@@ -22539,7 +22537,7 @@ class ItemSliding {
22539
22537
  }
22540
22538
  render() {
22541
22539
  const mode = getIonMode$1(this);
22542
- return (hAsync(Host, { key: '15f6a98f8c888e86c29827cdf55d98ace08699dd', class: {
22540
+ return (hAsync(Host, { key: '02174ca963753d3a51a4249068f3d436f8acb03d', class: {
22543
22541
  [mode]: true,
22544
22542
  'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
22545
22543
  'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
@@ -33646,11 +33644,18 @@ class Refresher {
33646
33644
  componentDidUpdate() {
33647
33645
  this.checkNativeRefresher();
33648
33646
  }
33649
- async connectedCallback() {
33647
+ /**
33648
+ * Validate the slot attribute before rendering, while the host still reflects the
33649
+ * developer's original markup. `connectedCallback` is too early: in the custom
33650
+ * elements build it runs during insertion, before frameworks such as React assign
33651
+ * the slot.
33652
+ */
33653
+ componentWillLoad() {
33650
33654
  if (this.el.getAttribute('slot') !== 'fixed') {
33651
33655
  printIonError('[ion-refresher] - Make sure you use: <ion-refresher slot="fixed">');
33652
- return;
33653
33656
  }
33657
+ }
33658
+ async connectedCallback() {
33654
33659
  const contentEl = this.el.closest(ION_CONTENT_ELEMENT_SELECTOR);
33655
33660
  if (!contentEl) {
33656
33661
  printIonContentErrorMsg(this.el);
@@ -34010,7 +34015,7 @@ class Refresher {
34010
34015
  }
34011
34016
  render() {
34012
34017
  const mode = getIonMode$1(this);
34013
- return (hAsync(Host, { key: 'b76e9fb79121799717063137135e448a3c784d82', slot: "fixed", class: {
34018
+ return (hAsync(Host, { key: 'fd9c8e51155d56f12148e8eb547e45c05807b4b5', slot: "fixed", class: {
34014
34019
  [mode]: true,
34015
34020
  // Used internally for styling
34016
34021
  [`refresher-${mode}`]: true,
@@ -37266,11 +37271,6 @@ class SegmentButton {
37266
37271
  addEventListener$1(segmentEl, 'ionSelect', this.updateState);
37267
37272
  addEventListener$1(segmentEl, 'ionStyle', this.updateStyle);
37268
37273
  }
37269
- // Prevent buttons from being disabled when associated with segment content
37270
- if (this.contentId && this.disabled) {
37271
- printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
37272
- this.disabled = false;
37273
- }
37274
37274
  }
37275
37275
  disconnectedCallback() {
37276
37276
  const segmentEl = this.segmentEl;
@@ -37287,6 +37287,15 @@ class SegmentButton {
37287
37287
  // Return if there is no contentId defined
37288
37288
  if (!this.contentId)
37289
37289
  return;
37290
+ /**
37291
+ * Checked here rather than in `connectedCallback` so frameworks that assign element
37292
+ * props after inserting the element have set `disabled` by now. A disabled ion-segment
37293
+ * pushes that onto its buttons too, which this guard should not undo.
37294
+ */
37295
+ if (this.disabled && this.segmentEl?.disabled !== true) {
37296
+ printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
37297
+ this.disabled = false;
37298
+ }
37290
37299
  // Attempt to find the Segment Content by its contentId
37291
37300
  const segmentContent = document.getElementById(this.contentId);
37292
37301
  // If no associated Segment Content exists, log an error and return
@@ -37321,7 +37330,7 @@ class SegmentButton {
37321
37330
  const { checked, type, disabled, hasIcon, hasLabel, layout, segmentEl } = this;
37322
37331
  const mode = getIonMode$1(this);
37323
37332
  const hasSegmentColor = () => segmentEl?.color !== undefined;
37324
- return (hAsync(Host, { key: '2b4b7ad8b981d2ee39aba5b9c734de8a5bd045ba', class: {
37333
+ return (hAsync(Host, { key: 'd8acc71d87e26b32f20b2d0f9a6acc9f0dab0dee', class: {
37325
37334
  [mode]: true,
37326
37335
  'in-toolbar': hostContext('ion-toolbar', this.el),
37327
37336
  'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
@@ -37337,7 +37346,7 @@ class SegmentButton {
37337
37346
  'ion-activatable': true,
37338
37347
  'ion-activatable-instant': true,
37339
37348
  'ion-focusable': true,
37340
- } }, hAsync("button", { key: '9cc58cfbe70844a0f5e1a307002e0d04e044be99', "aria-selected": checked ? 'true' : 'false', role: "tab", ref: (el) => (this.nativeEl = el), type: type, class: "button-native", part: "native", disabled: disabled, ...this.inheritedAttributes }, hAsync("span", { key: '6443551951ce589efdb2d0e1fd1a14e35b82ed19', class: "button-inner" }, hAsync("slot", { key: 'c3548b469ae6e5477d8372cb28bc70dff3a24d18' })), mode === 'md' && hAsync("ion-ripple-effect", { key: 'fb176415ca1702766c4d7a5964ec0bb467bdcb55' })), hAsync("div", { key: 'aa22b4752f8336d0e232a1e0894e87023b284a08', part: "indicator", class: "segment-button-indicator segment-button-indicator-animated" }, hAsync("div", { key: '61e29ea52048fa0583fce6c20c81614a4d0199cb', part: "indicator-background", class: "segment-button-indicator-background" }))));
37349
+ } }, hAsync("button", { key: 'ce65da07b1a012bce353b3c6c24eecfbd4071d54', "aria-selected": checked ? 'true' : 'false', role: "tab", ref: (el) => (this.nativeEl = el), type: type, class: "button-native", part: "native", disabled: disabled, ...this.inheritedAttributes }, hAsync("span", { key: '6c4b4dcd20e407e5dc31674bea23633d8a09187a', class: "button-inner" }, hAsync("slot", { key: '817145ae77a3c5ada88ab95723d881f1bde96b2a' })), mode === 'md' && hAsync("ion-ripple-effect", { key: '054d7e5e2a13013914fac6bbde8efdb28d9b459e' })), hAsync("div", { key: 'c48074881a302510ad4752eeb9383222cd3a54cb', part: "indicator", class: "segment-button-indicator segment-button-indicator-animated" }, hAsync("div", { key: '7672a6b10ee18ad026b798fbd8207dc3cd5683f9', part: "indicator-background", class: "segment-button-indicator-background" }))));
37341
37350
  }
37342
37351
  get el() { return getElement(this); }
37343
37352
  static get watchers() { return {
@@ -38381,7 +38390,7 @@ class Select {
38381
38390
  const hasOutlineFill = mode === 'md' && fill === 'outline';
38382
38391
  renderHiddenInput(true, el, name, parseValue(value), disabled);
38383
38392
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
38384
- return (hAsync(Host, { key: '5d1e5bf46d0f204efdcb55cc42cfde52e6db304b', onClick: this.onClick, class: createColorClasses$1(this.color, {
38393
+ return (hAsync(Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: createColorClasses$1(this.color, {
38385
38394
  [mode]: true,
38386
38395
  'in-item': inItem,
38387
38396
  'in-item-color': hostContext('ion-item.ion-color', el),
@@ -38399,7 +38408,7 @@ class Select {
38399
38408
  [`select-justify-${justify}`]: justifyEnabled,
38400
38409
  [`select-shape-${shape}`]: shape !== undefined,
38401
38410
  [`select-label-placement-${labelPlacement}`]: true,
38402
- }) }, hAsync("label", { key: '15fd1f8e06510ae8472c621cf8cf90e51172e0be', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), hAsync("div", { key: '7964e3d9351671899793b117896acdda25ec24c4', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, hAsync("slot", { key: 'aa309ef155c4025acfd7ed5739b5221c85097b36', name: "start" })), hAsync("div", { key: '23d5a9dfea64a9d81b0b36d9426b15bed98901b9', class: "select-control", part: "control" }, this.renderLabel(), hAsync("div", { key: '810da9fbfa8771e09b5fb768d64e5f04858b5833', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), hAsync("div", { key: 'bf1c04704326ecfa14cf2e49bb76d3fb45beb08d', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), hAsync("slot", { key: '76a8bcaeefdcaa908aebd820d93171b08165cee3', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '55a9c417a82323a44e16328fd62a634d9d7c558b', class: "select-highlight" })), this.renderBottomContent()));
38411
+ }) }, hAsync("label", { key: '944a2eb468154a21260d181fdaf67828a71eb902', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), hAsync("div", { key: '927200c53548b1bb4f52d6a167605b724a7b7d0d', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, hAsync("slot", { key: '6e14b95e9b95c116b16744d630600e90977782bc', name: "start" })), hAsync("div", { key: '8451ed4300ac005963075be36a04ea8763bc0fdd', class: "select-control", part: "control" }, this.renderLabel(), hAsync("div", { key: '207e7b63f3224a4870579365ac992da6784fb31f', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), hAsync("div", { key: '5c17367d488db4d570f31b25e33560efa9011500', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), hAsync("slot", { key: '21fd8c0d9bee8cffef9ef6984cacd31e8f38211c', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '1fff767db9a1ec07b274ef65ff7ae8fb976e6ad2', class: "select-highlight" })), this.renderBottomContent()));
38403
38412
  }
38404
38413
  get el() { return getElement(this); }
38405
38414
  static get watchers() { return {
@@ -38508,29 +38517,14 @@ const textForValue = (opts, value, compareWith, useHTML = false) => {
38508
38517
  return getOptionContent(selectOpt, undefined, true);
38509
38518
  }
38510
38519
  /**
38511
- * When custom HTML is enabled, extract only the default slot content.
38512
- * This ensures aria-label and other text-only contexts read only
38513
- * the relevant option text.
38520
+ * Every text-only context reads only the default slot, so the start
38521
+ * and end slots stay out of the `aria-label` and the overlay labels.
38522
+ * Both config paths derive that text through the same helper, so they
38523
+ * cannot disagree about what an option's text is. `null` marks an
38524
+ * option with no text, which is dropped from the joined text of a
38525
+ * `multiple` select rather than joined in as an empty entry.
38514
38526
  */
38515
- if (customHTMLEnabled) {
38516
- const content = getOptionContent(selectOpt);
38517
- if (typeof content === 'string') {
38518
- return content;
38519
- }
38520
- /**
38521
- * Elements were found in the default slot, extract and concatenate
38522
- * their text content while trimming whitespace.
38523
- */
38524
- if (content) {
38525
- const texts = Array.from(content.childNodes)
38526
- .map((n) => n.textContent?.trim())
38527
- .filter((t) => t);
38528
- return texts.join(' ') || null;
38529
- }
38530
- // Empty option
38531
- return null;
38532
- }
38533
- return getDefaultSlotPlainText(selectOpt);
38527
+ return getDefaultSlotPlainText(selectOpt) || null;
38534
38528
  };
38535
38529
  /**
38536
38530
  * Trims whitespace from all text nodes within a DOM tree.
@@ -38586,9 +38580,13 @@ const getOptionContent = (option, slotName, useHTML = false) => {
38586
38580
  if (nodes.length === 0) {
38587
38581
  return null;
38588
38582
  }
38589
- // Return plain text if no elements are found
38583
+ /**
38584
+ * Return plain text if no elements are found. This reads the option the
38585
+ * same way the non-custom-HTML path does, so the two do not disagree
38586
+ * about what an option's text is.
38587
+ */
38590
38588
  if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
38591
- return nodes.map((n) => n.textContent?.trim()).join(' ') || null;
38589
+ return getDefaultSlotPlainText(option) || null;
38592
38590
  }
38593
38591
  /**
38594
38592
  * Mirror known custom-element properties (e.g. ion-icon's `icon`)
@@ -38644,22 +38642,43 @@ const getOptionDefaultSlot = (option) => {
38644
38642
  }
38645
38643
  return defaultSlotNodes;
38646
38644
  };
38645
+ /**
38646
+ * Concatenates the text a node renders, skipping the subtrees of tags
38647
+ * whose contents the browser never paints (`script`, `style`, and the
38648
+ * rest of `blockedTags`). `textContent` includes those, so reading it
38649
+ * directly would put stylesheet or script source into the select text
38650
+ * and the `aria-label`.
38651
+ *
38652
+ * @param node - The node to read text from.
38653
+ * @returns The node's rendered text.
38654
+ */
38655
+ const getRenderedTextContent = (node) => {
38656
+ if (node.nodeType === Node.TEXT_NODE) {
38657
+ return node.textContent ?? '';
38658
+ }
38659
+ if (node.nodeType !== Node.ELEMENT_NODE) {
38660
+ return '';
38661
+ }
38662
+ if (blockedTags.includes(node.tagName.toLowerCase())) {
38663
+ return '';
38664
+ }
38665
+ return Array.from(node.childNodes)
38666
+ .map((child) => getRenderedTextContent(child))
38667
+ .join('');
38668
+ };
38647
38669
  /**
38648
38670
  * Extracts plain text from only the default slot of an option,
38649
- * excluding content assigned to named slots (start/end).
38671
+ * excluding content assigned to named slots (start/end). Text is
38672
+ * concatenated with no separator and collapsible whitespace is
38673
+ * collapsed, approximating how the browser renders the option.
38674
+ * NBSP is not collapsible, so it is preserved.
38675
+ *
38676
+ * @param option - The `ion-select-option` element to read text from.
38677
+ * @returns The option's default slot text.
38650
38678
  */
38651
38679
  const getDefaultSlotPlainText = (option) => {
38652
- const texts = Array.from(option.childNodes)
38653
- .filter((node) => {
38654
- if (node.nodeType === Node.ELEMENT_NODE) {
38655
- return !node.hasAttribute('slot');
38656
- }
38657
- return node.nodeType === Node.TEXT_NODE;
38658
- })
38659
- .filter((node) => node.nodeType === Node.TEXT_NODE)
38660
- .map((n) => n.textContent?.trim())
38661
- .filter((t) => t);
38662
- return texts.join(' ');
38680
+ const text = (getOptionDefaultSlot(option) ?? []).map((node) => getRenderedTextContent(node)).join('');
38681
+ return text.replace(/[ \t\n\r\f]+/g, ' ').replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, '');
38663
38682
  };
38664
38683
  /**
38665
38684
  * Extracts the rich content from an `ion-select-option`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ionic/core",
3
- "version": "9.0.1-nightly.20260820",
3
+ "version": "9.0.1-nightly.20260821",
4
4
  "description": "Base components for Ionic",
5
5
  "engines": {
6
6
  "node": ">= 16"
@@ -1,4 +0,0 @@
1
- /*!
2
- * (C) Ionic http://ionicframework.com - MIT License
3
- */
4
- import{w as e,r,c as s,a as i,j as t,h as n,d as o,g as a,e as h}from"./p-CKYcsw8f.js";import{g as f}from"./p-hHmYLOfE.js";import{I as l,c,p,e as d,g}from"./p-CazSodad.js";import{c as m,t as u,e as b,g as x,r as v}from"./p-RzUn7cKs.js";import{d as y,I as k}from"./p-T71k3C35.js";import{b as w}from"./p-CDBop-kz.js";import{c as j}from"./p-D0dfUysx.js";import{E as S}from"./p-DWCzVL3Y.js";import{s as Y}from"./p-BZVE25Gu.js";import{l as D,m as E}from"./p-BvabGprD.js";import{S as z}from"./p-D4RIp70E.js";import"./p-Dojwmvde.js";import"./p-CIGNaXM1.js";import"./p-ZjP4CjeZ.js";const N=e=>{const r=e.querySelector("ion-spinner"),s=r.shadowRoot.querySelector("circle"),i=e.querySelector(".spinner-arrow-container"),t=e.querySelector(".arrow-container"),n=t?t.querySelector("ion-icon"):null,o=j().duration(1e3).easing("ease-out"),a=j().addElement(i).keyframes([{offset:0,opacity:"0.3"},{offset:.45,opacity:"0.3"},{offset:.55,opacity:"1"},{offset:1,opacity:"1"}]),h=j().addElement(s).keyframes([{offset:0,strokeDasharray:"1px, 200px"},{offset:.2,strokeDasharray:"1px, 200px"},{offset:.55,strokeDasharray:"100px, 200px"},{offset:1,strokeDasharray:"100px, 200px"}]),f=j().addElement(r).keyframes([{offset:0,transform:"rotate(-90deg)"},{offset:1,transform:"rotate(210deg)"}]);if(t&&n){const e=j().addElement(t).keyframes([{offset:0,transform:"rotate(0deg)"},{offset:.3,transform:"rotate(0deg)"},{offset:.55,transform:"rotate(280deg)"},{offset:1,transform:"rotate(400deg)"}]),r=j().addElement(n).keyframes([{offset:0,transform:"translateX(2px) scale(0)"},{offset:.3,transform:"translateX(2px) scale(0)"},{offset:.55,transform:"translateX(-1.5px) scale(1)"},{offset:1,transform:"translateX(-1.5px) scale(1)"}]);o.addAnimation([e,r])}return o.addAnimation([a,h,f])},C=(r,s,i=200)=>{if(!r)return Promise.resolve();const t=u(r,i);return e((()=>{r.style.setProperty("transition",`${i}ms all ease-out`),void 0===s?r.style.removeProperty("transform"):r.style.setProperty("transform",`translate3d(0px, ${s}, 0px)`)})),t},M=()=>navigator.maxTouchPoints>0&&CSS.supports("background: -webkit-named-image(apple-pay-logo-black)"),P=async(e,r)=>{const s=e.querySelector("ion-refresher-content");if(!s)return Promise.resolve(!1);await new Promise((e=>m(s,e)));const i=e.querySelector("ion-refresher-content .refresher-pulling ion-spinner"),t=e.querySelector("ion-refresher-content .refresher-refreshing ion-spinner");return null!==i&&null!==t&&("ios"===r&&M()||"md"===r)},R=class{constructor(e){r(this,e),this.ionRefresh=s(this,"ionRefresh",7),this.ionPull=s(this,"ionPull",7),this.ionStart=s(this,"ionStart",7),this.ionPullStart=s(this,"ionPullStart",7),this.ionPullEnd=s(this,"ionPullEnd",7),this.appliedStyles=!1,this.didStart=!1,this.progress=0,this.pointerDown=!1,this.needsCompletion=!1,this.didRefresh=!1,this.contentFullscreen=!1,this.lastVelocityY=0,this.animations=[],this.nativeRefresher=!1,this.state=1,this.pullMin=60,this.pullMax=this.pullMin+60,this.closeDuration="280ms",this.snapbackDuration="280ms",this.pullFactor=1,this.disabled=!1}disabledChanged(){this.gesture&&this.gesture.enable(!this.disabled)}async checkNativeRefresher(){const e=await P(this.el,w(this));if(e&&!this.nativeRefresher){const e=this.el.closest("ion-content");this.setupNativeRefresher(e)}else e||this.destroyNativeRefresher()}destroyNativeRefresher(){this.scrollEl&&this.scrollListenerCallback&&(this.scrollEl.removeEventListener("scroll",this.scrollListenerCallback),this.scrollListenerCallback=void 0),this.nativeRefresher=!1}async resetNativeRefresher(e,r){this.state=r,"ios"===w(this)?await C(e,void 0,300):await u(this.el.querySelector(".refresher-refreshing-icon"),200),this.didRefresh=!1,this.needsCompletion=!1,this.pointerDown=!1,this.animations.forEach((e=>e.destroy())),this.animations=[],this.progress=0,this.state=1,this.ionPullEnd.emit({reason:32===r?"complete":"cancel"})}async setupiOSNativeRefresher(r,s){this.elementToTransform=this.scrollEl;const t=r.shadowRoot.querySelectorAll("svg");let n=.16*this.scrollEl.clientHeight;const o=t.length;e((()=>t.forEach((e=>e.style.setProperty("animation","none"))))),this.scrollListenerCallback=()=>{(this.pointerDown||1!==this.state)&&i((()=>{const r=this.scrollEl.scrollTop,i=this.el.clientHeight;if(r>0){if(8===this.state){const t=b(0,r/(.5*i),1);return void e((()=>{s.style.setProperty("opacity",(1-t).toString())}))}return}this.pointerDown&&(this.didStart||(this.didStart=!0,this.ionStart.emit(),this.ionPullStart.emit()),this.pointerDown&&this.ionPull.emit());const a=this.didStart?30:0,h=this.progress=b(0,(Math.abs(r)-a)/n,1);if(8===this.state||1===h){if(this.pointerDown&&(f=s,l=this.lastVelocityY,e((()=>{f.style.setProperty("--refreshing-rotation-duration",l>=1?"0.5s":"2s"),f.style.setProperty("opacity","1")}))),!this.didRefresh){this.beginRefresh(),this.didRefresh=!0,y({style:k.Light});const e=document.activeElement;void 0!==e?.blur&&e.blur(),this.pointerDown||C(this.elementToTransform,`${i}px`)}}else this.state=2,((r,s,i)=>{e((()=>{r.forEach(((e,r)=>{const t=r*(1/s),n=b(0,(i-t)/(1-t),1);e.style.setProperty("opacity",n.toString())}))}))})(t,o,h);var f,l}))},this.scrollEl.addEventListener("scroll",this.scrollListenerCallback);const{createGesture:a}=await import("./p-D0YpjgON.js");this.scrollEl&&(this.gesture=a({el:this.scrollEl,gestureName:"refresher",gesturePriority:31,direction:"y",threshold:5,onStart:()=>{this.pointerDown=!0,this.didRefresh||C(this.elementToTransform,"0px"),0===n&&(n=.16*this.scrollEl.clientHeight)},onMove:e=>{this.lastVelocityY=e.velocityY},onEnd:()=>{const e=this.didStart;this.pointerDown=!1,this.didStart=!1,this.needsCompletion?(this.resetNativeRefresher(this.elementToTransform,32),this.needsCompletion=!1):this.didRefresh?i((()=>C(this.elementToTransform,`${this.el.clientHeight}px`))):e&&this.ionPullEnd.emit({reason:"cancel"})}}),this.disabledChanged())}async setupMDNativeRefresher(r,s,i){const t=x(s).querySelector("circle"),n=this.el.querySelector("ion-refresher-content .refresher-pulling-icon"),o=x(i).querySelector("circle");null!==t&&null!==o&&e((()=>{t.style.setProperty("animation","none"),i.style.setProperty("animation-delay","-655ms"),o.style.setProperty("animation-delay","-655ms")}));const{createGesture:a}=await import("./p-D0YpjgON.js");this.scrollEl&&(this.gesture=a({el:this.scrollEl,gestureName:"refresher",gesturePriority:31,direction:"y",threshold:5,canStart:()=>8!==this.state&&32!==this.state&&0===this.scrollEl.scrollTop,onStart:e=>{this.progress=0,e.data={animation:void 0,didStart:!1,cancelled:!1}},onMove:s=>{if(s.velocityY<0&&0===this.progress&&!s.data.didStart||s.data.cancelled)s.data.cancelled=!0;else{if(!s.data.didStart){s.data.didStart=!0,this.state=2;const{scrollEl:i}=this,t=i.matches(l)?"overflow":"--overflow";e((()=>i.style.setProperty(t,"hidden")));const o=(e=>{const r=e.previousElementSibling;return null!==r&&"ION-HEADER"===r.tagName?"translate":"scale"})(r),a=((e,r,s)=>"scale"===e?((e,r)=>{const s=r.clientHeight,i=j().addElement(e).keyframes([{offset:0,transform:`scale(0) translateY(-${s}px)`},{offset:1,transform:"scale(1) translateY(100px)"}]);return N(e).addAnimation([i])})(r,s):((e,r)=>{const s=r.clientHeight,i=j().addElement(e).keyframes([{offset:0,transform:`translateY(-${s}px)`},{offset:1,transform:"translateY(100px)"}]);return N(e).addAnimation([i])})(r,s))(o,n,this.el);return s.data.animation=a,a.progressStart(!1,0),this.ionStart.emit(),this.ionPullStart.emit(),void this.animations.push(a)}this.progress=b(0,s.deltaY/180*.5,1),s.data.animation.progressStep(this.progress),this.ionPull.emit()}},onEnd:r=>{if(!r.data.didStart)return;this.gesture.enable(!1);const{scrollEl:s}=this,i=s.matches(l)?"overflow":"--overflow";if(e((()=>s.style.removeProperty(i))),this.progress<=.4)return void r.data.animation.progressEnd(0,this.progress,500).onFinish((()=>{this.animations.forEach((e=>e.destroy())),this.animations=[],this.gesture.enable(!0),this.state=1,this.ionPullEnd.emit({reason:"cancel"})}));const t=f([0,0],[0,0],[1,1],[1,1],this.progress)[0],o=(e=>j().duration(125).addElement(e).fromTo("transform","translateY(var(--ion-pulling-refresher-translate, 100px))","translateY(0px)"))(n);this.animations.push(o),e((async()=>{n.style.setProperty("--ion-pulling-refresher-translate",100*t+"px"),r.data.animation.progressEnd(),await o.play(),this.beginRefresh(),r.data.animation.destroy(),this.gesture.enable(!0)}))}}),this.disabledChanged())}async setupNativeRefresher(e){if(this.scrollListenerCallback||!e||this.nativeRefresher||!this.scrollEl)return;this.setCss(0,"",!1,""),this.nativeRefresher=!0;const r=this.el.querySelector("ion-refresher-content .refresher-pulling ion-spinner"),s=this.el.querySelector("ion-refresher-content .refresher-refreshing ion-spinner");"ios"===w(this)?this.setupiOSNativeRefresher(r,s):this.setupMDNativeRefresher(e,r,s)}componentDidUpdate(){this.checkNativeRefresher()}async connectedCallback(){if("fixed"!==this.el.getAttribute("slot"))return void t('[ion-refresher] - Make sure you use: <ion-refresher slot="fixed">');const e=this.el.closest(c);e?m(e,(async()=>{const r=d(e);if(this.scrollEl=await g(r??e),this.backgroundContentEl=await e.getBackgroundElement(),this.contentFullscreen=e.fullscreen,await P(this.el,w(this)))this.setupNativeRefresher(e);else{const{createGesture:r}=await import("./p-D0YpjgON.js");if(!e.isConnected)return;this.gesture=r({el:e,gestureName:"refresher",gesturePriority:31,direction:"y",threshold:20,passive:!1,canStart:()=>this.canStart(),onStart:()=>this.onStart(),onMove:e=>this.onMove(e),onEnd:()=>this.onEnd()}),this.disabledChanged()}})):p(this.el)}disconnectedCallback(){this.destroyNativeRefresher(),this.scrollEl=void 0,this.gesture&&(this.gesture.destroy(),this.gesture=void 0)}async complete(){this.nativeRefresher?(this.needsCompletion=!0,this.pointerDown||v((()=>v((()=>this.resetNativeRefresher(this.elementToTransform,32)))))):this.close(32,"120ms")}async cancel(){this.nativeRefresher?this.pointerDown||v((()=>v((()=>this.resetNativeRefresher(this.elementToTransform,16))))):this.close(16,"")}getProgress(){return Promise.resolve(this.progress)}canStart(){return!(!this.scrollEl||1!==this.state||this.scrollEl.scrollTop>0)}onStart(){this.progress=0,this.state=1,this.memoizeOverflowStyle(),this.contentFullscreen&&this.backgroundContentEl&&this.backgroundContentEl.style.setProperty("--offset-top","0px")}onMove(e){if(!this.scrollEl)return;const r=e.event;if(void 0!==r.touches&&r.touches.length>1)return;if(56&this.state)return;const s=Number.isNaN(this.pullFactor)||this.pullFactor<0?1:this.pullFactor,i=e.deltaY*s;if(i<=0)return this.progress=0,this.state=1,this.appliedStyles?void this.setCss(0,"",!1,""):void 0;if(1===this.state){if(this.scrollEl.scrollTop>0)return void(this.progress=0);this.state=2}if(r.cancelable&&r.preventDefault(),this.setCss(i,"0ms",!0,""),0===i)return void(this.progress=0);const t=this.pullMin;this.progress=i/t,this.didStart||(this.didStart=!0,this.ionStart.emit(),this.ionPullStart.emit()),this.ionPull.emit(),i<t?this.state=2:i>this.pullMax?this.beginRefresh():this.state=4}onEnd(){4===this.state?this.beginRefresh():2===this.state?this.cancel():1===this.state&&(this.restoreOverflowStyle(),this.didStart&&(this.didStart=!1,this.ionPullEnd.emit({reason:"cancel"})))}beginRefresh(){this.state=8,this.setCss(this.pullMin,this.snapbackDuration,!0,"");const e=document.activeElement;void 0!==e?.blur&&e.blur(),this.ionRefresh.emit({complete:this.complete.bind(this)})}close(e,r){setTimeout((()=>{this.state=1,this.progress=0,this.didStart=!1,this.setCss(0,"0ms",!1,"",!0),this.contentFullscreen&&this.backgroundContentEl&&this.backgroundContentEl?.style.removeProperty("--offset-top"),this.ionPullEnd.emit({reason:32===e?"complete":"cancel"})}),600),this.state=e,this.setCss(0,this.closeDuration,!0,r)}setCss(r,s,i,t,n=!1){this.nativeRefresher||(this.appliedStyles=r>0,e((()=>{if(this.scrollEl&&this.backgroundContentEl){const e=this.scrollEl.style,n=this.backgroundContentEl.style;e.transform=n.transform=r>0?`translateY(${r}px) translateZ(0px)`:"",e.transitionDuration=n.transitionDuration=s,e.transitionDelay=n.transitionDelay=t,e.overflow=i?"hidden":""}n&&this.restoreOverflowStyle()})))}memoizeOverflowStyle(){if(this.scrollEl){const{overflow:e,overflowX:r,overflowY:s}=this.scrollEl.style;this.overflowStyles={overflow:e??"",overflowX:r??"",overflowY:s??""}}}restoreOverflowStyle(){if(void 0!==this.overflowStyles&&void 0!==this.scrollEl){const{overflow:e,overflowX:r,overflowY:s}=this.overflowStyles;this.scrollEl.style.overflow=e,this.scrollEl.style.overflowX=r,this.scrollEl.style.overflowY=s,this.overflowStyles=void 0}}render(){const e=w(this);return n(o,{key:"b76e9fb79121799717063137135e448a3c784d82",slot:"fixed",class:{[e]:!0,[`refresher-${e}`]:!0,"refresher-native":this.nativeRefresher,"refresher-active":1!==this.state,"refresher-pulling":2===this.state,"refresher-ready":4===this.state,"refresher-refreshing":8===this.state,"refresher-cancelling":16===this.state,"refresher-completing":32===this.state}})}get el(){return a(this)}static get watchers(){return{disabled:[{disabledChanged:0}]}}};R.style={ios:"ion-refresher{top:0;display:none;position:absolute;width:100%;height:60px;pointer-events:none;z-index:-1}ion-refresher{inset-inline-start:0}ion-refresher.refresher-active{display:block}ion-refresher-content{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.refresher-pulling,.refresher-refreshing{display:none;width:100%}.refresher-pulling-icon,.refresher-refreshing-icon{-webkit-transform-origin:center;transform-origin:center;-webkit-transition:200ms;transition:200ms;font-size:30px;text-align:center}:host-context([dir=rtl]) .refresher-pulling-icon,:host-context([dir=rtl]) .refresher-refreshing-icon{-webkit-transform-origin:calc(100% - center);transform-origin:calc(100% - center)}[dir=rtl] .refresher-pulling-icon,[dir=rtl] .refresher-refreshing-icon{-webkit-transform-origin:calc(100% - center);transform-origin:calc(100% - center)}@supports selector(:dir(rtl)){.refresher-pulling-icon:dir(rtl),.refresher-refreshing-icon:dir(rtl){-webkit-transform-origin:calc(100% - center);transform-origin:calc(100% - center)}}.refresher-pulling-text,.refresher-refreshing-text{font-size:16px;text-align:center}ion-refresher-content .arrow-container{display:none}.refresher-pulling ion-refresher-content .refresher-pulling{display:block}.refresher-ready ion-refresher-content .refresher-pulling{display:block}.refresher-ready ion-refresher-content .refresher-pulling-icon{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.refresher-refreshing ion-refresher-content .refresher-refreshing{display:block}.refresher-cancelling ion-refresher-content .refresher-pulling{display:block}.refresher-cancelling ion-refresher-content .refresher-pulling-icon{-webkit-transform:scale(0);transform:scale(0)}.refresher-completing ion-refresher-content .refresher-refreshing{display:block}.refresher-completing ion-refresher-content .refresher-refreshing-icon{-webkit-transform:scale(0);transform:scale(0)}.refresher-native .refresher-pulling-text,.refresher-native .refresher-refreshing-text{display:none}.refresher-ios .refresher-pulling-icon,.refresher-ios .refresher-refreshing-icon{color:var(--ion-text-color, #000)}.refresher-ios .refresher-pulling-text,.refresher-ios .refresher-refreshing-text{color:var(--ion-text-color, #000)}.refresher-ios .refresher-refreshing .spinner-lines-ios line,.refresher-ios .refresher-refreshing .spinner-lines-small-ios line,.refresher-ios .refresher-refreshing .spinner-crescent circle{stroke:var(--ion-text-color, #000)}.refresher-ios .refresher-refreshing .spinner-bubbles circle,.refresher-ios .refresher-refreshing .spinner-circles circle,.refresher-ios .refresher-refreshing .spinner-dots circle{fill:var(--ion-text-color, #000)}ion-refresher.refresher-native{display:block;z-index:1}ion-refresher.refresher-native ion-spinner{-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;margin-top:0;margin-bottom:0}.refresher-native .refresher-refreshing ion-spinner{--refreshing-rotation-duration:2s;display:none;-webkit-animation:var(--refreshing-rotation-duration) ease-out refresher-rotate forwards;animation:var(--refreshing-rotation-duration) ease-out refresher-rotate forwards}.refresher-native .refresher-refreshing{display:none;-webkit-animation:250ms linear refresher-pop forwards;animation:250ms linear refresher-pop forwards}.refresher-native ion-spinner{width:32px;height:32px;color:var(--ion-color-step-450, var(--ion-background-color-step-450, #747577))}.refresher-native.refresher-refreshing .refresher-pulling ion-spinner,.refresher-native.refresher-completing .refresher-pulling ion-spinner{display:none}.refresher-native.refresher-refreshing .refresher-refreshing ion-spinner,.refresher-native.refresher-completing .refresher-refreshing ion-spinner{display:block}.refresher-native.refresher-pulling .refresher-pulling ion-spinner{display:block}.refresher-native.refresher-pulling .refresher-refreshing ion-spinner{display:none}.refresher-native.refresher-completing ion-refresher-content .refresher-refreshing-icon{-webkit-transform:scale(0) rotate(180deg);transform:scale(0) rotate(180deg);-webkit-transition:300ms;transition:300ms}@-webkit-keyframes refresher-pop{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}50%{-webkit-transform:scale(1.2);transform:scale(1.2);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes refresher-pop{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}50%{-webkit-transform:scale(1.2);transform:scale(1.2);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes refresher-rotate{from{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes refresher-rotate{from{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}",md:"ion-refresher{top:0;display:none;position:absolute;width:100%;height:60px;pointer-events:none;z-index:-1}ion-refresher{inset-inline-start:0}ion-refresher.refresher-active{display:block}ion-refresher-content{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.refresher-pulling,.refresher-refreshing{display:none;width:100%}.refresher-pulling-icon,.refresher-refreshing-icon{-webkit-transform-origin:center;transform-origin:center;-webkit-transition:200ms;transition:200ms;font-size:30px;text-align:center}:host-context([dir=rtl]) .refresher-pulling-icon,:host-context([dir=rtl]) .refresher-refreshing-icon{-webkit-transform-origin:calc(100% - center);transform-origin:calc(100% - center)}[dir=rtl] .refresher-pulling-icon,[dir=rtl] .refresher-refreshing-icon{-webkit-transform-origin:calc(100% - center);transform-origin:calc(100% - center)}@supports selector(:dir(rtl)){.refresher-pulling-icon:dir(rtl),.refresher-refreshing-icon:dir(rtl){-webkit-transform-origin:calc(100% - center);transform-origin:calc(100% - center)}}.refresher-pulling-text,.refresher-refreshing-text{font-size:16px;text-align:center}ion-refresher-content .arrow-container{display:none}.refresher-pulling ion-refresher-content .refresher-pulling{display:block}.refresher-ready ion-refresher-content .refresher-pulling{display:block}.refresher-ready ion-refresher-content .refresher-pulling-icon{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.refresher-refreshing ion-refresher-content .refresher-refreshing{display:block}.refresher-cancelling ion-refresher-content .refresher-pulling{display:block}.refresher-cancelling ion-refresher-content .refresher-pulling-icon{-webkit-transform:scale(0);transform:scale(0)}.refresher-completing ion-refresher-content .refresher-refreshing{display:block}.refresher-completing ion-refresher-content .refresher-refreshing-icon{-webkit-transform:scale(0);transform:scale(0)}.refresher-native .refresher-pulling-text,.refresher-native .refresher-refreshing-text{display:none}.refresher-md .refresher-pulling-icon,.refresher-md .refresher-refreshing-icon{color:var(--ion-text-color, #000)}.refresher-md .refresher-pulling-text,.refresher-md .refresher-refreshing-text{color:var(--ion-text-color, #000)}.refresher-md .refresher-refreshing .spinner-lines-md line,.refresher-md .refresher-refreshing .spinner-lines-small-md line,.refresher-md .refresher-refreshing .spinner-crescent circle{stroke:var(--ion-text-color, #000)}.refresher-md .refresher-refreshing .spinner-bubbles circle,.refresher-md .refresher-refreshing .spinner-circles circle,.refresher-md .refresher-refreshing .spinner-dots circle{fill:var(--ion-text-color, #000)}ion-refresher.refresher-native{display:block;z-index:1}ion-refresher.refresher-native ion-spinner{-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;margin-top:0;margin-bottom:0;width:24px;height:24px;color:var(--ion-color-primary, #0054e9)}ion-refresher.refresher-native .spinner-arrow-container{display:inherit}ion-refresher.refresher-native .arrow-container{display:block;position:absolute;width:24px;height:24px}ion-refresher.refresher-native .arrow-container ion-icon{-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;margin-top:0;margin-bottom:0;left:0;right:0;bottom:-4px;position:absolute;color:var(--ion-color-primary, #0054e9);font-size:12px}ion-refresher.refresher-native.refresher-pulling ion-refresher-content .refresher-pulling,ion-refresher.refresher-native.refresher-ready ion-refresher-content .refresher-pulling{display:-ms-flexbox;display:flex}ion-refresher.refresher-native.refresher-refreshing ion-refresher-content .refresher-refreshing,ion-refresher.refresher-native.refresher-completing ion-refresher-content .refresher-refreshing,ion-refresher.refresher-native.refresher-cancelling ion-refresher-content .refresher-refreshing{display:-ms-flexbox;display:flex}ion-refresher.refresher-native .refresher-pulling-icon{-webkit-transform:translateY(calc(-100% - 10px));transform:translateY(calc(-100% - 10px))}ion-refresher.refresher-native .refresher-pulling-icon,ion-refresher.refresher-native .refresher-refreshing-icon{-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;margin-top:0;margin-bottom:0;border-radius:100%;-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:8px;padding-inline-end:8px;padding-top:8px;padding-bottom:8px;display:-ms-flexbox;display:flex;border:1px solid var(--ion-color-step-200, var(--ion-background-color-step-200, #ececec));background:var(--ion-color-step-250, var(--ion-background-color-step-250, #ffffff));-webkit-box-shadow:0px 1px 6px rgba(0, 0, 0, 0.1);box-shadow:0px 1px 6px rgba(0, 0, 0, 0.1)}"};const T=class{constructor(e){r(this,e),this.customHTMLEnabled=h.get("innerHTMLTemplatesEnabled",S)}componentWillLoad(){if(void 0===this.pullingIcon){const e=M(),r=w(this);this.pullingIcon=h.get("refreshingIcon","ios"===r&&e?h.get("spinner",e?"lines":D):"circular")}if(void 0===this.refreshingSpinner){const e=w(this);this.refreshingSpinner=h.get("refreshingSpinner",h.get("spinner","ios"===e?"lines":"circular"))}}renderPullingText(){const{customHTMLEnabled:e,pullingText:r}=this;return e?n("div",{class:"refresher-pulling-text",innerHTML:Y(r)}):n("div",{class:"refresher-pulling-text"},r)}renderRefreshingText(){const{customHTMLEnabled:e,refreshingText:r}=this;return e?n("div",{class:"refresher-refreshing-text",innerHTML:Y(r)}):n("div",{class:"refresher-refreshing-text"},r)}render(){const e=this.pullingIcon,r=null!=e&&void 0!==z[e],s=w(this);return n(o,{key:"a1546008813bbcfa70f97e9b9025846ee0aed722",class:s},n("div",{key:"5422771d67fe201e22d4f9d7db6b685f3db5d99d",class:"refresher-pulling"},this.pullingIcon&&r&&n("div",{key:"5c2b6dfc3f01b42586ea83380548d454b220a7ca",class:"refresher-pulling-icon"},n("div",{key:"2c3799ca3f66960d7081c63c5a0840951f694baf",class:"spinner-arrow-container"},n("ion-spinner",{key:"03f766a9b9354dcb8f6975757a9b882c2eb5cf4a",name:this.pullingIcon,paused:!0}),"md"===s&&"circular"===this.pullingIcon&&n("div",{key:"e5f4ba7c6a70adb71f8985af0e23aca07d7b005a",class:"arrow-container"},n("ion-icon",{key:"ddccbd9164ae8daa97178fc53b52f74f1fd298ef",icon:E,"aria-hidden":"true"})))),this.pullingIcon&&!r&&n("div",{key:"6fb742f47f9149fa6dc3daefe5aaa77f925da4bd",class:"refresher-pulling-icon"},n("ion-icon",{key:"907657135eeac4c394be1eae4a659664a7bfacb0",icon:this.pullingIcon,lazy:!1,"aria-hidden":"true"})),void 0!==this.pullingText&&this.renderPullingText()),n("div",{key:"fb3094b3ed7e100ab9641c3221770889088e27f3",class:"refresher-refreshing"},this.refreshingSpinner&&n("div",{key:"bc8078f94e7cea3cb6f03a09e98540f0e0b38721",class:"refresher-refreshing-icon"},n("ion-spinner",{key:"8f39524f073aa828e941bcdd4d48e4d5dfc759c6",name:this.refreshingSpinner})),void 0!==this.refreshingText&&this.renderRefreshingText()))}get el(){return a(this)}};export{R as ion_refresher,T as ion_refresher_content}