@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
package/hydrate/index.js CHANGED
@@ -13337,7 +13337,7 @@ const isRTL$1 = (hostEl) => {
13337
13337
  return (document === null || document === void 0 ? void 0 : document.dir.toLowerCase()) === 'rtl';
13338
13338
  };
13339
13339
 
13340
- const contentCss = () => `:host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;-ms-flex:1;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}#background-content{right:0px;left:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{right:0px;left:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom) + var(--internal-content-safe-area-padding-bottom, 0px));position:absolute;color:var(--color);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:pan-x pan-y pinch-zoom;touch-action:pan-x pan-y pinch-zoom}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:""}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:100%;height:100%;-webkit-box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03);box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03)}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}::slotted([slot=fixed]){position:absolute;-webkit-transform:translateZ(0);transform:translateZ(0)}`;
13340
+ const contentCss = () => `:host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;-ms-flex:1;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}#background-content{right:0px;left:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{right:0px;left:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom) + var(--internal-content-safe-area-padding-bottom, 0px));position:absolute;color:var(--color);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:pan-x pan-y pinch-zoom;touch-action:pan-x pan-y pinch-zoom}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:""}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:100%;height:100%;-webkit-box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03);box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03)}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}::slotted([slot=fixed]){position:absolute;-webkit-transform:translateZ(0);transform:translateZ(0)}:host(.content-header-hide-scroll-partner:not(.content-footer-hide-scroll-partner)) .inner-scroll{-webkit-transform:translateY(0);transform:translateY(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;height:100%;-webkit-transition:height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), height 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1)}:host(.content-header-hide-scroll-partner:not(.content-footer-hide-scroll-partner).content-header-hide-scroll-hidden) .inner-scroll{-webkit-transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));-webkit-backface-visibility:hidden;backface-visibility:hidden;height:calc(100% + var(--header-hide-slide-y, 0px));-webkit-transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1)}:host(.content-footer-hide-scroll-partner:not(.content-header-hide-scroll-partner)) .inner-scroll{-webkit-transform:translateY(0);transform:translateY(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;height:100%;-webkit-transition:height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), height 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1)}:host(.content-footer-hide-scroll-partner:not(.content-header-hide-scroll-partner).content-footer-hide-scroll-hidden) .inner-scroll{-webkit-transform:translateY(0);transform:translateY(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;height:calc(100% + var(--footer-hide-slide-y, 0px));-webkit-transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1)}:host(.content-header-hide-scroll-partner.content-footer-hide-scroll-partner:not(.content-header-hide-scroll-hidden):not(.content-footer-hide-scroll-hidden)) .inner-scroll{-webkit-transform:translateY(0);transform:translateY(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;height:100%;-webkit-transition:height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), height 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), height 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1)}:host(.content-header-hide-scroll-partner.content-footer-hide-scroll-partner.content-header-hide-scroll-hidden:not(.content-footer-hide-scroll-hidden)) .inner-scroll{-webkit-transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));-webkit-backface-visibility:hidden;backface-visibility:hidden;height:calc(100% + var(--header-hide-slide-y, 0px));-webkit-transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1)}:host(.content-header-hide-scroll-partner.content-footer-hide-scroll-partner:not(.content-header-hide-scroll-hidden).content-footer-hide-scroll-hidden) .inner-scroll{-webkit-transform:translateY(0);transform:translateY(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;height:calc(100% + var(--footer-hide-slide-y, 0px));-webkit-transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1)}:host(.content-header-hide-scroll-partner.content-footer-hide-scroll-partner.content-header-hide-scroll-hidden.content-footer-hide-scroll-hidden) .inner-scroll{-webkit-transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));-webkit-backface-visibility:hidden;backface-visibility:hidden;height:calc(100% + var(--header-hide-slide-y, 0px) + var(--footer-hide-slide-y, 0px));-webkit-transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1)}`;
13341
13341
 
