@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
@@ -91,7 +91,7 @@ Buttons.style = {
91
91
  md: buttonsMdCss()
92
92
  };
93
93
 
94
- 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)}`;
94
+ 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)}`;
95
95
 
96
96
  const Content = class {
97
97
  constructor(hostRef) {
@@ -532,6 +532,171 @@ const updateScrollDetail = (detail, el, timestamp, shouldStart) => {
532
532
  };
533
533
  Content.style = contentCss();
534
534
 
535
+ /** Cumulative downward delta before hiding (header or footer `collapse="hide"`). */
536
+ const COLLAPSE_HIDE_THRESHOLD_PX = 24;
537
+ /**
538
+ * Cumulative upward delta before showing again after hide. Small bias
539
+ * (instead of "any upward delta") guards against inertial-scroll
540
+ * oscillation flicking the region back open during a downward gesture.
541
+ */
542
+ const COLLAPSE_SHOW_THRESHOLD_PX = 5;
543
+ const WHEEL_SCROLL_SUPPRESS_MS = 80;
544
+ const getContentHostFromScrollEl = (scrollEl) => {
545
+ const root = scrollEl.getRootNode();
546
+ if (root instanceof ShadowRoot && root.host instanceof HTMLElement) {
547
+ return root.host;
548
+ }
549
+ // Light-DOM fallback: the scroll element may live inside a non-shadow
550
+ // ion-content (e.g. custom scroll host). Walk up to the nearest ion-content.
551
+ return scrollEl.closest('ion-content');
552
+ };
553
+ const applySlideDistance = (regionEl, contentHost, slideCssVar, heightPx) => {
554
+ const value = `${Math.max(0, Math.ceil(heightPx))}px`;
555
+ regionEl.style.setProperty(slideCssVar, value);
556
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.style.setProperty(slideCssVar, value);
557
+ };
558
+ const clearSlideDistance = (regionEl, contentHost, slideCssVar) => {
559
+ regionEl.style.removeProperty(slideCssVar);
560
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.style.removeProperty(slideCssVar);
561
+ };
562
+ /**
563
+ * Scroll/wheel-driven hide/show for `collapse="hide"` on `ion-header` or `ion-footer`.
564
+ * Hide after {@link COLLAPSE_HIDE_THRESHOLD_PX}px cumulative downward delta; show after
565
+ * {@link COLLAPSE_SHOW_THRESHOLD_PX}px cumulative upward delta. Each direction drains
566
+ * (not resets) the opposing accumulator so inertial-scroll jitter doesn't stall either
567
+ * transition. Motion is defined in component SCSS and `content.scss`; this toggles
568
+ * classes and syncs the slide distance CSS var.
569
+ */
570
+ const createCollapseHideInteraction = ({ regionEl, scrollEl, slideCssVar, contentPartnerClass, contentHiddenClass, regionHiddenClass, }) => {
571
+ const contentHost = getContentHostFromScrollEl(scrollEl);
572
+ if (contentHost !== null) {
573
+ contentHost.classList.add(contentPartnerClass);
574
+ }
575
+ let resizeObserver;
576
+ let destroyed = false;
577
+ const syncSlideDistance = () => {
578
+ index.readTask(() => {
579
+ if (destroyed) {
580
+ return;
581
+ }
582
+ const heightPx = regionEl.offsetHeight;
583
+ index.writeTask(() => {
584
+ if (destroyed) {
585
+ return;
586
+ }
587
+ applySlideDistance(regionEl, contentHost, slideCssVar, heightPx);
588
+ });
589
+ });
590
+ };
591
+ if (typeof ResizeObserver !== 'undefined') {
592
+ resizeObserver = new ResizeObserver(() => {
593
+ syncSlideDistance();
594
+ });
595
+ resizeObserver.observe(regionEl);
596
+ }
597
+ syncSlideDistance();
598
+ requestAnimationFrame(() => {
599
+ if (!destroyed) {
600
+ syncSlideDistance();
601
+ }
602
+ });
603
+ let hidden = false;
604
+ let accDown = 0;
605
+ let accUp = 0;
606
+ let lastScrollTop = scrollEl.scrollTop;
607
+ let lastWheelTime = 0;
608
+ const setHidden = (next) => {
609
+ if (hidden === next || destroyed) {
610
+ return;
611
+ }
612
+ hidden = next;
613
+ // When transitioning to hidden, re-measure synchronously in case the
614
+ // initial layout reported offsetHeight === 0 (e.g. mid page transition).
615
+ // Without this the slide animates by 0px and only opacity fades.
616
+ if (hidden) {
617
+ const heightPx = regionEl.offsetHeight;
618
+ if (heightPx > 0) {
619
+ applySlideDistance(regionEl, contentHost, slideCssVar, heightPx);
620
+ }
621
+ }
622
+ index.writeTask(() => {
623
+ if (destroyed) {
624
+ return;
625
+ }
626
+ regionEl.classList.toggle(regionHiddenClass, hidden);
627
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.classList.toggle(contentHiddenClass, hidden);
628
+ if (hidden) {
629
+ // `inert` removes the subtree from the tab order and AT, AND moves
630
+ // focus out automatically in supporting browsers. `aria-hidden` is
631
+ // kept as a fallback for older engines without `inert` support.
632
+ regionEl.setAttribute('inert', '');
633
+ regionEl.setAttribute('aria-hidden', 'true');
634
+ }
635
+ else {
636
+ regionEl.removeAttribute('inert');
637
+ regionEl.removeAttribute('aria-hidden');
638
+ }
639
+ });
640
+ };
641
+ // Accumulate cumulative movement in each direction. The OPPOSITE accumulator
642
+ // is drained (not reset) by each event, so brief inertial jitter does not
643
+ // wipe a sustained gesture's accumulation. Crossing a threshold resets both.
644
+ const processDelta = (delta) => {
645
+ if (delta > 0) {
646
+ accUp = Math.max(0, accUp - delta);
647
+ accDown += delta;
648
+ if (accDown >= COLLAPSE_HIDE_THRESHOLD_PX) {
649
+ setHidden(true);
650
+ accDown = 0;
651
+ accUp = 0;
652
+ }
653
+ }
654
+ else if (delta < 0) {
655
+ const mag = -delta;
656
+ accDown = Math.max(0, accDown - mag);
657
+ accUp += mag;
658
+ if (accUp >= COLLAPSE_SHOW_THRESHOLD_PX) {
659
+ setHidden(false);
660
+ accUp = 0;
661
+ accDown = 0;
662
+ }
663
+ }
664
+ };
665
+ const onWheel = (ev) => {
666
+ if (destroyed) {
667
+ return;
668
+ }
669
+ lastWheelTime = performance.now();
670
+ processDelta(ev.deltaY);
671
+ };
672
+ const onScroll = () => {
673
+ if (destroyed) {
674
+ return;
675
+ }
676
+ const st = scrollEl.scrollTop;
677
+ if (performance.now() - lastWheelTime < WHEEL_SCROLL_SUPPRESS_MS) {
678
+ lastScrollTop = st;
679
+ return;
680
+ }
681
+ const delta = st - lastScrollTop;
682
+ lastScrollTop = st;
683
+ processDelta(delta);
684
+ };
685
+ scrollEl.addEventListener('wheel', onWheel, { passive: true });
686
+ scrollEl.addEventListener('scroll', onScroll, { passive: true });
687
+ return () => {
688
+ destroyed = true;
689
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
690
+ scrollEl.removeEventListener('wheel', onWheel);
691
+ scrollEl.removeEventListener('scroll', onScroll);
692
+ regionEl.classList.remove(regionHiddenClass);
693
+ regionEl.removeAttribute('inert');
694
+ regionEl.removeAttribute('aria-hidden');
695
+ contentHost === null || contentHost === void 0 ? void 0 : contentHost.classList.remove(contentPartnerClass, contentHiddenClass);
696
+ clearSlideDistance(regionEl, contentHost, slideCssVar);
697
+ };
698
+ };
699
+
535
700
  const handleFooterFade = (scrollEl, baseEl) => {
536
701
  index.readTask(() => {
537
702
  const scrollTop = scrollEl.scrollTop;
@@ -560,16 +725,26 @@ const handleFooterFade = (scrollEl, baseEl) => {
560
725
  });
561
726
  });
562
727
  };
728
+ const createFooterHideInteraction = (footerEl, scrollEl) => createCollapseHideInteraction({
729
+ regionEl: footerEl,
730
+ scrollEl,
731
+ slideCssVar: '--footer-hide-slide-y',
732
+ contentPartnerClass: 'content-footer-hide-scroll-partner',
733
+ contentHiddenClass: 'content-footer-hide-scroll-hidden',
734
+ regionHiddenClass: 'footer-collapse-hide-hidden',
735
+ });
563
736
 
564
- 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}`;
737
+ 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}`;
565
738
 
