@ionic/core 9.0.1-dev.11787248963.10a00c73 → 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 (56) 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-loading.js +1 -1
  6. package/components/ion-refresher-content.js +1 -1
  7. package/components/ion-select-modal.js +1 -1
  8. package/components/ion-select-popover.js +1 -1
  9. package/components/ion-select.js +1 -1
  10. package/components/ion-toast.js +1 -1
  11. package/{dist/ionic/p-DgUL3JbO.js → components/p-BE48ZNam.js} +1 -1
  12. package/components/{p-CaiZOhfC.js → p-C3QTG7as.js} +1 -1
  13. package/components/{p-B6x5_b9w.js → p-CmpstNYe.js} +1 -1
  14. package/components/{p-DqAI6tg7.js → p-CrzR7nZk.js} +1 -1
  15. package/components/{p-Bnc0m4SW.js → p-DGwySvgi.js} +1 -1
  16. package/components/{p-eFI3mtEX.js → p-e8f0KKOJ.js} +1 -1
  17. package/dist/cjs/{index-EJLjthTK.js → index-D4T0SA6Q.js} +1 -0
  18. package/dist/cjs/index.cjs.js +1 -1
  19. package/dist/cjs/ion-action-sheet.cjs.entry.js +2 -2
  20. package/dist/cjs/ion-alert.cjs.entry.js +2 -2
  21. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +1 -1
  22. package/dist/cjs/ion-loading.cjs.entry.js +1 -1
  23. package/dist/cjs/ion-refresher_2.cjs.entry.js +1 -1
  24. package/dist/cjs/ion-select-modal.cjs.entry.js +2 -2
  25. package/dist/cjs/ion-select_3.cjs.entry.js +50 -40
  26. package/dist/cjs/ion-toast.cjs.entry.js +1 -1
  27. package/dist/cjs/{select-option-render-7m1WdFzF.js → select-option-render-CgnqHkpg.js} +1 -1
  28. package/dist/collection/components/select/select.js +49 -39
  29. package/dist/docs.json +1 -1
  30. package/dist/esm/{index-elneMH8y.js → index-D3o-MD4_.js} +1 -1
  31. package/dist/esm/index.js +1 -1
  32. package/dist/esm/ion-action-sheet.entry.js +2 -2
  33. package/dist/esm/ion-alert.entry.js +2 -2
  34. package/dist/esm/ion-infinite-scroll_2.entry.js +1 -1
  35. package/dist/esm/ion-loading.entry.js +1 -1
  36. package/dist/esm/ion-refresher_2.entry.js +1 -1
  37. package/dist/esm/ion-select-modal.entry.js +2 -2
  38. package/dist/esm/ion-select_3.entry.js +50 -40
  39. package/dist/esm/ion-toast.entry.js +1 -1
  40. package/dist/esm/{select-option-render-lIuu64EV.js → select-option-render-Dv7KImop.js} +1 -1
  41. package/dist/ionic/index.esm.js +1 -1
  42. package/dist/ionic/ionic.esm.js +1 -1
  43. package/dist/ionic/{p-68507e70.entry.js → p-0a9d2de8.entry.js} +1 -1
  44. package/dist/ionic/{p-873a315a.entry.js → p-29970df5.entry.js} +1 -1
  45. package/dist/ionic/{p-886d9e66.entry.js → p-8edf9c85.entry.js} +1 -1
  46. package/{components/p-CqyGR9Aq.js → dist/ionic/p-BfiwBb5h.js} +1 -1
  47. package/dist/ionic/p-a389f473.entry.js +4 -0
  48. package/dist/ionic/{p-8dd4c026.entry.js → p-bdb4c7e5.entry.js} +1 -1
  49. package/dist/ionic/{p-34b9379b.entry.js → p-c075e3e4.entry.js} +1 -1
  50. package/dist/ionic/{p-05800a02.entry.js → p-c91501b7.entry.js} +1 -1
  51. package/dist/ionic/{p-959df5f8.entry.js → p-eeabd236.entry.js} +1 -1
  52. package/dist/ionic/{p-BZVE25Gu.js → p-fVT-pm3r.js} +1 -1
  53. package/hydrate/index.js +48 -38
  54. package/hydrate/index.mjs +48 -38
  55. package/package.json +1 -1
  56. package/dist/ionic/p-4437015c.entry.js +0 -4
@@ -8,7 +8,7 @@ var buttonActive = require('./button-active-BlWSD7uK.js');
8
8
  var helpers = require('./helpers-Dj5o76mq.js');
9
9
  var lockController = require('./lock-controller-aDB9wrEf.js');
10
10
  var overlays = require('./overlays-Bg0auTQa.js');
11
- var selectOptionRender = require('./select-option-render-7m1WdFzF.js');
11
+ var selectOptionRender = require('./select-option-render-CgnqHkpg.js');
12
12
  var theme = require('./theme-Bw0rpaNN.js');
13
13
  var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
14
14
  var animation = require('./animation-D-OqR4a4.js');
@@ -20,7 +20,7 @@ require('./gesture-controller-CeJslptU.js');
20
20
  require('./dir-zwDPRE5K.js');
21
21
  require('./hardware-back-button-JOAEFSzc.js');
22
22
  require('./framework-delegate-BZUx4TnE.js');