13342
13342
  /**
13343
13343
  * @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
@@ -18587,6 +18587,171 @@ const createKeyboardController = async (keyboardChangeCallback) => {
18587
18587
  return { init, destroy, isKeyboardVisible };
18588
18588
  };
18589
18589
 
18590
+ /** Cumulative downward delta before hiding (header or footer `collapse="hide"`). */
18591
+ const COLLAPSE_HIDE_THRESHOLD_PX = 24;
18592
+ /**
18593
+ * Cumulative upward delta before showing again after hide. Small bias
18594
+ * (instead of "any upward delta") guards against inertial-scroll
18595
+ * oscillation flicking the region back open during a downward gesture.
18596
+ */
18597
+ const COLLAPSE_SHOW_THRESHOLD_PX = 5;
18598
+ const WHEEL_SCROLL_SUPPRESS_MS = 80;
18599
+ const getContentHostFromScrollEl = (scrollEl) => {
18600
+ const root = scrollEl.getRootNode();
18601
+ if (root instanceof ShadowRoot && root.host instanceof HTMLElement) {
18602
+ return root.host;
18603
+ }
18604
+ // Light-DOM fallback: the scroll element may live inside a non-shadow
18605
+ // ion-content (e.g. custom scroll host). Walk up to the nearest ion-content.
18606
+ return scrollEl.closest('ion-content');
18607
+ };
18608
+ const applySlideDistance = (regionEl, contentHost, slideCssVar, heightPx) => {
18609
+ const value = `${Math.max(0, Math.ceil(heightPx))}px`;
18610
+ regionEl.style.setProperty(slideCssVar, value);
18611
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.style.setProperty(slideCssVar, value);
18612
+ };
18613
+ const clearSlideDistance = (regionEl, contentHost, slideCssVar) => {
18614
+ regionEl.style.removeProperty(slideCssVar);
18615
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.style.removeProperty(slideCssVar);
18616
+ };
18617
+ /**
18618
+ * Scroll/wheel-driven hide/show for `collapse="hide"` on `ion-header` or `ion-footer`.
18619
+ * Hide after {@link COLLAPSE_HIDE_THRESHOLD_PX}px cumulative downward delta; show after
18620
+ * {@link COLLAPSE_SHOW_THRESHOLD_PX}px cumulative upward delta. Each direction drains
18621
+ * (not resets) the opposing accumulator so inertial-scroll jitter doesn't stall either
18622
+ * transition. Motion is defined in component SCSS and `content.scss`; this toggles
18623
+ * classes and syncs the slide distance CSS var.
18624
+ */
18625
+ const createCollapseHideInteraction = ({ regionEl, scrollEl, slideCssVar, contentPartnerClass, contentHiddenClass, regionHiddenClass, }) => {
18626
+ const contentHost = getContentHostFromScrollEl(scrollEl);
18627
+ if (contentHost !== null) {
18628
+ contentHost.classList.add(contentPartnerClass);
18629
+ }
18630
+ let resizeObserver;
18631
+ let destroyed = false;
18632
+ const syncSlideDistance = () => {
18633
+ readTask(() => {
18634
+ if (destroyed) {
18635
+ return;
18636
+ }
18637
+ const heightPx = regionEl.offsetHeight;
18638
+ writeTask(() => {
18639
+ if (destroyed) {
18640
+ return;
18641
+ }
18642
+ applySlideDistance(regionEl, contentHost, slideCssVar, heightPx);
18643
+ });
18644
+ });
18645
+ };
18646
+ if (typeof ResizeObserver !== 'undefined') {
18647
+ resizeObserver = new ResizeObserver(() => {
18648
+ syncSlideDistance();
18649
+ });
18650
+ resizeObserver.observe(regionEl);
18651
+ }
18652
+ syncSlideDistance();
18653
+ requestAnimationFrame(() => {
18654
+ if (!destroyed) {
18655
+ syncSlideDistance();
18656
+ }
18657
+ });
18658
+ let hidden = false;
18659
+ let accDown = 0;
18660
+ let accUp = 0;
18661
+ let lastScrollTop = scrollEl.scrollTop;
18662
+ let lastWheelTime = 0;
18663
+ const setHidden = (next) => {
18664
+ if (hidden === next || destroyed) {
18665
+ return;
18666
+ }
18667
+ hidden = next;
18668
+ // When transitioning to hidden, re-measure synchronously in case the
18669
+ // initial layout reported offsetHeight === 0 (e.g. mid page transition).
18670
+ // Without this the slide animates by 0px and only opacity fades.
18671
+ if (hidden) {
18672
+ const heightPx = regionEl.offsetHeight;
18673
+ if (heightPx > 0) {
18674
+ applySlideDistance(regionEl, contentHost, slideCssVar, heightPx);
18675
+ }
18676
+ }
18677
+ writeTask(() => {
18678
+ if (destroyed) {
18679
+ return;
18680
+ }
18681
+ regionEl.classList.toggle(regionHiddenClass, hidden);
18682
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.classList.toggle(contentHiddenClass, hidden);
18683
+ if (hidden) {
18684
+ // `inert` removes the subtree from the tab order and AT, AND moves
18685
+ // focus out automatically in supporting browsers. `aria-hidden` is
18686
+ // kept as a fallback for older engines without `inert` support.
18687
+ regionEl.setAttribute('inert', '');
18688
+ regionEl.setAttribute('aria-hidden', 'true');
18689
+ }
18690
+ else {
18691
+ regionEl.removeAttribute('inert');
18692
+ regionEl.removeAttribute('aria-hidden');
18693
+ }
18694
+ });
18695
+ };
18696
+ // Accumulate cumulative movement in each direction. The OPPOSITE accumulator
18697
+ // is drained (not reset) by each event, so brief inertial jitter does not
18698
+ // wipe a sustained gesture's accumulation. Crossing a threshold resets both.
18699
+ const processDelta = (delta) => {
18700
+ if (delta > 0) {
18701
+ accUp = Math.max(0, accUp - delta);
18702
+ accDown += delta;
18703
+ if (accDown >= COLLAPSE_HIDE_THRESHOLD_PX) {
18704
+ setHidden(true);
18705
+ accDown = 0;
18706
+ accUp = 0;
18707
+ }
18708
+ }
18709
+ else if (delta < 0) {
18710
+ const mag = -delta;
18711
+ accDown = Math.max(0, accDown - mag);
18712
+ accUp += mag;
18713
+ if (accUp >= COLLAPSE_SHOW_THRESHOLD_PX) {
18714
+ setHidden(false);
18715
+ accUp = 0;
18716
+ accDown = 0;
18717
+ }
18718
+ }
18719
+ };
18720
+ const onWheel = (ev) => {
18721
+ if (destroyed) {
18722
+ return;
18723
+ }
18724
+ lastWheelTime = performance.now();
18725
+ processDelta(ev.deltaY);
18726
+ };
18727
+ const onScroll = () => {
18728
+ if (destroyed) {
18729
+ return;
18730
+ }
18731
+ const st = scrollEl.scrollTop;
18732
+ if (performance.now() - lastWheelTime < WHEEL_SCROLL_SUPPRESS_MS) {
18733
+ lastScrollTop = st;
18734
+ return;
18735
+ }
18736
+ const delta = st - lastScrollTop;
18737
+ lastScrollTop = st;
18738
+ processDelta(delta);
18739
+ };
18740
+ scrollEl.addEventListener('wheel', onWheel, { passive: true });
18741
+ scrollEl.addEventListener('scroll', onScroll, { passive: true });
18742
+ return () => {
18743
+ destroyed = true;
18744
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
18745
+ scrollEl.removeEventListener('wheel', onWheel);
18746
+ scrollEl.removeEventListener('scroll', onScroll);
18747
+ regionEl.classList.remove(regionHiddenClass);
18748
+ regionEl.removeAttribute('inert');
18749
+ regionEl.removeAttribute('aria-hidden');
18750
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.classList.remove(contentPartnerClass, contentHiddenClass);
18751
+ clearSlideDistance(regionEl, contentHost, slideCssVar);
18752
+ };
18753
+ };
18754
+
18590
18755
  const handleFooterFade = (scrollEl, baseEl) => {
18591
18756
  readTask(() => {
18592
18757
  const scrollTop = scrollEl.scrollTop;
@@ -18615,12 +18780,20 @@ const handleFooterFade = (scrollEl, baseEl) => {
18615
18780
  });
18616
18781
  });