566
- 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}`;
739
+ 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}`;
567
740
 
568
- 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}`;
741
+ 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}`;
569
742
 
570
743
  const Footer = class {
571
744
  constructor(hostRef) {
572
745
  index.registerInstance(this, hostRef);
746
+ this.didLoad = false;
747
+ this.setupToken = 0;
573
748
  this.keyboardCtrl = null;
574
749
  this.keyboardCtrlPromise = null;
575
750
  this.keyboardVisible = false;
@@ -584,25 +759,45 @@ const Footer = class {
584
759
  this.translucent = false;
585
760
  this.checkCollapsibleFooter = () => {
586
761
  const theme = ionicGlobal.getIonTheme(this);
587
- if (theme !== 'ios') {
588
- return;
589
- }
590
762
  const { collapse } = this;
591
763
  const hasFade = collapse === 'fade';
764
+ const hasHide = collapse === 'hide';
765
+ const runIosFade = theme === 'ios' && hasFade;
766
+ if (!runIosFade && !hasHide) {
767
+ this.destroyCollapsibleFooter();
768
+ return;
769
+ }
770
+ // Skip teardown/rebuild when the collapse mode and theme have not changed
771
+ // since the last setup — avoids thrashing listeners and resetting scroll
772
+ // accumulators on unrelated re-renders (e.g. keyboardVisible state flips).
773
+ const activeMode = hasHide ? 'hide' : 'fade';
774
+ if (this.appliedCollapse === activeMode && this.appliedTheme === theme) {
775
+ return;
776
+ }
592
777
  this.destroyCollapsibleFooter();
593
- if (hasFade) {
594
- const appRootSelector = index.config.get('appRootSelector', 'ion-app');
595
- const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
596
- const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
597
- if (!contentEl) {
598
- index$1.printIonContentErrorMsg(this.el);
599
- return;
600
- }
778
+ const appRootSelector = index.config.get('appRootSelector', 'ion-app');
779
+ const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
780
+ const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
781
+ if (!contentEl) {
782
+ index$1.printIonContentErrorMsg(this.el);
783
+ return;
784
+ }
785
+ this.appliedCollapse = activeMode;
786
+ this.appliedTheme = theme;
787
+ if (runIosFade) {
601
788
  this.setupFadeFooter(contentEl);
602
789
  }
790
+ else if (hasHide) {
791
+ void this.setupHideFooter(contentEl);
792
+ }
603
793
  };
604
794
  this.setupFadeFooter = async (contentEl) => {
605
- const scrollEl = (this.scrollEl = await index$1.getScrollElement(contentEl));
795
+ const token = ++this.setupToken;
796
+ const scrollEl = await index$1.getScrollElement(contentEl);
797
+ if (token !== this.setupToken) {
798
+ return;
799
+ }
800
+ this.scrollEl = scrollEl;
606
801
  /**
607
802
  * Handle fading of toolbars on scroll
608
803
  */
@@ -614,12 +809,18 @@ const Footer = class {
614
809
  };
615
810
  }
616
811
  componentDidLoad() {
812
+ this.didLoad = true;
617
813
  this.checkCollapsibleFooter();
618
814
  }
619
815
  componentDidUpdate() {
620
816
  this.checkCollapsibleFooter();
621
817
  }
622
818
  async connectedCallback() {
819
+ // On re-attach (didLoad already true but disconnectedCallback ran since),
820
+ // componentDidLoad will not fire again — re-run setup here.
821
+ if (this.didLoad) {
822
+ this.checkCollapsibleFooter();
823
+ }
623
824
  const promise = keyboardController.createKeyboardController(async (keyboardOpen, waitForResize) => {
624
825
  /**
625
826
  * If the keyboard is hiding, then we need to wait
@@ -647,6 +848,7 @@ const Footer = class {
647
848
  }
648
849
  }
649
850
  disconnectedCallback() {
851
+ this.destroyCollapsibleFooter();
650
852
  if (this.keyboardCtrlPromise) {
651
853
  this.keyboardCtrlPromise.then((ctrl) => ctrl.destroy());
652
854
  this.keyboardCtrlPromise = null;
@@ -656,18 +858,36 @@ const Footer = class {
656
858
  this.keyboardCtrl = null;
657
859
  }
658
860
  }
861
+ async setupHideFooter(contentEl) {
862
+ const token = ++this.setupToken;
863
+ const scrollEl = await index$1.getScrollElement(contentEl);
864
+ // A newer checkCollapsibleFooter ran while we were awaiting — abandon.
865
+ if (token !== this.setupToken) {
866
+ return;
867
+ }
868
+ this.scrollEl = scrollEl;
869
+ this.footerHideCleanup = createFooterHideInteraction(this.el, scrollEl);
870
+ }
659
871
  destroyCollapsibleFooter() {
872
+ // Invalidate any in-flight setupHideFooter/setupFadeFooter awaits.
873
+ this.setupToken++;
874
+ if (this.footerHideCleanup) {
875
+ this.footerHideCleanup();
876
+ this.footerHideCleanup = undefined;
877
+ }
660
878
  if (this.scrollEl && this.contentScrollCallback) {
661
879
  this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
662
880
  this.contentScrollCallback = undefined;
663
881
  }
882
+ this.appliedCollapse = undefined;
883
+ this.appliedTheme = undefined;
664
884
  }
665
885
  render() {
666
886
  const { translucent, collapse } = this;
667
887
  const theme = ionicGlobal.getIonTheme(this);
668
888
  const tabs = this.el.closest('ion-tabs');
669
889
  const tabBar = tabs === null || tabs === void 0 ? void 0 : tabs.querySelector(':scope > ion-tab-bar');
670
- return (index.h(index.Host, { key: '4a2989a177b47ee26ffa23e2c9f5418773584796', role: "contentinfo", class: {
890
+ return (index.h(index.Host, { key: '5df79a31f36febfad49c5858727e93c7ba5734f8', role: "contentinfo", class: {
671
891
  [theme]: true,
672
892
  // Used internally for styling
673
893
  [`footer-${theme}`]: true,
@@ -675,7 +895,7 @@ const Footer = class {
675
895
  [`footer-translucent-${theme}`]: translucent,
676
896
  ['footer-toolbar-padding']: !this.keyboardVisible && (!tabBar || tabBar.slot !== 'bottom'),
677
897
  [`footer-collapse-${collapse}`]: collapse !== undefined,
678
- } }, theme === 'ios' && translucent && index.h("div", { key: 'c644963db3e06254014e398ea02189d6127ccf61', class: "footer-background" }), index.h("slot", { key: '839e33c6c30f5c1c703239a19458ff10da9a5e76' })));
898
+ } }, theme === 'ios' && translucent && index.h("div", { key: '9175ae4f6576d82dff2a00a36e91f4b633d8c9ad', class: "footer-background" }), index.h("slot", { key: 'd6d618cdae4726822d8e82edb782c5c86fc7b77b' })));
679
899
  }
680
900
  get el() { return index.getElement(this); }
681
901
  };
@@ -861,6 +1081,14 @@ const scaleLargeTitles = (toolbars = [], scale = 1, transition = false) => {
861
1081
  titleDiv.style.transform = `scale3d(${scale}, ${scale}, 1)`;
862
1082
  });
863
1083
  };
1084
+ const createHeaderHideInteraction = (headerEl, scrollEl) => createCollapseHideInteraction({
1085
+ regionEl: headerEl,
1086
+ scrollEl,
1087
+ slideCssVar: '--header-hide-slide-y',
1088
+ contentPartnerClass: 'content-header-hide-scroll-partner',
1089
+ contentHiddenClass: 'content-header-hide-scroll-hidden',
1090
+ regionHiddenClass: 'header-collapse-hide-hidden',
1091
+ });
864
1092
  const handleHeaderFade = (scrollEl, baseEl, condenseHeader) => {
865
1093
  index.readTask(() => {
866
1094
  const scrollTop = scrollEl.scrollTop;
@@ -917,16 +1145,17 @@ const getRoleType = (isInsideMenu, isCondensed, theme) => {
917
1145
  return ROLE_BANNER;
918
1146
  };
919
1147
 
920
- 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}}`;
1148
+ 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}}`;
921
1149
 
922
- 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}`;
1150
+ 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}`;
923
1151
 
924
- 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}`;
1152
+ 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}`;
925
1153
 
926
1154
  const Header = class {
927
1155
  constructor(hostRef) {
928
1156
  index.registerInstance(this, hostRef);
929
1157
  this.inheritedAttributes = {};
1158
+ this.didLoad = false;
930
1159
  /**
931
1160
  * If `true`, the header will have a line at the bottom.
932
1161
  * TODO(ROU-10855): add support for this prop on ios/md themes
@@ -957,25 +1186,37 @@ const Header = class {
957
1186
  this.inheritedAttributes = helpers.inheritAriaAttributes(this.el);
958
1187
  }
959
1188
  componentDidLoad() {
1189
+ this.didLoad = true;
960
1190
  this.checkCollapsibleHeader();
961
1191
  }
962
1192
  componentDidUpdate() {
963
1193
  this.checkCollapsibleHeader();
964
1194
  }
1195
+ connectedCallback() {
1196
+ // On re-attach (didLoad already true but disconnectedCallback ran since),
1197
+ // componentDidLoad will not fire again — re-run setup here.
1198
+ if (this.didLoad) {
1199
+ this.checkCollapsibleHeader();
1200
+ }
1201
+ }
965
1202
  disconnectedCallback() {
966
1203
  this.destroyCollapsibleHeader();
967
1204
  }
968
1205
  async checkCollapsibleHeader() {
969
1206
  const theme = ionicGlobal.getIonTheme(this);
970
- if (theme !== 'ios') {
971
- return;
972
- }
973
1207
  const { collapse } = this;
974
1208
  const hasCondense = collapse === 'condense';
975
1209
  const hasFade = collapse === 'fade';
1210
+ const hasHide = collapse === 'hide';
1211
+ const runIosCollapse = theme === 'ios' && (hasCondense || hasFade);
1212
+ const runHide = hasHide;
1213
+ if (!runIosCollapse && !runHide) {
1214
+ this.destroyCollapsibleHeader();
1215
+ return;
1216
+ }
976
1217
  this.destroyCollapsibleHeader();
977
1218
  const appRootSelector = index.config.get('appRootSelector', 'ion-app');
978
- if (hasCondense) {
1219
+ if (runIosCollapse && hasCondense) {
979
1220
  const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
980
1221
  const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
981
1222
  // Cloned elements are always needed in iOS transition
@@ -986,7 +1227,7 @@ const Header = class {
986
1227
  });
987
1228
  await this.setupCondenseHeader(contentEl, pageEl);
988
1229
  }
989
- else if (hasFade) {
1230
+ else if (runIosCollapse && hasFade) {
990
1231
  const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
991
1232
  const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
992
1233
  if (!contentEl) {
@@ -996,12 +1237,29 @@ const Header = class {
996
1237
  const condenseHeader = contentEl.querySelector('ion-header[collapse="condense"]');
997
1238
  await this.setupFadeHeader(contentEl, condenseHeader);
998
1239
  }
1240
+ if (runHide) {
1241
+ const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
1242
+ const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
1243
+ if (!contentEl) {
1244
+ index$1.printIonContentErrorMsg(this.el);
1245
+ return;
1246
+ }
1247
+ await this.setupHideHeader(contentEl);
1248
+ }
1249
+ }
1250
+ async setupHideHeader(contentEl) {
1251
+ const scrollEl = (this.scrollEl = await index$1.getScrollElement(contentEl));
1252
+ this.headerHideCleanup = createHeaderHideInteraction(this.el, scrollEl);
999
1253
  }
1000
1254
  destroyCollapsibleHeader() {
1001
1255
  if (this.intersectionObserver) {
1002
1256
  this.intersectionObserver.disconnect();
1003
1257
  this.intersectionObserver = undefined;
1004
1258
  }
1259
+ if (this.headerHideCleanup) {
1260
+ this.headerHideCleanup();
1261
+ this.headerHideCleanup = undefined;
1262
+ }
1005
1263
  if (this.scrollEl && this.contentScrollCallback) {
1006
1264
  this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
1007
1265
  this.contentScrollCallback = undefined;
@@ -1068,7 +1326,7 @@ const Header = class {
1068
1326
  const isCondensed = collapse === 'condense';
1069
1327
  // banner role must be at top level, so remove role if inside a menu
1070
1328
  const roleType = getRoleType(theme.hostContext('ion-menu', this.el), isCondensed, theme$1);
1071
- return (index.h(index.Host, Object.assign({ key: 'b43e5f542bdcec5e94c299556183cf6d9d673438', role: roleType, class: {
1329
+ return (index.h(index.Host, Object.assign({ key: '5cae1ff0bbc5f2035325c128a9394caf7f1459a0', role: roleType, class: {
1072
1330
  [theme$1]: true,
1073
1331
  // Used internally for styling
1074
1332
  [`header-${theme$1}`]: true,
@@ -1076,7 +1334,7 @@ const Header = class {
1076
1334
  [`header-collapse-${collapse}`]: true,
1077
1335
  [`header-translucent-${theme$1}`]: this.translucent,
1078
1336
  ['header-divider']: divider,
1079
- } }, inheritedAttributes), theme$1 !== 'md' && translucent && index.h("div", { key: 'fd9938f02edd38e1afc83025373ec0aec5633711', class: "header-background" }), index.h("slot", { key: '900aaa7da5d6f08e6f94b128fa065348d595159e' })));
1337
+ } }, inheritedAttributes), theme$1 !== 'md' && translucent && index.h("div", { key: '705f120951a3dd429286b66cd0b511fa267b3702', class: "header-background" }), index.h("slot", { key: '1c7a9d474083cf92abfe88c02d363f8d420716ca' })));
1080
1338
  }
1081
1339
  get el() { return index.getElement(this); }
1082
1340
  };
@@ -16,9 +16,6 @@ require('./focus-visible-BIj-I3-C.js');
16
16
  const LENGTH_PERCENTAGE_PATTERN = /^[-+]?(?:\d+\.?\d*|\.\d+)(?:%|[a-z]+)$/i;
17
17
  // Matches simple `calc` / `min` / `max` / `clamp(...)` functions.
18
18
  const MATH_FUNCTION_PATTERN = /^(calc|min|max|clamp)\s*\(.+\)$/i;
19
- // Matches a `var(--name)` reference with an optional fallback, e.g.
20
- // `var(--my-gap)` or `var(--my-gap, 16px)`.
21
- const VAR_FUNCTION_PATTERN = /^var\(\s*--[^\s,)]+\s*(?:,[\s\S]*)?\)$/i;
22
19
  /**
23
20
  * Returns whether `value` matches the [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)
24
21
  * syntax. Accepts `<length>` (`<number>` + unit identifier) or `<percentage>` (`<number>%`).
@@ -33,17 +30,6 @@ function isValidLengthPercentage(value) {
33
30
  }
34
31
  return MATH_FUNCTION_PATTERN.test(v) || LENGTH_PERCENTAGE_PATTERN.test(v);
35
32
  }
36
- /**
37
- * Returns whether `value` is a single [`var()`](https://developer.mozilla.org/en-US/docs/Web/CSS/var)
38
- * reference, e.g. `var(--my-token)` or `var(--my-token, 16px)`. The referenced
39
- * custom property is resolved by the browser, so the resolved value is not
40
- * validated here.
41
- *
42
- * @param value String value to validate.
43
- */
44
- function isCssVariable(value) {
45
- return VAR_FUNCTION_PATTERN.test(value.trim());
46
- }
47
33
 
48
34
  const DEFAULT_COLUMNS = {
49
35
  xs: 2,
@@ -91,8 +77,7 @@ const Gallery = class {
91
77
  /**
92
78
  * The space between gallery items. Accepts valid CSS [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)
93
79
  * values like `16px`, `1rem`, `20%`, math functions like `calc(10px + 20%)`,
94
- * CSS variables like `var(--app-gallery-gap)`, or numbers (treated as pixel
95
- * values). Can also be set as a breakpoint map
80
+ * or numbers (treated as pixel values). Can also be set as a breakpoint map
96
81
  * (e.g. `{ xs: '8px', sm: '1rem', md: '24px' }`). Does not accept
97
82
  * space-separated values or CSS keyword values like `inherit`, `auto`, etc.
98
83
  */
@@ -213,10 +198,9 @@ const Gallery = class {
213
198
  return numericColumns;
214
199
  }
215
200
  /**
216
- * Normalize a single gap value (`gap` as a number, a string such as a CSS
217
- * length-percentage or `var()` reference, or one entry from a `gap`
218
- * breakpoint map) to a CSS length string. Returns `undefined` when the
219
- * input cannot be interpreted as a valid CSS length or `var()` reference.
201
+ * Normalize a single gap value (`gap` as a number, string, or one entry from
202
+ * a `gap` breakpoint map) to a CSS length string. Returns `undefined` when
203
+ * the input cannot be interpreted as a valid CSS length.
220
204
  */
221
205
  sanitizeGap(gap) {
222
206
  if (gap === undefined) {
@@ -233,9 +217,6 @@ const Gallery = class {
233
217
  if (typeof normalizedGap !== 'string') {
234
218
  return undefined;
235
219
  }
236
- if (isCssVariable(normalizedGap)) {
237
- return normalizedGap;
238
- }
239
220
  const isValidCssLength = isValidLengthPercentage(normalizedGap);
240
221
  return isValidCssLength ? normalizedGap : undefined;
241
222
  }
@@ -316,7 +297,7 @@ const Gallery = class {
316
297
  if (this.hasWarnedInvalidGap) {
317
298
  return;
318
299
  }
319
- index.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);
300
+ index.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);
320
301
  this.hasWarnedInvalidGap = true;
321
302
  }
322
303
  /**
@@ -502,11 +483,11 @@ const Gallery = class {
502
483
  const { layout } = this;
503
484
  const order = this.getOrder();
504
485
  const theme = ionicGlobal.getIonTheme(this);
505
- return (index.h(index.Host, { key: '4f578bea373b422f5dd41395ca04ade699a2f398', class: {
486
+ return (index.h(index.Host, { key: '1bf2973d22835c0dbddf3214b602f8c08b95e421', class: {
506
487
  [theme]: true,
507
488
  [`gallery-layout-${layout}`]: true,
508
489
  [`gallery-order-${order}`]: layout === 'masonry' && order !== undefined,
509
- } }, index.h("slot", { key: '0daa3ba1ea894c8c10ab077a6b83476ad5cf514d', onSlotchange: this.onSlotChange })));
490
+ } }, index.h("slot", { key: '0dea31f609f6afdb1d73ecb2d873909ffe49203f', onSlotchange: this.onSlotChange })));
510
491
  }
511
492
  get el() { return index.getElement(this); }
512
493
  static get watchers() { return {