23
- require('./index-EJLjthTK.js');
23
+ require('./index-D4T0SA6Q.js');
24
24
 
25
25
  /**
26
26
  * iOS Action Sheet Enter Animation
@@ -10,8 +10,8 @@ var helpers = require('./helpers-Dj5o76mq.js');
10
10
  var lockController = require('./lock-controller-aDB9wrEf.js');
11
11
  var overlayControlLabel = require('./overlay-control-label-D2sdL2O8.js');
12
12
  var overlays = require('./overlays-Bg0auTQa.js');
13
- var index$1 = require('./index-EJLjthTK.js');
14
- var selectOptionRender = require('./select-option-render-7m1WdFzF.js');
13
+ var index$1 = require('./index-D4T0SA6Q.js');
14
+ var selectOptionRender = require('./select-option-render-CgnqHkpg.js');
15
15
  var theme = require('./theme-Bw0rpaNN.js');
16
16
  var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
17
17
  var animation = require('./animation-D-OqR4a4.js');
@@ -7,7 +7,7 @@ var index = require('./index-BrVMoqUk.js');
7
7
  var index$1 = require('./index-C8zH6b3d.js');
8
8
  var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
9
9
  var config = require('./config-CjUbvdPW.js');
10
- var index$2 = require('./index-EJLjthTK.js');
10
+ var index$2 = require('./index-D4T0SA6Q.js');
11
11
  require('./helpers-Dj5o76mq.js');
12
12
  require('./dir-zwDPRE5K.js');
13
13
 
@@ -8,7 +8,7 @@ var config = require('./config-CjUbvdPW.js');
8
8
  var helpers = require('./helpers-Dj5o76mq.js');
9
9
  var lockController = require('./lock-controller-aDB9wrEf.js');
10
10
  var overlays = require('./overlays-Bg0auTQa.js');
11
- var index$1 = require('./index-EJLjthTK.js');
11
+ var index$1 = require('./index-D4T0SA6Q.js');
12
12
  var theme = require('./theme-Bw0rpaNN.js');
13
13
  var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
14
14
  var animation = require('./animation-D-OqR4a4.js');
@@ -11,7 +11,7 @@ var haptic = require('./haptic-Ch-X4gRx.js');
11
11
  var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
12
12
  var animation = require('./animation-D-OqR4a4.js');
13
13
  var config = require('./config-CjUbvdPW.js');
14
- var index$3 = require('./index-EJLjthTK.js');
14
+ var index$3 = require('./index-D4T0SA6Q.js');
15
15
  var index$2 = require('./index-wOmugbdg.js');
16
16
  var spinnerConfigs = require('./spinner-configs-DxHKnd3-.js');
17
17
  require('./dir-zwDPRE5K.js');
@@ -7,7 +7,7 @@ var index = require('./index-BrVMoqUk.js');
7
7
  var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
8
8
  var overlayControlLabel = require('./overlay-control-label-D2sdL2O8.js');
9
9
  var overlays = require('./overlays-Bg0auTQa.js');
10
- var selectOptionRender = require('./select-option-render-7m1WdFzF.js');
10
+ var selectOptionRender = require('./select-option-render-CgnqHkpg.js');
11
11
  var theme = require('./theme-Bw0rpaNN.js');
12
12
  require('./index-DkNv4J_i.js');
13
13
  require('./helpers-Dj5o76mq.js');
@@ -15,7 +15,7 @@ require('./dir-zwDPRE5K.js');
15
15
  require('./hardware-back-button-JOAEFSzc.js');
16
16
  require('./framework-delegate-BZUx4TnE.js');
17
17
  require('./gesture-controller-CeJslptU.js');
18
- require('./index-EJLjthTK.js');
18
+ require('./index-D4T0SA6Q.js');
19
19
 
20
20
  const ionicSelectModalMdCss = () => `.action-sheet-button-label-has-rich-content.sc-ion-select-modal-ionic,.alert-radio-label-has-rich-content.sc-ion-select-modal-ionic,.alert-checkbox-label-has-rich-content.sc-ion-select-modal-ionic,.select-option-label-has-rich-content.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:16px}.action-sheet-button-label-has-rich-content.sc-ion-select-modal-ionic,.alert-radio-label-has-rich-content.sc-ion-select-modal-ionic,.alert-checkbox-label-has-rich-content.sc-ion-select-modal-ionic,.select-option-content.sc-ion-select-modal-ionic{-ms-flex:1;flex:1}.action-sheet-button-label-text.sc-ion-select-modal-ionic,.alert-checkbox-label-text.sc-ion-select-modal-ionic,.alert-radio-label-text.sc-ion-select-modal-ionic,.select-option-label-text.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:12px}.select-option-start.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:8px}.select-option-description.sc-ion-select-modal-ionic{padding-left:0;padding-right:0;padding-top:5px;padding-bottom:0;display:block;color:var(--ion-color-step-700, var(--ion-text-color-step-300, #4d4d4d));font-size:0.75rem}.select-option-label.sc-ion-select-modal-ionic:not(.select-option-label-has-rich-content){text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.select-option-label-has-rich-content.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}ion-radio.select-option-has-rich-content.sc-ion-select-modal-ionic::part(label),ion-radio.select-option-has-rich-content.sc-ion-select-modal-ionic [part~="label"],ion-checkbox.select-option-has-rich-content.sc-ion-select-modal-ionic::part(label),ion-checkbox.select-option-has-rich-content.sc-ion-select-modal-ionic [part~="label"],.select-option-content.sc-ion-select-modal-ionic{-ms-flex:1;flex:1;white-space:normal}.select-option-start.sc-ion-select-modal-ionic>ion-avatar.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-avatar.sc-ion-select-modal-ionic{width:40px;height:40px}.select-option-start.sc-ion-select-modal-ionic>ion-icon.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-icon.sc-ion-select-modal-ionic{font-size:24px}.select-option-start.sc-ion-select-modal-ionic>ion-img.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>img.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>svg.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>ion-thumbnail.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-img.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>img.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>svg.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-thumbnail.sc-ion-select-modal-ionic{width:56px;height:56px}.select-option-start.sc-ion-select-modal-ionic>video.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>video.sc-ion-select-modal-ionic{width:114px;height:56px}.sc-ion-select-modal-ionic-h{height:100%}ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic::part(container),ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic [part~="container"]{display:none}ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic::part(label),ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic [part~="label"]{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0}ion-item.sc-ion-select-modal-ionic{--inner-border-width:0}.item-radio-checked.sc-ion-select-modal-ionic{--background:rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.08);--background-focused:var(--ion-color-primary, #0054e9);--background-focused-opacity:0.2;--background-hover:var(--ion-color-primary, #0054e9);--background-hover-opacity:0.12}.item-checkbox-checked.sc-ion-select-modal-ionic{--background-activated:var(--ion-item-color, var(--ion-text-color, #000));--background-focused:var(--ion-item-color, var(--ion-text-color, #000));--background-hover:var(--ion-item-color, var(--ion-text-color, #000));--color:var(--ion-color-primary, #0054e9)}`;
21
21
 
@@ -11,13 +11,13 @@ var validity = require('./validity-BpS37YFM.js');
11
11
  var helpers = require('./helpers-Dj5o76mq.js');
12
12
  var overlays = require('./overlays-Bg0auTQa.js');
13
13
  var dir = require('./dir-zwDPRE5K.js');
14
- var index$2 = require('./index-EJLjthTK.js');
14
+ var index$2 = require('./index-D4T0SA6Q.js');
15
15
  var theme = require('./theme-Bw0rpaNN.js');
16
16
  var watchOptions = require('./watch-options-CviOsrTS.js');
17
17
  var index$1 = require('./index-wOmugbdg.js');
18
18
  var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
19
19
  var overlayControlLabel = require('./overlay-control-label-D2sdL2O8.js');
20
- var selectOptionRender = require('./select-option-render-7m1WdFzF.js');
20
+ var selectOptionRender = require('./select-option-render-CgnqHkpg.js');
21
21
  require('./index-DkNv4J_i.js');
22
22
  require('./hardware-back-button-JOAEFSzc.js');
23
23
  require('./framework-delegate-BZUx4TnE.js');
@@ -906,7 +906,7 @@ const Select = class {
906
906
  const hasOutlineFill = mode === 'md' && fill === 'outline';
907
907
  helpers.renderHiddenInput(true, el, name, parseValue(value), disabled);
908
908
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
909
- return (index.h(index.Host, { key: '5d1e5bf46d0f204efdcb55cc42cfde52e6db304b', onClick: this.onClick, class: theme.createColorClasses(this.color, {
909
+ return (index.h(index.Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: theme.createColorClasses(this.color, {
910
910
  [mode]: true,
911
911
  'in-item': inItem,
912
912
  'in-item-color': theme.hostContext('ion-item.ion-color', el),
@@ -924,7 +924,7 @@ const Select = class {
924
924
  [`select-justify-${justify}`]: justifyEnabled,
925
925
  [`select-shape-${shape}`]: shape !== undefined,
926
926
  [`select-label-placement-${labelPlacement}`]: true,
927
- }) }, index.h("label", { key: '15fd1f8e06510ae8472c621cf8cf90e51172e0be', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), index.h("div", { key: '7964e3d9351671899793b117896acdda25ec24c4', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, index.h("slot", { key: 'aa309ef155c4025acfd7ed5739b5221c85097b36', name: "start" })), index.h("div", { key: '23d5a9dfea64a9d81b0b36d9426b15bed98901b9', class: "select-control", part: "control" }, this.renderLabel(), index.h("div", { key: '810da9fbfa8771e09b5fb768d64e5f04858b5833', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), index.h("div", { key: 'bf1c04704326ecfa14cf2e49bb76d3fb45beb08d', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), index.h("slot", { key: '76a8bcaeefdcaa908aebd820d93171b08165cee3', name: "end" })), shouldRenderHighlight && index.h("div", { key: '55a9c417a82323a44e16328fd62a634d9d7c558b', class: "select-highlight" })), this.renderBottomContent()));
927
+ }) }, index.h("label", { key: '944a2eb468154a21260d181fdaf67828a71eb902', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), index.h("div", { key: '927200c53548b1bb4f52d6a167605b724a7b7d0d', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, index.h("slot", { key: '6e14b95e9b95c116b16744d630600e90977782bc', name: "start" })), index.h("div", { key: '8451ed4300ac005963075be36a04ea8763bc0fdd', class: "select-control", part: "control" }, this.renderLabel(), index.h("div", { key: '207e7b63f3224a4870579365ac992da6784fb31f', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), index.h("div", { key: '5c17367d488db4d570f31b25e33560efa9011500', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), index.h("slot", { key: '21fd8c0d9bee8cffef9ef6984cacd31e8f38211c', name: "end" })), shouldRenderHighlight && index.h("div", { key: '1fff767db9a1ec07b274ef65ff7ae8fb976e6ad2', class: "select-highlight" })), this.renderBottomContent()));
928
928
  }
929
929
  get el() { return index.getElement(this); }
930
930
  static get watchers() { return {
@@ -993,29 +993,14 @@ const textForValue = (opts, value, compareWith, useHTML = false) => {
993
993
  return getOptionContent(selectOpt, undefined, true);
994
994
  }
995
995
  /**
996
- * When custom HTML is enabled, extract only the default slot content.
997
- * This ensures aria-label and other text-only contexts read only
998
- * the relevant option text.
996
+ * Every text-only context reads only the default slot, so the start
997
+ * and end slots stay out of the `aria-label` and the overlay labels.
998
+ * Both config paths derive that text through the same helper, so they
999
+ * cannot disagree about what an option's text is. `null` marks an
1000
+ * option with no text, which is dropped from the joined text of a
1001
+ * `multiple` select rather than joined in as an empty entry.
999
1002
  */
