pure-web-bottom-sheet 0.2.0 → 0.4.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.
@@ -1,5 +1,5 @@
1
1
  /* Needed until Prettier supports identifying embedded CSS by block comments */
2
- const styles = /*css*/`::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}}`;
2
+ const styles = /*css*/`::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 allow-discrete .5s ease-out,display allow-discrete .5s ease-out;translate:0 100vh}:host([data-sheet-snap-position="2"]) ::slotted(dialog:not([open])){transition:none}`;
3
3
  const template = /* HTML */ `
4
4
  <style>
5
5
  ${styles}
@@ -1 +1 @@
1
- {"version":3,"file":"bottom-sheet-dialog-manager.template.js","sources":["../../../../src/web/bottom-sheet-dialog-manager.template.ts"],"sourcesContent":["/* Needed until Prettier supports identifying embedded CSS by block comments */\nconst css = String.raw;\n\nconst styles = 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 ${styles}\n </style>\n <slot></slot>\n`;\n"],"names":[],"mappings":"AAAA;AAGA,MAAM,MAAM,UAAM,CAAA,uqBAAA,CAAA;;;;;;;;;;"}
1
+ {"version":3,"file":"bottom-sheet-dialog-manager.template.js","sources":["../../../../src/web/bottom-sheet-dialog-manager.template.ts"],"sourcesContent":["/* Needed until Prettier supports identifying embedded CSS by block comments */\nconst css = String.raw;\n\nconst styles = 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 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\nexport const template: string = /* HTML */ `\n <style>\n ${styles}\n </style>\n <slot></slot>\n`;\n"],"names":[],"mappings":"AAAA;AAGA,MAAM,MAAM,UAAM,CAAA,6gBAAA,CAAA;;;;;;;;;;"}
@@ -140,9 +140,15 @@ class BottomSheet extends HTMLElement {
140
140
  const matrix = new DOMMatrixReadOnly(style.transform);
141
141
  const yOffset = -matrix.m42;
142
142
  cleanupStyleProperties();
143
- requestAnimationFrame(() => {
144
- content.scrollTop = yOffset + content.scrollTop;
145
- });
143
+ // Pin the sheet height inline so the content scrollTop update below is based
144
+ // on the correct scroll height. Removing [data-scrolling] reactivates the
145
+ // scroll-timeline-driven "expand-sheet-height" animation, which will not
146
+ // produce a current time until the next layout pass, leaving the sheet height
147
+ // (and content scroll height) stale for the scrollTop assignment that follows.
148
+ sheet.style.height = `${(this.scrollTop / (this.scrollHeight - this.offsetHeight)) * 100}%`;
149
+ content.scrollTop = yOffset + content.scrollTop;
150
+ // Clear the temporary inline override now that the scrollTop is set
151
+ sheet.style.height = "";
146
152
  };
147
153
  const handleScroll = () => {
148
154
  if (!("scrolling" in this.dataset)) {
@@ -1 +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\n/**\n * BottomSheet custom element.\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 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<SnapPositionChangeEventDetail>(\"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\nexport interface BottomSheetHTMLAttributes {\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\nexport interface SnapPositionChangeEventDetail {\n snapPosition: string;\n}\n\nexport type BottomSheetEvents = {\n \"snap-position-change\": CustomEvent<SnapPositionChangeEventDetail>;\n};\n"],"names":[],"mappings":"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"}
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\n/**\n * BottomSheet custom element.\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 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<SnapPositionChangeEventDetail>(\"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 // Pin the sheet height inline so the content scrollTop update below is based\n // on the correct scroll height. Removing [data-scrolling] reactivates the\n // scroll-timeline-driven \"expand-sheet-height\" animation, which will not\n // produce a current time until the next layout pass, leaving the sheet height\n // (and content scroll height) stale for the scrollTop assignment that follows.\n sheet.style.height = `${(this.scrollTop / (this.scrollHeight - this.offsetHeight)) * 100}%`;\n content.scrollTop = yOffset + content.scrollTop;\n // Clear the temporary inline override now that the scrollTop is set\n sheet.style.height = \"\";\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\nexport interface BottomSheetHTMLAttributes {\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\nexport interface SnapPositionChangeEventDetail {\n snapPosition: string;\n}\n\nexport type BottomSheetEvents = {\n \"snap-position-change\": CustomEvent<SnapPositionChangeEventDetail>;\n};\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  const styles = /*css*/`:host{--sheet-max-height:calc(100dvh - 24px);--sheet-background:#f2f2f2;--sheet-border-radius:12px;--sheet-safe-max-height:calc(var(--sheet-max-height) - env(
3
3
  keyboard-inset-height,
4
4
  var(--sw-keyboard-height, 0px)
5
- ));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}.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: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:after{content:"";display:block;position:static;scroll-snap-align:var(--snap-point-align,end)}.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)))}}`;
5
+ ));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}.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: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)}:host(:not([nested-scroll])) .sheet:after{content:"";display:block;position:static;scroll-snap-align:var(--snap-point-align,end)}.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 var(--initial-snap-duration,.5s) backwards}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){:host{display:inherit;--snap-type-initial-reset:none}}@keyframes initial-snap{0%,49.99%{scroll-snap-type:y mandatory;--snap-point-align:none}50%,to{scroll-snap-type:var(--snap-type-initial-reset,y mandatory);--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;touch-action:pan-y pinch-zoom}: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;content-visibility:auto;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([nested-scroll]) .sheet{animation:expand-sheet-height linear forwards;animation-timeline:scroll()}@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:scroll()}@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;animation-timeline:scroll();transform:translateY(var(--sheet-timeline-at-scroll-start,0))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{animation:translate-sheet-content linear forwards;animation-timeline:scroll()}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{animation:translate-footer linear forwards;animation-timeline:scroll()}@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)))}}`;
6
6
  const template = /* HTML */ `
7
7
  <style>
8
8
  ${styles}