18617
18782
  };
18783
+ const createFooterHideInteraction = (footerEl, scrollEl) => createCollapseHideInteraction({
18784
+ regionEl: footerEl,
18785
+ scrollEl,
18786
+ slideCssVar: '--footer-hide-slide-y',
18787
+ contentPartnerClass: 'content-footer-hide-scroll-partner',
18788
+ contentHiddenClass: 'content-footer-hide-scroll-hidden',
18789
+ regionHiddenClass: 'footer-collapse-hide-hidden',
18790
+ });
18618
18791
 
18619
- const ionicFooterMdCss = () => `ion-footer{display:block;position:relative;-ms-flex-order:1;order:1;width:100%;z-index:10}ion-footer.footer-toolbar-padding ion-toolbar:last-of-type{padding-bottom:var(--ion-safe-area-bottom, 0)}.footer-md{-webkit-box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12)}.footer-md.ion-no-border{-webkit-box-shadow:none;box-shadow:none}`;
18792
+ const ionicFooterMdCss = () => `ion-footer{display:block;position:relative;-ms-flex-order:1;order:1;width:100%;z-index:10}ion-footer.footer-toolbar-padding ion-toolbar:last-of-type{padding-bottom:var(--ion-safe-area-bottom, 0)}ion-footer.footer-collapse-hide{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);opacity:1}ion-footer.footer-collapse-hide.footer-collapse-hide-hidden{-webkit-transform:translateY(var(--footer-hide-slide-y, 0px));transform:translateY(var(--footer-hide-slide-y, 0px));pointer-events:none;-webkit-transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);opacity:0}.footer-md{-webkit-box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12)}.footer-md.ion-no-border{-webkit-box-shadow:none;box-shadow:none}`;
18620
18793
 
18621
- const footerIosCss = () => `ion-footer{display:block;position:relative;-ms-flex-order:1;order:1;width:100%;z-index:10}ion-footer.footer-toolbar-padding ion-toolbar:last-of-type{padding-bottom:var(--ion-safe-area-bottom, 0)}.footer-ios ion-toolbar:first-of-type{--border-width:0.55px 0 0}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.footer-background{right:0;left:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}.footer-translucent-ios ion-toolbar{--opacity:0.8}}.footer-ios.ion-no-border ion-toolbar:first-of-type{--border-width:0}.footer-collapse-fade ion-toolbar{--opacity-scale:inherit}`;
18794
+ const footerIosCss = () => `ion-footer{display:block;position:relative;-ms-flex-order:1;order:1;width:100%;z-index:10}ion-footer.footer-toolbar-padding ion-toolbar:last-of-type{padding-bottom:var(--ion-safe-area-bottom, 0)}ion-footer.footer-collapse-hide{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);opacity:1}ion-footer.footer-collapse-hide.footer-collapse-hide-hidden{-webkit-transform:translateY(var(--footer-hide-slide-y, 0px));transform:translateY(var(--footer-hide-slide-y, 0px));pointer-events:none;-webkit-transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);opacity:0}.footer-ios ion-toolbar:first-of-type{--border-width:0.55px 0 0}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.footer-background{right:0;left:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}.footer-translucent-ios ion-toolbar{--opacity:0.8}}.footer-ios.ion-no-border ion-toolbar:first-of-type{--border-width:0}.footer-collapse-fade ion-toolbar{--opacity-scale:inherit}`;
18622
18795
 
18623
- const footerMdCss = () => `ion-footer{display:block;position:relative;-ms-flex-order:1;order:1;width:100%;z-index:10}ion-footer.footer-toolbar-padding ion-toolbar:last-of-type{padding-bottom:var(--ion-safe-area-bottom, 0)}.footer-md{-webkit-box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12)}.footer-md.ion-no-border{-webkit-box-shadow:none;box-shadow:none}`;
18796
+ const footerMdCss = () => `ion-footer{display:block;position:relative;-ms-flex-order:1;order:1;width:100%;z-index:10}ion-footer.footer-toolbar-padding ion-toolbar:last-of-type{padding-bottom:var(--ion-safe-area-bottom, 0)}ion-footer.footer-collapse-hide{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);opacity:1}ion-footer.footer-collapse-hide.footer-collapse-hide-hidden{-webkit-transform:translateY(var(--footer-hide-slide-y, 0px));transform:translateY(var(--footer-hide-slide-y, 0px));pointer-events:none;-webkit-transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);opacity:0}.footer-md{-webkit-box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12)}.footer-md.ion-no-border{-webkit-box-shadow:none;box-shadow:none}`;
18624
18797
 