1000
- if (customHTMLEnabled) {
1001
- const content = getOptionContent(selectOpt);
1002
- if (typeof content === 'string') {
1003
- return content;
1004
- }
1005
- /**
1006
- * Elements were found in the default slot, extract and concatenate
1007
- * their text content while trimming whitespace.
1008
- */
1009
- if (content) {
1010
- const texts = Array.from(content.childNodes)
1011
- .map((n) => n.textContent?.trim())
1012
- .filter((t) => t);
1013
- return texts.join(' ') || null;
1014
- }
1015
- // Empty option
1016
- return null;
1017
- }
1018
- return getDefaultSlotPlainText(selectOpt);
1003
+ return getDefaultSlotPlainText(selectOpt) || null;
1019
1004
  };
1020
1005
  /**
1021
1006
  * Trims whitespace from all text nodes within a DOM tree.
@@ -1071,9 +1056,13 @@ const getOptionContent = (option, slotName, useHTML = false) => {
1071
1056
  if (nodes.length === 0) {
1072
1057
  return null;
1073
1058
  }
1074
- // Return plain text if no elements are found
1059
+ /**
1060
+ * Return plain text if no elements are found. This reads the option the
1061
+ * same way the non-custom-HTML path does, so the two do not disagree
1062
+ * about what an option's text is.
1063
+ */
1075
1064
  if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
