@ionic/core 8.8.9-dev.11780493108.1d8e1a89 → 8.8.9-dev.11780493937.17fe092d

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 (48) hide show
  1. package/components/ion-content.js +1 -1
  2. package/components/ion-footer.js +1 -1
  3. package/components/ion-gallery.js +1 -1
  4. package/components/ion-header.js +1 -1
  5. package/components/ion-select-modal.js +1 -1
  6. package/components/ion-select.js +1 -1
  7. package/components/p-BF5oFX1I.js +4 -0
  8. package/components/p-CpFORZud.js +4 -0
  9. package/components/p-d77Zk1DK.js +4 -0
  10. package/components/p-hdGd8ben.js +4 -0
  11. package/dist/cjs/ion-app_8.cjs.entry.js +286 -28
  12. package/dist/cjs/ion-gallery.cjs.entry.js +7 -26
  13. package/dist/collection/components/content/content.css +56 -0
  14. package/dist/collection/components/footer/footer.ios.css +13 -0
  15. package/dist/collection/components/footer/footer.js +65 -18
  16. package/dist/collection/components/footer/footer.md.css +13 -0
  17. package/dist/collection/components/footer/footer.utils.js +9 -0
  18. package/dist/collection/components/gallery/gallery.js +9 -14
  19. package/dist/collection/components/header/header.ionic.css +75 -0
  20. package/dist/collection/components/header/header.ios.css +75 -0
  21. package/dist/collection/components/header/header.js +41 -11
  22. package/dist/collection/components/header/header.md.css +75 -0
  23. package/dist/collection/components/header/header.utils.js +9 -0
  24. package/dist/collection/utils/css-value-validation.js +0 -14
  25. package/dist/collection/utils/on-scroll/collapse-hide.utils.js +168 -0
  26. package/dist/docs.json +18 -10
  27. package/dist/esm/ion-app_8.entry.js +286 -28
  28. package/dist/esm/ion-gallery.entry.js +7 -26
  29. package/dist/html.html-data.json +9 -3
  30. package/dist/ionic/ionic.esm.js +1 -1
  31. package/dist/ionic/p-04b5794c.entry.js +4 -0
  32. package/dist/ionic/p-ad4d0138.entry.js +4 -0
  33. package/dist/types/components/footer/footer.d.ts +12 -2
  34. package/dist/types/components/footer/footer.utils.d.ts +1 -0
  35. package/dist/types/components/gallery/gallery.d.ts +4 -6
  36. package/dist/types/components/header/header.d.ts +10 -3
  37. package/dist/types/components/header/header.utils.d.ts +1 -0
  38. package/dist/types/components.d.ts +12 -12
  39. package/dist/types/utils/css-value-validation.d.ts +0 -9
  40. package/dist/types/utils/on-scroll/collapse-hide.utils.d.ts +26 -0
  41. package/hydrate/index.js +293 -54
  42. package/hydrate/index.mjs +293 -54
  43. package/package.json +1 -1
  44. package/components/p-7kL3tltU.js +0 -4
  45. package/components/p-BGiYL2RS.js +0 -4
  46. package/components/p-LB-QPk3e.js +0 -4
  47. package/dist/ionic/p-290778c1.entry.js +0 -4
  48. package/dist/ionic/p-70ee89c9.entry.js +0 -4
