@ajuarezso/sui-design-system 0.11.2 → 0.11.3

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.
@@ -10698,6 +10698,7 @@ class SuiModalSheet {
10698
10698
  }
10699
10699
  ngOnDestroy() {
10700
10700
  this.removeEscapeHandler();
10701
+ this.detachTouchSuppressor();
10701
10702
  this.unlockBodyScroll();
10702
10703
  if (this.wasOpen) {
10703
10704
  this.navbarVisibility?.release(this._sheetId);
@@ -10726,16 +10727,73 @@ class SuiModalSheet {
10726
10727
  setTimeout(() => {
10727
10728
  const initial = this.initialBreakpoint();
10728
10729
  this.snapTo(initial, false);
10730
+ this.attachTouchSuppressor();
10729
10731
  }, 0);
10730
10732
  }
10731
10733
  onClose() {
10732
10734
  this.removeEscapeHandler();
10735
+ this.detachTouchSuppressor();
10733
10736
  this.unlockBodyScroll();
10734
10737
  this.navbarVisibility?.release(this._sheetId);
10735
10738
  this.liveProgress.set(0);
10736
10739
  this.currentBreakpoint.set(0);
10737
10740
  this.closed.emit();
10738
10741
  }
10742
+ // ── Supresor de scroll nativo (handoff scroll→drag en iOS WKWebView) ──────
10743
+ //
10744
+ // GOTCHA WKWebView: con el body en touch-action pan-y (sheet al max), apenas
10745
+ // WebKit inicia el scroll nativo dispara `pointercancel` y deja de emitir
10746
+ // pointermove — el drag del sheet nunca recibe el gesto. Síntoma real
10747
+ // (iPhone, 2026-07-24): sheet al 100%, scroll en top 0, jalar hacia abajo →
10748
+ // el contenido rubber-bandea y el sheet no se reduce.
10749
+ //
10750
+ // Fix canon: touchmove NO-pasivo que hace preventDefault SOLO cuando el drag
10751
+ // debe tomar el gesto (scrollTop ≤ 0 + dedo hacia abajo, o drag ya activo).
10752
+ // Con el default prevenido, el scroll nativo nunca arranca y los pointer
10753
+ // events siguen fluyendo hacia la lógica de drag existente. Los touch
10754
+ // handlers de Angular son pasivos por default — por eso se atachan a mano.
10755
+ touchStartY = 0;
10756
+ touchStartHandler;
10757
+ touchMoveHandler;
10758
+ attachTouchSuppressor() {
10759
+ const body = this.bodyRef?.nativeElement;
10760
+ if (!body || this.touchMoveHandler)
10761
+ return;
10762
+ this.touchStartHandler = (e) => {
10763
+ this.touchStartY = e.touches[0]?.clientY ?? 0;
10764
+ };
10765
+ this.touchMoveHandler = (e) => {
10766
+ const y = e.touches[0]?.clientY ?? 0;
10767
+ const dy = y - this.touchStartY;
10768
+ /* Drag del sheet ya activo → el scroll nativo no debe pelear. */
10769
+ if (this.dragging()) {
10770
+ if (e.cancelable)
10771
+ e.preventDefault();
10772
+ return;
10773
+ }
10774
+ /* Sheet al max + body en top + dedo hacia abajo → este gesto es del
10775
+ sheet (reducir), no del scroll. Prevenir ANTES de que WebKit lo tome. */
10776
+ if (this.atMaxBreakpoint()) {
10777
+ const el = this.bodyRef?.nativeElement;
10778
+ if (el && el.scrollTop <= 0 && dy > 0 && e.cancelable) {
10779
+ e.preventDefault();
10780
+ }
10781
+ }
10782
+ };
10783
+ body.addEventListener('touchstart', this.touchStartHandler, { passive: true });
10784
+ body.addEventListener('touchmove', this.touchMoveHandler, { passive: false });
10785
+ }
10786
+ detachTouchSuppressor() {
10787
+ const body = this.bodyRef?.nativeElement;
10788
+ if (body) {
10789
+ if (this.touchStartHandler)
10790
+ body.removeEventListener('touchstart', this.touchStartHandler);
10791
+ if (this.touchMoveHandler)
10792
+ body.removeEventListener('touchmove', this.touchMoveHandler);
10793
+ }
10794
+ this.touchStartHandler = undefined;
10795
+ this.touchMoveHandler = undefined;
10796
+ }
10739
10797
  // ── Drag gesture ──────────────────────────────────────────────────────────
10740
10798
  onPointerDown(event) {
10741
10799
  /* Solo eventos primarios (un dedo, click izquierdo). Multi-touch zoom etc.
@@ -11012,13 +11070,13 @@ class SuiModalSheet {
11012
11070
  }
11013
11071
  }
11014
11072
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiModalSheet, deps: [], target: i0.ɵɵFactoryTarget.Component });
11015
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiModalSheet, isStandalone: true, selector: "sui-modal-sheet", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, breakpoints: { classPropertyName: "breakpoints", publicName: "breakpoints", isSignal: true, isRequired: false, transformFunction: null }, initialBreakpoint: { classPropertyName: "initialBreakpoint", publicName: "initialBreakpoint", isSignal: true, isRequired: false, transformFunction: null }, backdropBreakpoint: { classPropertyName: "backdropBreakpoint", publicName: "backdropBreakpoint", isSignal: true, isRequired: false, transformFunction: null }, showHandle: { classPropertyName: "showHandle", publicName: "showHandle", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, fullBody: { classPropertyName: "fullBody", publicName: "fullBody", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed", breakpointChange: "breakpointChange" }, host: { properties: { "attr.data-sui-sheet-open": "open() ? \"\" : null" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }, { propertyName: "handleRef", first: true, predicate: ["handle"], descendants: true }, { propertyName: "bodyRef", first: true, predicate: ["body"], descendants: true }], ngImport: i0, template: "@if (open()) {\n <!-- Backdrop con opacity din\u00E1mica.\n pointer-events: none cuando current \u2264 backdropBreakpoint para dejar\n interactivo el contenido debajo (ej. mapa). -->\n <div\n class=\"sui-sheet__backdrop\"\n [style.opacity]=\"backdropOpacity()\"\n [style.pointer-events]=\"backdropInteractive() ? 'auto' : 'none'\"\n (click)=\"onBackdropClick()\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Sheet container \u2014 anclado al bottom, altura din\u00E1mica.\n Usar `height` en vez de transform para que el \u00E1rea \"no cubierta\" del\n viewport (donde se ve el mapa) NO sea parte del DOM del sheet \u2014\n contenido de fondo autom\u00E1ticamente interactivo, scroll del body\n respeta la altura visible (no fantasma). -->\n <div\n #container\n class=\"sui-sheet\"\n role=\"dialog\"\n aria-modal=\"true\"\n [class.sui-sheet--dragging]=\"dragging()\"\n [style.max-height]=\"heightCss()\"\n [style.--sheet-progress]=\"liveProgress()\"\n >\n @if (showHandle()) {\n <!-- Drag handle (pill). Solo este elemento captura los pointer events\n del drag \u2014 el resto del sheet permite scroll/clicks normales. -->\n <div\n #handle\n class=\"sui-sheet__handle\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n >\n <div class=\"sui-sheet__handle-pill\"></div>\n </div>\n }\n\n <!-- Body con scroll interno. Consumer proyecta su contenido aqu\u00ED.\n Acepta drag con patr\u00F3n scroll-then-drag (iOS canon):\n - Si el body est\u00E1 scrolleado (scrollTop > 0), el drag se ignora y\n el touch hace scroll normal.\n - Si est\u00E1 en top (scrollTop === 0) y el user arrastra hacia abajo,\n se inicia drag del sheet.\n - Si est\u00E1 en max breakpoint y user arrastra hacia abajo, se inicia\n drag (incluso con scrollTop === 0 ya cubre eso).\n - Drag hacia arriba siempre permite scroll del body (no roba el gesto). -->\n <div\n #body\n class=\"sui-sheet__body\"\n [class.sui-sheet__body--full]=\"fullBody()\"\n [class.sui-sheet__body--scrollable]=\"atMaxBreakpoint()\"\n (pointerdown)=\"onBodyPointerDown($event)\"\n (pointermove)=\"onBodyPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n >\n <ng-content />\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.sui-sheet__backdrop{position:fixed;inset:0;z-index:1000;background-color:#3333333d;transition:opacity .35s cubic-bezier(.32,.72,0,1)}.sui-sheet--dragging~.sui-sheet__backdrop,:host([data-sui-sheet-open]) .sui-sheet--dragging+.sui-sheet__backdrop{transition:none}.sui-sheet{position:fixed;bottom:8px;left:8px;right:8px;z-index:1001;display:flex;flex-direction:column;box-sizing:border-box;height:max-content;background:var(--sui-bg-white-0, #ffffff);border-radius:36px 36px 54px 54px;corner-shape:squircle}@supports (clip-path: shape(from 0 0,close)){.sui-sheet{--sq-t: 45px;--sq-b: 68px;clip-path:shape(from 0 var(--sq-t),curve to var(--sq-t) 0 with 0 0/0 0,hline to calc(100% - var(--sq-t)),curve to 100% var(--sq-t) with 100% 0/100% 0,vline to calc(100% - var(--sq-b)),curve to calc(100% - var(--sq-b)) 100% with 100% 100%/100% 100%,hline to var(--sq-b),curve to 0 calc(100% - var(--sq-b)) with 0 100%/0 100%,close);box-shadow:none!important;filter:drop-shadow(0 -3px 8px rgba(14,18,27,.07))}}.sui-sheet{box-shadow:0 -8px 32px -12px #0e121b2e;overflow:hidden;overscroll-behavior:contain;will-change:max-height;transition:max-height .35s cubic-bezier(.32,.72,0,1)}.sui-sheet--dragging{transition:none}:host-context(html.platform-android) .sui-sheet{border-radius:var(--sui-radius-20, 20px);--sq-t: 25px;--sq-b: 25px}.sui-sheet__handle{flex-shrink:0;display:flex;align-items:center;justify-content:center;padding:12px 0 8px;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}.sui-sheet__handle:active{cursor:grabbing}.sui-sheet__handle-pill{width:36px;height:5px;border-radius:999px;background:var(--sui-bg-soft-200, #d4d4d8)}.sui-sheet__body{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;touch-action:none;padding:0 20px 20px}.sui-sheet__body--scrollable{touch-action:pan-y}.sui-sheet__body--full{padding:0}@media(max-width:767px){.sui-sheet__body{scrollbar-width:none}.sui-sheet__body::-webkit-scrollbar{display:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11073
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiModalSheet, isStandalone: true, selector: "sui-modal-sheet", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, breakpoints: { classPropertyName: "breakpoints", publicName: "breakpoints", isSignal: true, isRequired: false, transformFunction: null }, initialBreakpoint: { classPropertyName: "initialBreakpoint", publicName: "initialBreakpoint", isSignal: true, isRequired: false, transformFunction: null }, backdropBreakpoint: { classPropertyName: "backdropBreakpoint", publicName: "backdropBreakpoint", isSignal: true, isRequired: false, transformFunction: null }, showHandle: { classPropertyName: "showHandle", publicName: "showHandle", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, fullBody: { classPropertyName: "fullBody", publicName: "fullBody", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed", breakpointChange: "breakpointChange" }, host: { properties: { "attr.data-sui-sheet-open": "open() ? \"\" : null" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }, { propertyName: "handleRef", first: true, predicate: ["handle"], descendants: true }, { propertyName: "bodyRef", first: true, predicate: ["body"], descendants: true }], ngImport: i0, template: "@if (open()) {\n <!-- Backdrop con opacity din\u00E1mica.\n pointer-events: none cuando current \u2264 backdropBreakpoint para dejar\n interactivo el contenido debajo (ej. mapa). -->\n <div\n class=\"sui-sheet__backdrop\"\n [style.opacity]=\"backdropOpacity()\"\n [style.pointer-events]=\"backdropInteractive() ? 'auto' : 'none'\"\n (click)=\"onBackdropClick()\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Sheet container \u2014 anclado al bottom, altura din\u00E1mica.\n Usar `height` en vez de transform para que el \u00E1rea \"no cubierta\" del\n viewport (donde se ve el mapa) NO sea parte del DOM del sheet \u2014\n contenido de fondo autom\u00E1ticamente interactivo, scroll del body\n respeta la altura visible (no fantasma). -->\n <div\n #container\n class=\"sui-sheet\"\n role=\"dialog\"\n aria-modal=\"true\"\n [class.sui-sheet--dragging]=\"dragging()\"\n [style.max-height]=\"heightCss()\"\n [style.--sheet-progress]=\"liveProgress()\"\n >\n @if (showHandle()) {\n <!-- Drag handle (pill). Solo este elemento captura los pointer events\n del drag \u2014 el resto del sheet permite scroll/clicks normales. -->\n <div\n #handle\n class=\"sui-sheet__handle\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n >\n <div class=\"sui-sheet__handle-pill\"></div>\n </div>\n }\n\n <!-- Body con scroll interno. Consumer proyecta su contenido aqu\u00ED.\n Acepta drag con patr\u00F3n scroll-then-drag (iOS canon):\n - Si el body est\u00E1 scrolleado (scrollTop > 0), el drag se ignora y\n el touch hace scroll normal.\n - Si est\u00E1 en top (scrollTop === 0) y el user arrastra hacia abajo,\n se inicia drag del sheet.\n - Si est\u00E1 en max breakpoint y user arrastra hacia abajo, se inicia\n drag (incluso con scrollTop === 0 ya cubre eso).\n - Drag hacia arriba siempre permite scroll del body (no roba el gesto). -->\n <div\n #body\n class=\"sui-sheet__body\"\n [class.sui-sheet__body--full]=\"fullBody()\"\n [class.sui-sheet__body--scrollable]=\"atMaxBreakpoint()\"\n (pointerdown)=\"onBodyPointerDown($event)\"\n (pointermove)=\"onBodyPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n >\n <ng-content />\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.sui-sheet__backdrop{position:fixed;inset:0;z-index:1000;background-color:#3333333d;transition:opacity .35s cubic-bezier(.32,.72,0,1)}.sui-sheet--dragging~.sui-sheet__backdrop,:host([data-sui-sheet-open]) .sui-sheet--dragging+.sui-sheet__backdrop{transition:none}.sui-sheet{position:fixed;bottom:8px;left:8px;right:8px;z-index:1001;display:flex;flex-direction:column;box-sizing:border-box;height:max-content;background:var(--sui-bg-white-0, #ffffff);border-radius:36px 36px 54px 54px;corner-shape:squircle}@supports (clip-path: shape(from 0 0,close)){.sui-sheet{--sq-t: 45px;--sq-b: 68px;clip-path:shape(from 0 var(--sq-t),curve to var(--sq-t) 0 with 0 0/0 0,hline to calc(100% - var(--sq-t)),curve to 100% var(--sq-t) with 100% 0/100% 0,vline to calc(100% - var(--sq-b)),curve to calc(100% - var(--sq-b)) 100% with 100% 100%/100% 100%,hline to var(--sq-b),curve to 0 calc(100% - var(--sq-b)) with 0 100%/0 100%,close);box-shadow:none!important;filter:drop-shadow(0 -3px 8px rgba(14,18,27,.07))}}.sui-sheet{box-shadow:0 -8px 32px -12px #0e121b2e;overflow:hidden;overscroll-behavior:contain;will-change:max-height;transition:max-height .35s cubic-bezier(.32,.72,0,1)}.sui-sheet--dragging{transition:none}:host-context(html.platform-android) .sui-sheet{border-radius:var(--sui-radius-20, 20px);--sq-t: 25px;--sq-b: 25px}.sui-sheet__handle{flex-shrink:0;display:flex;align-items:center;justify-content:center;padding:12px 0 8px;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}.sui-sheet__handle:active{cursor:grabbing}.sui-sheet__handle-pill{width:36px;height:5px;border-radius:999px;background:var(--sui-bg-soft-200, #d4d4d8)}.sui-sheet__body{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;touch-action:none;padding:0 20px 20px}.sui-sheet__body--scrollable{touch-action:pan-y;overscroll-behavior-y:contain}.sui-sheet__body--full{padding:0}@media(max-width:767px){.sui-sheet__body{scrollbar-width:none}.sui-sheet__body::-webkit-scrollbar{display:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11016
11074
  }
11017
11075
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiModalSheet, decorators: [{
11018
11076
  type: Component,
11019
11077
  args: [{ selector: 'sui-modal-sheet', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: {
11020
11078
  '[attr.data-sui-sheet-open]': 'open() ? "" : null',
11021
- }, template: "@if (open()) {\n <!-- Backdrop con opacity din\u00E1mica.\n pointer-events: none cuando current \u2264 backdropBreakpoint para dejar\n interactivo el contenido debajo (ej. mapa). -->\n <div\n class=\"sui-sheet__backdrop\"\n [style.opacity]=\"backdropOpacity()\"\n [style.pointer-events]=\"backdropInteractive() ? 'auto' : 'none'\"\n (click)=\"onBackdropClick()\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Sheet container \u2014 anclado al bottom, altura din\u00E1mica.\n Usar `height` en vez de transform para que el \u00E1rea \"no cubierta\" del\n viewport (donde se ve el mapa) NO sea parte del DOM del sheet \u2014\n contenido de fondo autom\u00E1ticamente interactivo, scroll del body\n respeta la altura visible (no fantasma). -->\n <div\n #container\n class=\"sui-sheet\"\n role=\"dialog\"\n aria-modal=\"true\"\n [class.sui-sheet--dragging]=\"dragging()\"\n [style.max-height]=\"heightCss()\"\n [style.--sheet-progress]=\"liveProgress()\"\n >\n @if (showHandle()) {\n <!-- Drag handle (pill). Solo este elemento captura los pointer events\n del drag \u2014 el resto del sheet permite scroll/clicks normales. -->\n <div\n #handle\n class=\"sui-sheet__handle\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n >\n <div class=\"sui-sheet__handle-pill\"></div>\n </div>\n }\n\n <!-- Body con scroll interno. Consumer proyecta su contenido aqu\u00ED.\n Acepta drag con patr\u00F3n scroll-then-drag (iOS canon):\n - Si el body est\u00E1 scrolleado (scrollTop > 0), el drag se ignora y\n el touch hace scroll normal.\n - Si est\u00E1 en top (scrollTop === 0) y el user arrastra hacia abajo,\n se inicia drag del sheet.\n - Si est\u00E1 en max breakpoint y user arrastra hacia abajo, se inicia\n drag (incluso con scrollTop === 0 ya cubre eso).\n - Drag hacia arriba siempre permite scroll del body (no roba el gesto). -->\n <div\n #body\n class=\"sui-sheet__body\"\n [class.sui-sheet__body--full]=\"fullBody()\"\n [class.sui-sheet__body--scrollable]=\"atMaxBreakpoint()\"\n (pointerdown)=\"onBodyPointerDown($event)\"\n (pointermove)=\"onBodyPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n >\n <ng-content />\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.sui-sheet__backdrop{position:fixed;inset:0;z-index:1000;background-color:#3333333d;transition:opacity .35s cubic-bezier(.32,.72,0,1)}.sui-sheet--dragging~.sui-sheet__backdrop,:host([data-sui-sheet-open]) .sui-sheet--dragging+.sui-sheet__backdrop{transition:none}.sui-sheet{position:fixed;bottom:8px;left:8px;right:8px;z-index:1001;display:flex;flex-direction:column;box-sizing:border-box;height:max-content;background:var(--sui-bg-white-0, #ffffff);border-radius:36px 36px 54px 54px;corner-shape:squircle}@supports (clip-path: shape(from 0 0,close)){.sui-sheet{--sq-t: 45px;--sq-b: 68px;clip-path:shape(from 0 var(--sq-t),curve to var(--sq-t) 0 with 0 0/0 0,hline to calc(100% - var(--sq-t)),curve to 100% var(--sq-t) with 100% 0/100% 0,vline to calc(100% - var(--sq-b)),curve to calc(100% - var(--sq-b)) 100% with 100% 100%/100% 100%,hline to var(--sq-b),curve to 0 calc(100% - var(--sq-b)) with 0 100%/0 100%,close);box-shadow:none!important;filter:drop-shadow(0 -3px 8px rgba(14,18,27,.07))}}.sui-sheet{box-shadow:0 -8px 32px -12px #0e121b2e;overflow:hidden;overscroll-behavior:contain;will-change:max-height;transition:max-height .35s cubic-bezier(.32,.72,0,1)}.sui-sheet--dragging{transition:none}:host-context(html.platform-android) .sui-sheet{border-radius:var(--sui-radius-20, 20px);--sq-t: 25px;--sq-b: 25px}.sui-sheet__handle{flex-shrink:0;display:flex;align-items:center;justify-content:center;padding:12px 0 8px;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}.sui-sheet__handle:active{cursor:grabbing}.sui-sheet__handle-pill{width:36px;height:5px;border-radius:999px;background:var(--sui-bg-soft-200, #d4d4d8)}.sui-sheet__body{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;touch-action:none;padding:0 20px 20px}.sui-sheet__body--scrollable{touch-action:pan-y}.sui-sheet__body--full{padding:0}@media(max-width:767px){.sui-sheet__body{scrollbar-width:none}.sui-sheet__body::-webkit-scrollbar{display:none}}\n"] }]
11079
+ }, template: "@if (open()) {\n <!-- Backdrop con opacity din\u00E1mica.\n pointer-events: none cuando current \u2264 backdropBreakpoint para dejar\n interactivo el contenido debajo (ej. mapa). -->\n <div\n class=\"sui-sheet__backdrop\"\n [style.opacity]=\"backdropOpacity()\"\n [style.pointer-events]=\"backdropInteractive() ? 'auto' : 'none'\"\n (click)=\"onBackdropClick()\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Sheet container \u2014 anclado al bottom, altura din\u00E1mica.\n Usar `height` en vez de transform para que el \u00E1rea \"no cubierta\" del\n viewport (donde se ve el mapa) NO sea parte del DOM del sheet \u2014\n contenido de fondo autom\u00E1ticamente interactivo, scroll del body\n respeta la altura visible (no fantasma). -->\n <div\n #container\n class=\"sui-sheet\"\n role=\"dialog\"\n aria-modal=\"true\"\n [class.sui-sheet--dragging]=\"dragging()\"\n [style.max-height]=\"heightCss()\"\n [style.--sheet-progress]=\"liveProgress()\"\n >\n @if (showHandle()) {\n <!-- Drag handle (pill). Solo este elemento captura los pointer events\n del drag \u2014 el resto del sheet permite scroll/clicks normales. -->\n <div\n #handle\n class=\"sui-sheet__handle\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n >\n <div class=\"sui-sheet__handle-pill\"></div>\n </div>\n }\n\n <!-- Body con scroll interno. Consumer proyecta su contenido aqu\u00ED.\n Acepta drag con patr\u00F3n scroll-then-drag (iOS canon):\n - Si el body est\u00E1 scrolleado (scrollTop > 0), el drag se ignora y\n el touch hace scroll normal.\n - Si est\u00E1 en top (scrollTop === 0) y el user arrastra hacia abajo,\n se inicia drag del sheet.\n - Si est\u00E1 en max breakpoint y user arrastra hacia abajo, se inicia\n drag (incluso con scrollTop === 0 ya cubre eso).\n - Drag hacia arriba siempre permite scroll del body (no roba el gesto). -->\n <div\n #body\n class=\"sui-sheet__body\"\n [class.sui-sheet__body--full]=\"fullBody()\"\n [class.sui-sheet__body--scrollable]=\"atMaxBreakpoint()\"\n (pointerdown)=\"onBodyPointerDown($event)\"\n (pointermove)=\"onBodyPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n >\n <ng-content />\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.sui-sheet__backdrop{position:fixed;inset:0;z-index:1000;background-color:#3333333d;transition:opacity .35s cubic-bezier(.32,.72,0,1)}.sui-sheet--dragging~.sui-sheet__backdrop,:host([data-sui-sheet-open]) .sui-sheet--dragging+.sui-sheet__backdrop{transition:none}.sui-sheet{position:fixed;bottom:8px;left:8px;right:8px;z-index:1001;display:flex;flex-direction:column;box-sizing:border-box;height:max-content;background:var(--sui-bg-white-0, #ffffff);border-radius:36px 36px 54px 54px;corner-shape:squircle}@supports (clip-path: shape(from 0 0,close)){.sui-sheet{--sq-t: 45px;--sq-b: 68px;clip-path:shape(from 0 var(--sq-t),curve to var(--sq-t) 0 with 0 0/0 0,hline to calc(100% - var(--sq-t)),curve to 100% var(--sq-t) with 100% 0/100% 0,vline to calc(100% - var(--sq-b)),curve to calc(100% - var(--sq-b)) 100% with 100% 100%/100% 100%,hline to var(--sq-b),curve to 0 calc(100% - var(--sq-b)) with 0 100%/0 100%,close);box-shadow:none!important;filter:drop-shadow(0 -3px 8px rgba(14,18,27,.07))}}.sui-sheet{box-shadow:0 -8px 32px -12px #0e121b2e;overflow:hidden;overscroll-behavior:contain;will-change:max-height;transition:max-height .35s cubic-bezier(.32,.72,0,1)}.sui-sheet--dragging{transition:none}:host-context(html.platform-android) .sui-sheet{border-radius:var(--sui-radius-20, 20px);--sq-t: 25px;--sq-b: 25px}.sui-sheet__handle{flex-shrink:0;display:flex;align-items:center;justify-content:center;padding:12px 0 8px;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}.sui-sheet__handle:active{cursor:grabbing}.sui-sheet__handle-pill{width:36px;height:5px;border-radius:999px;background:var(--sui-bg-soft-200, #d4d4d8)}.sui-sheet__body{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;touch-action:none;padding:0 20px 20px}.sui-sheet__body--scrollable{touch-action:pan-y;overscroll-behavior-y:contain}.sui-sheet__body--full{padding:0}@media(max-width:767px){.sui-sheet__body{scrollbar-width:none}.sui-sheet__body::-webkit-scrollbar{display:none}}\n"] }]
11022
11080
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], breakpoints: [{ type: i0.Input, args: [{ isSignal: true, alias: "breakpoints", required: false }] }], initialBreakpoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialBreakpoint", required: false }] }], backdropBreakpoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropBreakpoint", required: false }] }], showHandle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHandle", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], fullBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullBody", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], breakpointChange: [{ type: i0.Output, args: ["breakpointChange"] }], containerRef: [{
11023
11081
  type: ViewChild,
11024
11082
  args: ['container']