1076
- return nodes.map((n) => n.textContent?.trim()).join(' ') || null;
1065
+ return getDefaultSlotPlainText(option) || null;
1077
1066
  }
1078
1067
  /**
1079
1068
  * Mirror known custom-element properties (e.g. ion-icon's `icon`)
@@ -1129,22 +1118,43 @@ const getOptionDefaultSlot = (option) => {
1129
1118
  }
1130
1119
  return defaultSlotNodes;
1131
1120
  };
1121
+ /**
1122
+ * Concatenates the text a node renders, skipping the subtrees of tags
1123
+ * whose contents the browser never paints (`script`, `style`, and the
1124
+ * rest of `blockedTags`). `textContent` includes those, so reading it
1125
+ * directly would put stylesheet or script source into the select text
1126
+ * and the `aria-label`.
1127
+ *
1128
+ * @param node - The node to read text from.
1129
+ * @returns The node's rendered text.
1130
+ */
1131
+ const getRenderedTextContent = (node) => {
1132
+ if (node.nodeType === Node.TEXT_NODE) {
1133
+ return node.textContent ?? '';
1134
+ }
1135
+ if (node.nodeType !== Node.ELEMENT_NODE) {
1136
+ return '';
1137
+ }
1138
+ if (index$2.blockedTags.includes(node.tagName.toLowerCase())) {
1139
+ return '';
1140
+ }
1141
+ return Array.from(node.childNodes)
1142
+ .map((child) => getRenderedTextContent(child))
1143
+ .join('');
1144
+ };
1132
1145
  /**
1133
1146
  * Extracts plain text from only the default slot of an option,
1134
- * excluding content assigned to named slots (start/end).
1147
+ * excluding content assigned to named slots (start/end). Text is
1148
+ * concatenated with no separator and collapsible whitespace is
1149
+ * collapsed, approximating how the browser renders the option.
1150
+ * NBSP is not collapsible, so it is preserved.
1151
+ *
1152
+ * @param option - The `ion-select-option` element to read text from.
1153
+ * @returns The option's default slot text.
1135
1154
  */
1136
1155
  const getDefaultSlotPlainText = (option) => {
1137
- const texts = Array.from(option.childNodes)
1138
- .filter((node) => {
1139
- if (node.nodeType === Node.ELEMENT_NODE) {
1140
- return !node.hasAttribute('slot');
1141
- }
1142
- return node.nodeType === Node.TEXT_NODE;
1143
- })
1144
- .filter((node) => node.nodeType === Node.TEXT_NODE)
1145
- .map((n) => n.textContent?.trim())
1146
- .filter((t) => t);
1147
- return texts.join(' ');
1156
+ const text = (getOptionDefaultSlot(option) ?? []).map((node) => getRenderedTextContent(node)).join('');
1157
+ return text.replace(/[ \t\n\r\f]+/g, ' ').replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, '');
1148
1158
  };
