pure-web-bottom-sheet 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +560 -0
- package/dist/react/BottomSheet.d.ts +12 -0
- package/dist/react/BottomSheetDialogManager.d.ts +12 -0
- package/dist/react/Client.d.ts +1 -0
- package/dist/react/ShadowRootTemplate.d.ts +13 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/react/BottomSheet.d.ts +12 -0
- package/dist/react/react/BottomSheet.js +2 -0
- package/dist/react/react/BottomSheet.js.map +1 -0
- package/dist/react/react/BottomSheetDialogManager.d.ts +12 -0
- package/dist/react/react/BottomSheetDialogManager.js +2 -0
- package/dist/react/react/BottomSheetDialogManager.js.map +1 -0
- package/dist/react/react/Client.d.ts +1 -0
- package/dist/react/react/Client.js +3 -0
- package/dist/react/react/Client.js.map +1 -0
- package/dist/react/react/ShadowRootTemplate.d.ts +13 -0
- package/dist/react/react/ShadowRootTemplate.js +3 -0
- package/dist/react/react/ShadowRootTemplate.js.map +1 -0
- package/dist/react/react/index.d.ts +3 -0
- package/dist/react/web/bottom-sheet-dialog-manager.d.ts +17 -0
- package/dist/react/web/bottom-sheet-dialog-manager.js +2 -0
- package/dist/react/web/bottom-sheet-dialog-manager.js.map +1 -0
- package/dist/react/web/bottom-sheet-dialog-manager.template.d.ts +1 -0
- package/dist/react/web/bottom-sheet-dialog-manager.template.js +2 -0
- package/dist/react/web/bottom-sheet-dialog-manager.template.js.map +1 -0
- package/dist/react/web/bottom-sheet.d.ts +47 -0
- package/dist/react/web/bottom-sheet.js +2 -0
- package/dist/react/web/bottom-sheet.js.map +1 -0
- package/dist/react/web/bottom-sheet.template.d.ts +1 -0
- package/dist/react/web/bottom-sheet.template.js +2 -0
- package/dist/react/web/bottom-sheet.template.js.map +1 -0
- package/dist/react/web/index.client.d.ts +4 -0
- package/dist/react/web/index.client.js +2 -0
- package/dist/react/web/index.client.js.map +1 -0
- package/dist/react/web/index.ssr.d.ts +4 -0
- package/dist/vue/index-fslx24KY.js +2 -0
- package/dist/vue/index-fslx24KY.js.map +1 -0
- package/dist/vue/index.client-BJCxko7x.js +2 -0
- package/dist/vue/index.client-BJCxko7x.js.map +1 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +2 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/vue/shims-vue.d.ts +9 -0
- package/dist/web/bottom-sheet-dialog-manager.d.ts +17 -0
- package/dist/web/bottom-sheet-dialog-manager.template.d.ts +1 -0
- package/dist/web/bottom-sheet.d.ts +47 -0
- package/dist/web/bottom-sheet.template.d.ts +1 -0
- package/dist/web/index.client.d.ts +4 -0
- package/dist/web/index.ssr.d.ts +4 -0
- package/dist/web.client.js +1 -0
- package/dist/web.ssr.js +1 -0
- package/package.json +117 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BottomSheetDialogManager.js","sources":["../../../../src/react/BottomSheetDialogManager.tsx"],"sourcesContent":["import {\n bottomSheetDialogManagerTemplate,\n BottomSheetDialogManager as BottomSheetDialogManagerElement,\n} from \"../web/index.ssr\";\nimport Client from \"./Client\";\nimport ShadowRootTemplate from \"./ShadowRootTemplate\";\n\ntype ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;\nexport type WebComponentProps<I extends HTMLElement> = React.DetailedHTMLProps<\n React.HTMLAttributes<I>,\n I\n> &\n ElementProps<I>;\n\ndeclare module \"react/jsx-runtime\" {\n namespace JSX {\n interface IntrinsicElements {\n \"bottom-sheet-dialog-manager\": WebComponentProps<BottomSheetDialogManagerElement>;\n }\n }\n}\n\nexport default function BottomSheetDialogManager({\n children,\n ...props\n}: WebComponentProps<BottomSheetDialogManagerElement>) {\n return (\n <>\n <bottom-sheet-dialog-manager {...props}>\n {<ShadowRootTemplate html={bottomSheetDialogManagerTemplate} />}\n {children}\n </bottom-sheet-dialog-manager>\n <Client />\n </>\n );\n}\n"],"names":["BottomSheetDialogManager","children","props","_jsxs","_jsx","ShadowRootTemplate","html","bottomSheetDialogManagerTemplate","Client"],"mappings":"4MAsBc,SAAUA,GAAyBC,SAC/CA,KACGC,IAEH,OACEC,eACEA,EAAA,8BAAA,IAAiCD,YAC9BE,EAACC,GAAmBC,KAAMC,IAC1BN,KAEHG,EAACI,EAAM,MAGb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function Client(): null;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import{useEffect as e}from"react";function t(){return e(()=>{import("../web/index.client.js").then(({BottomSheet:e,BottomSheetDialogManager:t})=>{customElements.get("bottom-sheet")||customElements.define("bottom-sheet",e),customElements.get("bottom-sheet-dialog-manager")||customElements.define("bottom-sheet-dialog-manager",t)})},[]),null}export{t as default};
|
|
3
|
+
//# sourceMappingURL=Client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Client.js","sources":["../../../../src/react/Client.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\n\nexport default function Client() {\n useEffect(() => {\n import(\"../web/index.client\").then(\n ({ BottomSheet, BottomSheetDialogManager }) => {\n if (!customElements.get(\"bottom-sheet\")) {\n customElements.define(\"bottom-sheet\", BottomSheet);\n }\n if (!customElements.get(\"bottom-sheet-dialog-manager\")) {\n customElements.define(\n \"bottom-sheet-dialog-manager\",\n BottomSheetDialogManager,\n );\n }\n },\n );\n }, []);\n return null;\n}\n"],"names":["Client","useEffect","import","then","BottomSheet","BottomSheetDialogManager","customElements","get","define"],"mappings":";kCAIc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAUA,CAAAA,CAAAA,CAAAA,CAgBtB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAfAC,CAAAA,CAAU,CAAA,CAAA,CAAA,CAAA,CACRC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAuBC,CAAAA,CAAAA,CAAAA,CAAAA,CAC5B,CAAA,CAAGC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAaC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CACTC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAeC,CAAAA,CAAAA,CAAAA,CAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACtBD,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAeE,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAgBJ,CAAAA,CAAAA,CAEnCE,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAeC,CAAAA,CAAAA,CAAAA,CAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACtBD,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAeE,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CACb,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACAH,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAKP,CAAA,CAAA,CAAA,CACI,CAAA,CAAA,CAAA,CACT,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare module "react/jsx-runtime" {
|
|
2
|
+
namespace JSX {
|
|
3
|
+
interface IntrinsicElements {
|
|
4
|
+
template: React.HTMLAttributes<HTMLTemplateElement> & {
|
|
5
|
+
shadowrootmode?: ShadowRootMode;
|
|
6
|
+
shadowrootdelegatesfocus?: string;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export default function Template({ html }: {
|
|
12
|
+
html: string;
|
|
13
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShadowRootTemplate.js","sources":["../../../../src/react/ShadowRootTemplate.tsx"],"sourcesContent":["\"use client\";\n\ndeclare module \"react/jsx-runtime\" {\n namespace JSX {\n interface IntrinsicElements {\n template: React.HTMLAttributes<HTMLTemplateElement> & {\n shadowrootmode?: ShadowRootMode;\n shadowrootdelegatesfocus?: string;\n };\n }\n }\n}\n\nconst isServer = typeof window === \"undefined\";\n\nexport default function Template({ html }: { html: string }) {\n if (isServer) {\n return (\n <template\n shadowrootmode=\"open\"\n dangerouslySetInnerHTML={{\n __html: html,\n }}\n />\n );\n }\n return null;\n}\n"],"names":["isServer","window","Template","html","_jsx","shadowrootmode","dangerouslySetInnerHTML","__html"],"mappings":";wCAaA,MAAMA,CAAAA,CAA6B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAXC,OAEV,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAUC,CAAAA,CAAAA,CAASC,KAAEA,CAAAA,CAAAA,CAAAA,CACjC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAIH,EAEAI,CAAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACEC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAe,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACfC,wBAAyB,CACvBC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAQJ,CAAAA,CAAAA,CAAAA,CAAAA,CAKT,CAAA,CAAA,CAAA,CACT,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class BottomSheetDialogManager extends HTMLElement {
|
|
2
|
+
constructor();
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Interface for the bottom-sheet-dialog-manager custom element.
|
|
6
|
+
* Provides type definitions for its custom properties.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Register in TypeScript for proper type checking:
|
|
10
|
+
* declare global {
|
|
11
|
+
* interface HTMLElementTagNameMap {
|
|
12
|
+
* "bottom-sheet-dialog-manager": BottomSheetDialogManager;
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
export interface BottomSheetDialogManager extends HTMLElement {
|
|
17
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{template as t}from"./bottom-sheet-dialog-manager.template.js";class e extends HTMLElement{constructor(){super();const e=HTMLElement.prototype.hasOwnProperty("attachInternals")?this.attachInternals():void 0;let a=e?.shadowRoot;a||(a=this.attachShadow({mode:"open"}),a.innerHTML=t),this.addEventListener("click",t=>{t.target instanceof HTMLDialogElement&&t.target.matches(":modal")&&t.target.close()}),this.addEventListener("snap-position-change",t=>{if(t.detail&&(this.dataset.sheetSnapPosition=t.detail.snapPosition),"2"==t.detail?.snapPosition&&t.target instanceof HTMLElement&&t.target.hasAttribute("swipe-to-dismiss")&&t.target.checkVisibility()){const e=t.target.parentElement;e instanceof HTMLDialogElement&&"0px"===getComputedStyle(e).getPropertyValue("translate")&&e.close()}})}}export{e as BottomSheetDialogManager};
|
|
2
|
+
//# sourceMappingURL=bottom-sheet-dialog-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bottom-sheet-dialog-manager.js","sources":["../../../../src/web/bottom-sheet-dialog-manager.ts"],"sourcesContent":["import { template } from \"./bottom-sheet-dialog-manager.template\";\n\nexport class BottomSheetDialogManager extends HTMLElement {\n constructor() {\n super();\n\n const supportsDeclarative =\n HTMLElement.prototype.hasOwnProperty(\"attachInternals\");\n const internals = supportsDeclarative ? this.attachInternals() : undefined;\n\n // Use existing declarative shadow root if present, otherwise create one\n let shadow = internals?.shadowRoot;\n if (!shadow) {\n shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = template;\n }\n\n this.addEventListener(\"click\", (event) => {\n if (\n event.target instanceof HTMLDialogElement &&\n event.target.matches(\":modal\")\n ) {\n event.target.close();\n }\n });\n this.addEventListener(\n \"snap-position-change\",\n (event: CustomEventInit<{ snapPosition: string }> & Event) => {\n if (event.detail) {\n this.dataset.sheetSnapPosition = event.detail.snapPosition;\n }\n if (\n event.detail?.snapPosition == \"2\" &&\n event.target instanceof HTMLElement &&\n event.target.hasAttribute(\"swipe-to-dismiss\") &&\n event.target.checkVisibility()\n ) {\n const parent = event.target.parentElement;\n if (\n parent instanceof HTMLDialogElement &&\n // Prevent Safari from closing the dialog immediately after opening\n // while the dialog open transition is still running.\n getComputedStyle(parent).getPropertyValue(\"translate\") === \"0px\"\n ) {\n parent.close();\n }\n }\n },\n );\n }\n}\n\n/**\n * Interface for the bottom-sheet-dialog-manager custom element.\n * Provides type definitions for its custom properties.\n *\n * @example\n * // Register in TypeScript for proper type checking:\n * declare global {\n * interface HTMLElementTagNameMap {\n * \"bottom-sheet-dialog-manager\": BottomSheetDialogManager;\n * }\n * }\n */\nexport interface BottomSheetDialogManager extends HTMLElement {}\n"],"names":["BottomSheetDialogManager","HTMLElement","constructor","super","internals","prototype","hasOwnProperty","this","attachInternals","undefined","shadow","shadowRoot","attachShadow","mode","innerHTML","template","addEventListener","event","target","HTMLDialogElement","matches","close","detail","dataset","sheetSnapPosition","snapPosition","hasAttribute","checkVisibility","parent","parentElement","getComputedStyle","getPropertyValue"],"mappings":"qEAEM,MAAOA,UAAiCC,YAC5C,WAAAC,GACEC,QAEA,MAEMC,EADJH,YAAYI,UAAUC,eAAe,mBACCC,KAAKC,uBAAoBC,EAGjE,IAAIC,EAASN,GAAWO,WACnBD,IACHA,EAASH,KAAKK,aAAa,CAAEC,KAAM,SACnCH,EAAOI,UAAYC,GAGrBR,KAAKS,iBAAiB,QAAUC,IAE5BA,EAAMC,kBAAkBC,mBACxBF,EAAMC,OAAOE,QAAQ,WAErBH,EAAMC,OAAOG,UAGjBd,KAAKS,iBACH,uBACCC,IAIC,GAHIA,EAAMK,SACRf,KAAKgB,QAAQC,kBAAoBP,EAAMK,OAAOG,cAGhB,KAA9BR,EAAMK,QAAQG,cACdR,EAAMC,kBAAkBjB,aACxBgB,EAAMC,OAAOQ,aAAa,qBAC1BT,EAAMC,OAAOS,kBACb,CACA,MAAMC,EAASX,EAAMC,OAAOW,cAE1BD,aAAkBT,mBAGyC,QAA3DW,iBAAiBF,GAAQG,iBAAiB,cAE1CH,EAAOP,OAEX,GAGN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const template: string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const t='<style>\n ::slotted(dialog){background:unset;border:none;height:100%;inset:0;margin:0;max-height:none;max-width:none;padding:0;position:fixed;top:auto;width:100%}::slotted(dialog:not(:modal)){pointer-events:none}::slotted(dialog[open]){translate:0 0}@starting-style{::slotted(dialog[open]){translate:0 100vh}}::slotted(dialog){transition:translate .5s ease-out,overlay .5s ease-out allow-discrete,display var(--display-transition-duration,.5s) ease-out allow-discrete;translate:0 100vh}:host([data-sheet-snap-position="2"]) ::slotted(dialog:not([open])){transition:none}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){::slotted(dialog){--display-transition-duration:0.1s}}\n </style><slot></slot>';export{t as template};
|
|
2
|
+
//# sourceMappingURL=bottom-sheet-dialog-manager.template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bottom-sheet-dialog-manager.template.js","sources":["../../../../src/web/bottom-sheet-dialog-manager.template.ts"],"sourcesContent":["const css = /*css*/ `\n ::slotted(dialog) {\n position: fixed;\n margin: 0;\n inset: 0;\n top: initial;\n border: none;\n background: unset;\n padding: 0;\n width: 100%;\n max-width: none;\n height: 100%;\n max-height: none;\n }\n\n ::slotted(dialog:not(:modal)) {\n pointer-events: none;\n }\n\n ::slotted(dialog[open]) {\n translate: 0 0;\n }\n\n @starting-style {\n ::slotted(dialog[open]) {\n translate: 0 100vh;\n }\n }\n\n ::slotted(dialog) {\n translate: 0 100vh;\n transition:\n translate 0.5s ease-out,\n overlay 0.5s ease-out allow-discrete,\n display var(--display-transition-duration, 0.5s) ease-out allow-discrete;\n }\n\n :host([data-sheet-snap-position=\"2\"]) ::slotted(dialog:not([open])) {\n transition: none;\n }\n\n /** Safari overrides */\n @supports (-webkit-touch-callout: none) or (-webkit-hyphens: none) {\n ::slotted(dialog) {\n /* \n For Safari we must user shorter duration for display property or otherwise\n the bottom sheet will not snap properly to the initial target on open.\n */\n --display-transition-duration: 0.1s;\n }\n }\n`;\n\nexport const template: string = /*html*/ `\n <style>\n ${css}\n </style>\n <slot></slot>\n`;\n"],"names":[],"mappings":"AAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export declare class BottomSheet extends HTMLElement {
|
|
2
|
+
#private;
|
|
3
|
+
static observedAttributes: string[];
|
|
4
|
+
constructor();
|
|
5
|
+
connectedCallback(): void;
|
|
6
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
7
|
+
disconnectedCallback(): void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Interface for the bottom-sheet custom element.
|
|
11
|
+
* Provides type definitions for its custom properties.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Register in TypeScript for proper type checking:
|
|
15
|
+
* declare global {
|
|
16
|
+
* interface HTMLElementTagNameMap {
|
|
17
|
+
* "bottom-sheet": BottomSheet;
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
export interface BottomSheet extends HTMLElement {
|
|
22
|
+
/**
|
|
23
|
+
* When set, the bottom sheet maximum height is based on the the height of its
|
|
24
|
+
* contents.
|
|
25
|
+
*/
|
|
26
|
+
["content-height"]?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* When set, enables scrolling the sheet inner content independently of the sheet.
|
|
29
|
+
*/
|
|
30
|
+
["nested-scroll"]?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* When set, enables resize optimization for the nested scroll mode to avoid reflows
|
|
33
|
+
* during sheet resizing. Only relevant when `nested-scroll` is also true. Not relevant
|
|
34
|
+
* for `expand-to-scroll` mode since it already avoids reflows.
|
|
35
|
+
*/
|
|
36
|
+
["nested-scroll-optimization"]?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* When set, content becomes scrollable only after full expansion. Only relevant
|
|
39
|
+
* when `nested-scroll` is also true.
|
|
40
|
+
*/
|
|
41
|
+
["expand-to-scroll"]?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* When set, allows swiping down to dismiss the bottom sheet when used together
|
|
44
|
+
* with the `bottom-sheet-dialog-manager` or with the Popover API.
|
|
45
|
+
*/
|
|
46
|
+
["swipe-to-dismiss"]?: boolean;
|
|
47
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{template as e}from"./bottom-sheet.template.js";class t extends HTMLElement{static observedAttributes=["nested-scroll-optimization"];#e=null;#t=()=>{this.style.setProperty("--sw-keyboard-height",`${window.visualViewport?.offsetTop??0}px`)};#s;#o=null;constructor(){super();const t=HTMLElement.prototype.hasOwnProperty("attachInternals")?this.attachInternals():void 0;let s=t?.shadowRoot;s||(s=this.attachShadow({mode:"open"}),s.innerHTML=e),this.#s=s;"onscrollsnapchange"in window&&this.addEventListener("scrollsnapchange",this.#i),CSS.supports("(animation-timeline: scroll()) and (animation-range: 0% 100%)")||(this.addEventListener("scroll",this.#n),this.#n())}connectedCallback(){"onscrollsnapchange"in window||this.#r(),window.visualViewport?.addEventListener("resize",this.#t)}#r(){this.#e=new IntersectionObserver(e=>{let t=1/0,s=-1/0,o=!1;for(const i of e){if(!(i.target instanceof HTMLElement)||null==i.target.dataset.snap)continue;const e=Number.parseInt(i.target.dataset.snap);i.isIntersecting?(o=!0,t=Math.min(t,e)):s=Math.max(s,e)}const i=o?t:s+1;this.#l(i.toString())},{root:this,threshold:0,rootMargin:"1000% 0px -100% 0px"});const e=this.#s.querySelectorAll(".sentinel");Array.from(e).forEach(e=>{this.#e?.observe(e)})}#i(e){const t=e;if(!(t.snapTargetBlock instanceof HTMLElement))return;const s=t.snapTargetBlock.dataset.snap??"1";this.#l(s)}#l(e){this.dataset.sheetSnapPosition=e,this.dispatchEvent(new CustomEvent("snap-position-change",{detail:{snapPosition:e},bubbles:!0,composed:!0}))}#n(){this.#s.querySelector(".sheet-wrapper")?.style.setProperty("--sheet-position",`${this.scrollTop}px`)}#a(){const e=this.#s.querySelector(".sheet-wrapper"),t=this.#s.querySelector(".sheet"),s=this.#s.querySelector(".sheet-content");if(!e||!t||!s)return;const o=CSS.supports("scroll-timeline: --sheet-timeline y"),i="onscrollend"in window&&!CSS.supports("-moz-appearance","none");let n,r,l;const a=()=>{const t=this.scrollTop/(this.scrollHeight-this.offsetHeight),s=(1-t)*n+t*r;e.style.setProperty("--sheet-content-offset",`${s}px`)},c=()=>{delete this.dataset.scrolling,["--sheet-content-offset","--sheet-content-offset-start","--sheet-content-offset-end"].forEach(t=>e.style.removeProperty(t))},h=()=>{e.style.setProperty("--sheet-content-offset-start",`${n}px`),e.style.setProperty("--sheet-content-offset-end",`${r}px`)},p=()=>{const e=getComputedStyle(s),t=-new DOMMatrixReadOnly(e.transform).m42;c(),requestAnimationFrame(()=>{s.scrollTop=t+s.scrollTop})},d=()=>{if("scrolling"in this.dataset)o||a();else{const i=e.offsetHeight-(t.offsetHeight-s.offsetHeight),l=s.scrollHeight-i;if(Math.floor(s.scrollTop)>l){const o=s.scrollHeight-s.offsetHeight-s.scrollTop,i=e.offsetHeight/(e.offsetHeight-t.offsetHeight);n=-(s.scrollHeight+(t.offsetHeight-s.offsetHeight))+o*i,r=-l,this.dataset.scrolling="",n+=s.scrollTop,r+=s.scrollTop,h()}else n=0,r=0,h(),this.dataset.scrolling="";if(o||a(),"ScrollTimeline"in window){const t=new ScrollTimeline({source:this,axis:"y"});e.style.setProperty("--sheet-timeline-at-scroll-start",`${t.currentTime}`)}}},f=()=>{window.clearTimeout(l),l=window.setTimeout(p,100)};this.addEventListener("scroll",d),i?this.addEventListener("scrollend",p):this.addEventListener("scroll",f),this.#o=()=>{this.removeEventListener("scroll",d),i?this.removeEventListener("scrollend",p):(this.removeEventListener("scroll",f),window.clearTimeout(l)),c(),this.#o=null}}attributeChangedCallback(e,t,s){if(t!==s)if("nested-scroll-optimization"===e)null!==s?this.#o||this.#a():this.#o&&this.#o();else console.warn(`Unhandled attribute: ${e}`)}disconnectedCallback(){this.#e?.disconnect(),window.visualViewport?.removeEventListener("resize",this.#t)}}export{t as BottomSheet};
|
|
2
|
+
//# sourceMappingURL=bottom-sheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bottom-sheet.js","sources":["../../../../src/web/bottom-sheet.ts"],"sourcesContent":["import { template } from \"./bottom-sheet.template\";\n\n/**\n * @see https://drafts.csswg.org/css-scroll-snap-2/#snapevent-interface\n */\ninterface SnapEvent extends Event {\n snapTargetBlock: Element;\n}\n\n/**\n * @see https://drafts.csswg.org/scroll-animations/#scrolltimeline-interface\n */\ninterface ScrollTimeline extends AnimationTimeline {\n readonly source: Element | null;\n readonly axis: string;\n}\ndeclare var ScrollTimeline: {\n prototype: ScrollTimeline;\n new ({ source, axis }: { source: Element; axis: string }): ScrollTimeline;\n};\n\nexport class BottomSheet extends HTMLElement {\n static observedAttributes = [\"nested-scroll-optimization\"];\n #observer: IntersectionObserver | null = null;\n #handleViewportResize = () => {\n this.style.setProperty(\n \"--sw-keyboard-height\",\n `${window.visualViewport?.offsetTop ?? 0}px`,\n );\n };\n #shadow: ShadowRoot;\n #cleanupNestedScrollResizeOptimization: (() => void) | null = null;\n\n constructor() {\n super();\n\n const supportsDeclarative =\n HTMLElement.prototype.hasOwnProperty(\"attachInternals\");\n const internals = supportsDeclarative ? this.attachInternals() : undefined;\n\n // Use existing declarative shadow root if present, otherwise create one\n let shadow = internals?.shadowRoot;\n if (!shadow) {\n shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = template;\n }\n this.#shadow = shadow;\n\n const supportsScrollSnapChange = \"onscrollsnapchange\" in window;\n if (supportsScrollSnapChange) {\n this.addEventListener(\"scrollsnapchange\", this.#handleScrollSnapChange);\n }\n\n if (\n !CSS.supports(\n \"(animation-timeline: scroll()) and (animation-range: 0% 100%)\",\n )\n ) {\n this.addEventListener(\"scroll\", this.#handleScroll);\n this.#handleScroll();\n }\n }\n\n connectedCallback() {\n const supportsScrollSnapChange = \"onscrollsnapchange\" in window;\n if (!supportsScrollSnapChange) {\n this.#setupIntersectionObserver();\n }\n\n window.visualViewport?.addEventListener(\n \"resize\",\n this.#handleViewportResize,\n );\n }\n\n #setupIntersectionObserver() {\n this.#observer = new IntersectionObserver(\n (entries) => {\n let lowestIntersectingSnap = Infinity;\n let highestNonIntersectingSnap = -Infinity;\n let hasIntersectingElement = false;\n\n for (const entry of entries) {\n if (\n !(entry.target instanceof HTMLElement) ||\n entry.target.dataset.snap == null\n ) {\n continue;\n }\n\n const snap = Number.parseInt(entry.target.dataset.snap);\n\n if (entry.isIntersecting) {\n hasIntersectingElement = true;\n lowestIntersectingSnap = Math.min(lowestIntersectingSnap, snap);\n } else {\n highestNonIntersectingSnap = Math.max(\n highestNonIntersectingSnap,\n snap,\n );\n }\n }\n\n const newSnapPosition = hasIntersectingElement\n ? lowestIntersectingSnap\n : highestNonIntersectingSnap + 1;\n\n this.#updateSnapPosition(newSnapPosition.toString());\n },\n {\n root: this,\n threshold: 0,\n rootMargin: \"1000% 0px -100% 0px\",\n },\n );\n\n const sentinels = this.#shadow.querySelectorAll(\".sentinel\");\n Array.from(sentinels).forEach((sentinel) => {\n this.#observer?.observe(sentinel);\n });\n }\n\n #handleScrollSnapChange(event: Event) {\n const snapEvent = event as SnapEvent;\n if (!(snapEvent.snapTargetBlock instanceof HTMLElement)) {\n return;\n }\n const newSnapPosition = snapEvent.snapTargetBlock.dataset.snap ?? \"1\";\n this.#updateSnapPosition(newSnapPosition);\n }\n\n #updateSnapPosition(position: string) {\n this.dataset.sheetSnapPosition = position;\n this.dispatchEvent(\n new CustomEvent<{ snapPosition: string }>(\"snap-position-change\", {\n detail: {\n snapPosition: position,\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n #handleScroll() {\n this.#shadow\n .querySelector<HTMLElement>(\".sheet-wrapper\")\n ?.style.setProperty(\"--sheet-position\", `${this.scrollTop}px`);\n }\n\n #setupNestedScrollResizeOptimization() {\n const wrapper = this.#shadow.querySelector<HTMLElement>(\".sheet-wrapper\");\n const sheet = this.#shadow.querySelector<HTMLElement>(\".sheet\");\n const content = this.#shadow.querySelector<HTMLElement>(\".sheet-content\");\n\n if (!wrapper || !sheet || !content) {\n return;\n }\n\n const SCROLL_END_TIMEOUT_MS = 100;\n const supportsScrollAnimations = CSS.supports(\n \"scroll-timeline: --sheet-timeline y\",\n );\n // Use scrollend event if available to detect end of scrolling\n // (exclude Firefox for now which has inconsistencies with scrollend\n // implementation with scroll chaining from nested scrollable elements)\n const supportScrollEnd =\n \"onscrollend\" in window && !CSS.supports(\"-moz-appearance\", \"none\");\n let contentYOffsetStart: number,\n contentYOffsetEnd: number,\n scrollTimeout: number;\n\n // If CSS scroll-timeline is not supported, we need to manually update\n // the y offset of the sheet content during scrolling\n const updateContentYOffset = () => {\n const t = this.scrollTop / (this.scrollHeight - this.offsetHeight);\n const contentTranslateY =\n (1 - t) * contentYOffsetStart + t * contentYOffsetEnd;\n wrapper.style.setProperty(\n \"--sheet-content-offset\",\n `${contentTranslateY}px`,\n );\n };\n\n const cleanupStyleProperties = () => {\n delete this.dataset.scrolling;\n [\n \"--sheet-content-offset\",\n \"--sheet-content-offset-start\",\n \"--sheet-content-offset-end\",\n ].forEach((p) => wrapper.style.removeProperty(p));\n };\n\n const updateOffsetProperties = () => {\n wrapper.style.setProperty(\n \"--sheet-content-offset-start\",\n `${contentYOffsetStart}px`,\n );\n wrapper.style.setProperty(\n \"--sheet-content-offset-end\",\n `${contentYOffsetEnd}px`,\n );\n };\n\n const handleScrollEnd = () => {\n const style = getComputedStyle(content);\n const matrix = new DOMMatrixReadOnly(style.transform);\n const yOffset = -matrix.m42;\n cleanupStyleProperties();\n requestAnimationFrame(() => {\n content.scrollTop = yOffset + content.scrollTop;\n });\n };\n\n const handleScroll = () => {\n if (!(\"scrolling\" in this.dataset)) {\n const contentMaxOffsetHeight =\n wrapper.offsetHeight - (sheet.offsetHeight - content.offsetHeight);\n // Threshold after which resizing sheet content anchors the inner\n // content to the bottom of the scrollport instead of top\n const scrollBottomAnchorThreshold =\n content.scrollHeight - contentMaxOffsetHeight;\n if (Math.floor(content.scrollTop) > scrollBottomAnchorThreshold) {\n const contentScrollBottom =\n content.scrollHeight - content.offsetHeight - content.scrollTop;\n\n // Size factor based on the current height of the bottom sheet\n const sheetSizeFactor =\n wrapper.offsetHeight / (wrapper.offsetHeight - sheet.offsetHeight);\n\n contentYOffsetStart =\n -(\n content.scrollHeight +\n (sheet.offsetHeight - content.offsetHeight)\n ) +\n contentScrollBottom * sheetSizeFactor;\n contentYOffsetEnd = -scrollBottomAnchorThreshold;\n\n // Toggle scrolling state on\n this.dataset.scrolling = \"\";\n\n // Readjust sheet content offset range based on current scroll position\n // of the sheet content after the layout change caused by toggling the\n // data-scrolling attribute\n contentYOffsetStart += content.scrollTop;\n contentYOffsetEnd += content.scrollTop;\n\n updateOffsetProperties();\n } else {\n contentYOffsetStart = 0;\n contentYOffsetEnd = 0;\n updateOffsetProperties();\n this.dataset.scrolling = \"\";\n }\n\n if (!supportsScrollAnimations) {\n updateContentYOffset();\n }\n\n if (\"ScrollTimeline\" in window) {\n // Needed for Safari 26+ to prevent flash of sheet position when toggling data-scrolling\n // before the scroll timeline is applied by the browser\n const timeline = new ScrollTimeline({\n source: this,\n axis: \"y\",\n });\n wrapper.style.setProperty(\n \"--sheet-timeline-at-scroll-start\",\n `${timeline.currentTime}`,\n );\n }\n } else if (!supportsScrollAnimations) {\n updateContentYOffset();\n }\n };\n\n const handleFallbackScrollEnd = () => {\n window.clearTimeout(scrollTimeout);\n scrollTimeout = window.setTimeout(handleScrollEnd, SCROLL_END_TIMEOUT_MS);\n };\n\n this.addEventListener(\"scroll\", handleScroll);\n if (supportScrollEnd) {\n this.addEventListener(\"scrollend\", handleScrollEnd);\n } else {\n this.addEventListener(\"scroll\", handleFallbackScrollEnd);\n }\n\n this.#cleanupNestedScrollResizeOptimization = () => {\n this.removeEventListener(\"scroll\", handleScroll);\n if (supportScrollEnd) {\n this.removeEventListener(\"scrollend\", handleScrollEnd);\n } else {\n this.removeEventListener(\"scroll\", handleFallbackScrollEnd);\n window.clearTimeout(scrollTimeout);\n }\n\n cleanupStyleProperties();\n this.#cleanupNestedScrollResizeOptimization = null;\n };\n }\n\n attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string | null,\n ) {\n if (oldValue === newValue) return;\n\n switch (name) {\n case \"nested-scroll-optimization\":\n if (newValue !== null) {\n if (!this.#cleanupNestedScrollResizeOptimization) {\n // Only setup if not already setup\n this.#setupNestedScrollResizeOptimization();\n }\n } else if (this.#cleanupNestedScrollResizeOptimization) {\n this.#cleanupNestedScrollResizeOptimization();\n }\n break;\n default:\n console.warn(`Unhandled attribute: ${name}`);\n }\n }\n\n disconnectedCallback() {\n this.#observer?.disconnect();\n window.visualViewport?.removeEventListener(\n \"resize\",\n this.#handleViewportResize,\n );\n }\n}\n\n/**\n * Interface for the bottom-sheet custom element.\n * Provides type definitions for its custom properties.\n *\n * @example\n * // Register in TypeScript for proper type checking:\n * declare global {\n * interface HTMLElementTagNameMap {\n * \"bottom-sheet\": BottomSheet;\n * }\n * }\n */\nexport interface BottomSheet extends HTMLElement {\n /**\n * When set, the bottom sheet maximum height is based on the the height of its\n * contents.\n */\n [\"content-height\"]?: boolean;\n /**\n * When set, enables scrolling the sheet inner content independently of the sheet.\n */\n [\"nested-scroll\"]?: boolean;\n /**\n * When set, enables resize optimization for the nested scroll mode to avoid reflows\n * during sheet resizing. Only relevant when `nested-scroll` is also true. Not relevant\n * for `expand-to-scroll` mode since it already avoids reflows.\n */\n [\"nested-scroll-optimization\"]?: boolean;\n /**\n * When set, content becomes scrollable only after full expansion. Only relevant\n * when `nested-scroll` is also true.\n */\n [\"expand-to-scroll\"]?: boolean;\n /**\n * When set, allows swiping down to dismiss the bottom sheet when used together\n * with the `bottom-sheet-dialog-manager` or with the Popover API.\n */\n [\"swipe-to-dismiss\"]?: boolean;\n}\n"],"names":["BottomSheet","HTMLElement","static","observer","handleViewportResize","this","style","setProperty","window","visualViewport","offsetTop","shadow","cleanupNestedScrollResizeOptimization","constructor","super","internals","prototype","hasOwnProperty","attachInternals","undefined","shadowRoot","attachShadow","mode","innerHTML","template","addEventListener","handleScrollSnapChange","CSS","supports","handleScroll","connectedCallback","setupIntersectionObserver","IntersectionObserver","entries","lowestIntersectingSnap","Infinity","highestNonIntersectingSnap","hasIntersectingElement","entry","target","dataset","snap","Number","parseInt","isIntersecting","Math","min","max","newSnapPosition","updateSnapPosition","toString","root","threshold","rootMargin","sentinels","querySelectorAll","Array","from","forEach","sentinel","observe","event","snapEvent","snapTargetBlock","position","sheetSnapPosition","dispatchEvent","CustomEvent","detail","snapPosition","bubbles","composed","querySelector","scrollTop","setupNestedScrollResizeOptimization","wrapper","sheet","content","supportsScrollAnimations","supportScrollEnd","contentYOffsetStart","contentYOffsetEnd","scrollTimeout","updateContentYOffset","t","scrollHeight","offsetHeight","contentTranslateY","cleanupStyleProperties","scrolling","p","removeProperty","updateOffsetProperties","handleScrollEnd","getComputedStyle","yOffset","DOMMatrixReadOnly","transform","m42","requestAnimationFrame","contentMaxOffsetHeight","scrollBottomAnchorThreshold","floor","contentScrollBottom","sheetSizeFactor","timeline","ScrollTimeline","source","axis","currentTime","handleFallbackScrollEnd","clearTimeout","setTimeout","removeEventListener","attributeChangedCallback","name","oldValue","newValue","console","warn","disconnectedCallback","disconnect"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const template: string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const t='<style>\n :host{--sheet-max-height:calc(100dvh - 24px);--sheet-background:#f2f2f2;--sheet-border-radius:12px;--sheet-safe-max-height:calc(var(--sheet-max-height) - env(\n keyboard-inset-height,\n var(--sw-keyboard-height, 0px)\n ));border-top-left-radius:var(--sheet-border-radius);border-top-right-radius:var(--sheet-border-radius);bottom:env(keyboard-inset-height,0);contain:strict;display:block;height:var(--sheet-max-height);left:0;max-height:var(--sheet-safe-max-height);overflow-y:scroll;overscroll-behavior-y:none;pointer-events:none;position:fixed;right:0;scroll-snap-type:y mandatory;scrollbar-width:none;will-change:scroll-position}:host(:focus-visible){outline:none}:host(:focus-visible) .handle{outline:auto;outline-offset:4px}:host([data-sheet-snap-position="-1"]) .sheet,:host([data-sheet-snap-position="-1"]) .snap:before,:host([data-sheet-snap-position="-1"]) ::slotted([slot=snap]):before{scroll-snap-align:none}.snap,::slotted([slot=snap]){position:relative;top:var(--snap)}.snap:before,::slotted([slot=snap]):before{content:"";height:1px;left:0;position:absolute;right:0;scroll-snap-align:var(--snap-point-align,start);top:0}.snap.initial,::slotted([slot=snap].initial){--snap-point-align:start}.snap.snap-bottom{height:auto;position:static;top:auto}.snap.snap-bottom:after{content:"";display:block;height:var(--sheet-max-height);max-height:var(--sheet-safe-max-height);position:static}:host(:not([swipe-to-dismiss])) .snap.snap-bottom:before{scroll-snap-align:none}.sentinel{position:relative}.sentinel[data-snap="0"]{top:-1px}.sentinel[data-snap="-1"]{top:2px}.sentinel[data-snap="1"]{top:1px}.sheet,.sheet-wrapper{border-radius:inherit}.sheet{background:var(--sheet-background);cursor:row-resize;display:flex;flex-direction:column;overflow:clip;pointer-events:all;scroll-snap-align:var(--snap-point-align,start)}.sheet-header{top:0}.sheet-footer,.sheet-header{background:inherit;position:sticky;width:100%}.sheet-footer{bottom:0}.sheet-content{flex:1 1 auto;padding:0 .5rem}.handle{background:#ccc;border-radius:5px;height:5px;margin:.5rem auto;width:40px}:host{animation:initial-snap .01s both}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){:host{animation:initial-snap .1s both;display:inherit}}@keyframes initial-snap{0%{--snap-point-align:none}50%{scroll-snap-type:none;--snap-point-align:none}}@supports (-webkit-touch-callout:none){.sheet-content,.sheet-footer,.sheet-header{overflow-x:scroll;overscroll-behavior-x:none;scrollbar-width:none}:is(.sheet-content,.sheet-header,.sheet-footer):after{box-sizing:content-box;content:"";display:block;height:1px;padding:inherit;padding-left:0;width:calc(100% + 1px)}.sheet-content{scrollbar-width:auto}}:host(:not([nested-scroll]):not([content-height])) .sheet-wrapper{height:100%}:host(:not([nested-scroll]):not([content-height])) .sheet{min-height:100%}:host([nested-scroll]) .sheet-wrapper{bottom:0;contain:strict;display:flex;flex-direction:column;height:100%;justify-content:end;position:sticky}:host([nested-scroll]) .sheet{bottom:0;display:flex;flex-direction:column;height:100%;max-height:100%;position:sticky}:host([nested-scroll]) .sheet-content{overflow-y:auto;scrollbar-gutter:stable;will-change:scroll-position}:host([nested-scroll]) .sheet-footer,:host([nested-scroll]) .sheet-header{flex:0 0 auto}:host([nested-scroll][expand-to-scroll]) .sheet-wrapper{position:static}:host([nested-scroll][expand-to-scroll]) .sheet{animation:none;height:100%;position:static}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-header{z-index:1}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{scrollbar-color:transparent transparent}@supports ((animation-timeline:scroll()) and (animation-range:0% 100%)){:host{scroll-timeline:--sheet-timeline y}:host([nested-scroll]) .sheet{animation:expand-sheet-height linear forwards;animation-timeline:--sheet-timeline}@keyframes expand-sheet-height{0%{height:0}to{height:100%}}:host([nested-scroll][expand-to-scroll]) .sheet-content{animation:overflow-y-toggle linear forwards;animation-timeline:--sheet-timeline}@keyframes overflow-y-toggle{0%,99.99%{overflow-y:hidden}to{overflow-y:auto}}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet{animation:translate-sheet linear forwards;transform:translateY(var(--sheet-timeline-at-scroll-start,0));animation-timeline:--sheet-timeline}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{animation:translate-sheet-content linear forwards;animation-timeline:--sheet-timeline}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{animation:translate-footer linear forwards;animation-timeline:--sheet-timeline}@keyframes translate-sheet{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes translate-sheet-content{0%{transform:translateY(var(--sheet-content-offset-start,0))}to{transform:translateY(var(--sheet-content-offset-end,0))}}@keyframes translate-footer{0%{transform:translateY(calc(var(--sheet-safe-max-height)*-1))}to{transform:translateY(0)}}}@supports (not ((animation-timeline:scroll()) and (animation-range:0% 100%))){:host([nested-scroll]) .sheet{height:var(--sheet-position)}:host([nested-scroll][expand-to-scroll]) .sheet-content{overflow-y:hidden}:host([nested-scroll][expand-to-scroll][data-sheet-snap-position="0"]) .sheet-content{overflow-y:auto}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet{height:100%;transform:translateY(calc(100% - var(--sheet-position, 0)))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{transform:translateY(var(--sheet-content-offset,0))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{transform:translateY(calc(var(--sheet-safe-max-height)*-1 + var(--sheet-position, 0)))}}\n </style><slot name="snap"><div class="initial snap" style="--snap: 100%"></div></slot><div class="sentinel" data-snap="1"></div><div class="snap snap-bottom" data-snap="2"></div><div class="sentinel" data-snap="0"></div><div class="sheet-wrapper"><aside class="sheet" part="sheet" data-snap="0"><div class="sentinel" data-snap="-1"></div><header class="sheet-header" part="header"><div class="handle" part="handle"></div><slot name="header"></slot></header><section class="sheet-content" part="content"><slot></slot></section><footer class="sheet-footer" part="footer"><slot name="footer"></slot></footer></aside></div>';export{t as template};
|
|
2
|
+
//# sourceMappingURL=bottom-sheet.template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bottom-sheet.template.js","sources":["../../../../src/web/bottom-sheet.template.ts"],"sourcesContent":["const css = /*css*/ `\r\n :host {\r\n --sheet-max-height: calc(100dvh - 24px);\r\n --sheet-background: rgb(242, 242, 242);\r\n --sheet-border-radius: 12px;\r\n /* \r\n The --sw-keyboard-height is needed to handle iOS Safari on-screen keyboard\r\n since iOS Safari pushes content offscreen by keyboard height when it is opened\r\n */\r\n --sheet-safe-max-height: calc(\r\n var(--sheet-max-height) - env(\r\n keyboard-inset-height,\r\n var(--sw-keyboard-height, 0px)\r\n )\r\n );\r\n display: block;\r\n position: fixed;\r\n right: 0;\r\n bottom: env(keyboard-inset-height, 0);\r\n left: 0;\r\n will-change: scroll-position;\r\n contain: strict;\r\n border-top-right-radius: var(--sheet-border-radius);\r\n border-top-left-radius: var(--sheet-border-radius);\r\n height: var(--sheet-max-height);\r\n max-height: var(--sheet-safe-max-height);\r\n overflow-y: scroll;\r\n /* Prevent rubberband effect when scrolling to the end of the sheet */\r\n overscroll-behavior-y: none;\r\n scroll-snap-type: y mandatory;\r\n scrollbar-width: none;\r\n pointer-events: none;\r\n }\r\n\r\n :host(:focus-visible) {\r\n outline: none;\r\n\r\n .handle {\r\n outline: auto;\r\n outline-offset: 4px;\r\n }\r\n }\r\n\r\n /* \r\n Disable snap alignment when sheet has reached the top and being scrolled\r\n to prevent snapping back to the top when the user scrolls the sheet on\r\n certain browsers (e.g. Firefox).\r\n */\r\n :host([data-sheet-snap-position=\"-1\"]) {\r\n .sheet,\r\n .snap::before,\r\n ::slotted([slot=\"snap\"])::before {\r\n scroll-snap-align: none;\r\n }\r\n }\r\n\r\n .snap,\r\n ::slotted([slot=\"snap\"]) {\r\n position: relative;\r\n top: var(--snap);\r\n }\r\n\r\n .snap::before,\r\n ::slotted([slot=\"snap\"])::before {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n left: 0;\r\n height: 1px; /* Height required for Safari to snap */\r\n scroll-snap-align: var(--snap-point-align, start);\r\n content: \"\";\r\n }\r\n\r\n .snap.initial,\r\n ::slotted([slot=\"snap\"].initial) {\r\n --snap-point-align: start;\r\n }\r\n\r\n .snap.snap-bottom {\r\n position: static;\r\n top: initial;\r\n height: auto;\r\n\r\n &::after {\r\n display: block;\r\n position: static;\r\n height: var(--sheet-max-height);\r\n max-height: var(--sheet-safe-max-height);\r\n content: \"\";\r\n }\r\n }\r\n\r\n :host(:not([swipe-to-dismiss])) .snap.snap-bottom::before {\r\n scroll-snap-align: none;\r\n }\r\n\r\n .sentinel {\r\n position: relative;\r\n\r\n &[data-snap=\"0\"] {\r\n top: -1px; /** Extra -1px needed for Safari */\r\n }\r\n &[data-snap=\"-1\"] {\r\n top: 2px; /** Extra +1px needed for Safari */\r\n }\r\n &[data-snap=\"1\"] {\r\n top: 1px;\r\n }\r\n }\r\n\r\n .sheet-wrapper {\r\n border-radius: inherit;\r\n }\r\n\r\n .sheet {\r\n display: flex;\r\n flex-direction: column;\r\n cursor: row-resize;\r\n border-radius: inherit;\r\n background: var(--sheet-background);\r\n overflow: clip;\r\n scroll-snap-align: var(--snap-point-align, start);\r\n pointer-events: all;\r\n }\r\n\r\n .sheet-header {\r\n position: sticky;\r\n top: 0;\r\n background: inherit;\r\n width: 100%;\r\n }\r\n\r\n .sheet-footer {\r\n position: sticky;\r\n bottom: 0;\r\n background: inherit;\r\n width: 100%;\r\n }\r\n\r\n .sheet-content {\r\n flex: 1 1 auto;\r\n padding: 0 0.5rem;\r\n }\r\n\r\n .handle {\r\n margin: 0.5rem auto;\r\n border-radius: 5px;\r\n background: #ccc;\r\n width: 40px;\r\n height: 5px;\r\n }\r\n\r\n :host {\r\n animation: initial-snap 0.01s both;\r\n }\r\n\r\n /* Safari overrides */\r\n @supports (-webkit-touch-callout: none) or (-webkit-hyphens: none) {\r\n :host {\r\n /* \r\n On Safari, when displaying in a dialog, we must inherit display property\r\n so that the animation runs each time the dialog is-reopened\r\n (display toggles between none and block).\r\n */\r\n display: inherit;\r\n /* \r\n On Safari the duration must be higher for the initial-snap animation\r\n to properly snap to the initial target.\r\n */\r\n animation: initial-snap 0.1s both;\r\n }\r\n }\r\n\r\n /*\r\n Temporarily disables scroll snapping for all snap points\r\n except the explicitly marked initial snap point (which overrides\r\n --snap-point-align) so that the sheet snaps to\r\n the initial snap point.\r\n */\r\n @keyframes initial-snap {\r\n 0% {\r\n --snap-point-align: none;\r\n }\r\n 50% {\r\n /* \r\n Needed for the iOS Safari\r\n See https://stackoverflow.com/q/65653679\r\n */\r\n scroll-snap-type: initial;\r\n --snap-point-align: none;\r\n }\r\n }\r\n\r\n /* Temporary workaround for iOS Safari bug https://bugs.webkit.org/show_bug.cgi?id=183870 */\r\n @supports (-webkit-touch-callout: none) {\r\n .sheet-content,\r\n .sheet-header,\r\n .sheet-footer {\r\n overflow-x: scroll;\r\n /* Prevent rubberband effect */\r\n overscroll-behavior-x: none;\r\n scrollbar-width: none;\r\n\r\n &::after {\r\n display: block;\r\n box-sizing: content-box;\r\n padding: inherit;\r\n padding-left: 0;\r\n width: calc(100% + 1px);\r\n height: 1px;\r\n content: \"\";\r\n }\r\n }\r\n .sheet-content {\r\n scrollbar-width: auto;\r\n }\r\n }\r\n\r\n :host(:not([nested-scroll]):not([content-height])) {\r\n .sheet-wrapper {\r\n height: 100%;\r\n }\r\n\r\n .sheet {\r\n min-height: 100%;\r\n }\r\n }\r\n\r\n :host([nested-scroll]) {\r\n .sheet-wrapper {\r\n display: flex;\r\n position: sticky;\r\n bottom: 0;\r\n flex-direction: column;\r\n justify-content: end;\r\n /* Fixes scroll-chaining issue on Firefox when sheet content is scrollable */\r\n contain: strict;\r\n height: 100%;\r\n }\r\n\r\n .sheet {\r\n display: flex;\r\n position: sticky;\r\n bottom: 0;\r\n flex-direction: column;\r\n height: 100%;\r\n max-height: 100%;\r\n }\r\n\r\n .sheet-content {\r\n will-change: scroll-position;\r\n overflow-y: auto;\r\n scrollbar-gutter: stable;\r\n }\r\n\r\n .sheet-header,\r\n .sheet-footer {\r\n /* Prevent shrinking the header and footer */\r\n flex: 0 0 auto;\r\n }\r\n }\r\n\r\n /*\r\n When expand-to-scroll is enabled, we do not need dynamic sheet height animation\r\n since sheet content is always fixed size and only scrollable at full height\r\n so we can simplify the layout and improve performance by disabling height animation.\r\n */\r\n :host([nested-scroll][expand-to-scroll]) {\r\n .sheet-wrapper {\r\n position: static;\r\n }\r\n\r\n .sheet {\r\n position: static;\r\n animation: none;\r\n height: 100%;\r\n }\r\n }\r\n\r\n /*\r\n Performance optimization for the nested-scroll mode:\r\n When the sheet is being actively scrolled, disable sheet height animation and\r\n switch to transform-based animation for the sheet content to improve performance\r\n and avoid jank because animating height would cause continuous reflow (layout).\r\n\r\n Follow use of [data-scrolling] for the specific CSS rules applied in this case.\r\n */\r\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\r\n .sheet-header {\r\n z-index: 1;\r\n }\r\n\r\n .sheet-content {\r\n /* Hide the scrollbar visually during scrolling */\r\n scrollbar-color: transparent transparent;\r\n }\r\n }\r\n\r\n @supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {\r\n :host {\r\n scroll-timeline: --sheet-timeline y;\r\n }\r\n\r\n :host([nested-scroll]) .sheet {\r\n animation: expand-sheet-height linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n\r\n @keyframes expand-sheet-height {\r\n from {\r\n height: 0;\r\n }\r\n to {\r\n height: 100%;\r\n }\r\n }\r\n\r\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\r\n animation: overflow-y-toggle linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n\r\n @keyframes overflow-y-toggle {\r\n 0%,\r\n 99.99% {\r\n overflow-y: hidden;\r\n }\r\n 100% {\r\n overflow-y: auto;\r\n }\r\n }\r\n\r\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\r\n .sheet {\r\n /* \r\n Safari bug fix: Pre-apply transform to prevent flickering. Safari 26+ has\r\n a one-frame delay when switching from height-based to transform-based animation,\r\n causing brief position shift. Setting an initial transform value ensures\r\n smooth transition.\r\n */\r\n transform: translateY(var(--sheet-timeline-at-scroll-start, 0));\r\n animation: translate-sheet linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n\r\n .sheet-content {\r\n animation: translate-sheet-content linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n\r\n .sheet-footer {\r\n animation: translate-footer linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n }\r\n\r\n @keyframes translate-sheet {\r\n from {\r\n transform: translateY(100%);\r\n }\r\n to {\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n @keyframes translate-sheet-content {\r\n from {\r\n transform: translateY(var(--sheet-content-offset-start, 0));\r\n }\r\n to {\r\n transform: translateY(var(--sheet-content-offset-end, 0));\r\n }\r\n }\r\n\r\n @keyframes translate-footer {\r\n from {\r\n transform: translateY(calc(-1 * var(--sheet-safe-max-height)));\r\n }\r\n to {\r\n transform: translateY(0);\r\n }\r\n }\r\n }\r\n\r\n /* Fallback for browsers that do not yet support scroll-driven animations */\r\n @supports (\r\n not ((animation-timeline: scroll()) and (animation-range: 0% 100%))\r\n ) {\r\n :host([nested-scroll]) .sheet {\r\n height: var(--sheet-position);\r\n }\r\n\r\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\r\n overflow-y: hidden;\r\n }\r\n\r\n :host([nested-scroll][expand-to-scroll][data-sheet-snap-position=\"0\"])\r\n .sheet-content {\r\n overflow-y: auto;\r\n }\r\n\r\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\r\n .sheet {\r\n transform: translateY(calc(100% - var(--sheet-position, 0)));\r\n height: 100%;\r\n }\r\n\r\n .sheet-content {\r\n transform: translateY(var(--sheet-content-offset, 0));\r\n }\r\n\r\n .sheet-footer {\r\n transform: translateY(\r\n calc(-1 * var(--sheet-safe-max-height) + var(--sheet-position, 0))\r\n );\r\n }\r\n }\r\n }\r\n`;\r\n\r\nexport const template: string = /*html*/ `\r\n <style>\r\n ${css}\r\n </style>\r\n <slot name=\"snap\">\r\n <div class=\"snap initial\" style=\"--snap: 100%\"></div>\r\n </slot>\r\n <div class=\"sentinel\" data-snap=\"1\"></div>\r\n <div class=\"snap snap-bottom\" data-snap=\"2\"></div>\r\n <div class=\"sentinel\" data-snap=\"0\"></div>\r\n <div class=\"sheet-wrapper\">\r\n <aside class=\"sheet\" part=\"sheet\" data-snap=\"0\">\r\n <div class=\"sentinel\" data-snap=\"-1\"></div>\r\n <header class=\"sheet-header\" part=\"header\">\r\n <div class=\"handle\" part=\"handle\"></div>\r\n <slot name=\"header\"></slot>\r\n </header>\r\n <section class=\"sheet-content\" part=\"content\">\r\n <slot></slot>\r\n </section>\r\n <footer class=\"sheet-footer\" part=\"footer\">\r\n <slot name=\"footer\"></slot>\r\n </footer>\r\n </aside>\r\n </div>\r\n`;\r\n"],"names":[],"mappings":"AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { BottomSheet } from "./bottom-sheet";
|
|
2
|
+
export { template as bottomSheetTemplate } from "./bottom-sheet.template";
|
|
3
|
+
export type { BottomSheetDialogManager } from "./bottom-sheet-dialog-manager";
|
|
4
|
+
export { template as bottomSheetDialogManagerTemplate } from "./bottom-sheet-dialog-manager.template";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{defineComponent as t,createBlock as e,openBlock as o,resolveDynamicComponent as s,h as n,Fragment as a,onMounted as l,unref as i,withCtx as r,createVNode as h,renderSlot as d}from"vue";const p='<style>\n :host{--sheet-max-height:calc(100dvh - 24px);--sheet-background:#f2f2f2;--sheet-border-radius:12px;--sheet-safe-max-height:calc(var(--sheet-max-height) - env(\n keyboard-inset-height,\n var(--sw-keyboard-height, 0px)\n ));border-top-left-radius:var(--sheet-border-radius);border-top-right-radius:var(--sheet-border-radius);bottom:env(keyboard-inset-height,0);contain:strict;display:block;height:var(--sheet-max-height);left:0;max-height:var(--sheet-safe-max-height);overflow-y:scroll;overscroll-behavior-y:none;pointer-events:none;position:fixed;right:0;scroll-snap-type:y mandatory;scrollbar-width:none;will-change:scroll-position}:host(:focus-visible){outline:none}:host(:focus-visible) .handle{outline:auto;outline-offset:4px}:host([data-sheet-snap-position="-1"]) .sheet,:host([data-sheet-snap-position="-1"]) .snap:before,:host([data-sheet-snap-position="-1"]) ::slotted([slot=snap]):before{scroll-snap-align:none}.snap,::slotted([slot=snap]){position:relative;top:var(--snap)}.snap:before,::slotted([slot=snap]):before{content:"";height:1px;left:0;position:absolute;right:0;scroll-snap-align:var(--snap-point-align,start);top:0}.snap.initial,::slotted([slot=snap].initial){--snap-point-align:start}.snap.snap-bottom{height:auto;position:static;top:auto}.snap.snap-bottom:after{content:"";display:block;height:var(--sheet-max-height);max-height:var(--sheet-safe-max-height);position:static}:host(:not([swipe-to-dismiss])) .snap.snap-bottom:before{scroll-snap-align:none}.sentinel{position:relative}.sentinel[data-snap="0"]{top:-1px}.sentinel[data-snap="-1"]{top:2px}.sentinel[data-snap="1"]{top:1px}.sheet,.sheet-wrapper{border-radius:inherit}.sheet{background:var(--sheet-background);cursor:row-resize;display:flex;flex-direction:column;overflow:clip;pointer-events:all;scroll-snap-align:var(--snap-point-align,start)}.sheet-header{top:0}.sheet-footer,.sheet-header{background:inherit;position:sticky;width:100%}.sheet-footer{bottom:0}.sheet-content{flex:1 1 auto;padding:0 .5rem}.handle{background:#ccc;border-radius:5px;height:5px;margin:.5rem auto;width:40px}:host{animation:initial-snap .01s both}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){:host{animation:initial-snap .1s both;display:inherit}}@keyframes initial-snap{0%{--snap-point-align:none}50%{scroll-snap-type:none;--snap-point-align:none}}@supports (-webkit-touch-callout:none){.sheet-content,.sheet-footer,.sheet-header{overflow-x:scroll;overscroll-behavior-x:none;scrollbar-width:none}:is(.sheet-content,.sheet-header,.sheet-footer):after{box-sizing:content-box;content:"";display:block;height:1px;padding:inherit;padding-left:0;width:calc(100% + 1px)}.sheet-content{scrollbar-width:auto}}:host(:not([nested-scroll]):not([content-height])) .sheet-wrapper{height:100%}:host(:not([nested-scroll]):not([content-height])) .sheet{min-height:100%}:host([nested-scroll]) .sheet-wrapper{bottom:0;contain:strict;display:flex;flex-direction:column;height:100%;justify-content:end;position:sticky}:host([nested-scroll]) .sheet{bottom:0;display:flex;flex-direction:column;height:100%;max-height:100%;position:sticky}:host([nested-scroll]) .sheet-content{overflow-y:auto;scrollbar-gutter:stable;will-change:scroll-position}:host([nested-scroll]) .sheet-footer,:host([nested-scroll]) .sheet-header{flex:0 0 auto}:host([nested-scroll][expand-to-scroll]) .sheet-wrapper{position:static}:host([nested-scroll][expand-to-scroll]) .sheet{animation:none;height:100%;position:static}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-header{z-index:1}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{scrollbar-color:transparent transparent}@supports ((animation-timeline:scroll()) and (animation-range:0% 100%)){:host{scroll-timeline:--sheet-timeline y}:host([nested-scroll]) .sheet{animation:expand-sheet-height linear forwards;animation-timeline:--sheet-timeline}@keyframes expand-sheet-height{0%{height:0}to{height:100%}}:host([nested-scroll][expand-to-scroll]) .sheet-content{animation:overflow-y-toggle linear forwards;animation-timeline:--sheet-timeline}@keyframes overflow-y-toggle{0%,99.99%{overflow-y:hidden}to{overflow-y:auto}}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet{animation:translate-sheet linear forwards;transform:translateY(var(--sheet-timeline-at-scroll-start,0));animation-timeline:--sheet-timeline}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{animation:translate-sheet-content linear forwards;animation-timeline:--sheet-timeline}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{animation:translate-footer linear forwards;animation-timeline:--sheet-timeline}@keyframes translate-sheet{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes translate-sheet-content{0%{transform:translateY(var(--sheet-content-offset-start,0))}to{transform:translateY(var(--sheet-content-offset-end,0))}}@keyframes translate-footer{0%{transform:translateY(calc(var(--sheet-safe-max-height)*-1))}to{transform:translateY(0)}}}@supports (not ((animation-timeline:scroll()) and (animation-range:0% 100%))){:host([nested-scroll]) .sheet{height:var(--sheet-position)}:host([nested-scroll][expand-to-scroll]) .sheet-content{overflow-y:hidden}:host([nested-scroll][expand-to-scroll][data-sheet-snap-position="0"]) .sheet-content{overflow-y:auto}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet{height:100%;transform:translateY(calc(100% - var(--sheet-position, 0)))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{transform:translateY(var(--sheet-content-offset,0))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{transform:translateY(calc(var(--sheet-safe-max-height)*-1 + var(--sheet-position, 0)))}}\n </style><slot name="snap"><div class="initial snap" style="--snap: 100%"></div></slot><div class="sentinel" data-snap="1"></div><div class="snap snap-bottom" data-snap="2"></div><div class="sentinel" data-snap="0"></div><div class="sheet-wrapper"><aside class="sheet" part="sheet" data-snap="0"><div class="sentinel" data-snap="-1"></div><header class="sheet-header" part="header"><div class="handle" part="handle"></div><slot name="header"></slot></header><section class="sheet-content" part="content"><slot></slot></section><footer class="sheet-footer" part="footer"><slot name="footer"></slot></footer></aside></div>',c='<style>\n ::slotted(dialog){background:unset;border:none;height:100%;inset:0;margin:0;max-height:none;max-width:none;padding:0;position:fixed;top:auto;width:100%}::slotted(dialog:not(:modal)){pointer-events:none}::slotted(dialog[open]){translate:0 0}@starting-style{::slotted(dialog[open]){translate:0 100vh}}::slotted(dialog){transition:translate .5s ease-out,overlay .5s ease-out allow-discrete,display var(--display-transition-duration,.5s) ease-out allow-discrete;translate:0 100vh}:host([data-sheet-snap-position="2"]) ::slotted(dialog:not([open])){transition:none}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){::slotted(dialog){--display-transition-duration:0.1s}}\n </style><slot></slot>';var m=t({__name:"ShadowRootTemplate",props:{html:{type:String,required:!0}},setup(t){const l=t,i="undefined"==typeof window,r=()=>n(a,i?[n("template",{shadowrootmode:"open",innerHTML:l.html})]:[]);return(t,n)=>(o(),e(s({render:r})))}}),g=t({__name:"VBottomSheet",setup(s){const a=t({name:"bottom-sheet",setup:(t,{attrs:e,slots:o})=>()=>n("bottom-sheet",e,o)});return l(()=>{import("./index.client-BJCxko7x.js").then(({BottomSheet:t})=>{customElements.get("bottom-sheet")||customElements.define("bottom-sheet",t)})}),(t,s)=>(o(),e(i(a),null,{default:r(()=>[h(m,{html:i(p)},null,8,["html"]),d(t.$slots,"default")]),_:3}))}}),f=t({__name:"VBottomSheetDialogManager",setup(s){const a=t({name:"bottom-sheet-dialog-manager",setup:(t,{attrs:e,slots:o})=>()=>n("bottom-sheet-dialog-manager",e,o)});return l(()=>{import("./index.client-BJCxko7x.js").then(({BottomSheetDialogManager:t})=>{customElements.get("bottom-sheet-dialog-manager")||customElements.define("bottom-sheet-dialog-manager",t)})}),(t,s)=>(o(),e(i(a),null,{default:r(()=>[h(m,{html:i(c)},null,8,["html"]),d(t.$slots,"default")]),_:3}))}});export{g as _,c as a,f as b,p as t};
|
|
2
|
+
//# sourceMappingURL=index-fslx24KY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-fslx24KY.js","sources":["../../src/web/bottom-sheet.template.ts","../../src/web/bottom-sheet-dialog-manager.template.ts","../../src/vue/ShadowRootTemplate.vue","../../src/vue/VBottomSheet.vue","../../src/vue/VBottomSheetDialogManager.vue"],"sourcesContent":["const css = /*css*/ `\r\n :host {\r\n --sheet-max-height: calc(100dvh - 24px);\r\n --sheet-background: rgb(242, 242, 242);\r\n --sheet-border-radius: 12px;\r\n /* \r\n The --sw-keyboard-height is needed to handle iOS Safari on-screen keyboard\r\n since iOS Safari pushes content offscreen by keyboard height when it is opened\r\n */\r\n --sheet-safe-max-height: calc(\r\n var(--sheet-max-height) - env(\r\n keyboard-inset-height,\r\n var(--sw-keyboard-height, 0px)\r\n )\r\n );\r\n display: block;\r\n position: fixed;\r\n right: 0;\r\n bottom: env(keyboard-inset-height, 0);\r\n left: 0;\r\n will-change: scroll-position;\r\n contain: strict;\r\n border-top-right-radius: var(--sheet-border-radius);\r\n border-top-left-radius: var(--sheet-border-radius);\r\n height: var(--sheet-max-height);\r\n max-height: var(--sheet-safe-max-height);\r\n overflow-y: scroll;\r\n /* Prevent rubberband effect when scrolling to the end of the sheet */\r\n overscroll-behavior-y: none;\r\n scroll-snap-type: y mandatory;\r\n scrollbar-width: none;\r\n pointer-events: none;\r\n }\r\n\r\n :host(:focus-visible) {\r\n outline: none;\r\n\r\n .handle {\r\n outline: auto;\r\n outline-offset: 4px;\r\n }\r\n }\r\n\r\n /* \r\n Disable snap alignment when sheet has reached the top and being scrolled\r\n to prevent snapping back to the top when the user scrolls the sheet on\r\n certain browsers (e.g. Firefox).\r\n */\r\n :host([data-sheet-snap-position=\"-1\"]) {\r\n .sheet,\r\n .snap::before,\r\n ::slotted([slot=\"snap\"])::before {\r\n scroll-snap-align: none;\r\n }\r\n }\r\n\r\n .snap,\r\n ::slotted([slot=\"snap\"]) {\r\n position: relative;\r\n top: var(--snap);\r\n }\r\n\r\n .snap::before,\r\n ::slotted([slot=\"snap\"])::before {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n left: 0;\r\n height: 1px; /* Height required for Safari to snap */\r\n scroll-snap-align: var(--snap-point-align, start);\r\n content: \"\";\r\n }\r\n\r\n .snap.initial,\r\n ::slotted([slot=\"snap\"].initial) {\r\n --snap-point-align: start;\r\n }\r\n\r\n .snap.snap-bottom {\r\n position: static;\r\n top: initial;\r\n height: auto;\r\n\r\n &::after {\r\n display: block;\r\n position: static;\r\n height: var(--sheet-max-height);\r\n max-height: var(--sheet-safe-max-height);\r\n content: \"\";\r\n }\r\n }\r\n\r\n :host(:not([swipe-to-dismiss])) .snap.snap-bottom::before {\r\n scroll-snap-align: none;\r\n }\r\n\r\n .sentinel {\r\n position: relative;\r\n\r\n &[data-snap=\"0\"] {\r\n top: -1px; /** Extra -1px needed for Safari */\r\n }\r\n &[data-snap=\"-1\"] {\r\n top: 2px; /** Extra +1px needed for Safari */\r\n }\r\n &[data-snap=\"1\"] {\r\n top: 1px;\r\n }\r\n }\r\n\r\n .sheet-wrapper {\r\n border-radius: inherit;\r\n }\r\n\r\n .sheet {\r\n display: flex;\r\n flex-direction: column;\r\n cursor: row-resize;\r\n border-radius: inherit;\r\n background: var(--sheet-background);\r\n overflow: clip;\r\n scroll-snap-align: var(--snap-point-align, start);\r\n pointer-events: all;\r\n }\r\n\r\n .sheet-header {\r\n position: sticky;\r\n top: 0;\r\n background: inherit;\r\n width: 100%;\r\n }\r\n\r\n .sheet-footer {\r\n position: sticky;\r\n bottom: 0;\r\n background: inherit;\r\n width: 100%;\r\n }\r\n\r\n .sheet-content {\r\n flex: 1 1 auto;\r\n padding: 0 0.5rem;\r\n }\r\n\r\n .handle {\r\n margin: 0.5rem auto;\r\n border-radius: 5px;\r\n background: #ccc;\r\n width: 40px;\r\n height: 5px;\r\n }\r\n\r\n :host {\r\n animation: initial-snap 0.01s both;\r\n }\r\n\r\n /* Safari overrides */\r\n @supports (-webkit-touch-callout: none) or (-webkit-hyphens: none) {\r\n :host {\r\n /* \r\n On Safari, when displaying in a dialog, we must inherit display property\r\n so that the animation runs each time the dialog is-reopened\r\n (display toggles between none and block).\r\n */\r\n display: inherit;\r\n /* \r\n On Safari the duration must be higher for the initial-snap animation\r\n to properly snap to the initial target.\r\n */\r\n animation: initial-snap 0.1s both;\r\n }\r\n }\r\n\r\n /*\r\n Temporarily disables scroll snapping for all snap points\r\n except the explicitly marked initial snap point (which overrides\r\n --snap-point-align) so that the sheet snaps to\r\n the initial snap point.\r\n */\r\n @keyframes initial-snap {\r\n 0% {\r\n --snap-point-align: none;\r\n }\r\n 50% {\r\n /* \r\n Needed for the iOS Safari\r\n See https://stackoverflow.com/q/65653679\r\n */\r\n scroll-snap-type: initial;\r\n --snap-point-align: none;\r\n }\r\n }\r\n\r\n /* Temporary workaround for iOS Safari bug https://bugs.webkit.org/show_bug.cgi?id=183870 */\r\n @supports (-webkit-touch-callout: none) {\r\n .sheet-content,\r\n .sheet-header,\r\n .sheet-footer {\r\n overflow-x: scroll;\r\n /* Prevent rubberband effect */\r\n overscroll-behavior-x: none;\r\n scrollbar-width: none;\r\n\r\n &::after {\r\n display: block;\r\n box-sizing: content-box;\r\n padding: inherit;\r\n padding-left: 0;\r\n width: calc(100% + 1px);\r\n height: 1px;\r\n content: \"\";\r\n }\r\n }\r\n .sheet-content {\r\n scrollbar-width: auto;\r\n }\r\n }\r\n\r\n :host(:not([nested-scroll]):not([content-height])) {\r\n .sheet-wrapper {\r\n height: 100%;\r\n }\r\n\r\n .sheet {\r\n min-height: 100%;\r\n }\r\n }\r\n\r\n :host([nested-scroll]) {\r\n .sheet-wrapper {\r\n display: flex;\r\n position: sticky;\r\n bottom: 0;\r\n flex-direction: column;\r\n justify-content: end;\r\n /* Fixes scroll-chaining issue on Firefox when sheet content is scrollable */\r\n contain: strict;\r\n height: 100%;\r\n }\r\n\r\n .sheet {\r\n display: flex;\r\n position: sticky;\r\n bottom: 0;\r\n flex-direction: column;\r\n height: 100%;\r\n max-height: 100%;\r\n }\r\n\r\n .sheet-content {\r\n will-change: scroll-position;\r\n overflow-y: auto;\r\n scrollbar-gutter: stable;\r\n }\r\n\r\n .sheet-header,\r\n .sheet-footer {\r\n /* Prevent shrinking the header and footer */\r\n flex: 0 0 auto;\r\n }\r\n }\r\n\r\n /*\r\n When expand-to-scroll is enabled, we do not need dynamic sheet height animation\r\n since sheet content is always fixed size and only scrollable at full height\r\n so we can simplify the layout and improve performance by disabling height animation.\r\n */\r\n :host([nested-scroll][expand-to-scroll]) {\r\n .sheet-wrapper {\r\n position: static;\r\n }\r\n\r\n .sheet {\r\n position: static;\r\n animation: none;\r\n height: 100%;\r\n }\r\n }\r\n\r\n /*\r\n Performance optimization for the nested-scroll mode:\r\n When the sheet is being actively scrolled, disable sheet height animation and\r\n switch to transform-based animation for the sheet content to improve performance\r\n and avoid jank because animating height would cause continuous reflow (layout).\r\n\r\n Follow use of [data-scrolling] for the specific CSS rules applied in this case.\r\n */\r\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\r\n .sheet-header {\r\n z-index: 1;\r\n }\r\n\r\n .sheet-content {\r\n /* Hide the scrollbar visually during scrolling */\r\n scrollbar-color: transparent transparent;\r\n }\r\n }\r\n\r\n @supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {\r\n :host {\r\n scroll-timeline: --sheet-timeline y;\r\n }\r\n\r\n :host([nested-scroll]) .sheet {\r\n animation: expand-sheet-height linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n\r\n @keyframes expand-sheet-height {\r\n from {\r\n height: 0;\r\n }\r\n to {\r\n height: 100%;\r\n }\r\n }\r\n\r\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\r\n animation: overflow-y-toggle linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n\r\n @keyframes overflow-y-toggle {\r\n 0%,\r\n 99.99% {\r\n overflow-y: hidden;\r\n }\r\n 100% {\r\n overflow-y: auto;\r\n }\r\n }\r\n\r\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\r\n .sheet {\r\n /* \r\n Safari bug fix: Pre-apply transform to prevent flickering. Safari 26+ has\r\n a one-frame delay when switching from height-based to transform-based animation,\r\n causing brief position shift. Setting an initial transform value ensures\r\n smooth transition.\r\n */\r\n transform: translateY(var(--sheet-timeline-at-scroll-start, 0));\r\n animation: translate-sheet linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n\r\n .sheet-content {\r\n animation: translate-sheet-content linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n\r\n .sheet-footer {\r\n animation: translate-footer linear forwards;\r\n animation-timeline: --sheet-timeline;\r\n }\r\n }\r\n\r\n @keyframes translate-sheet {\r\n from {\r\n transform: translateY(100%);\r\n }\r\n to {\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n @keyframes translate-sheet-content {\r\n from {\r\n transform: translateY(var(--sheet-content-offset-start, 0));\r\n }\r\n to {\r\n transform: translateY(var(--sheet-content-offset-end, 0));\r\n }\r\n }\r\n\r\n @keyframes translate-footer {\r\n from {\r\n transform: translateY(calc(-1 * var(--sheet-safe-max-height)));\r\n }\r\n to {\r\n transform: translateY(0);\r\n }\r\n }\r\n }\r\n\r\n /* Fallback for browsers that do not yet support scroll-driven animations */\r\n @supports (\r\n not ((animation-timeline: scroll()) and (animation-range: 0% 100%))\r\n ) {\r\n :host([nested-scroll]) .sheet {\r\n height: var(--sheet-position);\r\n }\r\n\r\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\r\n overflow-y: hidden;\r\n }\r\n\r\n :host([nested-scroll][expand-to-scroll][data-sheet-snap-position=\"0\"])\r\n .sheet-content {\r\n overflow-y: auto;\r\n }\r\n\r\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\r\n .sheet {\r\n transform: translateY(calc(100% - var(--sheet-position, 0)));\r\n height: 100%;\r\n }\r\n\r\n .sheet-content {\r\n transform: translateY(var(--sheet-content-offset, 0));\r\n }\r\n\r\n .sheet-footer {\r\n transform: translateY(\r\n calc(-1 * var(--sheet-safe-max-height) + var(--sheet-position, 0))\r\n );\r\n }\r\n }\r\n }\r\n`;\r\n\r\nexport const template: string = /*html*/ `\r\n <style>\r\n ${css}\r\n </style>\r\n <slot name=\"snap\">\r\n <div class=\"snap initial\" style=\"--snap: 100%\"></div>\r\n </slot>\r\n <div class=\"sentinel\" data-snap=\"1\"></div>\r\n <div class=\"snap snap-bottom\" data-snap=\"2\"></div>\r\n <div class=\"sentinel\" data-snap=\"0\"></div>\r\n <div class=\"sheet-wrapper\">\r\n <aside class=\"sheet\" part=\"sheet\" data-snap=\"0\">\r\n <div class=\"sentinel\" data-snap=\"-1\"></div>\r\n <header class=\"sheet-header\" part=\"header\">\r\n <div class=\"handle\" part=\"handle\"></div>\r\n <slot name=\"header\"></slot>\r\n </header>\r\n <section class=\"sheet-content\" part=\"content\">\r\n <slot></slot>\r\n </section>\r\n <footer class=\"sheet-footer\" part=\"footer\">\r\n <slot name=\"footer\"></slot>\r\n </footer>\r\n </aside>\r\n </div>\r\n`;\r\n","const css = /*css*/ `\n ::slotted(dialog) {\n position: fixed;\n margin: 0;\n inset: 0;\n top: initial;\n border: none;\n background: unset;\n padding: 0;\n width: 100%;\n max-width: none;\n height: 100%;\n max-height: none;\n }\n\n ::slotted(dialog:not(:modal)) {\n pointer-events: none;\n }\n\n ::slotted(dialog[open]) {\n translate: 0 0;\n }\n\n @starting-style {\n ::slotted(dialog[open]) {\n translate: 0 100vh;\n }\n }\n\n ::slotted(dialog) {\n translate: 0 100vh;\n transition:\n translate 0.5s ease-out,\n overlay 0.5s ease-out allow-discrete,\n display var(--display-transition-duration, 0.5s) ease-out allow-discrete;\n }\n\n :host([data-sheet-snap-position=\"2\"]) ::slotted(dialog:not([open])) {\n transition: none;\n }\n\n /** Safari overrides */\n @supports (-webkit-touch-callout: none) or (-webkit-hyphens: none) {\n ::slotted(dialog) {\n /* \n For Safari we must user shorter duration for display property or otherwise\n the bottom sheet will not snap properly to the initial target on open.\n */\n --display-transition-duration: 0.1s;\n }\n }\n`;\n\nexport const template: string = /*html*/ `\n <style>\n ${css}\n </style>\n <slot></slot>\n`;\n","<script setup lang=\"ts\">\nimport { h, Fragment } from \"vue\";\n\nconst props = defineProps({\n html: {\n type: String,\n required: true,\n },\n});\n\nconst isServer = typeof window === \"undefined\";\n\nconst renderShadowRootTemplate = () => {\n if (!isServer) return h(Fragment, []);\n\n return h(Fragment, [\n h(\"template\", {\n shadowrootmode: \"open\",\n innerHTML: props.html,\n }),\n ]);\n};\n</script>\n\n<template>\n <component :is=\"{ render: renderShadowRootTemplate }\" />\n</template>\n","<template>\n <BottomSheet>\n <ShadowRootTemplate :html=\"bottomSheetTemplate\"></ShadowRootTemplate>\n <slot></slot>\n </BottomSheet>\n</template>\n\n<script setup lang=\"ts\">\nimport { defineComponent, h, onMounted } from \"vue\";\nimport { bottomSheetTemplate } from \"../web/index.ssr\";\nimport ShadowRootTemplate from \"./ShadowRootTemplate.vue\";\n\n// Vue wrapper component for the BottomSheet web component so that\n// the library users do not need to define bottom-sheet as a custom element\nconst BottomSheet = defineComponent({\n name: \"bottom-sheet\",\n setup(_, { attrs, slots }) {\n return () => h(\"bottom-sheet\", attrs, slots);\n },\n});\n\nonMounted(() => {\n import(\"../web/index.client\").then(({ BottomSheet }) => {\n if (!customElements.get(\"bottom-sheet\")) {\n customElements.define(\"bottom-sheet\", BottomSheet);\n }\n });\n});\n</script>\n","<template>\n <BottomSheetDialogManager>\n <ShadowRootTemplate\n :html=\"bottomSheetDialogManagerTemplate\"\n ></ShadowRootTemplate>\n <slot></slot>\n </BottomSheetDialogManager>\n</template>\n\n<script setup lang=\"ts\">\nimport { defineComponent, h, onMounted } from \"vue\";\nimport { bottomSheetDialogManagerTemplate } from \"../web/index.ssr\";\nimport ShadowRootTemplate from \"./ShadowRootTemplate.vue\";\n\n// Vue wrapper component for the BottomSheetDialogManager web component so that\n// the library users do not need to define bottom-sheet-dialog-manager as a custom element\nconst BottomSheetDialogManager = defineComponent({\n name: \"bottom-sheet-dialog-manager\",\n setup(_, { attrs, slots }) {\n return () => h(\"bottom-sheet-dialog-manager\", attrs, slots);\n },\n});\n\nonMounted(() => {\n import(\"../web/index.client\").then(({ BottomSheetDialogManager }) => {\n if (!customElements.get(\"bottom-sheet-dialog-manager\")) {\n customElements.define(\n \"bottom-sheet-dialog-manager\",\n BottomSheetDialogManager,\n );\n }\n });\n});\n</script>\n"],"names":["template","props","__props","isServer","window","renderShadowRootTemplate","h","Fragment","shadowrootmode","innerHTML","html","_openBlock","_createBlock","_resolveDynamicComponent","BottomSheet","defineComponent","name","setup","_","attrs","slots","onMounted","import","then","customElements","get","define","_unref","_createVNode","ShadowRootTemplate","bottomSheetTemplate","_renderSlot","_ctx","$slots","BottomSheetDialogManager","bottomSheetDialogManagerTemplate"],"mappings":"gMAAA,MAAoBA,EAAA,4zMCAAA,EAAA,qyBCGpB,MAAMC,EAAQC,EAORC,EAA6B,oBAAXC,OAElBC,EAA2B,IAGxBC,EAAEC,EAFJJ,EAEc,CACjBG,EAAE,WAAY,CACZE,eAAgB,OAChBC,UAAWR,EAAMS,QALa,kBAYlCC,IAAAC,EAAwDC,UAA9BR,6CCX5B,MAAMS,EAAcC,EAAgB,CAClCC,KAAM,eACNC,MAAA,CAAMC,GAAGC,MAAEA,EAAAC,MAAOA,KACT,IAAMd,EAAE,eAAgBa,EAAOC,YAI1CC,EAAU,KACRC,OAAO,8BAAuBC,KAAK,EAAGT,YAAAA,MAC/BU,eAAeC,IAAI,iBACtBD,eAAeE,OAAO,eAAgBZ,mBAvB1CF,EAGce,EAAAb,GAAA,KAAA,WAFZ,IAAqE,CAArEc,EAAqEC,EAAA,CAAhDnB,KAAMiB,EAAAG,IAAmB,KAAA,EAAA,CAAA,SAC9CC,EAAaC,EAAAC,OAAA,wECajB,MAAMC,EAA2BnB,EAAgB,CAC/CC,KAAM,8BACNC,MAAA,CAAMC,GAAGC,MAAEA,EAAAC,MAAOA,KACT,IAAMd,EAAE,8BAA+Ba,EAAOC,YAIzDC,EAAU,KACRC,OAAO,8BAAuBC,KAAK,EAAGW,yBAAAA,MAC/BV,eAAeC,IAAI,gCACtBD,eAAeE,OACb,8BACAQ,mBA3BNtB,EAK2Be,EAAAO,GAAA,KAAA,WAJzB,IAEsB,CAFtBN,EAEsBC,EAAA,CADnBnB,KAAMiB,EAAAQ,IAAgC,KAAA,EAAA,CAAA,SAEzCJ,EAAaC,EAAAC,OAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{t as e,a as t}from"./index-fslx24KY.js";import"vue";class s extends HTMLElement{static observedAttributes=["nested-scroll-optimization"];#e=null;#t=()=>{this.style.setProperty("--sw-keyboard-height",`${window.visualViewport?.offsetTop??0}px`)};#s;#o=null;constructor(){super();const t=HTMLElement.prototype.hasOwnProperty("attachInternals")?this.attachInternals():void 0;let s=t?.shadowRoot;s||(s=this.attachShadow({mode:"open"}),s.innerHTML=e),this.#s=s;"onscrollsnapchange"in window&&this.addEventListener("scrollsnapchange",this.#n),CSS.supports("(animation-timeline: scroll()) and (animation-range: 0% 100%)")||(this.addEventListener("scroll",this.#i),this.#i())}connectedCallback(){"onscrollsnapchange"in window||this.#r(),window.visualViewport?.addEventListener("resize",this.#t)}#r(){this.#e=new IntersectionObserver(e=>{let t=1/0,s=-1/0,o=!1;for(const n of e){if(!(n.target instanceof HTMLElement)||null==n.target.dataset.snap)continue;const e=Number.parseInt(n.target.dataset.snap);n.isIntersecting?(o=!0,t=Math.min(t,e)):s=Math.max(s,e)}const n=o?t:s+1;this.#l(n.toString())},{root:this,threshold:0,rootMargin:"1000% 0px -100% 0px"});const e=this.#s.querySelectorAll(".sentinel");Array.from(e).forEach(e=>{this.#e?.observe(e)})}#n(e){const t=e;if(!(t.snapTargetBlock instanceof HTMLElement))return;const s=t.snapTargetBlock.dataset.snap??"1";this.#l(s)}#l(e){this.dataset.sheetSnapPosition=e,this.dispatchEvent(new CustomEvent("snap-position-change",{detail:{snapPosition:e},bubbles:!0,composed:!0}))}#i(){this.#s.querySelector(".sheet-wrapper")?.style.setProperty("--sheet-position",`${this.scrollTop}px`)}#a(){const e=this.#s.querySelector(".sheet-wrapper"),t=this.#s.querySelector(".sheet"),s=this.#s.querySelector(".sheet-content");if(!e||!t||!s)return;const o=CSS.supports("scroll-timeline: --sheet-timeline y"),n="onscrollend"in window&&!CSS.supports("-moz-appearance","none");let i,r,l;const a=()=>{const t=this.scrollTop/(this.scrollHeight-this.offsetHeight),s=(1-t)*i+t*r;e.style.setProperty("--sheet-content-offset",`${s}px`)},c=()=>{delete this.dataset.scrolling,["--sheet-content-offset","--sheet-content-offset-start","--sheet-content-offset-end"].forEach(t=>e.style.removeProperty(t))},h=()=>{e.style.setProperty("--sheet-content-offset-start",`${i}px`),e.style.setProperty("--sheet-content-offset-end",`${r}px`)},p=()=>{const e=getComputedStyle(s),t=-new DOMMatrixReadOnly(e.transform).m42;c(),requestAnimationFrame(()=>{s.scrollTop=t+s.scrollTop})},d=()=>{if("scrolling"in this.dataset)o||a();else{const n=e.offsetHeight-(t.offsetHeight-s.offsetHeight),l=s.scrollHeight-n;if(Math.floor(s.scrollTop)>l){const o=s.scrollHeight-s.offsetHeight-s.scrollTop,n=e.offsetHeight/(e.offsetHeight-t.offsetHeight);i=-(s.scrollHeight+(t.offsetHeight-s.offsetHeight))+o*n,r=-l,this.dataset.scrolling="",i+=s.scrollTop,r+=s.scrollTop,h()}else i=0,r=0,h(),this.dataset.scrolling="";if(o||a(),"ScrollTimeline"in window){const t=new ScrollTimeline({source:this,axis:"y"});e.style.setProperty("--sheet-timeline-at-scroll-start",`${t.currentTime}`)}}},m=()=>{window.clearTimeout(l),l=window.setTimeout(p,100)};this.addEventListener("scroll",d),n?this.addEventListener("scrollend",p):this.addEventListener("scroll",m),this.#o=()=>{this.removeEventListener("scroll",d),n?this.removeEventListener("scrollend",p):(this.removeEventListener("scroll",m),window.clearTimeout(l)),c(),this.#o=null}}attributeChangedCallback(e,t,s){if(t!==s)if("nested-scroll-optimization"===e)null!==s?this.#o||this.#a():this.#o&&this.#o();else console.warn(`Unhandled attribute: ${e}`)}disconnectedCallback(){this.#e?.disconnect(),window.visualViewport?.removeEventListener("resize",this.#t)}}class o extends HTMLElement{constructor(){super();const e=HTMLElement.prototype.hasOwnProperty("attachInternals")?this.attachInternals():void 0;let s=e?.shadowRoot;s||(s=this.attachShadow({mode:"open"}),s.innerHTML=t),this.addEventListener("click",e=>{e.target instanceof HTMLDialogElement&&e.target.matches(":modal")&&e.target.close()}),this.addEventListener("snap-position-change",e=>{if(e.detail&&(this.dataset.sheetSnapPosition=e.detail.snapPosition),"2"==e.detail?.snapPosition&&e.target instanceof HTMLElement&&e.target.hasAttribute("swipe-to-dismiss")&&e.target.checkVisibility()){const t=e.target.parentElement;t instanceof HTMLDialogElement&&"0px"===getComputedStyle(t).getPropertyValue("translate")&&t.close()}})}}export{s as BottomSheet,o as BottomSheetDialogManager};
|
|
2
|
+
//# sourceMappingURL=index.client-BJCxko7x.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.client-BJCxko7x.js","sources":["../../src/web/bottom-sheet.ts","../../src/web/bottom-sheet-dialog-manager.ts"],"sourcesContent":["import { template } from \"./bottom-sheet.template\";\n\n/**\n * @see https://drafts.csswg.org/css-scroll-snap-2/#snapevent-interface\n */\ninterface SnapEvent extends Event {\n snapTargetBlock: Element;\n}\n\n/**\n * @see https://drafts.csswg.org/scroll-animations/#scrolltimeline-interface\n */\ninterface ScrollTimeline extends AnimationTimeline {\n readonly source: Element | null;\n readonly axis: string;\n}\ndeclare var ScrollTimeline: {\n prototype: ScrollTimeline;\n new ({ source, axis }: { source: Element; axis: string }): ScrollTimeline;\n};\n\nexport class BottomSheet extends HTMLElement {\n static observedAttributes = [\"nested-scroll-optimization\"];\n #observer: IntersectionObserver | null = null;\n #handleViewportResize = () => {\n this.style.setProperty(\n \"--sw-keyboard-height\",\n `${window.visualViewport?.offsetTop ?? 0}px`,\n );\n };\n #shadow: ShadowRoot;\n #cleanupNestedScrollResizeOptimization: (() => void) | null = null;\n\n constructor() {\n super();\n\n const supportsDeclarative =\n HTMLElement.prototype.hasOwnProperty(\"attachInternals\");\n const internals = supportsDeclarative ? this.attachInternals() : undefined;\n\n // Use existing declarative shadow root if present, otherwise create one\n let shadow = internals?.shadowRoot;\n if (!shadow) {\n shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = template;\n }\n this.#shadow = shadow;\n\n const supportsScrollSnapChange = \"onscrollsnapchange\" in window;\n if (supportsScrollSnapChange) {\n this.addEventListener(\"scrollsnapchange\", this.#handleScrollSnapChange);\n }\n\n if (\n !CSS.supports(\n \"(animation-timeline: scroll()) and (animation-range: 0% 100%)\",\n )\n ) {\n this.addEventListener(\"scroll\", this.#handleScroll);\n this.#handleScroll();\n }\n }\n\n connectedCallback() {\n const supportsScrollSnapChange = \"onscrollsnapchange\" in window;\n if (!supportsScrollSnapChange) {\n this.#setupIntersectionObserver();\n }\n\n window.visualViewport?.addEventListener(\n \"resize\",\n this.#handleViewportResize,\n );\n }\n\n #setupIntersectionObserver() {\n this.#observer = new IntersectionObserver(\n (entries) => {\n let lowestIntersectingSnap = Infinity;\n let highestNonIntersectingSnap = -Infinity;\n let hasIntersectingElement = false;\n\n for (const entry of entries) {\n if (\n !(entry.target instanceof HTMLElement) ||\n entry.target.dataset.snap == null\n ) {\n continue;\n }\n\n const snap = Number.parseInt(entry.target.dataset.snap);\n\n if (entry.isIntersecting) {\n hasIntersectingElement = true;\n lowestIntersectingSnap = Math.min(lowestIntersectingSnap, snap);\n } else {\n highestNonIntersectingSnap = Math.max(\n highestNonIntersectingSnap,\n snap,\n );\n }\n }\n\n const newSnapPosition = hasIntersectingElement\n ? lowestIntersectingSnap\n : highestNonIntersectingSnap + 1;\n\n this.#updateSnapPosition(newSnapPosition.toString());\n },\n {\n root: this,\n threshold: 0,\n rootMargin: \"1000% 0px -100% 0px\",\n },\n );\n\n const sentinels = this.#shadow.querySelectorAll(\".sentinel\");\n Array.from(sentinels).forEach((sentinel) => {\n this.#observer?.observe(sentinel);\n });\n }\n\n #handleScrollSnapChange(event: Event) {\n const snapEvent = event as SnapEvent;\n if (!(snapEvent.snapTargetBlock instanceof HTMLElement)) {\n return;\n }\n const newSnapPosition = snapEvent.snapTargetBlock.dataset.snap ?? \"1\";\n this.#updateSnapPosition(newSnapPosition);\n }\n\n #updateSnapPosition(position: string) {\n this.dataset.sheetSnapPosition = position;\n this.dispatchEvent(\n new CustomEvent<{ snapPosition: string }>(\"snap-position-change\", {\n detail: {\n snapPosition: position,\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n #handleScroll() {\n this.#shadow\n .querySelector<HTMLElement>(\".sheet-wrapper\")\n ?.style.setProperty(\"--sheet-position\", `${this.scrollTop}px`);\n }\n\n #setupNestedScrollResizeOptimization() {\n const wrapper = this.#shadow.querySelector<HTMLElement>(\".sheet-wrapper\");\n const sheet = this.#shadow.querySelector<HTMLElement>(\".sheet\");\n const content = this.#shadow.querySelector<HTMLElement>(\".sheet-content\");\n\n if (!wrapper || !sheet || !content) {\n return;\n }\n\n const SCROLL_END_TIMEOUT_MS = 100;\n const supportsScrollAnimations = CSS.supports(\n \"scroll-timeline: --sheet-timeline y\",\n );\n // Use scrollend event if available to detect end of scrolling\n // (exclude Firefox for now which has inconsistencies with scrollend\n // implementation with scroll chaining from nested scrollable elements)\n const supportScrollEnd =\n \"onscrollend\" in window && !CSS.supports(\"-moz-appearance\", \"none\");\n let contentYOffsetStart: number,\n contentYOffsetEnd: number,\n scrollTimeout: number;\n\n // If CSS scroll-timeline is not supported, we need to manually update\n // the y offset of the sheet content during scrolling\n const updateContentYOffset = () => {\n const t = this.scrollTop / (this.scrollHeight - this.offsetHeight);\n const contentTranslateY =\n (1 - t) * contentYOffsetStart + t * contentYOffsetEnd;\n wrapper.style.setProperty(\n \"--sheet-content-offset\",\n `${contentTranslateY}px`,\n );\n };\n\n const cleanupStyleProperties = () => {\n delete this.dataset.scrolling;\n [\n \"--sheet-content-offset\",\n \"--sheet-content-offset-start\",\n \"--sheet-content-offset-end\",\n ].forEach((p) => wrapper.style.removeProperty(p));\n };\n\n const updateOffsetProperties = () => {\n wrapper.style.setProperty(\n \"--sheet-content-offset-start\",\n `${contentYOffsetStart}px`,\n );\n wrapper.style.setProperty(\n \"--sheet-content-offset-end\",\n `${contentYOffsetEnd}px`,\n );\n };\n\n const handleScrollEnd = () => {\n const style = getComputedStyle(content);\n const matrix = new DOMMatrixReadOnly(style.transform);\n const yOffset = -matrix.m42;\n cleanupStyleProperties();\n requestAnimationFrame(() => {\n content.scrollTop = yOffset + content.scrollTop;\n });\n };\n\n const handleScroll = () => {\n if (!(\"scrolling\" in this.dataset)) {\n const contentMaxOffsetHeight =\n wrapper.offsetHeight - (sheet.offsetHeight - content.offsetHeight);\n // Threshold after which resizing sheet content anchors the inner\n // content to the bottom of the scrollport instead of top\n const scrollBottomAnchorThreshold =\n content.scrollHeight - contentMaxOffsetHeight;\n if (Math.floor(content.scrollTop) > scrollBottomAnchorThreshold) {\n const contentScrollBottom =\n content.scrollHeight - content.offsetHeight - content.scrollTop;\n\n // Size factor based on the current height of the bottom sheet\n const sheetSizeFactor =\n wrapper.offsetHeight / (wrapper.offsetHeight - sheet.offsetHeight);\n\n contentYOffsetStart =\n -(\n content.scrollHeight +\n (sheet.offsetHeight - content.offsetHeight)\n ) +\n contentScrollBottom * sheetSizeFactor;\n contentYOffsetEnd = -scrollBottomAnchorThreshold;\n\n // Toggle scrolling state on\n this.dataset.scrolling = \"\";\n\n // Readjust sheet content offset range based on current scroll position\n // of the sheet content after the layout change caused by toggling the\n // data-scrolling attribute\n contentYOffsetStart += content.scrollTop;\n contentYOffsetEnd += content.scrollTop;\n\n updateOffsetProperties();\n } else {\n contentYOffsetStart = 0;\n contentYOffsetEnd = 0;\n updateOffsetProperties();\n this.dataset.scrolling = \"\";\n }\n\n if (!supportsScrollAnimations) {\n updateContentYOffset();\n }\n\n if (\"ScrollTimeline\" in window) {\n // Needed for Safari 26+ to prevent flash of sheet position when toggling data-scrolling\n // before the scroll timeline is applied by the browser\n const timeline = new ScrollTimeline({\n source: this,\n axis: \"y\",\n });\n wrapper.style.setProperty(\n \"--sheet-timeline-at-scroll-start\",\n `${timeline.currentTime}`,\n );\n }\n } else if (!supportsScrollAnimations) {\n updateContentYOffset();\n }\n };\n\n const handleFallbackScrollEnd = () => {\n window.clearTimeout(scrollTimeout);\n scrollTimeout = window.setTimeout(handleScrollEnd, SCROLL_END_TIMEOUT_MS);\n };\n\n this.addEventListener(\"scroll\", handleScroll);\n if (supportScrollEnd) {\n this.addEventListener(\"scrollend\", handleScrollEnd);\n } else {\n this.addEventListener(\"scroll\", handleFallbackScrollEnd);\n }\n\n this.#cleanupNestedScrollResizeOptimization = () => {\n this.removeEventListener(\"scroll\", handleScroll);\n if (supportScrollEnd) {\n this.removeEventListener(\"scrollend\", handleScrollEnd);\n } else {\n this.removeEventListener(\"scroll\", handleFallbackScrollEnd);\n window.clearTimeout(scrollTimeout);\n }\n\n cleanupStyleProperties();\n this.#cleanupNestedScrollResizeOptimization = null;\n };\n }\n\n attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string | null,\n ) {\n if (oldValue === newValue) return;\n\n switch (name) {\n case \"nested-scroll-optimization\":\n if (newValue !== null) {\n if (!this.#cleanupNestedScrollResizeOptimization) {\n // Only setup if not already setup\n this.#setupNestedScrollResizeOptimization();\n }\n } else if (this.#cleanupNestedScrollResizeOptimization) {\n this.#cleanupNestedScrollResizeOptimization();\n }\n break;\n default:\n console.warn(`Unhandled attribute: ${name}`);\n }\n }\n\n disconnectedCallback() {\n this.#observer?.disconnect();\n window.visualViewport?.removeEventListener(\n \"resize\",\n this.#handleViewportResize,\n );\n }\n}\n\n/**\n * Interface for the bottom-sheet custom element.\n * Provides type definitions for its custom properties.\n *\n * @example\n * // Register in TypeScript for proper type checking:\n * declare global {\n * interface HTMLElementTagNameMap {\n * \"bottom-sheet\": BottomSheet;\n * }\n * }\n */\nexport interface BottomSheet extends HTMLElement {\n /**\n * When set, the bottom sheet maximum height is based on the the height of its\n * contents.\n */\n [\"content-height\"]?: boolean;\n /**\n * When set, enables scrolling the sheet inner content independently of the sheet.\n */\n [\"nested-scroll\"]?: boolean;\n /**\n * When set, enables resize optimization for the nested scroll mode to avoid reflows\n * during sheet resizing. Only relevant when `nested-scroll` is also true. Not relevant\n * for `expand-to-scroll` mode since it already avoids reflows.\n */\n [\"nested-scroll-optimization\"]?: boolean;\n /**\n * When set, content becomes scrollable only after full expansion. Only relevant\n * when `nested-scroll` is also true.\n */\n [\"expand-to-scroll\"]?: boolean;\n /**\n * When set, allows swiping down to dismiss the bottom sheet when used together\n * with the `bottom-sheet-dialog-manager` or with the Popover API.\n */\n [\"swipe-to-dismiss\"]?: boolean;\n}\n","import { template } from \"./bottom-sheet-dialog-manager.template\";\n\nexport class BottomSheetDialogManager extends HTMLElement {\n constructor() {\n super();\n\n const supportsDeclarative =\n HTMLElement.prototype.hasOwnProperty(\"attachInternals\");\n const internals = supportsDeclarative ? this.attachInternals() : undefined;\n\n // Use existing declarative shadow root if present, otherwise create one\n let shadow = internals?.shadowRoot;\n if (!shadow) {\n shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = template;\n }\n\n this.addEventListener(\"click\", (event) => {\n if (\n event.target instanceof HTMLDialogElement &&\n event.target.matches(\":modal\")\n ) {\n event.target.close();\n }\n });\n this.addEventListener(\n \"snap-position-change\",\n (event: CustomEventInit<{ snapPosition: string }> & Event) => {\n if (event.detail) {\n this.dataset.sheetSnapPosition = event.detail.snapPosition;\n }\n if (\n event.detail?.snapPosition == \"2\" &&\n event.target instanceof HTMLElement &&\n event.target.hasAttribute(\"swipe-to-dismiss\") &&\n event.target.checkVisibility()\n ) {\n const parent = event.target.parentElement;\n if (\n parent instanceof HTMLDialogElement &&\n // Prevent Safari from closing the dialog immediately after opening\n // while the dialog open transition is still running.\n getComputedStyle(parent).getPropertyValue(\"translate\") === \"0px\"\n ) {\n parent.close();\n }\n }\n },\n );\n }\n}\n\n/**\n * Interface for the bottom-sheet-dialog-manager custom element.\n * Provides type definitions for its custom properties.\n *\n * @example\n * // Register in TypeScript for proper type checking:\n * declare global {\n * interface HTMLElementTagNameMap {\n * \"bottom-sheet-dialog-manager\": BottomSheetDialogManager;\n * }\n * }\n */\nexport interface BottomSheetDialogManager extends HTMLElement {}\n"],"names":["BottomSheet","HTMLElement","static","observer","handleViewportResize","this","style","setProperty","window","visualViewport","offsetTop","shadow","cleanupNestedScrollResizeOptimization","constructor","super","internals","prototype","hasOwnProperty","attachInternals","shadowRoot","attachShadow","mode","innerHTML","template","addEventListener","handleScrollSnapChange","CSS","supports","handleScroll","connectedCallback","setupIntersectionObserver","IntersectionObserver","entries","lowestIntersectingSnap","Infinity","highestNonIntersectingSnap","hasIntersectingElement","entry","target","dataset","snap","Number","parseInt","isIntersecting","Math","min","max","newSnapPosition","updateSnapPosition","toString","root","threshold","rootMargin","sentinels","querySelectorAll","Array","from","forEach","sentinel","observe","event","snapEvent","snapTargetBlock","position","sheetSnapPosition","dispatchEvent","CustomEvent","detail","snapPosition","bubbles","composed","querySelector","scrollTop","setupNestedScrollResizeOptimization","wrapper","sheet","content","supportsScrollAnimations","supportScrollEnd","contentYOffsetStart","contentYOffsetEnd","scrollTimeout","updateContentYOffset","t","scrollHeight","offsetHeight","contentTranslateY","cleanupStyleProperties","scrolling","p","removeProperty","updateOffsetProperties","handleScrollEnd","getComputedStyle","yOffset","DOMMatrixReadOnly","transform","m42","requestAnimationFrame","contentMaxOffsetHeight","scrollBottomAnchorThreshold","floor","contentScrollBottom","sheetSizeFactor","timeline","ScrollTimeline","source","axis","currentTime","handleFallbackScrollEnd","clearTimeout","setTimeout","removeEventListener","attributeChangedCallback","name","oldValue","newValue","console","warn","disconnectedCallback","disconnect","BottomSheetDialogManager","HTMLDialogElement","matches","close","hasAttribute","checkVisibility","parent","parentElement","getPropertyValue"],"mappings":"2DAqBO,MAAMA,UAAoBC,YAC/BC,0BAA4B,CAAC,8BAC7BC,GAAyC,KACzCC,GAAwB,KACtBC,KAAKC,MAAMC,YACT,uBACA,GAAGC,OAAOC,gBAAgBC,WAAa,QAG3CC,GACAC,GAA8D,KAE9D,WAAAC,GACEC,QAEA,MAEMC,EADJd,YAAYe,UAAUC,eAAe,mBACCZ,KAAKa,uBAAoB,EAGjE,IAAIP,EAASI,GAAWI,WACnBR,IACHA,EAASN,KAAKe,aAAa,CAAEC,KAAM,SACnCV,EAAOW,UAAYC,GAErBlB,MAAKM,EAAUA,EAEkB,uBAAwBH,QAEvDH,KAAKmB,iBAAiB,mBAAoBnB,MAAKoB,GAI9CC,IAAIC,SACH,mEAGFtB,KAAKmB,iBAAiB,SAAUnB,MAAKuB,GACrCvB,MAAKuB,IAET,CAEA,iBAAAC,GACmC,uBAAwBrB,QAEvDH,MAAKyB,IAGPtB,OAAOC,gBAAgBe,iBACrB,SACAnB,MAAKD,EAET,CAEA,EAAA0B,GACEzB,MAAKF,EAAY,IAAI4B,qBAClBC,IACC,IAAIC,EAAyBC,IACzBC,GAA6BD,IAC7BE,GAAyB,EAE7B,IAAA,MAAWC,KAASL,EAAS,CAC3B,KACIK,EAAMC,kBAAkBrC,cACG,MAA7BoC,EAAMC,OAAOC,QAAQC,KAErB,SAGF,MAAMA,EAAOC,OAAOC,SAASL,EAAMC,OAAOC,QAAQC,MAE9CH,EAAMM,gBACRP,GAAyB,EACzBH,EAAyBW,KAAKC,IAAIZ,EAAwBO,IAE1DL,EAA6BS,KAAKE,IAChCX,EACAK,EAGN,CAEA,MAAMO,EAAkBX,EACpBH,EACAE,EAA6B,EAEjC9B,MAAK2C,EAAoBD,EAAgBE,aAE3C,CACEC,KAAM7C,KACN8C,UAAW,EACXC,WAAY,wBAIhB,MAAMC,EAAYhD,MAAKM,EAAQ2C,iBAAiB,aAChDC,MAAMC,KAAKH,GAAWI,QAASC,IAC7BrD,MAAKF,GAAWwD,QAAQD,IAE5B,CAEA,EAAAjC,CAAwBmC,GACtB,MAAMC,EAAYD,EAClB,KAAMC,EAAUC,2BAA2B7D,aACzC,OAEF,MAAM8C,EAAkBc,EAAUC,gBAAgBvB,QAAQC,MAAQ,IAClEnC,MAAK2C,EAAoBD,EAC3B,CAEA,EAAAC,CAAoBe,GAClB1D,KAAKkC,QAAQyB,kBAAoBD,EACjC1D,KAAK4D,cACH,IAAIC,YAAsC,uBAAwB,CAChEC,OAAQ,CACNC,aAAcL,GAEhBM,SAAS,EACTC,UAAU,IAGhB,CAEA,EAAA1C,GACEvB,MAAKM,EACF4D,cAA2B,mBAC1BjE,MAAMC,YAAY,mBAAoB,GAAGF,KAAKmE,cACpD,CAEA,EAAAC,GACE,MAAMC,EAAUrE,MAAKM,EAAQ4D,cAA2B,kBAClDI,EAAQtE,MAAKM,EAAQ4D,cAA2B,UAChDK,EAAUvE,MAAKM,EAAQ4D,cAA2B,kBAExD,IAAKG,IAAYC,IAAUC,EACzB,OAGF,MACMC,EAA2BnD,IAAIC,SACnC,uCAKImD,EACJ,gBAAiBtE,SAAWkB,IAAIC,SAAS,kBAAmB,QAC9D,IAAIoD,EACFC,EACAC,EAIF,MAAMC,EAAuB,KAC3B,MAAMC,EAAI9E,KAAKmE,WAAanE,KAAK+E,aAAe/E,KAAKgF,cAC/CC,GACH,EAAIH,GAAKJ,EAAsBI,EAAIH,EACtCN,EAAQpE,MAAMC,YACZ,yBACA,GAAG+E,QAIDC,EAAyB,YACtBlF,KAAKkC,QAAQiD,UACpB,CACE,yBACA,+BACA,8BACA/B,QAASgC,GAAMf,EAAQpE,MAAMoF,eAAeD,KAG1CE,EAAyB,KAC7BjB,EAAQpE,MAAMC,YACZ,+BACA,GAAGwE,OAELL,EAAQpE,MAAMC,YACZ,6BACA,GAAGyE,QAIDY,EAAkB,KACtB,MAAMtF,EAAQuF,iBAAiBjB,GAEzBkB,GADS,IAAIC,kBAAkBzF,EAAM0F,WACnBC,IACxBV,IACAW,sBAAsB,KACpBtB,EAAQJ,UAAYsB,EAAUlB,EAAQJ,aAIpC5C,EAAe,KACnB,GAAM,cAAevB,KAAKkC,QAwDdsC,GACVK,QAzDkC,CAClC,MAAMiB,EACJzB,EAAQW,cAAgBV,EAAMU,aAAeT,EAAQS,cAGjDe,EACJxB,EAAQQ,aAAee,EACzB,GAAIvD,KAAKyD,MAAMzB,EAAQJ,WAAa4B,EAA6B,CAC/D,MAAME,EACJ1B,EAAQQ,aAAeR,EAAQS,aAAeT,EAAQJ,UAGlD+B,EACJ7B,EAAQW,cAAgBX,EAAQW,aAAeV,EAAMU,cAEvDN,IAEIH,EAAQQ,cACPT,EAAMU,aAAeT,EAAQS,eAEhCiB,EAAsBC,EACxBvB,GAAqBoB,EAGrB/F,KAAKkC,QAAQiD,UAAY,GAKzBT,GAAuBH,EAAQJ,UAC/BQ,GAAqBJ,EAAQJ,UAE7BmB,GACF,MACEZ,EAAsB,EACtBC,EAAoB,EACpBW,IACAtF,KAAKkC,QAAQiD,UAAY,GAO3B,GAJKX,GACHK,IAGE,mBAAoB1E,OAAQ,CAG9B,MAAMgG,EAAW,IAAIC,eAAe,CAClCC,OAAQrG,KACRsG,KAAM,MAERjC,EAAQpE,MAAMC,YACZ,mCACA,GAAGiG,EAASI,cAEhB,CACF,GAKIC,EAA0B,KAC9BrG,OAAOsG,aAAa7B,GACpBA,EAAgBzE,OAAOuG,WAAWnB,EAvHN,MA0H9BvF,KAAKmB,iBAAiB,SAAUI,GAC5BkD,EACFzE,KAAKmB,iBAAiB,YAAaoE,GAEnCvF,KAAKmB,iBAAiB,SAAUqF,GAGlCxG,MAAKO,EAAyC,KAC5CP,KAAK2G,oBAAoB,SAAUpF,GAC/BkD,EACFzE,KAAK2G,oBAAoB,YAAapB,IAEtCvF,KAAK2G,oBAAoB,SAAUH,GACnCrG,OAAOsG,aAAa7B,IAGtBM,IACAlF,MAAKO,EAAyC,KAElD,CAEA,wBAAAqG,CACEC,EACAC,EACAC,GAEA,GAAID,IAAaC,EAEjB,GACO,+BADCF,EAEa,OAAbE,EACG/G,MAAKO,GAERP,MAAKoE,IAEEpE,MAAKO,GACdP,MAAKO,SAIPyG,QAAQC,KAAK,wBAAwBJ,IAE3C,CAEA,oBAAAK,GACElH,MAAKF,GAAWqH,aAChBhH,OAAOC,gBAAgBuG,oBACrB,SACA3G,MAAKD,EAET,ECzUK,MAAMqH,UAAiCxH,YAC5C,WAAAY,GACEC,QAEA,MAEMC,EADJd,YAAYe,UAAUC,eAAe,mBACCZ,KAAKa,uBAAoB,EAGjE,IAAIP,EAASI,GAAWI,WACnBR,IACHA,EAASN,KAAKe,aAAa,CAAEC,KAAM,SACnCV,EAAOW,UAAYC,GAGrBlB,KAAKmB,iBAAiB,QAAUoC,IAE5BA,EAAMtB,kBAAkBoF,mBACxB9D,EAAMtB,OAAOqF,QAAQ,WAErB/D,EAAMtB,OAAOsF,UAGjBvH,KAAKmB,iBACH,uBACCoC,IAIC,GAHIA,EAAMO,SACR9D,KAAKkC,QAAQyB,kBAAoBJ,EAAMO,OAAOC,cAGhB,KAA9BR,EAAMO,QAAQC,cACdR,EAAMtB,kBAAkBrC,aACxB2D,EAAMtB,OAAOuF,aAAa,qBAC1BjE,EAAMtB,OAAOwF,kBACb,CACA,MAAMC,EAASnE,EAAMtB,OAAO0F,cAE1BD,aAAkBL,mBAGyC,QAA3D7B,iBAAiBkC,GAAQE,iBAAiB,cAE1CF,EAAOH,OAEX,GAGN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class BottomSheetDialogManager extends HTMLElement {
|
|
2
|
+
constructor();
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Interface for the bottom-sheet-dialog-manager custom element.
|
|
6
|
+
* Provides type definitions for its custom properties.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Register in TypeScript for proper type checking:
|
|
10
|
+
* declare global {
|
|
11
|
+
* interface HTMLElementTagNameMap {
|
|
12
|
+
* "bottom-sheet-dialog-manager": BottomSheetDialogManager;
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
export interface BottomSheetDialogManager extends HTMLElement {
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const template: string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export declare class BottomSheet extends HTMLElement {
|
|
2
|
+
#private;
|
|
3
|
+
static observedAttributes: string[];
|
|
4
|
+
constructor();
|
|
5
|
+
connectedCallback(): void;
|
|
6
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
7
|
+
disconnectedCallback(): void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Interface for the bottom-sheet custom element.
|
|
11
|
+
* Provides type definitions for its custom properties.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Register in TypeScript for proper type checking:
|
|
15
|
+
* declare global {
|
|
16
|
+
* interface HTMLElementTagNameMap {
|
|
17
|
+
* "bottom-sheet": BottomSheet;
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
export interface BottomSheet extends HTMLElement {
|
|
22
|
+
/**
|
|
23
|
+
* When set, the bottom sheet maximum height is based on the the height of its
|
|
24
|
+
* contents.
|
|
25
|
+
*/
|
|
26
|
+
["content-height"]?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* When set, enables scrolling the sheet inner content independently of the sheet.
|
|
29
|
+
*/
|
|
30
|
+
["nested-scroll"]?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* When set, enables resize optimization for the nested scroll mode to avoid reflows
|
|
33
|
+
* during sheet resizing. Only relevant when `nested-scroll` is also true. Not relevant
|
|
34
|
+
* for `expand-to-scroll` mode since it already avoids reflows.
|
|
35
|
+
*/
|
|
36
|
+
["nested-scroll-optimization"]?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* When set, content becomes scrollable only after full expansion. Only relevant
|
|
39
|
+
* when `nested-scroll` is also true.
|
|
40
|
+
*/
|
|
41
|
+
["expand-to-scroll"]?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* When set, allows swiping down to dismiss the bottom sheet when used together
|
|
44
|
+
* with the `bottom-sheet-dialog-manager` or with the Popover API.
|
|
45
|
+
*/
|
|
46
|
+
["swipe-to-dismiss"]?: boolean;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const template: string;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { BottomSheet } from './bottom-sheet';
|
|
2
|
+
export { template as bottomSheetTemplate } from './bottom-sheet.template';
|
|
3
|
+
export type { BottomSheetDialogManager } from './bottom-sheet-dialog-manager';
|
|
4
|
+
export { template as bottomSheetDialogManagerTemplate } from './bottom-sheet-dialog-manager.template';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class t extends HTMLElement{static observedAttributes=["nested-scroll-optimization"];#t=null;#e=()=>{this.style.setProperty("--sw-keyboard-height",`${window.visualViewport?.offsetTop??0}px`)};#s;#o=null;constructor(){super();const t=HTMLElement.prototype.hasOwnProperty("attachInternals")?this.attachInternals():void 0;let e=t?.shadowRoot;e||(e=this.attachShadow({mode:"open"}),e.innerHTML='<style>\n :host{--sheet-max-height:calc(100dvh - 24px);--sheet-background:#f2f2f2;--sheet-border-radius:12px;--sheet-safe-max-height:calc(var(--sheet-max-height) - env(\n keyboard-inset-height,\n var(--sw-keyboard-height, 0px)\n ));border-top-left-radius:var(--sheet-border-radius);border-top-right-radius:var(--sheet-border-radius);bottom:env(keyboard-inset-height,0);contain:strict;display:block;height:var(--sheet-max-height);left:0;max-height:var(--sheet-safe-max-height);overflow-y:scroll;overscroll-behavior-y:none;pointer-events:none;position:fixed;right:0;scroll-snap-type:y mandatory;scrollbar-width:none;will-change:scroll-position}:host(:focus-visible){outline:none}:host(:focus-visible) .handle{outline:auto;outline-offset:4px}:host([data-sheet-snap-position="-1"]) .sheet,:host([data-sheet-snap-position="-1"]) .snap:before,:host([data-sheet-snap-position="-1"]) ::slotted([slot=snap]):before{scroll-snap-align:none}.snap,::slotted([slot=snap]){position:relative;top:var(--snap)}.snap:before,::slotted([slot=snap]):before{content:"";height:1px;left:0;position:absolute;right:0;scroll-snap-align:var(--snap-point-align,start);top:0}.snap.initial,::slotted([slot=snap].initial){--snap-point-align:start}.snap.snap-bottom{height:auto;position:static;top:auto}.snap.snap-bottom:after{content:"";display:block;height:var(--sheet-max-height);max-height:var(--sheet-safe-max-height);position:static}:host(:not([swipe-to-dismiss])) .snap.snap-bottom:before{scroll-snap-align:none}.sentinel{position:relative}.sentinel[data-snap="0"]{top:-1px}.sentinel[data-snap="-1"]{top:2px}.sentinel[data-snap="1"]{top:1px}.sheet,.sheet-wrapper{border-radius:inherit}.sheet{background:var(--sheet-background);cursor:row-resize;display:flex;flex-direction:column;overflow:clip;pointer-events:all;scroll-snap-align:var(--snap-point-align,start)}.sheet-header{top:0}.sheet-footer,.sheet-header{background:inherit;position:sticky;width:100%}.sheet-footer{bottom:0}.sheet-content{flex:1 1 auto;padding:0 .5rem}.handle{background:#ccc;border-radius:5px;height:5px;margin:.5rem auto;width:40px}:host{animation:initial-snap .01s both}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){:host{animation:initial-snap .1s both;display:inherit}}@keyframes initial-snap{0%{--snap-point-align:none}50%{scroll-snap-type:none;--snap-point-align:none}}@supports (-webkit-touch-callout:none){.sheet-content,.sheet-footer,.sheet-header{overflow-x:scroll;overscroll-behavior-x:none;scrollbar-width:none}:is(.sheet-content,.sheet-header,.sheet-footer):after{box-sizing:content-box;content:"";display:block;height:1px;padding:inherit;padding-left:0;width:calc(100% + 1px)}.sheet-content{scrollbar-width:auto}}:host(:not([nested-scroll]):not([content-height])) .sheet-wrapper{height:100%}:host(:not([nested-scroll]):not([content-height])) .sheet{min-height:100%}:host([nested-scroll]) .sheet-wrapper{bottom:0;contain:strict;display:flex;flex-direction:column;height:100%;justify-content:end;position:sticky}:host([nested-scroll]) .sheet{bottom:0;display:flex;flex-direction:column;height:100%;max-height:100%;position:sticky}:host([nested-scroll]) .sheet-content{overflow-y:auto;scrollbar-gutter:stable;will-change:scroll-position}:host([nested-scroll]) .sheet-footer,:host([nested-scroll]) .sheet-header{flex:0 0 auto}:host([nested-scroll][expand-to-scroll]) .sheet-wrapper{position:static}:host([nested-scroll][expand-to-scroll]) .sheet{animation:none;height:100%;position:static}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-header{z-index:1}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{scrollbar-color:transparent transparent}@supports ((animation-timeline:scroll()) and (animation-range:0% 100%)){:host{scroll-timeline:--sheet-timeline y}:host([nested-scroll]) .sheet{animation:expand-sheet-height linear forwards;animation-timeline:--sheet-timeline}@keyframes expand-sheet-height{0%{height:0}to{height:100%}}:host([nested-scroll][expand-to-scroll]) .sheet-content{animation:overflow-y-toggle linear forwards;animation-timeline:--sheet-timeline}@keyframes overflow-y-toggle{0%,99.99%{overflow-y:hidden}to{overflow-y:auto}}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet{animation:translate-sheet linear forwards;transform:translateY(var(--sheet-timeline-at-scroll-start,0));animation-timeline:--sheet-timeline}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{animation:translate-sheet-content linear forwards;animation-timeline:--sheet-timeline}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{animation:translate-footer linear forwards;animation-timeline:--sheet-timeline}@keyframes translate-sheet{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes translate-sheet-content{0%{transform:translateY(var(--sheet-content-offset-start,0))}to{transform:translateY(var(--sheet-content-offset-end,0))}}@keyframes translate-footer{0%{transform:translateY(calc(var(--sheet-safe-max-height)*-1))}to{transform:translateY(0)}}}@supports (not ((animation-timeline:scroll()) and (animation-range:0% 100%))){:host([nested-scroll]) .sheet{height:var(--sheet-position)}:host([nested-scroll][expand-to-scroll]) .sheet-content{overflow-y:hidden}:host([nested-scroll][expand-to-scroll][data-sheet-snap-position="0"]) .sheet-content{overflow-y:auto}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet{height:100%;transform:translateY(calc(100% - var(--sheet-position, 0)))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{transform:translateY(var(--sheet-content-offset,0))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{transform:translateY(calc(var(--sheet-safe-max-height)*-1 + var(--sheet-position, 0)))}}\n </style><slot name="snap"><div class="initial snap" style="--snap: 100%"></div></slot><div class="sentinel" data-snap="1"></div><div class="snap snap-bottom" data-snap="2"></div><div class="sentinel" data-snap="0"></div><div class="sheet-wrapper"><aside class="sheet" part="sheet" data-snap="0"><div class="sentinel" data-snap="-1"></div><header class="sheet-header" part="header"><div class="handle" part="handle"></div><slot name="header"></slot></header><section class="sheet-content" part="content"><slot></slot></section><footer class="sheet-footer" part="footer"><slot name="footer"></slot></footer></aside></div>'),this.#s=e;"onscrollsnapchange"in window&&this.addEventListener("scrollsnapchange",this.#n),CSS.supports("(animation-timeline: scroll()) and (animation-range: 0% 100%)")||(this.addEventListener("scroll",this.#a),this.#a())}connectedCallback(){"onscrollsnapchange"in window||this.#i(),window.visualViewport?.addEventListener("resize",this.#e)}#i(){this.#t=new IntersectionObserver(t=>{let e=1/0,s=-1/0,o=!1;for(const n of t){if(!(n.target instanceof HTMLElement)||null==n.target.dataset.snap)continue;const t=Number.parseInt(n.target.dataset.snap);n.isIntersecting?(o=!0,e=Math.min(e,t)):s=Math.max(s,t)}const n=o?e:s+1;this.#l(n.toString())},{root:this,threshold:0,rootMargin:"1000% 0px -100% 0px"});const t=this.#s.querySelectorAll(".sentinel");Array.from(t).forEach(t=>{this.#t?.observe(t)})}#n(t){const e=t;if(!(e.snapTargetBlock instanceof HTMLElement))return;const s=e.snapTargetBlock.dataset.snap??"1";this.#l(s)}#l(t){this.dataset.sheetSnapPosition=t,this.dispatchEvent(new CustomEvent("snap-position-change",{detail:{snapPosition:t},bubbles:!0,composed:!0}))}#a(){this.#s.querySelector(".sheet-wrapper")?.style.setProperty("--sheet-position",`${this.scrollTop}px`)}#r(){const t=this.#s.querySelector(".sheet-wrapper"),e=this.#s.querySelector(".sheet"),s=this.#s.querySelector(".sheet-content");if(!t||!e||!s)return;const o=CSS.supports("scroll-timeline: --sheet-timeline y"),n="onscrollend"in window&&!CSS.supports("-moz-appearance","none");let a,i,l;const r=()=>{const e=this.scrollTop/(this.scrollHeight-this.offsetHeight),s=(1-e)*a+e*i;t.style.setProperty("--sheet-content-offset",`${s}px`)},h=()=>{delete this.dataset.scrolling,["--sheet-content-offset","--sheet-content-offset-start","--sheet-content-offset-end"].forEach(e=>t.style.removeProperty(e))},c=()=>{t.style.setProperty("--sheet-content-offset-start",`${a}px`),t.style.setProperty("--sheet-content-offset-end",`${i}px`)},d=()=>{const t=getComputedStyle(s),e=-new DOMMatrixReadOnly(t.transform).m42;h(),requestAnimationFrame(()=>{s.scrollTop=e+s.scrollTop})},p=()=>{if("scrolling"in this.dataset)o||r();else{const n=t.offsetHeight-(e.offsetHeight-s.offsetHeight),l=s.scrollHeight-n;if(Math.floor(s.scrollTop)>l){const o=s.scrollHeight-s.offsetHeight-s.scrollTop,n=t.offsetHeight/(t.offsetHeight-e.offsetHeight);a=-(s.scrollHeight+(e.offsetHeight-s.offsetHeight))+o*n,i=-l,this.dataset.scrolling="",a+=s.scrollTop,i+=s.scrollTop,c()}else a=0,i=0,c(),this.dataset.scrolling="";if(o||r(),"ScrollTimeline"in window){const e=new ScrollTimeline({source:this,axis:"y"});t.style.setProperty("--sheet-timeline-at-scroll-start",`${e.currentTime}`)}}},m=()=>{window.clearTimeout(l),l=window.setTimeout(d,100)};this.addEventListener("scroll",p),n?this.addEventListener("scrollend",d):this.addEventListener("scroll",m),this.#o=()=>{this.removeEventListener("scroll",p),n?this.removeEventListener("scrollend",d):(this.removeEventListener("scroll",m),window.clearTimeout(l)),h(),this.#o=null}}attributeChangedCallback(t,e,s){if(e!==s)if("nested-scroll-optimization"===t)null!==s?this.#o||this.#r():this.#o&&this.#o();else console.warn(`Unhandled attribute: ${t}`)}disconnectedCallback(){this.#t?.disconnect(),window.visualViewport?.removeEventListener("resize",this.#e)}}class e extends HTMLElement{constructor(){super();const t=HTMLElement.prototype.hasOwnProperty("attachInternals")?this.attachInternals():void 0;let e=t?.shadowRoot;e||(e=this.attachShadow({mode:"open"}),e.innerHTML='<style>\n ::slotted(dialog){background:unset;border:none;height:100%;inset:0;margin:0;max-height:none;max-width:none;padding:0;position:fixed;top:auto;width:100%}::slotted(dialog:not(:modal)){pointer-events:none}::slotted(dialog[open]){translate:0 0}@starting-style{::slotted(dialog[open]){translate:0 100vh}}::slotted(dialog){transition:translate .5s ease-out,overlay .5s ease-out allow-discrete,display var(--display-transition-duration,.5s) ease-out allow-discrete;translate:0 100vh}:host([data-sheet-snap-position="2"]) ::slotted(dialog:not([open])){transition:none}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){::slotted(dialog){--display-transition-duration:0.1s}}\n </style><slot></slot>'),this.addEventListener("click",t=>{t.target instanceof HTMLDialogElement&&t.target.matches(":modal")&&t.target.close()}),this.addEventListener("snap-position-change",t=>{if(t.detail&&(this.dataset.sheetSnapPosition=t.detail.snapPosition),"2"==t.detail?.snapPosition&&t.target instanceof HTMLElement&&t.target.hasAttribute("swipe-to-dismiss")&&t.target.checkVisibility()){const e=t.target.parentElement;e instanceof HTMLDialogElement&&"0px"===getComputedStyle(e).getPropertyValue("translate")&&e.close()}})}}function s(){customElements.define("bottom-sheet",t),customElements.define("bottom-sheet-dialog-manager",e)}export{t as BottomSheet,e as BottomSheetDialogManager,s as registerSheetElements};
|
package/dist/web.ssr.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const t='<style>\n :host{--sheet-max-height:calc(100dvh - 24px);--sheet-background:#f2f2f2;--sheet-border-radius:12px;--sheet-safe-max-height:calc(var(--sheet-max-height) - env(\n keyboard-inset-height,\n var(--sw-keyboard-height, 0px)\n ));border-top-left-radius:var(--sheet-border-radius);border-top-right-radius:var(--sheet-border-radius);bottom:env(keyboard-inset-height,0);contain:strict;display:block;height:var(--sheet-max-height);left:0;max-height:var(--sheet-safe-max-height);overflow-y:scroll;overscroll-behavior-y:none;pointer-events:none;position:fixed;right:0;scroll-snap-type:y mandatory;scrollbar-width:none;will-change:scroll-position}:host(:focus-visible){outline:none}:host(:focus-visible) .handle{outline:auto;outline-offset:4px}:host([data-sheet-snap-position="-1"]) .sheet,:host([data-sheet-snap-position="-1"]) .snap:before,:host([data-sheet-snap-position="-1"]) ::slotted([slot=snap]):before{scroll-snap-align:none}.snap,::slotted([slot=snap]){position:relative;top:var(--snap)}.snap:before,::slotted([slot=snap]):before{content:"";height:1px;left:0;position:absolute;right:0;scroll-snap-align:var(--snap-point-align,start);top:0}.snap.initial,::slotted([slot=snap].initial){--snap-point-align:start}.snap.snap-bottom{height:auto;position:static;top:auto}.snap.snap-bottom:after{content:"";display:block;height:var(--sheet-max-height);max-height:var(--sheet-safe-max-height);position:static}:host(:not([swipe-to-dismiss])) .snap.snap-bottom:before{scroll-snap-align:none}.sentinel{position:relative}.sentinel[data-snap="0"]{top:-1px}.sentinel[data-snap="-1"]{top:2px}.sentinel[data-snap="1"]{top:1px}.sheet,.sheet-wrapper{border-radius:inherit}.sheet{background:var(--sheet-background);cursor:row-resize;display:flex;flex-direction:column;overflow:clip;pointer-events:all;scroll-snap-align:var(--snap-point-align,start)}.sheet-header{top:0}.sheet-footer,.sheet-header{background:inherit;position:sticky;width:100%}.sheet-footer{bottom:0}.sheet-content{flex:1 1 auto;padding:0 .5rem}.handle{background:#ccc;border-radius:5px;height:5px;margin:.5rem auto;width:40px}:host{animation:initial-snap .01s both}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){:host{animation:initial-snap .1s both;display:inherit}}@keyframes initial-snap{0%{--snap-point-align:none}50%{scroll-snap-type:none;--snap-point-align:none}}@supports (-webkit-touch-callout:none){.sheet-content,.sheet-footer,.sheet-header{overflow-x:scroll;overscroll-behavior-x:none;scrollbar-width:none}:is(.sheet-content,.sheet-header,.sheet-footer):after{box-sizing:content-box;content:"";display:block;height:1px;padding:inherit;padding-left:0;width:calc(100% + 1px)}.sheet-content{scrollbar-width:auto}}:host(:not([nested-scroll]):not([content-height])) .sheet-wrapper{height:100%}:host(:not([nested-scroll]):not([content-height])) .sheet{min-height:100%}:host([nested-scroll]) .sheet-wrapper{bottom:0;contain:strict;display:flex;flex-direction:column;height:100%;justify-content:end;position:sticky}:host([nested-scroll]) .sheet{bottom:0;display:flex;flex-direction:column;height:100%;max-height:100%;position:sticky}:host([nested-scroll]) .sheet-content{overflow-y:auto;scrollbar-gutter:stable;will-change:scroll-position}:host([nested-scroll]) .sheet-footer,:host([nested-scroll]) .sheet-header{flex:0 0 auto}:host([nested-scroll][expand-to-scroll]) .sheet-wrapper{position:static}:host([nested-scroll][expand-to-scroll]) .sheet{animation:none;height:100%;position:static}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-header{z-index:1}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{scrollbar-color:transparent transparent}@supports ((animation-timeline:scroll()) and (animation-range:0% 100%)){:host{scroll-timeline:--sheet-timeline y}:host([nested-scroll]) .sheet{animation:expand-sheet-height linear forwards;animation-timeline:--sheet-timeline}@keyframes expand-sheet-height{0%{height:0}to{height:100%}}:host([nested-scroll][expand-to-scroll]) .sheet-content{animation:overflow-y-toggle linear forwards;animation-timeline:--sheet-timeline}@keyframes overflow-y-toggle{0%,99.99%{overflow-y:hidden}to{overflow-y:auto}}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet{animation:translate-sheet linear forwards;transform:translateY(var(--sheet-timeline-at-scroll-start,0));animation-timeline:--sheet-timeline}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{animation:translate-sheet-content linear forwards;animation-timeline:--sheet-timeline}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{animation:translate-footer linear forwards;animation-timeline:--sheet-timeline}@keyframes translate-sheet{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes translate-sheet-content{0%{transform:translateY(var(--sheet-content-offset-start,0))}to{transform:translateY(var(--sheet-content-offset-end,0))}}@keyframes translate-footer{0%{transform:translateY(calc(var(--sheet-safe-max-height)*-1))}to{transform:translateY(0)}}}@supports (not ((animation-timeline:scroll()) and (animation-range:0% 100%))){:host([nested-scroll]) .sheet{height:var(--sheet-position)}:host([nested-scroll][expand-to-scroll]) .sheet-content{overflow-y:hidden}:host([nested-scroll][expand-to-scroll][data-sheet-snap-position="0"]) .sheet-content{overflow-y:auto}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet{height:100%;transform:translateY(calc(100% - var(--sheet-position, 0)))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{transform:translateY(var(--sheet-content-offset,0))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{transform:translateY(calc(var(--sheet-safe-max-height)*-1 + var(--sheet-position, 0)))}}\n </style><slot name="snap"><div class="initial snap" style="--snap: 100%"></div></slot><div class="sentinel" data-snap="1"></div><div class="snap snap-bottom" data-snap="2"></div><div class="sentinel" data-snap="0"></div><div class="sheet-wrapper"><aside class="sheet" part="sheet" data-snap="0"><div class="sentinel" data-snap="-1"></div><header class="sheet-header" part="header"><div class="handle" part="handle"></div><slot name="header"></slot></header><section class="sheet-content" part="content"><slot></slot></section><footer class="sheet-footer" part="footer"><slot name="footer"></slot></footer></aside></div>',e='<style>\n ::slotted(dialog){background:unset;border:none;height:100%;inset:0;margin:0;max-height:none;max-width:none;padding:0;position:fixed;top:auto;width:100%}::slotted(dialog:not(:modal)){pointer-events:none}::slotted(dialog[open]){translate:0 0}@starting-style{::slotted(dialog[open]){translate:0 100vh}}::slotted(dialog){transition:translate .5s ease-out,overlay .5s ease-out allow-discrete,display var(--display-transition-duration,.5s) ease-out allow-discrete;translate:0 100vh}:host([data-sheet-snap-position="2"]) ::slotted(dialog:not([open])){transition:none}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){::slotted(dialog){--display-transition-duration:0.1s}}\n </style><slot></slot>';export{e as bottomSheetDialogManagerTemplate,t as bottomSheetTemplate};
|