@@ -1,3 +1,64 @@
1
+ /**
2
+ * Convert a pixels given value into rem
3
+ *
4
+ * @param pixels - Value in pixels to be converted (i.e. px)
5
+ * @param context (optional) - Baseline value
6
+ */
7
+ /**
8
+ * Convert a font size to a dynamic font size.
9
+ * Fonts that participate in Dynamic Type should use
10
+ * dynamic font sizes.
11
+ * @param size - The initial font size including the unit (i.e. px or pt)
12
+ * @param unit (optional) - The unit to convert to. Use this if you want to
13
+ * convert to a unit other than $baselineUnit.
14
+ */
15
+ /**
16
+ * Convert a font size to a dynamic font size but impose
17
+ * a maximum font size.
18
+ * @param size - The initial font size including the unit (i.e. px or pt)
19
+ * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
20
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
21
+ * convert to a unit other than $baselineUnit.
22
+ */
23
+ /**
24
+ * Convert a font size to a dynamic font size but impose
25
+ * a minimum font size.
26
+ * @param size - The initial font size including the unit (i.e. px or pt)
27
+ * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
28
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
29
+ * convert to a unit other than $baselineUnit.
30
+ */
31
+ /**
32
+ * Convert a font size to a dynamic font size but impose
33
+ * maximum and minimum font sizes.
34
+ * @param size - The initial font size including the unit (i.e. px or pt)
35
+ * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
36
+ * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
37
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
38
+ * convert to a unit other than $baselineUnit.
39
+ */
40
+ /**
41
+ * A heuristic that applies CSS to tablet
42
+ * viewports.
43
+ *
44
+ * Usage:
45
+ * @include tablet-viewport() {
46
+ * :host {
47
+ * background-color: green;
48
+ * }
49
+ * }
50
+ */
51
+ /**
52
+ * A heuristic that applies CSS to mobile
53
+ * viewports (i.e. phones, not tablets).
54
+ *
55
+ * Usage:
56
+ * @include mobile-viewport() {
57
+ * :host {
58
+ * background-color: blue;
59
+ * }
60
+ * }
61
+ */
1
62
  ion-header {
2
63
  display: block;
3
64
  position: relative;
@@ -9,6 +70,20 @@ ion-header ion-toolbar:first-of-type {
9
70
  padding-top: var(--ion-safe-area-top, 0);
10
71
  }
11
72
 
73
+ ion-header.header-collapse-hide {
74
+ transform: translateY(0);
75
+ transition: transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);
76
+ opacity: 1;
77
+ z-index: 10;
78
+ }
79
+
80
+ ion-header.header-collapse-hide.header-collapse-hide-hidden {
81
+ transform: translateY(calc(-1 * var(--header-hide-slide-y, 0px)));
82
+ pointer-events: none;
83
+ transition: transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);
84
+ opacity: 0;
85
+ }
86
+
12
87
  /**
13
88
  * Convert a pixels given value into rem
14
89
  *
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { readTask, writeTask } from "@stencil/core";
5
5
  import { clamp } from "../../utils/helpers";
6
+ import { createCollapseHideInteraction } from "../../utils/on-scroll/collapse-hide.utils";
6
7
  const TRANSITION = 'all 0.2s ease-in-out';
7
8
  const ROLE_NONE = 'none';
8
9
  const ROLE_BANNER = 'banner';
@@ -179,6 +180,14 @@ export const scaleLargeTitles = (toolbars = [], scale = 1, transition = false) =
179
180
  titleDiv.style.transform = `scale3d(${scale}, ${scale}, 1)`;
180
181
  });
181
182
  };
183
+ export const createHeaderHideInteraction = (headerEl, scrollEl) => createCollapseHideInteraction({
184
+ regionEl: headerEl,
185
+ scrollEl,
186
+ slideCssVar: '--header-hide-slide-y',
187
+ contentPartnerClass: 'content-header-hide-scroll-partner',
188
+ contentHiddenClass: 'content-header-hide-scroll-hidden',
189
+ regionHiddenClass: 'header-collapse-hide-hidden',
190
+ });
182
191
  export const handleHeaderFade = (scrollEl, baseEl, condenseHeader) => {
183
192
  readTask(() => {
184
193
  const scrollTop = scrollEl.scrollTop;
@@ -9,9 +9,6 @@
9
9
  const LENGTH_PERCENTAGE_PATTERN = /^[-+]?(?:\d+\.?\d*|\.\d+)(?:%|[a-z]+)$/i;
10
10
  // Matches simple `calc` / `min` / `max` / `clamp(...)` functions.
11
11
  const MATH_FUNCTION_PATTERN = /^(calc|min|max|clamp)\s*\(.+\)$/i;
12
- // Matches a `var(--name)` reference with an optional fallback, e.g.
13
- // `var(--my-gap)` or `var(--my-gap, 16px)`.
14
- const VAR_FUNCTION_PATTERN = /^var\(\s*--[^\s,)]+\s*(?:,[\s\S]*)?\)$/i;
15
12
  /**
16
13
  * Returns whether `value` matches the [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)
17
14
  * syntax. Accepts `<length>` (`<number>` + unit identifier) or `<percentage>` (`<number>%`).
@@ -26,14 +23,3 @@ export function isValidLengthPercentage(value) {
26
23
  }
27
24
  return MATH_FUNCTION_PATTERN.test(v) || LENGTH_PERCENTAGE_PATTERN.test(v);
28
25
  }
29
- /**
30
- * Returns whether `value` is a single [`var()`](https://developer.mozilla.org/en-US/docs/Web/CSS/var)
31
- * reference, e.g. `var(--my-token)` or `var(--my-token, 16px)`. The referenced
32
- * custom property is resolved by the browser, so the resolved value is not
33
- * validated here.
34
- *
35
- * @param value String value to validate.
36
- */
37
- export function isCssVariable(value) {
38
- return VAR_FUNCTION_PATTERN.test(value.trim());
39
- }
@@ -0,0 +1,168 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { readTask, writeTask } from "@stencil/core";
5
+ /** Cumulative downward delta before hiding (header or footer `collapse="hide"`). */
6
+ export const COLLAPSE_HIDE_THRESHOLD_PX = 24;
7
+ /**
8
+ * Cumulative upward delta before showing again after hide. Small bias
9
+ * (instead of "any upward delta") guards against inertial-scroll
10
+ * oscillation flicking the region back open during a downward gesture.
11
+ */
12
+ export const COLLAPSE_SHOW_THRESHOLD_PX = 5;
13
+ const WHEEL_SCROLL_SUPPRESS_MS = 80;
14
+ const getContentHostFromScrollEl = (scrollEl) => {
15
+ const root = scrollEl.getRootNode();
16
+ if (root instanceof ShadowRoot && root.host instanceof HTMLElement) {
17
+ return root.host;
18
+ }
19
+ // Light-DOM fallback: the scroll element may live inside a non-shadow
20
+ // ion-content (e.g. custom scroll host). Walk up to the nearest ion-content.
21
+ return scrollEl.closest('ion-content');
22
+ };
23
+ const applySlideDistance = (regionEl, contentHost, slideCssVar, heightPx) => {
24
+ const value = `${Math.max(0, Math.ceil(heightPx))}px`;
25
+ regionEl.style.setProperty(slideCssVar, value);
26
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.style.setProperty(slideCssVar, value);
27
+ };
28
+ const clearSlideDistance = (regionEl, contentHost, slideCssVar) => {
29
+ regionEl.style.removeProperty(slideCssVar);
30
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.style.removeProperty(slideCssVar);
31
+ };
32
+ /**
33
+ * Scroll/wheel-driven hide/show for `collapse="hide"` on `ion-header` or `ion-footer`.
34
+ * Hide after {@link COLLAPSE_HIDE_THRESHOLD_PX}px cumulative downward delta; show after
35
+ * {@link COLLAPSE_SHOW_THRESHOLD_PX}px cumulative upward delta. Each direction drains
36
+ * (not resets) the opposing accumulator so inertial-scroll jitter doesn't stall either
37
+ * transition. Motion is defined in component SCSS and `content.scss`; this toggles
38
+ * classes and syncs the slide distance CSS var.
39
+ */
40
+ export const createCollapseHideInteraction = ({ regionEl, scrollEl, slideCssVar, contentPartnerClass, contentHiddenClass, regionHiddenClass, }) => {
41
+ const contentHost = getContentHostFromScrollEl(scrollEl);
42
+ if (contentHost !== null) {
43
+ contentHost.classList.add(contentPartnerClass);
44
+ }
45
+ let resizeObserver;
46
+ let destroyed = false;
47
+ const syncSlideDistance = () => {
48
+ readTask(() => {
49
+ if (destroyed) {
50
+ return;
51
+ }
52
+ const heightPx = regionEl.offsetHeight;
53
+ writeTask(() => {
54
+ if (destroyed) {
55
+ return;
56
+ }
57
+ applySlideDistance(regionEl, contentHost, slideCssVar, heightPx);
58
+ });
59
+ });
60
+ };
61
+ if (typeof ResizeObserver !== 'undefined') {
62
+ resizeObserver = new ResizeObserver(() => {
63
+ syncSlideDistance();
64
+ });
65
+ resizeObserver.observe(regionEl);
66
+ }
67
+ syncSlideDistance();
68
+ requestAnimationFrame(() => {
69
+ if (!destroyed) {
70
+ syncSlideDistance();
71
+ }
72
+ });
73
+ let hidden = false;
74
+ let accDown = 0;
75
+ let accUp = 0;
76
+ let lastScrollTop = scrollEl.scrollTop;
77
+ let lastWheelTime = 0;
78
+ const setHidden = (next) => {
79
+ if (hidden === next || destroyed) {
80
+ return;
81
+ }
82
+ hidden = next;
83
+ // When transitioning to hidden, re-measure synchronously in case the
84
+ // initial layout reported offsetHeight === 0 (e.g. mid page transition).
85
+ // Without this the slide animates by 0px and only opacity fades.
86
+ if (hidden) {
87
+ const heightPx = regionEl.offsetHeight;
88
+ if (heightPx > 0) {
89
+ applySlideDistance(regionEl, contentHost, slideCssVar, heightPx);
90
+ }
91
+ }
92
+ writeTask(() => {
93
+ if (destroyed) {
94
+ return;
95
+ }
96
+ regionEl.classList.toggle(regionHiddenClass, hidden);
97
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.classList.toggle(contentHiddenClass, hidden);
98
+ if (hidden) {
99
+ // `inert` removes the subtree from the tab order and AT, AND moves
100
+ // focus out automatically in supporting browsers. `aria-hidden` is
101
+ // kept as a fallback for older engines without `inert` support.
102
+ regionEl.setAttribute('inert', '');
103
+ regionEl.setAttribute('aria-hidden', 'true');
104
+ }
105
+ else {
106
+ regionEl.removeAttribute('inert');
107
+ regionEl.removeAttribute('aria-hidden');
108
+ }
109
+ });
110
+ };
111
+ // Accumulate cumulative movement in each direction. The OPPOSITE accumulator
112
+ // is drained (not reset) by each event, so brief inertial jitter does not
113
+ // wipe a sustained gesture's accumulation. Crossing a threshold resets both.
114
+ const processDelta = (delta) => {
115
+ if (delta > 0) {
116
+ accUp = Math.max(0, accUp - delta);
117
+ accDown += delta;
118
+ if (accDown >= COLLAPSE_HIDE_THRESHOLD_PX) {
119
+ setHidden(true);
120
+ accDown = 0;
121
+ accUp = 0;
122
+ }
123
+ }
124
+ else if (delta < 0) {
125
+ const mag = -delta;
126
+ accDown = Math.max(0, accDown - mag);
127
+ accUp += mag;
128
+ if (accUp >= COLLAPSE_SHOW_THRESHOLD_PX) {
129
+ setHidden(false);
130
+ accUp = 0;
131
+ accDown = 0;
132
+ }
133
+ }
134
+ };
135
+ const onWheel = (ev) => {
136
+ if (destroyed) {
137
+ return;
138
+ }
139
+ lastWheelTime = performance.now();
140
+ processDelta(ev.deltaY);
141
+ };
142
+ const onScroll = () => {
143
+ if (destroyed) {
144
+ return;
145
+ }
146
+ const st = scrollEl.scrollTop;
147
+ if (performance.now() - lastWheelTime < WHEEL_SCROLL_SUPPRESS_MS) {
148
+ lastScrollTop = st;
149
+ return;
150
+ }
151
+ const delta = st - lastScrollTop;
152
+ lastScrollTop = st;
153
+ processDelta(delta);
154
+ };
155
+ scrollEl.addEventListener('wheel', onWheel, { passive: true });
156
+ scrollEl.addEventListener('scroll', onScroll, { passive: true });
157
+ return () => {
158
+ destroyed = true;
159
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
160
+ scrollEl.removeEventListener('wheel', onWheel);
161
+ scrollEl.removeEventListener('scroll', onScroll);
162
+ regionEl.classList.remove(regionHiddenClass);
163
+ regionEl.removeAttribute('inert');
164
+ regionEl.removeAttribute('aria-hidden');
165
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.classList.remove(contentPartnerClass, contentHiddenClass);
166
+ clearSlideDistance(regionEl, contentHost, slideCssVar);
167
+ };
168
+ };
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-06-03T13:27:38",
2
+ "timestamp": "2026-06-03T13:41:16",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.43.0",
@@ -14112,22 +14112,26 @@
14112
14112
  "props": [
14113
14113
  {
14114
14114
  "name": "collapse",
14115
- "type": "\"fade\" | undefined",
14115
+ "type": "\"fade\" | \"hide\" | undefined",
14116
14116
  "complexType": {
14117
- "original": "'fade'",
14118
- "resolved": "\"fade\" | undefined",
14117
+ "original": "'fade' | 'hide'",
14118
+ "resolved": "\"fade\" | \"hide\" | undefined",
14119
14119
  "references": {}
14120
14120
  },
14121
14121
  "mutable": false,
14122
14122
  "attr": "collapse",
14123
14123
  "reflectToAttr": false,
14124
- "docs": "Describes the scroll effect that will be applied to the footer.\nOnly applies when the theme is `\"ios\"`.",
14124
+ "docs": "Describes the scroll effect that will be applied to the footer.\n\n- `\"fade\"` only applies when the theme is `\"ios\"`.\n- `\"hide\"` applies to all themes (`\"ios\"`, `\"md\"`, and `\"ionic\"`): the footer\n slides down and fades out after cumulative downward scrolling on the page content,\n and returns on any upward scroll (same behavior as `ion-header[collapse=\"hide\"]`).",
14125
14125
  "docsTags": [],
14126
14126
  "values": [
14127
14127
  {
14128
14128
  "value": "fade",
14129
14129
  "type": "string"
14130
14130
  },
14131
+ {
14132
+ "value": "hide",
14133
+ "type": "string"
14134
+ },
14131
14135
  {
14132
14136
  "type": "undefined"
14133
14137
  }
@@ -14308,7 +14312,7 @@
14308
14312
  "mutable": false,
14309
14313
  "attr": "gap",
14310
14314
  "reflectToAttr": false,
14311
- "docs": "The space between gallery items. Accepts valid CSS [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)\nvalues like `16px`, `1rem`, `20%`, math functions like `calc(10px + 20%)`,\nCSS variables like `var(--app-gallery-gap)`, or numbers (treated as pixel\nvalues). Can also be set as a breakpoint map\n(e.g. `{ xs: '8px', sm: '1rem', md: '24px' }`). Does not accept\nspace-separated values or CSS keyword values like `inherit`, `auto`, etc.",
14315
+ "docs": "The space between gallery items. Accepts valid CSS [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)\nvalues like `16px`, `1rem`, `20%`, math functions like `calc(10px + 20%)`,\nor numbers (treated as pixel values). Can also be set as a breakpoint map\n(e.g. `{ xs: '8px', sm: '1rem', md: '24px' }`). Does not accept\nspace-separated values or CSS keyword values like `inherit`, `auto`, etc.",
14312
14316
  "docsTags": [
14313
14317
  {
14314
14318
  "name": "default",
@@ -14653,16 +14657,16 @@
14653
14657
  "props": [
14654
14658
  {
14655
14659
  "name": "collapse",
14656
- "type": "\"condense\" | \"fade\" | undefined",
14660
+ "type": "\"condense\" | \"fade\" | \"hide\" | undefined",
14657
14661
  "complexType": {
14658
- "original": "'condense' | 'fade'",
14659
- "resolved": "\"condense\" | \"fade\" | undefined",
14662
+ "original": "'condense' | 'fade' | 'hide'",
14663
+ "resolved": "\"condense\" | \"fade\" | \"hide\" | undefined",
14660
14664
  "references": {}
14661
14665
  },
14662
14666
  "mutable": false,
14663
14667
  "attr": "collapse",
14664
14668
  "reflectToAttr": false,
14665
- "docs": "Describes the scroll effect that will be applied to the header.\nOnly applies when the theme is `\"ios\"`.\n\nTypically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)",
14669
+ "docs": "Describes the scroll effect that will be applied to the header.\n\n- `\"condense\"` and `\"fade\"` only apply when the theme is `\"ios\"`.\n Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles).\n- `\"hide\"` applies to all themes (`\"ios\"`, `\"md\"`, and `\"ionic\"`): the header\n slides up and fades out after cumulative downward scrolling on the page content,\n and returns on any upward scroll.",
14666
14670
  "docsTags": [],
14667
14671
  "values": [
14668
14672
  {
@@ -14673,6 +14677,10 @@
14673
14677
  "value": "fade",
14674
14678
  "type": "string"
14675
14679
  },
14680
+ {
14681
+ "value": "hide",
14682
+ "type": "string"
14683
+ },
14676
14684
  {
14677
14685
  "type": "undefined"
14678
14686
  }