1149
1159
  /**
1150
1160
  * Extracts the rich content from an `ion-select-option`.
@@ -8,7 +8,7 @@ var config = require('./config-CjUbvdPW.js');
8
8
  var helpers = require('./helpers-Dj5o76mq.js');
9
9
  var lockController = require('./lock-controller-aDB9wrEf.js');
10
10
  var overlays = require('./overlays-Bg0auTQa.js');
11
- var index$3 = require('./index-EJLjthTK.js');
11
+ var index$3 = require('./index-D4T0SA6Q.js');
12
12
  var theme = require('./theme-Bw0rpaNN.js');
13
13
  var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
14
14
  var animation = require('./animation-D-OqR4a4.js');
@@ -4,7 +4,7 @@
4
4
  'use strict';
5
5
 
6
6
  var index = require('./index-BrVMoqUk.js');
7
- var index$1 = require('./index-EJLjthTK.js');
7
+ var index$1 = require('./index-D4T0SA6Q.js');
8
8
 
9
9
  /**
10
10
  * Converts a DOM node into a Stencil VNode (or text string) so the
@@ -8,7 +8,7 @@ import { focusVisibleElement, renderHiddenInput, inheritAttributes } from "../..
8
8
  import { printIonWarning } from "../../utils/logging/index";
9
9
  import { actionSheetController, alertController, popoverController, modalController } from "../../utils/overlays";
10
10
  import { isRTL } from "../../utils/rtl/index";
11
- import { reflectPropertiesToAttributes, sanitizeDOMTree } from "../../utils/sanitization/index";
11
+ import { blockedTags, reflectPropertiesToAttributes, sanitizeDOMTree } from "../../utils/sanitization/index";
12
12
  import { createSlotMutationController } from "../../utils/slot-mutation-controller";
13
13
  import { createColorClasses, hostContext } from "../../utils/theme";
14
14
  import { watchForOptions } from "../../utils/watch-options";
@@ -947,7 +947,7 @@ export class Select {
947
947
  const hasOutlineFill = mode === 'md' && fill === 'outline';
948
948
  renderHiddenInput(true, el, name, parseValue(value), disabled);
949
949
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
950
- return (h(Host, { key: '5d1e5bf46d0f204efdcb55cc42cfde52e6db304b', onClick: this.onClick, class: createColorClasses(this.color, {
950
+ return (h(Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: createColorClasses(this.color, {
951
951
  [mode]: true,
952
952
  'in-item': inItem,
953
953
  'in-item-color': hostContext('ion-item.ion-color', el),
@@ -965,7 +965,7 @@ export class Select {
965
965
  [`select-justify-${justify}`]: justifyEnabled,
966
966
  [`select-shape-${shape}`]: shape !== undefined,
967
967
  [`select-label-placement-${labelPlacement}`]: true,
968
- }) }, h("label", { key: '15fd1f8e06510ae8472c621cf8cf90e51172e0be', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), h("div", { key: '7964e3d9351671899793b117896acdda25ec24c4', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, h("slot", { key: 'aa309ef155c4025acfd7ed5739b5221c85097b36', name: "start" })), h("div", { key: '23d5a9dfea64a9d81b0b36d9426b15bed98901b9', class: "select-control", part: "control" }, this.renderLabel(), h("div", { key: '810da9fbfa8771e09b5fb768d64e5f04858b5833', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), h("div", { key: 'bf1c04704326ecfa14cf2e49bb76d3fb45beb08d', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), h("slot", { key: '76a8bcaeefdcaa908aebd820d93171b08165cee3', name: "end" })), shouldRenderHighlight && h("div", { key: '55a9c417a82323a44e16328fd62a634d9d7c558b', class: "select-highlight" })), this.renderBottomContent()));
968
+ }) }, h("label", { key: '944a2eb468154a21260d181fdaf67828a71eb902', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), h("div", { key: '927200c53548b1bb4f52d6a167605b724a7b7d0d', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, h("slot", { key: '6e14b95e9b95c116b16744d630600e90977782bc', name: "start" })), h("div", { key: '8451ed4300ac005963075be36a04ea8763bc0fdd', class: "select-control", part: "control" }, this.renderLabel(), h("div", { key: '207e7b63f3224a4870579365ac992da6784fb31f', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), h("div", { key: '5c17367d488db4d570f31b25e33560efa9011500', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), h("slot", { key: '21fd8c0d9bee8cffef9ef6984cacd31e8f38211c', name: "end" })), shouldRenderHighlight && h("div", { key: '1fff767db9a1ec07b274ef65ff7ae8fb976e6ad2', class: "select-highlight" })), this.renderBottomContent()));
969
969
  }
970
970
  static get is() { return "ion-select"; }
971
971
  static get encapsulation() { return "shadow"; }
@@ -1663,29 +1663,14 @@ const textForValue = (opts, value, compareWith, useHTML = false) => {
1663
1663
  return getOptionContent(selectOpt, undefined, true);
1664
1664
  }
1665
1665
  /**
1666
- * When custom HTML is enabled, extract only the default slot content.
1667
- * This ensures aria-label and other text-only contexts read only
1668
- * the relevant option text.
1666
+ * Every text-only context reads only the default slot, so the start
1667
+ * and end slots stay out of the `aria-label` and the overlay labels.
1668
+ * Both config paths derive that text through the same helper, so they
1669
+ * cannot disagree about what an option's text is. `null` marks an
1670
+ * option with no text, which is dropped from the joined text of a
1671
+ * `multiple` select rather than joined in as an empty entry.
1669
1672
  */