18625
18798
  /**
18626
18799
  * @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
@@ -18629,6 +18802,8 @@ const footerMdCss = () => `ion-footer{display:block;position:relative;-ms-flex-o
18629
18802
  class Footer {
18630
18803
  constructor(hostRef) {
18631
18804
  registerInstance(this, hostRef);
18805
+ this.didLoad = false;
18806
+ this.setupToken = 0;
18632
18807
  this.keyboardCtrl = null;
18633
18808
  this.keyboardCtrlPromise = null;
18634
18809
  this.keyboardVisible = false;
@@ -18643,25 +18818,45 @@ class Footer {
18643
18818
  this.translucent = false;
18644
18819
  this.checkCollapsibleFooter = () => {
18645
18820
  const theme = getIonTheme(this);
18646
- if (theme !== 'ios') {
18647
- return;
18648
- }
18649
18821
  const { collapse } = this;
18650
18822
  const hasFade = collapse === 'fade';
18823
+ const hasHide = collapse === 'hide';
18824
+ const runIosFade = theme === 'ios' && hasFade;
18825
+ if (!runIosFade && !hasHide) {
18826
+ this.destroyCollapsibleFooter();
18827
+ return;
18828
+ }
18829
+ // Skip teardown/rebuild when the collapse mode and theme have not changed
18830
+ // since the last setup — avoids thrashing listeners and resetting scroll
18831
+ // accumulators on unrelated re-renders (e.g. keyboardVisible state flips).
18832
+ const activeMode = hasHide ? 'hide' : 'fade';
18833
+ if (this.appliedCollapse === activeMode && this.appliedTheme === theme) {
18834
+ return;
18835
+ }
18651
18836
  this.destroyCollapsibleFooter();
18652
- if (hasFade) {
18653
- const appRootSelector = config.get('appRootSelector', 'ion-app');
18654
- const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
18655
- const contentEl = pageEl ? findIonContent(pageEl) : null;
18656
- if (!contentEl) {
18657
- printIonContentErrorMsg(this.el);
18658
- return;
18659
- }
18837
+ const appRootSelector = config.get('appRootSelector', 'ion-app');
18838
+ const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
18839
+ const contentEl = pageEl ? findIonContent(pageEl) : null;
18840
+ if (!contentEl) {
18841
+ printIonContentErrorMsg(this.el);
18842
+ return;
18843
+ }
18844
+ this.appliedCollapse = activeMode;
18845
+ this.appliedTheme = theme;
18846
+ if (runIosFade) {
18660
18847
  this.setupFadeFooter(contentEl);
18661
18848
  }
18849
+ else if (hasHide) {
18850
+ void this.setupHideFooter(contentEl);
18851
+ }
18662
18852
  };
18663
18853
  this.setupFadeFooter = async (contentEl) => {
18664
- const scrollEl = (this.scrollEl = await getScrollElement(contentEl));
18854
+ const token = ++this.setupToken;
18855
+ const scrollEl = await getScrollElement(contentEl);
18856
+ if (token !== this.setupToken) {
18857
+ return;
18858
+ }
18859
+ this.scrollEl = scrollEl;
18665
18860
  /**
18666
18861
  * Handle fading of toolbars on scroll
18667
18862
  */
@@ -18673,12 +18868,18 @@ class Footer {
18673
18868
  };
18674
18869
  }
18675
18870
  componentDidLoad() {
18871
+ this.didLoad = true;
18676
18872
  this.checkCollapsibleFooter();
18677
18873
  }
18678
18874
  componentDidUpdate() {
18679
18875
  this.checkCollapsibleFooter();
18680
18876
  }