@@ -1 +1 @@
1
- {"version":3,"file":"bottom-sheet.template.js","sources":["../../../../src/web/bottom-sheet.template.ts"],"sourcesContent":["/* Needed until Prettier supports identifying embedded CSS by block comments */\nconst css = String.raw;\n\nconst styles = css`\n :host {\n --sheet-max-height: calc(100dvh - 24px);\n --sheet-background: rgb(242, 242, 242);\n --sheet-border-radius: 12px;\n /* \n The --sw-keyboard-height is needed to handle iOS Safari on-screen keyboard\n since iOS Safari pushes content offscreen by keyboard height when it is opened\n */\n --sheet-safe-max-height: calc(\n var(--sheet-max-height) - env(\n keyboard-inset-height,\n var(--sw-keyboard-height, 0px)\n )\n );\n display: block;\n position: fixed;\n right: 0;\n bottom: env(keyboard-inset-height, 0);\n left: 0;\n will-change: scroll-position;\n contain: strict;\n border-top-right-radius: var(--sheet-border-radius);\n border-top-left-radius: var(--sheet-border-radius);\n height: var(--sheet-max-height);\n max-height: var(--sheet-safe-max-height);\n overflow-y: scroll;\n /* Prevent rubberband effect when scrolling to the end of the sheet */\n overscroll-behavior-y: none;\n scroll-snap-type: y mandatory;\n scrollbar-width: none;\n pointer-events: none;\n }\n\n :host(:focus-visible) {\n outline: none;\n\n .handle {\n outline: auto;\n outline-offset: 4px;\n }\n }\n\n .snap,\n ::slotted([slot=\"snap\"]) {\n position: relative;\n top: var(--snap);\n }\n\n .snap::before,\n ::slotted([slot=\"snap\"])::before {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n height: 1px; /* Height required for Safari to snap */\n scroll-snap-align: var(--snap-point-align, start);\n content: \"\";\n }\n\n .snap.initial,\n ::slotted([slot=\"snap\"].initial) {\n --snap-point-align: start;\n }\n\n .snap.snap-bottom {\n position: static;\n top: initial;\n height: auto;\n\n &::after {\n display: block;\n position: static;\n height: var(--sheet-max-height);\n max-height: var(--sheet-safe-max-height);\n content: \"\";\n }\n }\n\n :host(:not([swipe-to-dismiss])) .snap.snap-bottom::before {\n scroll-snap-align: none;\n }\n\n .sentinel {\n position: relative;\n\n &[data-snap=\"0\"] {\n top: -1px; /** Extra -1px needed for Safari */\n }\n &[data-snap=\"1\"] {\n top: 1px;\n }\n }\n\n .sheet-wrapper {\n border-radius: inherit;\n }\n\n .sheet {\n display: flex;\n flex-direction: column;\n cursor: row-resize;\n border-radius: inherit;\n background: var(--sheet-background);\n overflow: clip;\n scroll-snap-align: var(--snap-point-align, start);\n pointer-events: all;\n }\n\n /* \n Needed for Safari/Firefox to prevent abrupt scroll re-snapping in case the\n sheet DOM content is dynamically changed. Without this, these browsers would\n re-snap to the start of the .sheet element.\n See related spec: https://drafts.csswg.org/css-scroll-snap-1/#re-snap\n */\n .sheet::after {\n display: block;\n position: static;\n scroll-snap-align: var(--snap-point-align, end);\n content: \"\";\n }\n\n .sheet-header {\n position: sticky;\n top: 0;\n background: inherit;\n width: 100%;\n }\n\n .sheet-footer {\n position: sticky;\n bottom: 0;\n background: inherit;\n width: 100%;\n }\n\n .sheet-content {\n flex: 1 1 auto;\n padding: 0 0.5rem;\n }\n\n .handle {\n margin: 0.5rem auto;\n border-radius: 5px;\n background: #ccc;\n width: 40px;\n height: 5px;\n }\n\n :host {\n animation: initial-snap 0.01s both;\n }\n\n /* Safari overrides */\n @supports (-webkit-touch-callout: none) or (-webkit-hyphens: none) {\n :host {\n /* \n On Safari, when displaying in a dialog, we must inherit display property\n so that the animation runs each time the dialog is-reopened\n (display toggles between none and block).\n */\n display: inherit;\n /* \n On Safari the duration must be higher for the initial-snap animation\n to properly snap to the initial target.\n */\n animation: initial-snap 0.1s both;\n }\n }\n\n /*\n Temporarily disables scroll snapping for all snap points\n except the explicitly marked initial snap point (which overrides\n --snap-point-align) so that the sheet snaps to\n the initial snap point.\n */\n @keyframes initial-snap {\n 0% {\n --snap-point-align: none;\n }\n 50% {\n /* \n Needed for the iOS Safari\n See https://stackoverflow.com/q/65653679\n */\n scroll-snap-type: initial;\n --snap-point-align: none;\n }\n }\n\n /* Temporary workaround for iOS Safari bug https://bugs.webkit.org/show_bug.cgi?id=183870 */\n @supports (-webkit-touch-callout: none) {\n .sheet-content,\n .sheet-header,\n .sheet-footer {\n overflow-x: scroll;\n /* Prevent rubberband effect */\n overscroll-behavior-x: none;\n scrollbar-width: none;\n\n &::after {\n display: block;\n box-sizing: content-box;\n padding: inherit;\n padding-left: 0;\n width: calc(100% + 1px);\n height: 1px;\n content: \"\";\n }\n }\n .sheet-content {\n scrollbar-width: auto;\n }\n }\n\n :host(:not([nested-scroll]):not([content-height])) {\n .sheet-wrapper {\n height: 100%;\n }\n\n .sheet {\n min-height: 100%;\n }\n }\n\n :host([nested-scroll]) {\n .sheet-wrapper {\n display: flex;\n position: sticky;\n bottom: 0;\n flex-direction: column;\n justify-content: end;\n /* Fixes scroll-chaining issue on Firefox when sheet content is scrollable */\n contain: strict;\n height: 100%;\n }\n\n .sheet {\n display: flex;\n position: sticky;\n bottom: 0;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n }\n\n .sheet-content {\n will-change: scroll-position;\n overflow-y: auto;\n scrollbar-gutter: stable;\n }\n\n .sheet-header,\n .sheet-footer {\n /* Prevent shrinking the header and footer */\n flex: 0 0 auto;\n }\n }\n\n /*\n When expand-to-scroll is enabled, we do not need dynamic sheet height animation\n since sheet content is always fixed size and only scrollable at full height\n so we can simplify the layout and improve performance by disabling height animation.\n */\n :host([nested-scroll][expand-to-scroll]) {\n .sheet-wrapper {\n position: static;\n }\n\n .sheet {\n position: static;\n animation: none;\n height: 100%;\n }\n }\n\n /*\n Performance optimization for the nested-scroll mode:\n When the sheet is being actively scrolled, disable sheet height animation and\n switch to transform-based animation for the sheet content to improve performance\n and avoid jank because animating height would cause continuous reflow (layout).\n\n Follow use of [data-scrolling] for the specific CSS rules applied in this case.\n */\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet-header {\n z-index: 1;\n }\n\n .sheet-content {\n /* Hide the scrollbar visually during scrolling */\n scrollbar-color: transparent transparent;\n }\n }\n\n @supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {\n :host {\n scroll-timeline: --sheet-timeline y;\n }\n\n :host([nested-scroll]) .sheet {\n animation: expand-sheet-height linear forwards;\n animation-timeline: --sheet-timeline;\n }\n\n @keyframes expand-sheet-height {\n from {\n height: 0;\n }\n to {\n height: 100%;\n }\n }\n\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\n animation: overflow-y-toggle linear forwards;\n animation-timeline: --sheet-timeline;\n }\n\n @keyframes overflow-y-toggle {\n 0%,\n 99.99% {\n overflow-y: hidden;\n }\n 100% {\n overflow-y: auto;\n }\n }\n\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet {\n /* \n Safari bug fix: Pre-apply transform to prevent flickering. Safari 26+ has\n a one-frame delay when switching from height-based to transform-based animation,\n causing brief position shift. Setting an initial transform value ensures\n smooth transition.\n */\n transform: translateY(var(--sheet-timeline-at-scroll-start, 0));\n animation: translate-sheet linear forwards;\n animation-timeline: --sheet-timeline;\n }\n\n .sheet-content {\n animation: translate-sheet-content linear forwards;\n animation-timeline: --sheet-timeline;\n }\n\n .sheet-footer {\n animation: translate-footer linear forwards;\n animation-timeline: --sheet-timeline;\n }\n }\n\n @keyframes translate-sheet {\n from {\n transform: translateY(100%);\n }\n to {\n transform: translateY(0);\n }\n }\n\n @keyframes translate-sheet-content {\n from {\n transform: translateY(var(--sheet-content-offset-start, 0));\n }\n to {\n transform: translateY(var(--sheet-content-offset-end, 0));\n }\n }\n\n @keyframes translate-footer {\n from {\n transform: translateY(calc(-1 * var(--sheet-safe-max-height)));\n }\n to {\n transform: translateY(0);\n }\n }\n }\n\n /* Fallback for browsers that do not yet support scroll-driven animations */\n @supports (\n not ((animation-timeline: scroll()) and (animation-range: 0% 100%))\n ) {\n :host([nested-scroll]) .sheet {\n height: var(--sheet-position);\n }\n\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\n overflow-y: hidden;\n }\n\n :host([nested-scroll][expand-to-scroll][data-sheet-snap-position=\"0\"])\n .sheet-content {\n overflow-y: auto;\n }\n\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet {\n transform: translateY(calc(100% - var(--sheet-position, 0)));\n height: 100%;\n }\n\n .sheet-content {\n transform: translateY(var(--sheet-content-offset, 0));\n }\n\n .sheet-footer {\n transform: translateY(\n calc(-1 * var(--sheet-safe-max-height) + var(--sheet-position, 0))\n );\n }\n }\n }\n`;\n\nexport const template: string = /* HTML */ `\n <style>\n ${styles}\n </style>\n <slot name=\"snap\">\n <div class=\"snap initial\" style=\"--snap: 100%\"></div>\n </slot>\n <div class=\"sentinel\" data-snap=\"1\"></div>\n <div class=\"snap snap-bottom\" data-snap=\"2\"></div>\n <div class=\"sentinel\" data-snap=\"0\"></div>\n <div class=\"sheet-wrapper\">\n <aside class=\"sheet\" part=\"sheet\" data-snap=\"0\">\n <header class=\"sheet-header\" part=\"header\">\n <div class=\"handle\" part=\"handle\"></div>\n <slot name=\"header\"></slot>\n </header>\n <section class=\"sheet-content\" part=\"content\">\n <slot></slot>\n </section>\n <footer class=\"sheet-footer\" part=\"footer\">\n <slot name=\"footer\"></slot>\n </footer>\n </aside>\n </div>\n`;\n"],"names":[],"mappings":"AAAA;AAGA,MAAM,MAAM,UAAM,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"bottom-sheet.template.js","sources":["../../../../src/web/bottom-sheet.template.ts"],"sourcesContent":["/* Needed until Prettier supports identifying embedded CSS by block comments */\nconst css = String.raw;\n\nconst styles = css`\n :host {\n --sheet-max-height: calc(100dvh - 24px);\n --sheet-background: rgb(242, 242, 242);\n --sheet-border-radius: 12px;\n /* \n The --sw-keyboard-height is needed to handle iOS Safari on-screen keyboard\n since iOS Safari pushes content offscreen by keyboard height when it is opened\n */\n --sheet-safe-max-height: calc(\n var(--sheet-max-height) - env(\n keyboard-inset-height,\n var(--sw-keyboard-height, 0px)\n )\n );\n display: block;\n position: fixed;\n right: 0;\n bottom: env(keyboard-inset-height, 0);\n left: 0;\n will-change: scroll-position;\n contain: strict;\n border-top-right-radius: var(--sheet-border-radius);\n border-top-left-radius: var(--sheet-border-radius);\n height: var(--sheet-max-height);\n max-height: var(--sheet-safe-max-height);\n overflow-y: scroll;\n /* Prevent rubberband effect when scrolling to the end of the sheet */\n overscroll-behavior-y: none;\n scroll-snap-type: y mandatory;\n scrollbar-width: none;\n pointer-events: none;\n }\n\n :host(:focus-visible) {\n outline: none;\n\n .handle {\n outline: auto;\n outline-offset: 4px;\n }\n }\n\n .snap,\n ::slotted([slot=\"snap\"]) {\n position: relative;\n top: var(--snap);\n }\n\n .snap::before,\n ::slotted([slot=\"snap\"])::before {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n height: 1px; /* Height required for Safari to snap */\n scroll-snap-align: var(--snap-point-align, start);\n content: \"\";\n }\n\n .snap.initial,\n ::slotted([slot=\"snap\"].initial) {\n --snap-point-align: start;\n }\n\n .snap.snap-bottom {\n position: static;\n top: initial;\n height: auto;\n\n &::after {\n display: block;\n position: static;\n height: var(--sheet-max-height);\n max-height: var(--sheet-safe-max-height);\n content: \"\";\n }\n }\n\n :host(:not([swipe-to-dismiss])) .snap.snap-bottom::before {\n scroll-snap-align: none;\n }\n\n .sentinel {\n position: relative;\n\n &[data-snap=\"0\"] {\n top: -1px; /** Extra -1px needed for Safari */\n }\n &[data-snap=\"1\"] {\n top: 1px;\n }\n }\n\n .sheet-wrapper {\n border-radius: inherit;\n }\n\n .sheet {\n display: flex;\n flex-direction: column;\n cursor: row-resize;\n border-radius: inherit;\n background: var(--sheet-background);\n overflow: clip;\n scroll-snap-align: var(--snap-point-align, start);\n pointer-events: all;\n }\n\n /* \n Needed for Safari/Firefox to prevent abrupt scroll re-snapping in case the\n sheet DOM content is dynamically changed. Without this, these browsers would\n re-snap to the start of the .sheet element.\n See related spec: https://drafts.csswg.org/css-scroll-snap-1/#re-snap\n */\n :host(:not([nested-scroll])) .sheet::after {\n display: block;\n position: static;\n scroll-snap-align: var(--snap-point-align, end);\n content: \"\";\n }\n\n .sheet-header {\n position: sticky;\n top: 0;\n background: inherit;\n width: 100%;\n }\n\n .sheet-footer {\n position: sticky;\n bottom: 0;\n background: inherit;\n width: 100%;\n }\n\n .sheet-content {\n flex: 1 1 auto;\n padding: 0 0.5rem;\n }\n\n .handle {\n margin: 0.5rem auto;\n border-radius: 5px;\n background: #ccc;\n width: 40px;\n height: 5px;\n }\n\n :host {\n animation: initial-snap var(--initial-snap-duration, 0.5s) backwards;\n }\n\n /* Safari overrides */\n @supports (-webkit-touch-callout: none) or (-webkit-hyphens: none) {\n :host {\n /* \n On Safari, when displaying in a dialog, we must inherit display property\n so that the animation runs each time the dialog is-reopened\n (display toggles between none and block).\n */\n display: inherit;\n /*\n On Safari, we need to briefly reset scroll-snap-type after the initial snap\n before re-enabling scroll-snap-align on other snap points to prevent scroll\n position from being reset to the initial snap point.\n */\n --snap-type-initial-reset: none;\n }\n }\n\n /*\n Temporarily disables scroll snapping for all snap points\n except the explicitly marked initial snap point (which overrides\n --snap-point-align) so that the sheet snaps to\n the initial snap point.\n */\n @keyframes initial-snap {\n /*\n Phase 1 (0%-49.99%): Disable scroll snapping for all snap points except \n the initial snap point. Keep the host scroll-snap-type at the base value\n (y mandatory) so the browser can snap to the initial snap point during\n this window.\n */\n 0%,\n 49.99% {\n scroll-snap-type: y mandatory;\n --snap-point-align: none;\n }\n /*\n Phase 2 (50%-100%): On Safari, set the host scroll-snap-type temporarily\n to none (via --snap-type-initial-reset) to prevent the scroll position resetting\n when the scroll-snap-align is re-enabled on all snap points after the animation ends.\n See https://stackoverflow.com/q/65653679\n */\n 50%,\n 100% {\n scroll-snap-type: var(--snap-type-initial-reset, y mandatory);\n --snap-point-align: none;\n }\n }\n\n /* Temporary workaround for iOS Safari bug https://bugs.webkit.org/show_bug.cgi?id=183870 */\n @supports (-webkit-touch-callout: none) {\n .sheet-content,\n .sheet-header,\n .sheet-footer {\n overflow-x: scroll;\n /* Prevent rubberband effect */\n overscroll-behavior-x: none;\n scrollbar-width: none;\n /* Prevent horizontal scrolling using touch gestures */\n touch-action: pan-y pinch-zoom;\n\n &::after {\n display: block;\n box-sizing: content-box;\n padding: inherit;\n padding-left: 0;\n width: calc(100% + 1px);\n height: 1px;\n content: \"\";\n }\n }\n .sheet-content {\n scrollbar-width: auto;\n }\n }\n\n :host(:not([nested-scroll]):not([content-height])) {\n .sheet-wrapper {\n height: 100%;\n }\n\n .sheet {\n min-height: 100%;\n }\n }\n\n :host([nested-scroll]) {\n .sheet-wrapper {\n display: flex;\n position: sticky;\n bottom: 0;\n flex-direction: column;\n justify-content: end;\n /* Needed for Firefox to properly render sticky items due to using contain: strict */\n content-visibility: auto;\n /* Fixes scroll-chaining issue on Firefox when sheet content is scrollable */\n contain: strict;\n height: 100%;\n }\n\n .sheet {\n display: flex;\n position: sticky;\n bottom: 0;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n }\n\n .sheet-content {\n will-change: scroll-position;\n overflow-y: auto;\n scrollbar-gutter: stable;\n }\n\n .sheet-header,\n .sheet-footer {\n /* Prevent shrinking the header and footer */\n flex: 0 0 auto;\n }\n }\n\n /*\n When expand-to-scroll is enabled, we do not need dynamic sheet height animation\n since sheet content is always fixed size and only scrollable at full height\n so we can simplify the layout and improve performance by disabling height animation.\n */\n :host([nested-scroll][expand-to-scroll]) {\n .sheet-wrapper {\n position: static;\n }\n\n .sheet {\n position: static;\n animation: none;\n height: 100%;\n }\n }\n\n /*\n Performance optimization for the nested-scroll mode:\n When the sheet is being actively scrolled, disable sheet height animation and\n switch to transform-based animation for the sheet content to improve performance\n and avoid jank because animating height would cause continuous reflow (layout).\n\n Follow use of [data-scrolling] for the specific CSS rules applied in this case.\n */\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet-header {\n z-index: 1;\n }\n\n .sheet-content {\n /* Hide the scrollbar visually during scrolling */\n scrollbar-color: transparent transparent;\n }\n }\n\n @supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {\n :host([nested-scroll]) .sheet {\n animation: expand-sheet-height linear forwards;\n animation-timeline: scroll();\n }\n\n @keyframes expand-sheet-height {\n from {\n height: 0;\n }\n to {\n height: 100%;\n }\n }\n\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\n animation: overflow-y-toggle linear forwards;\n animation-timeline: scroll();\n }\n\n @keyframes overflow-y-toggle {\n 0%,\n 99.99% {\n overflow-y: hidden;\n }\n 100% {\n overflow-y: auto;\n }\n }\n\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet {\n /* \n Safari bug fix: Pre-apply transform to prevent flickering. Safari 26+ has\n a one-frame delay when switching from height-based to transform-based animation,\n causing brief position shift. Setting an initial transform value ensures\n smooth transition.\n */\n transform: translateY(var(--sheet-timeline-at-scroll-start, 0));\n animation: translate-sheet linear forwards;\n animation-timeline: scroll();\n }\n\n .sheet-content {\n animation: translate-sheet-content linear forwards;\n animation-timeline: scroll();\n }\n\n .sheet-footer {\n animation: translate-footer linear forwards;\n animation-timeline: scroll();\n }\n }\n\n @keyframes translate-sheet {\n from {\n transform: translateY(100%);\n }\n to {\n transform: translateY(0);\n }\n }\n\n @keyframes translate-sheet-content {\n from {\n transform: translateY(var(--sheet-content-offset-start, 0));\n }\n to {\n transform: translateY(var(--sheet-content-offset-end, 0));\n }\n }\n\n @keyframes translate-footer {\n from {\n transform: translateY(calc(-1 * var(--sheet-safe-max-height)));\n }\n to {\n transform: translateY(0);\n }\n }\n }\n\n /* Fallback for browsers that do not yet support scroll-driven animations */\n @supports (\n not ((animation-timeline: scroll()) and (animation-range: 0% 100%))\n ) {\n :host([nested-scroll]) .sheet {\n height: var(--sheet-position);\n }\n\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\n overflow-y: hidden;\n }\n\n :host([nested-scroll][expand-to-scroll][data-sheet-snap-position=\"0\"])\n .sheet-content {\n overflow-y: auto;\n }\n\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet {\n transform: translateY(calc(100% - var(--sheet-position, 0)));\n height: 100%;\n }\n\n .sheet-content {\n transform: translateY(var(--sheet-content-offset, 0));\n }\n\n .sheet-footer {\n transform: translateY(\n calc(-1 * var(--sheet-safe-max-height) + var(--sheet-position, 0))\n );\n }\n }\n }\n`;\n\nexport const template: string = /* HTML */ `\n <style>\n ${styles}\n </style>\n <slot name=\"snap\">\n <div class=\"snap initial\" style=\"--snap: 100%\"></div>\n </slot>\n <div class=\"sentinel\" data-snap=\"1\"></div>\n <div class=\"snap snap-bottom\" data-snap=\"2\"></div>\n <div class=\"sentinel\" data-snap=\"0\"></div>\n <div class=\"sheet-wrapper\">\n <aside class=\"sheet\" part=\"sheet\" data-snap=\"0\">\n <header class=\"sheet-header\" part=\"header\">\n <div class=\"handle\" part=\"handle\"></div>\n <slot name=\"header\"></slot>\n </header>\n <section class=\"sheet-content\" part=\"content\">\n <slot></slot>\n </section>\n <footer class=\"sheet-footer\" part=\"footer\">\n <slot name=\"footer\"></slot>\n </footer>\n </aside>\n </div>\n`;\n"],"names":[],"mappings":"AAAA;AAGA,MAAM,MAAM,UAAM,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,3 +1,7 @@
1
- export { BottomSheet } from './bottom-sheet.js';
2
- export { BottomSheetDialogManager } from './bottom-sheet-dialog-manager.js';
1
+ import { BottomSheet } from './bottom-sheet.js';
2
+ import { BottomSheetDialogManager } from './bottom-sheet-dialog-manager.js';
3
+
4
+
5
+
6
+ export { BottomSheet, BottomSheetDialogManager };
3
7
  //# sourceMappingURL=index.client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
@@ -1,4 +1,4 @@
1
- import { defineComponent, createBlock, openBlock, resolveDynamicComponent, h, Fragment, onMounted } from 'vue';
1
+ import { defineComponent, openBlock, createBlock, resolveDynamicComponent, h, Fragment, onMounted } from 'vue';
2
2
 
3
3
  var _sfc_main$1 = /* @__PURE__ */ defineComponent({
4
4
  __name: "ShadowRootTemplate",
@@ -29,7 +29,7 @@ var _sfc_main$1 = /* @__PURE__ */ defineComponent({
29
29
  const styles$1 = /*css*/`:host{--sheet-max-height:calc(100dvh - 24px);--sheet-background:#f2f2f2;--sheet-border-radius:12px;--sheet-safe-max-height:calc(var(--sheet-max-height) - env(
30
30
  keyboard-inset-height,
31
31
  var(--sw-keyboard-height, 0px)
32
- ));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}.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: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:after{content:"";display:block;position:static;scroll-snap-align:var(--snap-point-align,end)}.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)))}}`;
32
+ ));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}.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: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)}:host(:not([nested-scroll])) .sheet:after{content:"";display:block;position:static;scroll-snap-align:var(--snap-point-align,end)}.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 var(--initial-snap-duration,.5s) backwards}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){:host{display:inherit;--snap-type-initial-reset:none}}@keyframes initial-snap{0%,49.99%{scroll-snap-type:y mandatory;--snap-point-align:none}50%,to{scroll-snap-type:var(--snap-type-initial-reset,y mandatory);--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;touch-action:pan-y pinch-zoom}: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;content-visibility:auto;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([nested-scroll]) .sheet{animation:expand-sheet-height linear forwards;animation-timeline:scroll()}@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:scroll()}@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;animation-timeline:scroll();transform:translateY(var(--sheet-timeline-at-scroll-start,0))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{animation:translate-sheet-content linear forwards;animation-timeline:scroll()}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{animation:translate-footer linear forwards;animation-timeline:scroll()}@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)))}}`;
33
33
  const template$1 = (
34
34
  /* HTML */
35
35
  `