1670
- if (customHTMLEnabled) {
1671
- const content = getOptionContent(selectOpt);
1672
- if (typeof content === 'string') {
1673
- return content;
1674
- }
1675
- /**
1676
- * Elements were found in the default slot, extract and concatenate
1677
- * their text content while trimming whitespace.
1678
- */
1679
- if (content) {
1680
- const texts = Array.from(content.childNodes)
1681
- .map((n) => n.textContent?.trim())
1682
- .filter((t) => t);
1683
- return texts.join(' ') || null;
1684
- }
1685
- // Empty option
1686
- return null;
1687
- }
1688
- return getDefaultSlotPlainText(selectOpt);
1673
+ return getDefaultSlotPlainText(selectOpt) || null;
1689
1674
  };
1690
1675
  /**
1691
1676
  * Trims whitespace from all text nodes within a DOM tree.
@@ -1741,9 +1726,13 @@ const getOptionContent = (option, slotName, useHTML = false) => {
1741
1726
  if (nodes.length === 0) {
1742
1727
  return null;
1743
1728
  }
1744
- // Return plain text if no elements are found
1729
+ /**
1730
+ * Return plain text if no elements are found. This reads the option the
1731
+ * same way the non-custom-HTML path does, so the two do not disagree
1732
+ * about what an option's text is.
1733
+ */
1745
1734
  if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
1746
- return nodes.map((n) => n.textContent?.trim()).join(' ') || null;
1735
+ return getDefaultSlotPlainText(option) || null;
1747
1736
  }
1748
1737
  /**
1749
1738
  * Mirror known custom-element properties (e.g. ion-icon's `icon`)
@@ -1799,22 +1788,43 @@ const getOptionDefaultSlot = (option) => {
1799
1788
  }
1800
1789
  return defaultSlotNodes;
1801
1790
  };
1791
+ /**
1792
+ * Concatenates the text a node renders, skipping the subtrees of tags
1793
+ * whose contents the browser never paints (`script`, `style`, and the
1794
+ * rest of `blockedTags`). `textContent` includes those, so reading it
1795
+ * directly would put stylesheet or script source into the select text
1796
+ * and the `aria-label`.
1797
+ *
1798
+ * @param node - The node to read text from.
1799
+ * @returns The node's rendered text.
1800
+ */
1801
+ const getRenderedTextContent = (node) => {
1802
+ if (node.nodeType === Node.TEXT_NODE) {
1803
+ return node.textContent ?? '';
1804
+ }
1805
+ if (node.nodeType !== Node.ELEMENT_NODE) {
1806
+ return '';
1807
+ }
1808
+ if (blockedTags.includes(node.tagName.toLowerCase())) {
1809
+ return '';
1810
+ }
1811
+ return Array.from(node.childNodes)
1812
+ .map((child) => getRenderedTextContent(child))
1813
+ .join('');
1814
+ };
1802
1815
  /**
1803
1816
  * Extracts plain text from only the default slot of an option,
1804
- * excluding content assigned to named slots (start/end).
1817
+ * excluding content assigned to named slots (start/end). Text is
1818
+ * concatenated with no separator and collapsible whitespace is
1819
+ * collapsed, approximating how the browser renders the option.
1820
+ * NBSP is not collapsible, so it is preserved.
1821
+ *
1822
+ * @param option - The `ion-select-option` element to read text from.
1823
+ * @returns The option's default slot text.
1805
1824
  */
1806
1825
  const getDefaultSlotPlainText = (option) => {
1807
- const texts = Array.from(option.childNodes)
1808
- .filter((node) => {
1809
- if (node.nodeType === Node.ELEMENT_NODE) {
1810
- return !node.hasAttribute('slot');
1811
- }
1812
- return node.nodeType === Node.TEXT_NODE;
1813
- })
1814
- .filter((node) => node.nodeType === Node.TEXT_NODE)
1815
- .map((n) => n.textContent?.trim())
1816
- .filter((t) => t);
1817
- return texts.join(' ');
1826
+ const text = (getOptionDefaultSlot(option) ?? []).map((node) => getRenderedTextContent(node)).join('');
1827
+ return text.replace(/[ \t\n\r\f]+/g, ' ').replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, '');
1818
1828
  };