18681
18877
  async connectedCallback() {
18878
+ // On re-attach (didLoad already true but disconnectedCallback ran since),
18879
+ // componentDidLoad will not fire again — re-run setup here.
18880
+ if (this.didLoad) {
18881
+ this.checkCollapsibleFooter();
18882
+ }
18682
18883
  const promise = createKeyboardController(async (keyboardOpen, waitForResize) => {
18683
18884
  /**
18684
18885
  * If the keyboard is hiding, then we need to wait
@@ -18706,6 +18907,7 @@ class Footer {
18706
18907
  }
18707
18908
  }
18708
18909
  disconnectedCallback() {
18910
+ this.destroyCollapsibleFooter();
18709
18911
  if (this.keyboardCtrlPromise) {
18710
18912
  this.keyboardCtrlPromise.then((ctrl) => ctrl.destroy());
18711
18913
  this.keyboardCtrlPromise = null;
@@ -18715,18 +18917,36 @@ class Footer {
18715
18917
  this.keyboardCtrl = null;
18716
18918
  }
18717
18919
  }
18920
+ async setupHideFooter(contentEl) {
18921
+ const token = ++this.setupToken;
18922
+ const scrollEl = await getScrollElement(contentEl);
18923
+ // A newer checkCollapsibleFooter ran while we were awaiting — abandon.
18924
+ if (token !== this.setupToken) {
18925
+ return;
18926
+ }
18927
+ this.scrollEl = scrollEl;
18928
+ this.footerHideCleanup = createFooterHideInteraction(this.el, scrollEl);
18929
+ }
18718
18930
  destroyCollapsibleFooter() {
18931
+ // Invalidate any in-flight setupHideFooter/setupFadeFooter awaits.
18932
+ this.setupToken++;
18933
+ if (this.footerHideCleanup) {
18934
+ this.footerHideCleanup();
18935
+ this.footerHideCleanup = undefined;
18936
+ }
18719
18937
  if (this.scrollEl && this.contentScrollCallback) {
18720
18938
  this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
18721
18939
  this.contentScrollCallback = undefined;
18722
18940
  }
18941
+ this.appliedCollapse = undefined;
18942
+ this.appliedTheme = undefined;
18723
18943
  }
18724
18944
  render() {
18725
18945
  const { translucent, collapse } = this;
18726
18946
  const theme = getIonTheme(this);
18727
18947
  const tabs = this.el.closest('ion-tabs');
18728
18948
  const tabBar = tabs === null || tabs === void 0 ? void 0 : tabs.querySelector(':scope > ion-tab-bar');
18729
- return (hAsync(Host, { key: '4a2989a177b47ee26ffa23e2c9f5418773584796', role: "contentinfo", class: {
18949
+ return (hAsync(Host, { key: '5df79a31f36febfad49c5858727e93c7ba5734f8', role: "contentinfo", class: {
18730
18950
  [theme]: true,
18731
18951
  // Used internally for styling
18732
18952
  [`footer-${theme}`]: true,
@@ -18734,7 +18954,7 @@ class Footer {
18734
18954
  [`footer-translucent-${theme}`]: translucent,
18735
18955
  ['footer-toolbar-padding']: !this.keyboardVisible && (!tabBar || tabBar.slot !== 'bottom'),
18736
18956
  [`footer-collapse-${collapse}`]: collapse !== undefined,
18737
- } }, theme === 'ios' && translucent && hAsync("div", { key: 'c644963db3e06254014e398ea02189d6127ccf61', class: "footer-background" }), hAsync("slot", { key: '839e33c6c30f5c1c703239a19458ff10da9a5e76' })));
18957
+ } }, theme === 'ios' && translucent && hAsync("div", { key: '9175ae4f6576d82dff2a00a36e91f4b633d8c9ad', class: "footer-background" }), hAsync("slot", { key: 'd6d618cdae4726822d8e82edb782c5c86fc7b77b' })));
18738
18958
  }
18739
18959
  get el() { return getElement(this); }
18740
18960
  static get style() { return {
@@ -18764,9 +18984,6 @@ class Footer {
18764
18984
  const LENGTH_PERCENTAGE_PATTERN = /^[-+]?(?:\d+\.?\d*|\.\d+)(?:%|[a-z]+)$/i;
18765
18985
  // Matches simple `calc` / `min` / `max` / `clamp(...)` functions.
18766
18986
  const MATH_FUNCTION_PATTERN = /^(calc|min|max|clamp)\s*\(.+\)$/i;
18767
- // Matches a `var(--name)` reference with an optional fallback, e.g.
18768
- // `var(--my-gap)` or `var(--my-gap, 16px)`.
18769
- const VAR_FUNCTION_PATTERN = /^var\(\s*--[^\s,)]+\s*(?:,[\s\S]*)?\)$/i;
18770
18987
  /**
18771
18988
  * Returns whether `value` matches the [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)
18772
18989
  * syntax. Accepts `<length>` (`<number>` + unit identifier) or `<percentage>` (`<number>%`).
@@ -18781,17 +18998,6 @@ function isValidLengthPercentage(value) {
18781
18998
  }
18782
18999
  return MATH_FUNCTION_PATTERN.test(v) || LENGTH_PERCENTAGE_PATTERN.test(v);
18783
19000
  }
18784
- /**
18785
- * Returns whether `value` is a single [`var()`](https://developer.mozilla.org/en-US/docs/Web/CSS/var)
18786
- * reference, e.g. `var(--my-token)` or `var(--my-token, 16px)`. The referenced
18787
- * custom property is resolved by the browser, so the resolved value is not
18788
- * validated here.
18789
- *
18790
- * @param value String value to validate.
18791
- */
18792
- function isCssVariable(value) {
18793
- return VAR_FUNCTION_PATTERN.test(value.trim());
18794
- }
18795
19001
 
18796
19002
  const DEFAULT_COLUMNS = {
18797
19003
  xs: 2,
@@ -18845,8 +19051,7 @@ class Gallery {
18845
19051
  /**
18846
19052
  * The space between gallery items. Accepts valid CSS [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)
18847
19053
  * values like `16px`, `1rem`, `20%`, math functions like `calc(10px + 20%)`,
18848
- * CSS variables like `var(--app-gallery-gap)`, or numbers (treated as pixel
18849
- * values). Can also be set as a breakpoint map
19054
+ * or numbers (treated as pixel values). Can also be set as a breakpoint map
18850
19055
  * (e.g. `{ xs: '8px', sm: '1rem', md: '24px' }`). Does not accept
18851
19056
  * space-separated values or CSS keyword values like `inherit`, `auto`, etc.
18852
19057
  */
@@ -18967,10 +19172,9 @@ class Gallery {
18967
19172
  return numericColumns;
18968
19173
  }
18969
19174
  /**
18970
- * Normalize a single gap value (`gap` as a number, a string such as a CSS
18971
- * length-percentage or `var()` reference, or one entry from a `gap`
18972
- * breakpoint map) to a CSS length string. Returns `undefined` when the
18973
- * input cannot be interpreted as a valid CSS length or `var()` reference.
19175
+ * Normalize a single gap value (`gap` as a number, string, or one entry from
19176
+ * a `gap` breakpoint map) to a CSS length string. Returns `undefined` when
19177
+ * the input cannot be interpreted as a valid CSS length.
18974
19178
  */
18975
19179
  sanitizeGap(gap) {
18976
19180
  if (gap === undefined) {
@@ -18987,9 +19191,6 @@ class Gallery {
18987
19191
  if (typeof normalizedGap !== 'string') {
18988
19192
  return undefined;
18989
19193
  }
18990
- if (isCssVariable(normalizedGap)) {
18991
- return normalizedGap;
18992
- }
18993
19194
  const isValidCssLength = isValidLengthPercentage(normalizedGap);
18994
19195
  return isValidCssLength ? normalizedGap : undefined;
18995
19196
  }
@@ -19070,7 +19271,7 @@ class Gallery {
19070
19271
  if (this.hasWarnedInvalidGap) {
19071
19272
  return;
19072
19273
  }
19073
- printIonWarning(`[ion-gallery] - Invalid "gap" value (${JSON.stringify(gap)}). Expected a non-negative number, CSS length string, CSS variable (e.g. var(--app-gap)), or breakpoint map object (e.g. { xs: 8, md: "1rem" }).`, this.el);
19274
+ printIonWarning(`[ion-gallery] - Invalid "gap" value (${JSON.stringify(gap)}). Expected a non-negative number, CSS length string, or breakpoint map object (e.g. { xs: 8, md: "1rem" }).`, this.el);
19074
19275
  this.hasWarnedInvalidGap = true;
19075
19276
  }
19076
19277
  /**
@@ -19256,11 +19457,11 @@ class Gallery {
19256
19457
  const { layout } = this;
19257
19458
  const order = this.getOrder();
19258
19459
  const theme = getIonTheme(this);
19259
- return (hAsync(Host, { key: '4f578bea373b422f5dd41395ca04ade699a2f398', class: {
19460
+ return (hAsync(Host, { key: '1bf2973d22835c0dbddf3214b602f8c08b95e421', class: {
19260
19461
  [theme]: true,
19261
19462
  [`gallery-layout-${layout}`]: true,
19262
19463
  [`gallery-order-${order}`]: layout === 'masonry' && order !== undefined,
19263
- } }, hAsync("slot", { key: '0daa3ba1ea894c8c10ab077a6b83476ad5cf514d', onSlotchange: this.onSlotChange })));
19464
+ } }, hAsync("slot", { key: '0dea31f609f6afdb1d73ecb2d873909ffe49203f', onSlotchange: this.onSlotChange })));
19264
19465
  }
19265
19466
  get el() { return getElement(this); }
19266
19467
  static get watchers() { return {
@@ -19503,6 +19704,14 @@ const scaleLargeTitles = (toolbars = [], scale = 1, transition = false) => {
19503
19704
  titleDiv.style.transform = `scale3d(${scale}, ${scale}, 1)`;
19504
19705
  });
19505
19706
  };
19707
+ const createHeaderHideInteraction = (headerEl, scrollEl) => createCollapseHideInteraction({
19708
+ regionEl: headerEl,
19709
+ scrollEl,
19710
+ slideCssVar: '--header-hide-slide-y',
19711
+ contentPartnerClass: 'content-header-hide-scroll-partner',
19712
+ contentHiddenClass: 'content-header-hide-scroll-hidden',
19713
+ regionHiddenClass: 'header-collapse-hide-hidden',
19714
+ });
19506
19715
  const handleHeaderFade = (scrollEl, baseEl, condenseHeader) => {
19507
19716
  readTask(() => {
19508
19717
  const scrollTop = scrollEl.scrollTop;
@@ -19559,11 +19768,11 @@ const getRoleType = (isInsideMenu, isCondensed, theme) => {
19559
19768
  return ROLE_BANNER;
19560
19769
  };
19561
19770
 
19562
- const headerIonicCss = () => `ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}ion-header{z-index:10}ion-header.header-divider{border-bottom:var(--token-border-size-025, var(--token-scale-025, 1px)) var(--token-border-style-solid, solid) var(--token-border-default, var(--token-primitives-neutral-400, #d5d5d5))}ion-toolbar+ion-toolbar{--padding-start:var(--token-space-400, var(--token-scale-400, 16px));--padding-end:var(--token-space-400, var(--token-scale-400, 16px))}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.header-background{right:0;left:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(var(--token-scale-100, 4px));backdrop-filter:saturate(180%) blur(var(--token-scale-100, 4px))}.header-translucent-ionic ion-toolbar{--opacity:0.7}}`;
19771
+ const headerIonicCss = () => `ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}ion-header.header-collapse-hide{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);opacity:1;z-index:10}ion-header.header-collapse-hide.header-collapse-hide-hidden{-webkit-transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));pointer-events:none;-webkit-transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);opacity:0}ion-header{z-index:10}ion-header.header-divider{border-bottom:var(--token-border-size-025, var(--token-scale-025, 1px)) var(--token-border-style-solid, solid) var(--token-border-default, var(--token-primitives-neutral-400, #d5d5d5))}ion-toolbar+ion-toolbar{--padding-start:var(--token-space-400, var(--token-scale-400, 16px));--padding-end:var(--token-space-400, var(--token-scale-400, 16px))}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.header-background{right:0;left:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(var(--token-scale-100, 4px));backdrop-filter:saturate(180%) blur(var(--token-scale-100, 4px))}.header-translucent-ionic ion-toolbar{--opacity:0.7}}`;
19563
19772
 
19564
- const headerIosCss = () => `ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}ion-header{z-index:10}.header-ios ion-toolbar:last-of-type{--border-width:0 0 0.55px}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.header-background{right:0;left:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}.header-translucent-ios ion-toolbar{--opacity:0.8}.header-collapse-condense-inactive .header-background{-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}}.header-ios.ion-no-border ion-toolbar:last-of-type{--border-width:0}.header-collapse-fade ion-toolbar{--opacity-scale:inherit}.header-collapse-fade.header-transitioning ion-toolbar{--background:transparent;--border-style:none}.header-collapse-condense{z-index:9}.header-collapse-condense ion-toolbar{position:-webkit-sticky;position:sticky;top:0}.header-collapse-condense ion-toolbar:first-of-type{padding-top:0px;z-index:1}.header-collapse-condense ion-toolbar{z-index:0}.header-collapse-condense ion-toolbar:last-of-type{--border-width:0px}.header-collapse-condense ion-toolbar ion-searchbar{padding-top:0px;padding-bottom:13px}.header-collapse-main{--opacity-scale:1}.header-collapse-main ion-toolbar{--opacity-scale:inherit}.header-collapse-main ion-toolbar.in-toolbar ion-title,.header-collapse-main ion-toolbar.in-toolbar ion-buttons{-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.header-collapse-condense ion-toolbar,.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar{--background:var(--ion-background-color, #fff)}.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar{--border-style:none;--opacity-scale:1}.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse{opacity:0;pointer-events:none}.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse{visibility:hidden}ion-header.header-ios:not(.header-collapse-main):has(~ion-content ion-header.header-ios[collapse=condense],~ion-content ion-header.header-ios.header-collapse-condense){opacity:0}`;
19773
+ const headerIosCss = () => `ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}ion-header.header-collapse-hide{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);opacity:1;z-index:10}ion-header.header-collapse-hide.header-collapse-hide-hidden{-webkit-transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));pointer-events:none;-webkit-transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);opacity:0}ion-header{z-index:10}.header-ios ion-toolbar:last-of-type{--border-width:0 0 0.55px}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.header-background{right:0;left:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}.header-translucent-ios ion-toolbar{--opacity:0.8}.header-collapse-condense-inactive .header-background{-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}}.header-ios.ion-no-border ion-toolbar:last-of-type{--border-width:0}.header-collapse-fade ion-toolbar{--opacity-scale:inherit}.header-collapse-fade.header-transitioning ion-toolbar{--background:transparent;--border-style:none}.header-collapse-condense{z-index:9}.header-collapse-condense ion-toolbar{position:-webkit-sticky;position:sticky;top:0}.header-collapse-condense ion-toolbar:first-of-type{padding-top:0px;z-index:1}.header-collapse-condense ion-toolbar{z-index:0}.header-collapse-condense ion-toolbar:last-of-type{--border-width:0px}.header-collapse-condense ion-toolbar ion-searchbar{padding-top:0px;padding-bottom:13px}.header-collapse-main{--opacity-scale:1}.header-collapse-main ion-toolbar{--opacity-scale:inherit}.header-collapse-main ion-toolbar.in-toolbar ion-title,.header-collapse-main ion-toolbar.in-toolbar ion-buttons{-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.header-collapse-condense ion-toolbar,.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar{--background:var(--ion-background-color, #fff)}.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar{--border-style:none;--opacity-scale:1}.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse{opacity:0;pointer-events:none}.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse{visibility:hidden}ion-header.header-ios:not(.header-collapse-main):has(~ion-content ion-header.header-ios[collapse=condense],~ion-content ion-header.header-ios.header-collapse-condense){opacity:0}`;
19565
19774
 
19566
- const headerMdCss = () => `ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}ion-header{z-index:10}.header-md{-webkit-box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12)}.header-md.header-collapse-condense{display:none}.header-md.ion-no-border{-webkit-box-shadow:none;box-shadow:none}`;
19775
+ const headerMdCss = () => `ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}ion-header.header-collapse-hide{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);transition:transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1), -webkit-transform 300ms cubic-bezier(0, 0, 0.2, 1);opacity:1;z-index:10}ion-header.header-collapse-hide.header-collapse-hide-hidden{-webkit-transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));transform:translateY(calc(-1 * var(--header-hide-slide-y, 0px)));pointer-events:none;-webkit-transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);transition:transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1), -webkit-transform 200ms cubic-bezier(0.4, 0, 1, 1);opacity:0}ion-header{z-index:10}.header-md{-webkit-box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12)}.header-md.header-collapse-condense{display:none}.header-md.ion-no-border{-webkit-box-shadow:none;box-shadow:none}`;
19567
19776
 
19568
19777
  /**
19569
19778
  * @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
@@ -19573,6 +19782,7 @@ class Header {
19573
19782
  constructor(hostRef) {
19574
19783
  registerInstance(this, hostRef);
19575
19784
  this.inheritedAttributes = {};
19785
+ this.didLoad = false;
19576
19786
  /**
19577
19787
  * If `true`, the header will have a line at the bottom.
19578
19788
  * TODO(ROU-10855): add support for this prop on ios/md themes
@@ -19603,25 +19813,37 @@ class Header {
19603
19813
  this.inheritedAttributes = inheritAriaAttributes(this.el);
19604
19814
  }
19605
19815
  componentDidLoad() {
19816
+ this.didLoad = true;
19606
19817
  this.checkCollapsibleHeader();
19607
19818
  }
19608
19819
  componentDidUpdate() {
19609
19820
  this.checkCollapsibleHeader();
19610
19821
  }
19822
+ connectedCallback() {
19823
+ // On re-attach (didLoad already true but disconnectedCallback ran since),
19824
+ // componentDidLoad will not fire again — re-run setup here.
19825
+ if (this.didLoad) {
19826
+ this.checkCollapsibleHeader();
19827
+ }
19828
+ }
19611
19829
  disconnectedCallback() {
19612
19830
  this.destroyCollapsibleHeader();
19613
19831
  }
19614
19832
  async checkCollapsibleHeader() {
19615
19833
  const theme = getIonTheme(this);
19616
- if (theme !== 'ios') {
19617
- return;
19618
- }
19619
19834
  const { collapse } = this;
19620
19835
  const hasCondense = collapse === 'condense';
19621
19836
  const hasFade = collapse === 'fade';
19837
+ const hasHide = collapse === 'hide';
19838
+ const runIosCollapse = theme === 'ios' && (hasCondense || hasFade);
19839
+ const runHide = hasHide;
19840
+ if (!runIosCollapse && !runHide) {
19841
+ this.destroyCollapsibleHeader();
19842
+ return;
19843
+ }
19622
19844
  this.destroyCollapsibleHeader();
19623
19845
  const appRootSelector = config.get('appRootSelector', 'ion-app');
19624
- if (hasCondense) {
19846
+ if (runIosCollapse && hasCondense) {
19625
19847
  const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
19626
19848
  const contentEl = pageEl ? findIonContent(pageEl) : null;
19627
19849
  // Cloned elements are always needed in iOS transition
@@ -19632,7 +19854,7 @@ class Header {
19632
19854
  });
19633
19855
  await this.setupCondenseHeader(contentEl, pageEl);
19634
19856
  }
19635
- else if (hasFade) {
19857
+ else if (runIosCollapse && hasFade) {
19636
19858
  const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
19637
19859
  const contentEl = pageEl ? findIonContent(pageEl) : null;
19638
19860
  if (!contentEl) {
@@ -19642,12 +19864,29 @@ class Header {
19642
19864
  const condenseHeader = contentEl.querySelector('ion-header[collapse="condense"]');
19643
19865
  await this.setupFadeHeader(contentEl, condenseHeader);
19644
19866
  }
19867
+ if (runHide) {
19868
+ const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
19869
+ const contentEl = pageEl ? findIonContent(pageEl) : null;
19870
+ if (!contentEl) {
19871
+ printIonContentErrorMsg(this.el);
19872
+ return;
19873
+ }
19874
+ await this.setupHideHeader(contentEl);
19875
+ }
19876
+ }
19877
+ async setupHideHeader(contentEl) {
19878
+ const scrollEl = (this.scrollEl = await getScrollElement(contentEl));
19879
+ this.headerHideCleanup = createHeaderHideInteraction(this.el, scrollEl);
19645
19880
  }
19646
19881
  destroyCollapsibleHeader() {
19647
19882
  if (this.intersectionObserver) {
19648
19883
  this.intersectionObserver.disconnect();
19649
19884
  this.intersectionObserver = undefined;
19650
19885
  }
19886
+ if (this.headerHideCleanup) {
19887
+ this.headerHideCleanup();
19888
+ this.headerHideCleanup = undefined;
19889
+ }
19651
19890
  if (this.scrollEl && this.contentScrollCallback) {
19652
19891
  this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
19653
19892
  this.contentScrollCallback = undefined;
@@ -19714,7 +19953,7 @@ class Header {
19714
19953
  const isCondensed = collapse === 'condense';
19715
19954
  // banner role must be at top level, so remove role if inside a menu
19716
19955
  const roleType = getRoleType(hostContext('ion-menu', this.el), isCondensed, theme);
19717
- return (hAsync(Host, Object.assign({ key: 'b43e5f542bdcec5e94c299556183cf6d9d673438', role: roleType, class: {
19956
+ return (hAsync(Host, Object.assign({ key: '5cae1ff0bbc5f2035325c128a9394caf7f1459a0', role: roleType, class: {
19718
19957
  [theme]: true,
19719
19958
  // Used internally for styling
19720
19959
  [`header-${theme}`]: true,
@@ -19722,7 +19961,7 @@ class Header {
19722
19961
  [`header-collapse-${collapse}`]: true,
19723
19962
  [`header-translucent-${theme}`]: this.translucent,
19724
19963
  ['header-divider']: divider,
19725
- } }, inheritedAttributes), theme !== 'md' && translucent && hAsync("div", { key: 'fd9938f02edd38e1afc83025373ec0aec5633711', class: "header-background" }), hAsync("slot", { key: '900aaa7da5d6f08e6f94b128fa065348d595159e' })));
19964
+ } }, inheritedAttributes), theme !== 'md' && translucent && hAsync("div", { key: '705f120951a3dd429286b66cd0b511fa267b3702', class: "header-background" }), hAsync("slot", { key: '1c7a9d474083cf92abfe88c02d363f8d420716ca' })));
19726
19965
  }
19727
19966
  get el() { return getElement(this); }
19728
19967
  static get style() { return {