@@ -59,7 +59,7 @@ const template$1 = (
59
59
  `
60
60
  );
61
61
 
62
- const styles = /*css*/`::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}}`;
62
+ const styles = /*css*/`::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 allow-discrete .5s ease-out,display allow-discrete .5s ease-out;translate:0 100vh}:host([data-sheet-snap-position="2"]) ::slotted(dialog:not([open])){transition:none}`;
63
63
  const template = (
64
64
  /* HTML */
65
65
  `
@@ -74,7 +74,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
74
74
  __name: "Client",
75
75
  setup(__props) {
76
76
  onMounted(() => {
77
- import('./index.client-JhdfOtKM.js').then(
77
+ import('./index.client-BnjqgBI2.js').then(
78
78
  ({ BottomSheet, BottomSheetDialogManager }) => {
79
79
  if (!customElements.get("bottom-sheet")) {
80
80
  customElements.define("bottom-sheet", BottomSheet);
@@ -110,4 +110,4 @@ const VBottomSheetDialogManager = (props, { slots }) => {
110
110
  };
111
111
 
112
112
  export { VBottomSheet as V, template as a, VBottomSheetDialogManager as b, template$1 as t };
113
- //# sourceMappingURL=index-CrwMlGJU.js.map
113
+ //# sourceMappingURL=index-0rU4KEd4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-0rU4KEd4.js","sources":["../../src/vue/ShadowRootTemplate.vue","../../src/web/bottom-sheet.template.ts","../../src/web/bottom-sheet-dialog-manager.template.ts","../../src/vue/Client.vue","../../src/vue/VBottomSheet.ts","../../src/vue/VBottomSheetDialogManager.ts"],"sourcesContent":["<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","/* Needed until Prettier supports identifying embedded CSS by block comments */\nconst css = String.raw;\n\nconst styles = css`\n :host {\n --sheet-max-height: calc(100dvh - 24px);\n --sheet-background: rgb(242, 242, 242);\n --sheet-border-radius: 12px;\n /* \n The --sw-keyboard-height is needed to handle iOS Safari on-screen keyboard\n since iOS Safari pushes content offscreen by keyboard height when it is opened\n */\n --sheet-safe-max-height: calc(\n var(--sheet-max-height) - env(\n keyboard-inset-height,\n var(--sw-keyboard-height, 0px)\n )\n );\n display: block;\n position: fixed;\n right: 0;\n bottom: env(keyboard-inset-height, 0);\n left: 0;\n will-change: scroll-position;\n contain: strict;\n border-top-right-radius: var(--sheet-border-radius);\n border-top-left-radius: var(--sheet-border-radius);\n height: var(--sheet-max-height);\n max-height: var(--sheet-safe-max-height);\n overflow-y: scroll;\n /* Prevent rubberband effect when scrolling to the end of the sheet */\n overscroll-behavior-y: none;\n scroll-snap-type: y mandatory;\n scrollbar-width: none;\n pointer-events: none;\n }\n\n :host(:focus-visible) {\n outline: none;\n\n .handle {\n outline: auto;\n outline-offset: 4px;\n }\n }\n\n .snap,\n ::slotted([slot=\"snap\"]) {\n position: relative;\n top: var(--snap);\n }\n\n .snap::before,\n ::slotted([slot=\"snap\"])::before {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n height: 1px; /* Height required for Safari to snap */\n scroll-snap-align: var(--snap-point-align, start);\n content: \"\";\n }\n\n .snap.initial,\n ::slotted([slot=\"snap\"].initial) {\n --snap-point-align: start;\n }\n\n .snap.snap-bottom {\n position: static;\n top: initial;\n height: auto;\n\n &::after {\n display: block;\n position: static;\n height: var(--sheet-max-height);\n max-height: var(--sheet-safe-max-height);\n content: \"\";\n }\n }\n\n :host(:not([swipe-to-dismiss])) .snap.snap-bottom::before {\n scroll-snap-align: none;\n }\n\n .sentinel {\n position: relative;\n\n &[data-snap=\"0\"] {\n top: -1px; /** Extra -1px needed for Safari */\n }\n &[data-snap=\"1\"] {\n top: 1px;\n }\n }\n\n .sheet-wrapper {\n border-radius: inherit;\n }\n\n .sheet {\n display: flex;\n flex-direction: column;\n cursor: row-resize;\n border-radius: inherit;\n background: var(--sheet-background);\n overflow: clip;\n scroll-snap-align: var(--snap-point-align, start);\n pointer-events: all;\n }\n\n /* \n Needed for Safari/Firefox to prevent abrupt scroll re-snapping in case the\n sheet DOM content is dynamically changed. Without this, these browsers would\n re-snap to the start of the .sheet element.\n See related spec: https://drafts.csswg.org/css-scroll-snap-1/#re-snap\n */\n :host(:not([nested-scroll])) .sheet::after {\n display: block;\n position: static;\n scroll-snap-align: var(--snap-point-align, end);\n content: \"\";\n }\n\n .sheet-header {\n position: sticky;\n top: 0;\n background: inherit;\n width: 100%;\n }\n\n .sheet-footer {\n position: sticky;\n bottom: 0;\n background: inherit;\n width: 100%;\n }\n\n .sheet-content {\n flex: 1 1 auto;\n padding: 0 0.5rem;\n }\n\n .handle {\n margin: 0.5rem auto;\n border-radius: 5px;\n background: #ccc;\n width: 40px;\n height: 5px;\n }\n\n :host {\n animation: initial-snap var(--initial-snap-duration, 0.5s) backwards;\n }\n\n /* Safari overrides */\n @supports (-webkit-touch-callout: none) or (-webkit-hyphens: none) {\n :host {\n /* \n On Safari, when displaying in a dialog, we must inherit display property\n so that the animation runs each time the dialog is-reopened\n (display toggles between none and block).\n */\n display: inherit;\n /*\n On Safari, we need to briefly reset scroll-snap-type after the initial snap\n before re-enabling scroll-snap-align on other snap points to prevent scroll\n position from being reset to the initial snap point.\n */\n --snap-type-initial-reset: none;\n }\n }\n\n /*\n Temporarily disables scroll snapping for all snap points\n except the explicitly marked initial snap point (which overrides\n --snap-point-align) so that the sheet snaps to\n the initial snap point.\n */\n @keyframes initial-snap {\n /*\n Phase 1 (0%-49.99%): Disable scroll snapping for all snap points except \n the initial snap point. Keep the host scroll-snap-type at the base value\n (y mandatory) so the browser can snap to the initial snap point during\n this window.\n */\n 0%,\n 49.99% {\n scroll-snap-type: y mandatory;\n --snap-point-align: none;\n }\n /*\n Phase 2 (50%-100%): On Safari, set the host scroll-snap-type temporarily\n to none (via --snap-type-initial-reset) to prevent the scroll position resetting\n when the scroll-snap-align is re-enabled on all snap points after the animation ends.\n See https://stackoverflow.com/q/65653679\n */\n 50%,\n 100% {\n scroll-snap-type: var(--snap-type-initial-reset, y mandatory);\n --snap-point-align: none;\n }\n }\n\n /* Temporary workaround for iOS Safari bug https://bugs.webkit.org/show_bug.cgi?id=183870 */\n @supports (-webkit-touch-callout: none) {\n .sheet-content,\n .sheet-header,\n .sheet-footer {\n overflow-x: scroll;\n /* Prevent rubberband effect */\n overscroll-behavior-x: none;\n scrollbar-width: none;\n /* Prevent horizontal scrolling using touch gestures */\n touch-action: pan-y pinch-zoom;\n\n &::after {\n display: block;\n box-sizing: content-box;\n padding: inherit;\n padding-left: 0;\n width: calc(100% + 1px);\n height: 1px;\n content: \"\";\n }\n }\n .sheet-content {\n scrollbar-width: auto;\n }\n }\n\n :host(:not([nested-scroll]):not([content-height])) {\n .sheet-wrapper {\n height: 100%;\n }\n\n .sheet {\n min-height: 100%;\n }\n }\n\n :host([nested-scroll]) {\n .sheet-wrapper {\n display: flex;\n position: sticky;\n bottom: 0;\n flex-direction: column;\n justify-content: end;\n /* Needed for Firefox to properly render sticky items due to using contain: strict */\n content-visibility: auto;\n /* Fixes scroll-chaining issue on Firefox when sheet content is scrollable */\n contain: strict;\n height: 100%;\n }\n\n .sheet {\n display: flex;\n position: sticky;\n bottom: 0;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n }\n\n .sheet-content {\n will-change: scroll-position;\n overflow-y: auto;\n scrollbar-gutter: stable;\n }\n\n .sheet-header,\n .sheet-footer {\n /* Prevent shrinking the header and footer */\n flex: 0 0 auto;\n }\n }\n\n /*\n When expand-to-scroll is enabled, we do not need dynamic sheet height animation\n since sheet content is always fixed size and only scrollable at full height\n so we can simplify the layout and improve performance by disabling height animation.\n */\n :host([nested-scroll][expand-to-scroll]) {\n .sheet-wrapper {\n position: static;\n }\n\n .sheet {\n position: static;\n animation: none;\n height: 100%;\n }\n }\n\n /*\n Performance optimization for the nested-scroll mode:\n When the sheet is being actively scrolled, disable sheet height animation and\n switch to transform-based animation for the sheet content to improve performance\n and avoid jank because animating height would cause continuous reflow (layout).\n\n Follow use of [data-scrolling] for the specific CSS rules applied in this case.\n */\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet-header {\n z-index: 1;\n }\n\n .sheet-content {\n /* Hide the scrollbar visually during scrolling */\n scrollbar-color: transparent transparent;\n }\n }\n\n @supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {\n :host([nested-scroll]) .sheet {\n animation: expand-sheet-height linear forwards;\n animation-timeline: scroll();\n }\n\n @keyframes expand-sheet-height {\n from {\n height: 0;\n }\n to {\n height: 100%;\n }\n }\n\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\n animation: overflow-y-toggle linear forwards;\n animation-timeline: scroll();\n }\n\n @keyframes overflow-y-toggle {\n 0%,\n 99.99% {\n overflow-y: hidden;\n }\n 100% {\n overflow-y: auto;\n }\n }\n\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet {\n /* \n Safari bug fix: Pre-apply transform to prevent flickering. Safari 26+ has\n a one-frame delay when switching from height-based to transform-based animation,\n causing brief position shift. Setting an initial transform value ensures\n smooth transition.\n */\n transform: translateY(var(--sheet-timeline-at-scroll-start, 0));\n animation: translate-sheet linear forwards;\n animation-timeline: scroll();\n }\n\n .sheet-content {\n animation: translate-sheet-content linear forwards;\n animation-timeline: scroll();\n }\n\n .sheet-footer {\n animation: translate-footer linear forwards;\n animation-timeline: scroll();\n }\n }\n\n @keyframes translate-sheet {\n from {\n transform: translateY(100%);\n }\n to {\n transform: translateY(0);\n }\n }\n\n @keyframes translate-sheet-content {\n from {\n transform: translateY(var(--sheet-content-offset-start, 0));\n }\n to {\n transform: translateY(var(--sheet-content-offset-end, 0));\n }\n }\n\n @keyframes translate-footer {\n from {\n transform: translateY(calc(-1 * var(--sheet-safe-max-height)));\n }\n to {\n transform: translateY(0);\n }\n }\n }\n\n /* Fallback for browsers that do not yet support scroll-driven animations */\n @supports (\n not ((animation-timeline: scroll()) and (animation-range: 0% 100%))\n ) {\n :host([nested-scroll]) .sheet {\n height: var(--sheet-position);\n }\n\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\n overflow-y: hidden;\n }\n\n :host([nested-scroll][expand-to-scroll][data-sheet-snap-position=\"0\"])\n .sheet-content {\n overflow-y: auto;\n }\n\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet {\n transform: translateY(calc(100% - var(--sheet-position, 0)));\n height: 100%;\n }\n\n .sheet-content {\n transform: translateY(var(--sheet-content-offset, 0));\n }\n\n .sheet-footer {\n transform: translateY(\n calc(-1 * var(--sheet-safe-max-height) + var(--sheet-position, 0))\n );\n }\n }\n }\n`;\n\nexport const template: string = /* HTML */ `\n <style>\n ${styles}\n </style>\n <slot name=\"snap\">\n <div class=\"snap initial\" style=\"--snap: 100%\"></div>\n </slot>\n <div class=\"sentinel\" data-snap=\"1\"></div>\n <div class=\"snap snap-bottom\" data-snap=\"2\"></div>\n <div class=\"sentinel\" data-snap=\"0\"></div>\n <div class=\"sheet-wrapper\">\n <aside class=\"sheet\" part=\"sheet\" data-snap=\"0\">\n <header class=\"sheet-header\" part=\"header\">\n <div class=\"handle\" part=\"handle\"></div>\n <slot name=\"header\"></slot>\n </header>\n <section class=\"sheet-content\" part=\"content\">\n <slot></slot>\n </section>\n <footer class=\"sheet-footer\" part=\"footer\">\n <slot name=\"footer\"></slot>\n </footer>\n </aside>\n </div>\n`;\n","/* Needed until Prettier supports identifying embedded CSS by block comments */\nconst css = String.raw;\n\nconst styles = 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 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\nexport const template: string = /* HTML */ `\n <style>\n ${styles}\n </style>\n <slot></slot>\n`;\n","<script setup lang=\"ts\">\nimport { onMounted } from \"vue\";\n\nonMounted(() => {\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</script>\n","import { FunctionalComponent, h } from \"vue\";\nimport ShadowRootTemplate from \"./ShadowRootTemplate.vue\";\nimport {\n BottomSheetEvents,\n BottomSheetHTMLAttributes,\n} from \"../web/bottom-sheet\";\nimport { bottomSheetTemplate } from \"../web/index.ssr\";\nimport Client from \"./Client.vue\";\nimport { CustomElementProps } from \"./custom-element-props\";\n\nconst VBottomSheet: FunctionalComponent<\n CustomElementProps<BottomSheetHTMLAttributes, BottomSheetEvents>\n> = (props, { slots }) => {\n return h(\"bottom-sheet\", props, [\n h(ShadowRootTemplate, { html: bottomSheetTemplate }),\n slots.default?.(),\n h(Client),\n ]);\n};\n\nexport default VBottomSheet;\n","import { FunctionalComponent, h } from \"vue\";\nimport ShadowRootTemplate from \"./ShadowRootTemplate.vue\";\nimport { BottomSheetEvents } from \"../web/bottom-sheet\";\nimport { bottomSheetDialogManagerTemplate } from \"../web/index.ssr\";\nimport Client from \"./Client.vue\";\nimport { CustomElementProps } from \"./custom-element-props\";\n\nconst VBottomSheetDialogManager: FunctionalComponent<\n CustomElementProps<{}, BottomSheetEvents>\n> = (props, { slots }) => {\n return h(\"bottom-sheet-dialog-manager\", props, [\n h(ShadowRootTemplate, { html: bottomSheetDialogManagerTemplate }),\n slots?.default?.(),\n h(Client),\n ]);\n};\n\nexport default VBottomSheetDialogManager;\n"],"names":["_openBlock","_createBlock","_resolveDynamicComponent","styles","template","ShadowRootTemplate","bottomSheetTemplate","Client","bottomSheetDialogManagerTemplate"],"mappings":";;;;;;;;;;;AAGA,IAAA,MAAM,KAAA,GAAQ,OAAA;AAOd,IAAA,MAAM,QAAA,GAAW,OAAO,MAAA,KAAW,WAAA;AAEnC,IAAA,MAAM,2BAA2B,MAAM;AACrC,MAAA,IAAI,CAAC,QAAA,EAAU,OAAO,CAAA,CAAE,QAAA,EAAU,EAAE,CAAA;AAEpC,MAAA,OAAO,EAAE,QAAA,EAAU;AAAA,QACjB,EAAE,UAAA,EAAY;AAAA,UACZ,cAAA,EAAgB,MAAA;AAAA,UAChB,WAAW,KAAA,CAAM;AAAA,SAClB;AAAA,OACF,CAAA;AAAA,IACH,CAAA;;AAIE,MAAA,OAAAA,SAAA,IAAAC,WAAA,CAAwDC,uBAAA,WAA9B,wBAAA,EAAwB,CAAA,CAAA;AAAA;;;;ACtBpD,MAAMC,QAAA,UAAS,CAAA;AAAA;AAAA;AAAA,o8KAAA,CAAA;AAAA,MAAAC,UAAA;AAAA;AAAA,EAAA;AAAA;AAAA,IAAA,EAAAD,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;ACAf,MAAM,MAAA,UAAS,CAAA,6gBAAA,CAAA;AAAA,MAAA,QAAA;AAAA;AAAA,EAAA;AAAA;AAAA,IAAA,EAAA,MAAA;AAAA;AAAA;AAAA;AAAA;;;;;ACAf,IAAA,SAAA,CAAU,MAAM;AACd,MAAA,OAAO,4BAAqB,CAAA,CAAE,IAAA;AAAA,QAC5B,CAAC,EAAE,WAAA,EAAa,wBAAA,EAAyB,KAAM;AAC7C,UAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,cAAc,CAAA,EAAG;AACvC,YAAA,cAAA,CAAe,MAAA,CAAO,gBAAgB,WAAW,CAAA;AAAA,UACnD;AACA,UAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,6BAA6B,CAAA,EAAG;AACtD,YAAA,cAAA,CAAe,MAAA;AAAA,cACb,6BAAA;AAAA,cACA;AAAA,aACF;AAAA,UACF;AAAA,QACF;AAAA,OACF;AAAA,IACF,CAAC,CAAA;;;;;;ACPD,MAAM,YAAA,GAEF,CAAC,KAAA,EAAO,EAAE,OAAM,KAAM;AACxB,EAAA,OAAO,CAAA,CAAE,gBAAgB,KAAA,EAAO;AAAA,IAC9B,CAAA,CAAEE,WAAA,EAAoB,EAAE,IAAA,EAAMC,YAAqB,CAAA;AAAA,IACnD,MAAM,OAAA,IAAU;AAAA,IAChB,EAAEC,SAAM;AAAA,GACT,CAAA;AACH;;ACXA,MAAM,yBAAA,GAEF,CAAC,KAAA,EAAO,EAAE,OAAM,KAAM;AACxB,EAAA,OAAO,CAAA,CAAE,+BAA+B,KAAA,EAAO;AAAA,IAC7C,CAAA,CAAEF,WAAA,EAAoB,EAAE,IAAA,EAAMG,UAAkC,CAAA;AAAA,IAChE,OAAO,OAAA,IAAU;AAAA,IACjB,EAAED,SAAM;AAAA,GACT,CAAA;AACH;;;;"}
@@ -1,4 +1,4 @@
1
- import { t as template, a as template$1 } from './index-CrwMlGJU.js';
1
+ import { t as template, a as template$1 } from './index-0rU4KEd4.js';
2
2
  import 'vue';
3
3
 
4
4
  class BottomSheet extends HTMLElement {
@@ -145,9 +145,9 @@ class BottomSheet extends HTMLElement {
145
145
  const matrix = new DOMMatrixReadOnly(style.transform);
146
146
  const yOffset = -matrix.m42;
147
147
  cleanupStyleProperties();
148
- requestAnimationFrame(() => {
149
- content.scrollTop = yOffset + content.scrollTop;
150
- });
148
+ sheet.style.height = `${this.scrollTop / (this.scrollHeight - this.offsetHeight) * 100}%`;
149
+ content.scrollTop = yOffset + content.scrollTop;
150
+ sheet.style.height = "";
151
151
  };
152
152
  const handleScroll = () => {
153
153
  if (!("scrolling" in this.dataset)) {
@@ -267,4 +267,4 @@ class BottomSheetDialogManager extends HTMLElement {
267
267
  }
268
268
 
269
269
  export { BottomSheet, BottomSheetDialogManager };
270
- //# sourceMappingURL=index.client-JhdfOtKM.js.map
270
+ //# sourceMappingURL=index.client-BnjqgBI2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.client-BnjqgBI2.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\n/**\n * BottomSheet custom element.\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 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<SnapPositionChangeEventDetail>(\"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 // Pin the sheet height inline so the content scrollTop update below is based\n // on the correct scroll height. Removing [data-scrolling] reactivates the\n // scroll-timeline-driven \"expand-sheet-height\" animation, which will not\n // produce a current time until the next layout pass, leaving the sheet height\n // (and content scroll height) stale for the scrollTop assignment that follows.\n sheet.style.height = `${(this.scrollTop / (this.scrollHeight - this.offsetHeight)) * 100}%`;\n content.scrollTop = yOffset + content.scrollTop;\n // Clear the temporary inline override now that the scrollTop is set\n sheet.style.height = \"\";\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\nexport interface BottomSheetHTMLAttributes {\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\nexport interface SnapPositionChangeEventDetail {\n snapPosition: string;\n}\n\nexport type BottomSheetEvents = {\n \"snap-position-change\": CustomEvent<SnapPositionChangeEventDetail>;\n};\n","import { SnapPositionChangeEventDetail } from \"./bottom-sheet\";\nimport { 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<SnapPositionChangeEventDetail> & 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":["template"],"mappings":"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"}
package/dist/vue/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { V as VBottomSheet, b as VBottomSheetDialogManager } from './index-CrwMlGJU.js';
1
+ export { V as VBottomSheet, b as VBottomSheetDialogManager } from './index-0rU4KEd4.js';
2
2
  import 'vue';
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +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='\n <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}.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: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:after{content:"";display:block;position:static;scroll-snap-align:var(--snap-point-align,end)}.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>\n <slot name="snap">\n <div class="snap initial" style="--snap: 100%"></div>\n </slot>\n <div class="sentinel" data-snap="1"></div>\n <div class="snap snap-bottom" data-snap="2"></div>\n <div class="sentinel" data-snap="0"></div>\n <div class="sheet-wrapper">\n <aside class="sheet" part="sheet" data-snap="0">\n <header class="sheet-header" part="header">\n <div class="handle" part="handle"></div>\n <slot name="header"></slot>\n </header>\n <section class="sheet-content" part="content">\n <slot></slot>\n </section>\n <footer class="sheet-footer" part="footer">\n <slot name="footer"></slot>\n </footer>\n </aside>\n </div>\n'),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='\n <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>\n <slot></slot>\n'),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};
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='\n <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}.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: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)}:host(:not([nested-scroll])) .sheet:after{content:"";display:block;position:static;scroll-snap-align:var(--snap-point-align,end)}.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 var(--initial-snap-duration,.5s) backwards}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){:host{display:inherit;--snap-type-initial-reset:none}}@keyframes initial-snap{0%,49.99%{scroll-snap-type:y mandatory;--snap-point-align:none}50%,to{scroll-snap-type:var(--snap-type-initial-reset,y mandatory);--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;touch-action:pan-y pinch-zoom}: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;content-visibility:auto;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([nested-scroll]) .sheet{animation:expand-sheet-height linear forwards;animation-timeline:scroll()}@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:scroll()}@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;animation-timeline:scroll();transform:translateY(var(--sheet-timeline-at-scroll-start,0))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{animation:translate-sheet-content linear forwards;animation-timeline:scroll()}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{animation:translate-footer linear forwards;animation-timeline:scroll()}@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>\n <slot name="snap">\n <div class="snap initial" style="--snap: 100%"></div>\n </slot>\n <div class="sentinel" data-snap="1"></div>\n <div class="snap snap-bottom" data-snap="2"></div>\n <div class="sentinel" data-snap="0"></div>\n <div class="sheet-wrapper">\n <aside class="sheet" part="sheet" data-snap="0">\n <header class="sheet-header" part="header">\n <div class="handle" part="handle"></div>\n <slot name="header"></slot>\n </header>\n <section class="sheet-content" part="content">\n <slot></slot>\n </section>\n <footer class="sheet-footer" part="footer">\n <slot name="footer"></slot>\n </footer>\n </aside>\n </div>\n'),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),o=-new DOMMatrixReadOnly(t.transform).m42;h(),e.style.height=this.scrollTop/(this.scrollHeight-this.offsetHeight)*100+"%",s.scrollTop=o+s.scrollTop,e.style.height=""},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}`)}}},f=()=>{window.clearTimeout(l),l=window.setTimeout(d,100)};this.addEventListener("scroll",p),n?this.addEventListener("scrollend",d):this.addEventListener("scroll",f),this.#o=()=>{this.removeEventListener("scroll",p),n?this.removeEventListener("scrollend",d):(this.removeEventListener("scroll",f),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='\n <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 allow-discrete .5s ease-out,display allow-discrete .5s ease-out;translate:0 100vh}:host([data-sheet-snap-position="2"]) ::slotted(dialog:not([open])){transition:none}\n </style>\n <slot></slot>\n'),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 CHANGED
@@ -1 +1 @@
1
- const t='\n <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}.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: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:after{content:"";display:block;position:static;scroll-snap-align:var(--snap-point-align,end)}.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>\n <slot name="snap">\n <div class="snap initial" style="--snap: 100%"></div>\n </slot>\n <div class="sentinel" data-snap="1"></div>\n <div class="snap snap-bottom" data-snap="2"></div>\n <div class="sentinel" data-snap="0"></div>\n <div class="sheet-wrapper">\n <aside class="sheet" part="sheet" data-snap="0">\n <header class="sheet-header" part="header">\n <div class="handle" part="handle"></div>\n <slot name="header"></slot>\n </header>\n <section class="sheet-content" part="content">\n <slot></slot>\n </section>\n <footer class="sheet-footer" part="footer">\n <slot name="footer"></slot>\n </footer>\n </aside>\n </div>\n',e='\n <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>\n <slot></slot>\n';export{e as bottomSheetDialogManagerTemplate,t as bottomSheetTemplate};
1
+ const t='\n <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}.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: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)}:host(:not([nested-scroll])) .sheet:after{content:"";display:block;position:static;scroll-snap-align:var(--snap-point-align,end)}.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 var(--initial-snap-duration,.5s) backwards}@supports (-webkit-touch-callout:none) or (-webkit-hyphens:none){:host{display:inherit;--snap-type-initial-reset:none}}@keyframes initial-snap{0%,49.99%{scroll-snap-type:y mandatory;--snap-point-align:none}50%,to{scroll-snap-type:var(--snap-type-initial-reset,y mandatory);--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;touch-action:pan-y pinch-zoom}: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;content-visibility:auto;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([nested-scroll]) .sheet{animation:expand-sheet-height linear forwards;animation-timeline:scroll()}@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:scroll()}@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;animation-timeline:scroll();transform:translateY(var(--sheet-timeline-at-scroll-start,0))}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-content{animation:translate-sheet-content linear forwards;animation-timeline:scroll()}:host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) .sheet-footer{animation:translate-footer linear forwards;animation-timeline:scroll()}@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>\n <slot name="snap">\n <div class="snap initial" style="--snap: 100%"></div>\n </slot>\n <div class="sentinel" data-snap="1"></div>\n <div class="snap snap-bottom" data-snap="2"></div>\n <div class="sentinel" data-snap="0"></div>\n <div class="sheet-wrapper">\n <aside class="sheet" part="sheet" data-snap="0">\n <header class="sheet-header" part="header">\n <div class="handle" part="handle"></div>\n <slot name="header"></slot>\n </header>\n <section class="sheet-content" part="content">\n <slot></slot>\n </section>\n <footer class="sheet-footer" part="footer">\n <slot name="footer"></slot>\n </footer>\n </aside>\n </div>\n',e='\n <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 allow-discrete .5s ease-out,display allow-discrete .5s ease-out;translate:0 100vh}:host([data-sheet-snap-position="2"]) ::slotted(dialog:not([open])){transition:none}\n </style>\n <slot></slot>\n';export{e as bottomSheetDialogManagerTemplate,t as bottomSheetTemplate};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pure-web-bottom-sheet",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "A performant, lightweight, and accessible bottom sheet web component powered by CSS scroll snap and CSS scroll-driven animations. Works with any framework, supports SSR, multiple snap points, and nested scrolling mode.",
5
5
  "keywords": [
6
6
  "bottom sheet",
@@ -91,6 +91,12 @@
91
91
  "@rollup/plugin-terser": "^0.4.4",
92
92
  "@rollup/plugin-typescript": "^12.3.0",
93
93
  "@types/react": "^19.2.2",
94
+ "@types/wait-on": "^5.3.4",
95
+ "@wdio/cli": "^9.25.0",
96
+ "@wdio/globals": "^9.23.0",
97
+ "@wdio/local-runner": "^9.25.0",
98
+ "@wdio/mocha-framework": "^9.25.0",
99
+ "@wdio/spec-reporter": "^9.25.0",
94
100
  "cssnano": "^7.1.1",
95
101
  "htmlnano": "^2.1.5",
96
102
  "postcss-nesting": "^13.0.2",
@@ -102,7 +108,8 @@
102
108
  "tslib": "^2.8.1",
103
109
  "typescript": "^5.9.3",
104
110
  "unplugin-dts": "^1.0.0-beta.6",
105
- "unplugin-vue": "^7.0.3"
111
+ "unplugin-vue": "^7.0.3",
112
+ "wait-on": "^9.0.4"
106
113
  },
107
114
  "scripts": {
108
115
  "clean": "rm -rf dist",
@@ -110,7 +117,8 @@
110
117
  "build:prod": "NODE_ENV=production npm run build",
111
118
  "watch": "rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript --watch",
112
119
  "test:format": "prettier . --check",
113
- "test:types": "tsc --noEmit"
120
+ "test:types": "tsc --noEmit",
121
+ "test:wdio": "wdio run ./wdio.conf.ts"
114
122
  },
115
123
  "engines": {
116
124
  "node": ">=24.0.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-CrwMlGJU.js","sources":["../../src/vue/ShadowRootTemplate.vue","../../src/web/bottom-sheet.template.ts","../../src/web/bottom-sheet-dialog-manager.template.ts","../../src/vue/Client.vue","../../src/vue/VBottomSheet.ts","../../src/vue/VBottomSheetDialogManager.ts"],"sourcesContent":["<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","/* Needed until Prettier supports identifying embedded CSS by block comments */\nconst css = String.raw;\n\nconst styles = css`\n :host {\n --sheet-max-height: calc(100dvh - 24px);\n --sheet-background: rgb(242, 242, 242);\n --sheet-border-radius: 12px;\n /* \n The --sw-keyboard-height is needed to handle iOS Safari on-screen keyboard\n since iOS Safari pushes content offscreen by keyboard height when it is opened\n */\n --sheet-safe-max-height: calc(\n var(--sheet-max-height) - env(\n keyboard-inset-height,\n var(--sw-keyboard-height, 0px)\n )\n );\n display: block;\n position: fixed;\n right: 0;\n bottom: env(keyboard-inset-height, 0);\n left: 0;\n will-change: scroll-position;\n contain: strict;\n border-top-right-radius: var(--sheet-border-radius);\n border-top-left-radius: var(--sheet-border-radius);\n height: var(--sheet-max-height);\n max-height: var(--sheet-safe-max-height);\n overflow-y: scroll;\n /* Prevent rubberband effect when scrolling to the end of the sheet */\n overscroll-behavior-y: none;\n scroll-snap-type: y mandatory;\n scrollbar-width: none;\n pointer-events: none;\n }\n\n :host(:focus-visible) {\n outline: none;\n\n .handle {\n outline: auto;\n outline-offset: 4px;\n }\n }\n\n .snap,\n ::slotted([slot=\"snap\"]) {\n position: relative;\n top: var(--snap);\n }\n\n .snap::before,\n ::slotted([slot=\"snap\"])::before {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n height: 1px; /* Height required for Safari to snap */\n scroll-snap-align: var(--snap-point-align, start);\n content: \"\";\n }\n\n .snap.initial,\n ::slotted([slot=\"snap\"].initial) {\n --snap-point-align: start;\n }\n\n .snap.snap-bottom {\n position: static;\n top: initial;\n height: auto;\n\n &::after {\n display: block;\n position: static;\n height: var(--sheet-max-height);\n max-height: var(--sheet-safe-max-height);\n content: \"\";\n }\n }\n\n :host(:not([swipe-to-dismiss])) .snap.snap-bottom::before {\n scroll-snap-align: none;\n }\n\n .sentinel {\n position: relative;\n\n &[data-snap=\"0\"] {\n top: -1px; /** Extra -1px needed for Safari */\n }\n &[data-snap=\"1\"] {\n top: 1px;\n }\n }\n\n .sheet-wrapper {\n border-radius: inherit;\n }\n\n .sheet {\n display: flex;\n flex-direction: column;\n cursor: row-resize;\n border-radius: inherit;\n background: var(--sheet-background);\n overflow: clip;\n scroll-snap-align: var(--snap-point-align, start);\n pointer-events: all;\n }\n\n /* \n Needed for Safari/Firefox to prevent abrupt scroll re-snapping in case the\n sheet DOM content is dynamically changed. Without this, these browsers would\n re-snap to the start of the .sheet element.\n See related spec: https://drafts.csswg.org/css-scroll-snap-1/#re-snap\n */\n .sheet::after {\n display: block;\n position: static;\n scroll-snap-align: var(--snap-point-align, end);\n content: \"\";\n }\n\n .sheet-header {\n position: sticky;\n top: 0;\n background: inherit;\n width: 100%;\n }\n\n .sheet-footer {\n position: sticky;\n bottom: 0;\n background: inherit;\n width: 100%;\n }\n\n .sheet-content {\n flex: 1 1 auto;\n padding: 0 0.5rem;\n }\n\n .handle {\n margin: 0.5rem auto;\n border-radius: 5px;\n background: #ccc;\n width: 40px;\n height: 5px;\n }\n\n :host {\n animation: initial-snap 0.01s both;\n }\n\n /* Safari overrides */\n @supports (-webkit-touch-callout: none) or (-webkit-hyphens: none) {\n :host {\n /* \n On Safari, when displaying in a dialog, we must inherit display property\n so that the animation runs each time the dialog is-reopened\n (display toggles between none and block).\n */\n display: inherit;\n /* \n On Safari the duration must be higher for the initial-snap animation\n to properly snap to the initial target.\n */\n animation: initial-snap 0.1s both;\n }\n }\n\n /*\n Temporarily disables scroll snapping for all snap points\n except the explicitly marked initial snap point (which overrides\n --snap-point-align) so that the sheet snaps to\n the initial snap point.\n */\n @keyframes initial-snap {\n 0% {\n --snap-point-align: none;\n }\n 50% {\n /* \n Needed for the iOS Safari\n See https://stackoverflow.com/q/65653679\n */\n scroll-snap-type: initial;\n --snap-point-align: none;\n }\n }\n\n /* Temporary workaround for iOS Safari bug https://bugs.webkit.org/show_bug.cgi?id=183870 */\n @supports (-webkit-touch-callout: none) {\n .sheet-content,\n .sheet-header,\n .sheet-footer {\n overflow-x: scroll;\n /* Prevent rubberband effect */\n overscroll-behavior-x: none;\n scrollbar-width: none;\n\n &::after {\n display: block;\n box-sizing: content-box;\n padding: inherit;\n padding-left: 0;\n width: calc(100% + 1px);\n height: 1px;\n content: \"\";\n }\n }\n .sheet-content {\n scrollbar-width: auto;\n }\n }\n\n :host(:not([nested-scroll]):not([content-height])) {\n .sheet-wrapper {\n height: 100%;\n }\n\n .sheet {\n min-height: 100%;\n }\n }\n\n :host([nested-scroll]) {\n .sheet-wrapper {\n display: flex;\n position: sticky;\n bottom: 0;\n flex-direction: column;\n justify-content: end;\n /* Fixes scroll-chaining issue on Firefox when sheet content is scrollable */\n contain: strict;\n height: 100%;\n }\n\n .sheet {\n display: flex;\n position: sticky;\n bottom: 0;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n }\n\n .sheet-content {\n will-change: scroll-position;\n overflow-y: auto;\n scrollbar-gutter: stable;\n }\n\n .sheet-header,\n .sheet-footer {\n /* Prevent shrinking the header and footer */\n flex: 0 0 auto;\n }\n }\n\n /*\n When expand-to-scroll is enabled, we do not need dynamic sheet height animation\n since sheet content is always fixed size and only scrollable at full height\n so we can simplify the layout and improve performance by disabling height animation.\n */\n :host([nested-scroll][expand-to-scroll]) {\n .sheet-wrapper {\n position: static;\n }\n\n .sheet {\n position: static;\n animation: none;\n height: 100%;\n }\n }\n\n /*\n Performance optimization for the nested-scroll mode:\n When the sheet is being actively scrolled, disable sheet height animation and\n switch to transform-based animation for the sheet content to improve performance\n and avoid jank because animating height would cause continuous reflow (layout).\n\n Follow use of [data-scrolling] for the specific CSS rules applied in this case.\n */\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet-header {\n z-index: 1;\n }\n\n .sheet-content {\n /* Hide the scrollbar visually during scrolling */\n scrollbar-color: transparent transparent;\n }\n }\n\n @supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {\n :host {\n scroll-timeline: --sheet-timeline y;\n }\n\n :host([nested-scroll]) .sheet {\n animation: expand-sheet-height linear forwards;\n animation-timeline: --sheet-timeline;\n }\n\n @keyframes expand-sheet-height {\n from {\n height: 0;\n }\n to {\n height: 100%;\n }\n }\n\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\n animation: overflow-y-toggle linear forwards;\n animation-timeline: --sheet-timeline;\n }\n\n @keyframes overflow-y-toggle {\n 0%,\n 99.99% {\n overflow-y: hidden;\n }\n 100% {\n overflow-y: auto;\n }\n }\n\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet {\n /* \n Safari bug fix: Pre-apply transform to prevent flickering. Safari 26+ has\n a one-frame delay when switching from height-based to transform-based animation,\n causing brief position shift. Setting an initial transform value ensures\n smooth transition.\n */\n transform: translateY(var(--sheet-timeline-at-scroll-start, 0));\n animation: translate-sheet linear forwards;\n animation-timeline: --sheet-timeline;\n }\n\n .sheet-content {\n animation: translate-sheet-content linear forwards;\n animation-timeline: --sheet-timeline;\n }\n\n .sheet-footer {\n animation: translate-footer linear forwards;\n animation-timeline: --sheet-timeline;\n }\n }\n\n @keyframes translate-sheet {\n from {\n transform: translateY(100%);\n }\n to {\n transform: translateY(0);\n }\n }\n\n @keyframes translate-sheet-content {\n from {\n transform: translateY(var(--sheet-content-offset-start, 0));\n }\n to {\n transform: translateY(var(--sheet-content-offset-end, 0));\n }\n }\n\n @keyframes translate-footer {\n from {\n transform: translateY(calc(-1 * var(--sheet-safe-max-height)));\n }\n to {\n transform: translateY(0);\n }\n }\n }\n\n /* Fallback for browsers that do not yet support scroll-driven animations */\n @supports (\n not ((animation-timeline: scroll()) and (animation-range: 0% 100%))\n ) {\n :host([nested-scroll]) .sheet {\n height: var(--sheet-position);\n }\n\n :host([nested-scroll][expand-to-scroll]) .sheet-content {\n overflow-y: hidden;\n }\n\n :host([nested-scroll][expand-to-scroll][data-sheet-snap-position=\"0\"])\n .sheet-content {\n overflow-y: auto;\n }\n\n :host([nested-scroll]:not([expand-to-scroll])[data-scrolling]) {\n .sheet {\n transform: translateY(calc(100% - var(--sheet-position, 0)));\n height: 100%;\n }\n\n .sheet-content {\n transform: translateY(var(--sheet-content-offset, 0));\n }\n\n .sheet-footer {\n transform: translateY(\n calc(-1 * var(--sheet-safe-max-height) + var(--sheet-position, 0))\n );\n }\n }\n }\n`;\n\nexport const template: string = /* HTML */ `\n <style>\n ${styles}\n </style>\n <slot name=\"snap\">\n <div class=\"snap initial\" style=\"--snap: 100%\"></div>\n </slot>\n <div class=\"sentinel\" data-snap=\"1\"></div>\n <div class=\"snap snap-bottom\" data-snap=\"2\"></div>\n <div class=\"sentinel\" data-snap=\"0\"></div>\n <div class=\"sheet-wrapper\">\n <aside class=\"sheet\" part=\"sheet\" data-snap=\"0\">\n <header class=\"sheet-header\" part=\"header\">\n <div class=\"handle\" part=\"handle\"></div>\n <slot name=\"header\"></slot>\n </header>\n <section class=\"sheet-content\" part=\"content\">\n <slot></slot>\n </section>\n <footer class=\"sheet-footer\" part=\"footer\">\n <slot name=\"footer\"></slot>\n </footer>\n </aside>\n </div>\n`;\n","/* Needed until Prettier supports identifying embedded CSS by block comments */\nconst css = String.raw;\n\nconst styles = 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 ${styles}\n </style>\n <slot></slot>\n`;\n","<script setup lang=\"ts\">\nimport { onMounted } from \"vue\";\n\nonMounted(() => {\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</script>\n","import { FunctionalComponent, h } from \"vue\";\nimport ShadowRootTemplate from \"./ShadowRootTemplate.vue\";\nimport {\n BottomSheetEvents,\n BottomSheetHTMLAttributes,\n} from \"../web/bottom-sheet\";\nimport { bottomSheetTemplate } from \"../web/index.ssr\";\nimport Client from \"./Client.vue\";\nimport { CustomElementProps } from \"./custom-element-props\";\n\nconst VBottomSheet: FunctionalComponent<\n CustomElementProps<BottomSheetHTMLAttributes, BottomSheetEvents>\n> = (props, { slots }) => {\n return h(\"bottom-sheet\", props, [\n h(ShadowRootTemplate, { html: bottomSheetTemplate }),\n slots.default?.(),\n h(Client),\n ]);\n};\n\nexport default VBottomSheet;\n","import { FunctionalComponent, h } from \"vue\";\nimport ShadowRootTemplate from \"./ShadowRootTemplate.vue\";\nimport { BottomSheetEvents } from \"../web/bottom-sheet\";\nimport { bottomSheetDialogManagerTemplate } from \"../web/index.ssr\";\nimport Client from \"./Client.vue\";\nimport { CustomElementProps } from \"./custom-element-props\";\n\nconst VBottomSheetDialogManager: FunctionalComponent<\n CustomElementProps<{}, BottomSheetEvents>\n> = (props, { slots }) => {\n return h(\"bottom-sheet-dialog-manager\", props, [\n h(ShadowRootTemplate, { html: bottomSheetDialogManagerTemplate }),\n slots?.default?.(),\n h(Client),\n ]);\n};\n\nexport default VBottomSheetDialogManager;\n"],"names":["_openBlock","_createBlock","_resolveDynamicComponent","styles","template","ShadowRootTemplate","bottomSheetTemplate","Client","bottomSheetDialogManagerTemplate"],"mappings":";;;;;;;;;;;AAGA,IAAA,MAAM,KAAA,GAAQ,OAAA;AAOd,IAAA,MAAM,QAAA,GAAW,OAAO,MAAA,KAAW,WAAA;AAEnC,IAAA,MAAM,2BAA2B,MAAM;AACrC,MAAA,IAAI,CAAC,QAAA,EAAU,OAAO,CAAA,CAAE,QAAA,EAAU,EAAE,CAAA;AAEpC,MAAA,OAAO,EAAE,QAAA,EAAU;AAAA,QACjB,EAAE,UAAA,EAAY;AAAA,UACZ,cAAA,EAAgB,MAAA;AAAA,UAChB,WAAW,KAAA,CAAM;AAAA,SAClB;AAAA,OACF,CAAA;AAAA,IACH,CAAA;;AAIE,MAAA,OAAAA,SAAA,IAAAC,WAAA,CAAwDC,uBAAA,WAA9B,wBAAA,EAAwB,CAAA,CAAA;AAAA;;;;ACtBpD,MAAMC,QAAA,UAAS,CAAA;AAAA;AAAA;AAAA,q1KAAA,CAAA;AAAA,MAAAC,UAAA;AAAA;AAAA,EAAA;AAAA;AAAA,IAAA,EAAAD,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;ACAf,MAAM,MAAA,UAAS,CAAA,uqBAAA,CAAA;AAAA,MAAA,QAAA;AAAA;AAAA,EAAA;AAAA;AAAA,IAAA,EAAA,MAAA;AAAA;AAAA;AAAA;AAAA;;;;;ACAf,IAAA,SAAA,CAAU,MAAM;AACd,MAAA,OAAO,4BAAqB,CAAA,CAAE,IAAA;AAAA,QAC5B,CAAC,EAAE,WAAA,EAAa,wBAAA,EAAyB,KAAM;AAC7C,UAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,cAAc,CAAA,EAAG;AACvC,YAAA,cAAA,CAAe,MAAA,CAAO,gBAAgB,WAAW,CAAA;AAAA,UACnD;AACA,UAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,6BAA6B,CAAA,EAAG;AACtD,YAAA,cAAA,CAAe,MAAA;AAAA,cACb,6BAAA;AAAA,cACA;AAAA,aACF;AAAA,UACF;AAAA,QACF;AAAA,OACF;AAAA,IACF,CAAC,CAAA;;;;;;ACPD,MAAM,YAAA,GAEF,CAAC,KAAA,EAAO,EAAE,OAAM,KAAM;AACxB,EAAA,OAAO,CAAA,CAAE,gBAAgB,KAAA,EAAO;AAAA,IAC9B,CAAA,CAAEE,WAAA,EAAoB,EAAE,IAAA,EAAMC,YAAqB,CAAA;AAAA,IACnD,MAAM,OAAA,IAAU;AAAA,IAChB,EAAEC,SAAM;AAAA,GACT,CAAA;AACH;;ACXA,MAAM,yBAAA,GAEF,CAAC,KAAA,EAAO,EAAE,OAAM,KAAM;AACxB,EAAA,OAAO,CAAA,CAAE,+BAA+B,KAAA,EAAO;AAAA,IAC7C,CAAA,CAAEF,WAAA,EAAoB,EAAE,IAAA,EAAMG,UAAkC,CAAA;AAAA,IAChE,OAAO,OAAA,IAAU;AAAA,IACjB,EAAED,SAAM;AAAA,GACT,CAAA;AACH;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.client-JhdfOtKM.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\n/**\n * BottomSheet custom element.\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 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<SnapPositionChangeEventDetail>(\"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\nexport interface BottomSheetHTMLAttributes {\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\nexport interface SnapPositionChangeEventDetail {\n snapPosition: string;\n}\n\nexport type BottomSheetEvents = {\n \"snap-position-change\": CustomEvent<SnapPositionChangeEventDetail>;\n};\n","import { SnapPositionChangeEventDetail } from \"./bottom-sheet\";\nimport { 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<SnapPositionChangeEventDetail> & 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":["template"],"mappings":"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"}