1819
1829
  /**
1820
1830
  * Extracts the rich content from an `ion-select-option`.
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-08-20T18:04:41",
2
+ "timestamp": "2026-08-21T06:11:59",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.43.5",
@@ -420,4 +420,4 @@ class IonicSafeString {
420
420
  }
421
421
  }
422
422
 
423
- export { IonicSafeString as I, sanitizeDOMTree as a, reflectPropertiesToAttributes as r, sanitizeDOMString as s };
423
+ export { IonicSafeString as I, sanitizeDOMTree as a, blockedTags as b, reflectPropertiesToAttributes as r, sanitizeDOMString as s };
package/dist/esm/index.js CHANGED
@@ -10,7 +10,7 @@ export { createGesture } from './index-BmLuEdV7.js';
10
10
  export { g as getPlatforms, i as initialize, a as isPlatform } from './ionic-global-lrowsHfi.js';
11
11
  export { c as componentOnReady } from './helpers-BIgoInJU.js';
12
12
  export { L as LogLevel } from './index-CKYcsw8f.js';
13
- export { I as IonicSafeString } from './index-elneMH8y.js';
13
+ export { I as IonicSafeString } from './index-D3o-MD4_.js';
14
14
  export { g as getMode, s as setupConfig } from './config-DWCzVL3Y.js';
15
15
  export { o as openURL } from './theme-byZM6qHV.js';
16
16
  export { m as menuController } from './index-C5ZdL0qp.js';
@@ -6,7 +6,7 @@ import { c as createButtonActiveGesture } from './button-active-ChA4D-ml.js';
6
6
  import { r as raf } from './helpers-BIgoInJU.js';
7
7
  import { c as createLockController } from './lock-controller-B-hirT0v.js';
8
8
  import { c as createDelegateController, d as createTriggerController, B as BACKDROP, i as isCancel, e as present, f as dismiss, g as eventMethod, s as safeCall, h as prepareOverlay, j as cleanupRootFocusTrapAccessibility, k as setOverlayId } from './overlays-BpnIFlXI.js';
9
- import { r as renderOptionLabel } from './select-option-render-lIuu64EV.js';
9
+ import { r as renderOptionLabel } from './select-option-render-Dv7KImop.js';
10
10
  import { g as getClassMap } from './theme-byZM6qHV.js';
11
11
  import { b as getIonMode } from './ionic-global-lrowsHfi.js';
12
12
  import { c as createAnimation } from './animation-TxGPYeDn.js';
@@ -18,7 +18,7 @@ import './gesture-controller-B_gJaBk0.js';
18
18
  import './dir-Dojwmvde.js';
19
19
  import './hardware-back-button-D8W4L0JP.js';
20
20
  import './framework-delegate-DaLWnISz.js';
21
- import './index-elneMH8y.js';
21
+ import './index-D3o-MD4_.js';
22
22
 
23
23
  /**
24
24
  * iOS Action Sheet Enter Animation
@@ -8,8 +8,8 @@ import { r as raf } from './helpers-BIgoInJU.js';
8
8
  import { c as createLockController } from './lock-controller-B-hirT0v.js';
9
9
  import { g as getOverlayLabelJustify, a as getOverlayLabelPlacement } from './overlay-control-label-BSQPZ79H.js';
10
10
  import { c as createDelegateController, d as createTriggerController, B as BACKDROP, i as isCancel, h as prepareOverlay, k as setOverlayId, j as cleanupRootFocusTrapAccessibility, e as present, f as dismiss, g as eventMethod, s as safeCall } from './overlays-BpnIFlXI.js';
11
- import { s as sanitizeDOMString } from './index-elneMH8y.js';
12
- import { r as renderOptionLabel } from './select-option-render-lIuu64EV.js';
11
+ import { s as sanitizeDOMString } from './index-D3o-MD4_.js';
12
+ import { r as renderOptionLabel } from './select-option-render-Dv7KImop.js';
13
13
  import { g as getClassMap } from './theme-byZM6qHV.js';
14
14
  import { b as getIonMode } from './ionic-global-lrowsHfi.js';
15
15
  import { c as createAnimation } from './animation-TxGPYeDn.js';
@@ -5,7 +5,7 @@ import { r as registerInstance, c as createEvent, w as writeTask, a as readTask,
5
5
  import { a as findClosestIonContent, p as printIonContentErrorMsg, g as getScrollElement } from './index-BmOR8tCv.js';
6
6
  import { b as getIonMode } from './ionic-global-lrowsHfi.js';
7
7
  import { E as ENABLE_HTML_CONTENT_DEFAULT } from './config-DWCzVL3Y.js';
8
- import { s as sanitizeDOMString } from './index-elneMH8y.js';
8
+ import { s as sanitizeDOMString } from './index-D3o-MD4_.js';
9
9
  import './helpers-BIgoInJU.js';
10
10
  import './dir-Dojwmvde.js';
11
11
 
@@ -6,7 +6,7 @@ import { E as ENABLE_HTML_CONTENT_DEFAULT } from './config-DWCzVL3Y.js';
6
6
  import { r as raf } from './helpers-BIgoInJU.js';
7
7
  import { c as createLockController } from './lock-controller-B-hirT0v.js';
8
8
  import { c as createDelegateController, d as createTriggerController, B as BACKDROP, h as prepareOverlay, k as setOverlayId, j as cleanupRootFocusTrapAccessibility, e as present, f as dismiss, g as eventMethod } from './overlays-BpnIFlXI.js';
9
- import { s as sanitizeDOMString } from './index-elneMH8y.js';
9
+ import { s as sanitizeDOMString } from './index-D3o-MD4_.js';
10
10
  import { g as getClassMap } from './theme-byZM6qHV.js';
11
11
  import { b as getIonMode } from './ionic-global-lrowsHfi.js';
12
12
  import { c as createAnimation } from './animation-TxGPYeDn.js';
@@ -9,7 +9,7 @@ import { d as hapticImpact, I as ImpactStyle } from './haptic-Cq4UAeka.js';
9
9
  import { b as getIonMode } from './ionic-global-lrowsHfi.js';
10
10
  import { c as createAnimation } from './animation-TxGPYeDn.js';
11
11
  import { E as ENABLE_HTML_CONTENT_DEFAULT } from './config-DWCzVL3Y.js';
12
- import { s as sanitizeDOMString } from './index-elneMH8y.js';
12
+ import { s as sanitizeDOMString } from './index-D3o-MD4_.js';
13
13
  import { l as arrowDown, m as caretBackSharp } from './index-BvabGprD.js';
14
14
  import { S as SPINNERS } from './spinner-configs-D4RIp70E.js';
15
15
  import './dir-Dojwmvde.js';
@@ -5,7 +5,7 @@ import { r as registerInstance, h, i as forceUpdate, d as Host, g as getElement
5
5
  import { b as getIonMode } from './ionic-global-lrowsHfi.js';
6
6
  import { a as getOverlayLabelPlacement, g as getOverlayLabelJustify } from './overlay-control-label-BSQPZ79H.js';
7
7
  import { s as safeCall } from './overlays-BpnIFlXI.js';
8
- import { r as renderOptionLabel } from './select-option-render-lIuu64EV.js';
8
+ import { r as renderOptionLabel } from './select-option-render-Dv7KImop.js';
9
9
  import { g as getClassMap } from './theme-byZM6qHV.js';
10
10
  import './index-ZjP4CjeZ.js';
11
11
  import './helpers-BIgoInJU.js';
@@ -13,7 +13,7 @@ import './dir-Dojwmvde.js';
13
13
  import './hardware-back-button-D8W4L0JP.js';
14
14
  import './framework-delegate-DaLWnISz.js';
15
15
  import './gesture-controller-B_gJaBk0.js';
16
- import './index-elneMH8y.js';
16
+ import './index-D3o-MD4_.js';
17
17
 
18
18
  const ionicSelectModalMdCss = () => `.action-sheet-button-label-has-rich-content.sc-ion-select-modal-ionic,.alert-radio-label-has-rich-content.sc-ion-select-modal-ionic,.alert-checkbox-label-has-rich-content.sc-ion-select-modal-ionic,.select-option-label-has-rich-content.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:16px}.action-sheet-button-label-has-rich-content.sc-ion-select-modal-ionic,.alert-radio-label-has-rich-content.sc-ion-select-modal-ionic,.alert-checkbox-label-has-rich-content.sc-ion-select-modal-ionic,.select-option-content.sc-ion-select-modal-ionic{-ms-flex:1;flex:1}.action-sheet-button-label-text.sc-ion-select-modal-ionic,.alert-checkbox-label-text.sc-ion-select-modal-ionic,.alert-radio-label-text.sc-ion-select-modal-ionic,.select-option-label-text.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:12px}.select-option-start.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:8px}.select-option-description.sc-ion-select-modal-ionic{padding-left:0;padding-right:0;padding-top:5px;padding-bottom:0;display:block;color:var(--ion-color-step-700, var(--ion-text-color-step-300, #4d4d4d));font-size:0.75rem}.select-option-label.sc-ion-select-modal-ionic:not(.select-option-label-has-rich-content){text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.select-option-label-has-rich-content.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}ion-radio.select-option-has-rich-content.sc-ion-select-modal-ionic::part(label),ion-radio.select-option-has-rich-content.sc-ion-select-modal-ionic [part~="label"],ion-checkbox.select-option-has-rich-content.sc-ion-select-modal-ionic::part(label),ion-checkbox.select-option-has-rich-content.sc-ion-select-modal-ionic [part~="label"],.select-option-content.sc-ion-select-modal-ionic{-ms-flex:1;flex:1;white-space:normal}.select-option-start.sc-ion-select-modal-ionic>ion-avatar.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-avatar.sc-ion-select-modal-ionic{width:40px;height:40px}.select-option-start.sc-ion-select-modal-ionic>ion-icon.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-icon.sc-ion-select-modal-ionic{font-size:24px}.select-option-start.sc-ion-select-modal-ionic>ion-img.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>img.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>svg.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>ion-thumbnail.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-img.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>img.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>svg.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-thumbnail.sc-ion-select-modal-ionic{width:56px;height:56px}.select-option-start.sc-ion-select-modal-ionic>video.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>video.sc-ion-select-modal-ionic{width:114px;height:56px}.sc-ion-select-modal-ionic-h{height:100%}ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic::part(container),ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic [part~="container"]{display:none}ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic::part(label),ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic [part~="label"]{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0}ion-item.sc-ion-select-modal-ionic{--inner-border-width:0}.item-radio-checked.sc-ion-select-modal-ionic{--background:rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.08);--background-focused:var(--ion-color-primary, #0054e9);--background-focused-opacity:0.2;--background-hover:var(--ion-color-primary, #0054e9);--background-hover-opacity:0.12}.item-checkbox-checked.sc-ion-select-modal-ionic{--background-activated:var(--ion-item-color, var(--ion-text-color, #000));--background-focused:var(--ion-item-color, var(--ion-text-color, #000));--background-hover:var(--ion-item-color, var(--ion-text-color, #000));--color:var(--ion-color-primary, #0054e9)}`;
19
19