{"version":3,"file":"fixed-action-bar.cjs","sources":["../../../packages/components/src/fixed-action-bar.ts"],"sourcesContent":["import { LitElement, css, html } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\nimport { styleMap } from 'lit/directives/style-map.js'\nimport { safeCustomElement } from './base/define'\n\nfunction isAndroidDevice() {\n  if (typeof navigator === 'undefined') {\n    return false\n  }\n\n  return /Android/i.test(navigator.userAgent)\n}\n\n@safeCustomElement('qxs-fixed-action-bar')\nexport class QxsFixedActionBar extends LitElement {\n  static styles = css`\n    :host {\n      display: block;\n      width: 100%;\n    }\n\n    .placeholder {\n      width: 100%;\n    }\n\n    .actionbar {\n      position: fixed;\n      bottom: 0;\n      z-index: 10;\n      box-sizing: border-box;\n      text-align: center;\n      background-color: var(--qxs-bg-color, #fff);\n      transition: box-shadow 0.3s ease;\n    }\n\n    .actionbar.is-shadow {\n      box-shadow: 0 0 1px 0 var(--qxs-border-color, #f3f3f2);\n    }\n  `\n\n  @property({ type: Number }) padding = 8\n  @property({ type: String, attribute: 'class-name' }) className = ''\n\n  @state() private _barHeight = 0\n  @state() private _barLeft = 0\n  @state() private _barWidth = 0\n  @state() private _isBottom = false\n\n  @query('.actionbar') private _actionbar?: HTMLDivElement\n\n  private _actionbarObserver: ResizeObserver | null = null\n  private _hostObserver: ResizeObserver | null = null\n  private _resizeHandler = () => {\n    this._syncGeometry()\n    this._syncScrollState()\n  }\n  private _scrollFrame = 0\n\n  connectedCallback() {\n    super.connectedCallback()\n    window.addEventListener('resize', this._resizeHandler, { passive: true })\n    window.addEventListener('scroll', this._handleScroll, { passive: true })\n  }\n\n  firstUpdated() {\n    this._initObservers()\n    queueMicrotask(() => {\n      if (!this.isConnected) {\n        return\n      }\n\n      this._syncGeometry()\n      this._syncScrollState()\n    })\n  }\n\n  disconnectedCallback() {\n    super.disconnectedCallback()\n    window.removeEventListener('resize', this._resizeHandler)\n    window.removeEventListener('scroll', this._handleScroll)\n    this._actionbarObserver?.disconnect()\n    this._hostObserver?.disconnect()\n\n    if (this._scrollFrame) {\n      cancelAnimationFrame(this._scrollFrame)\n      this._scrollFrame = 0\n    }\n  }\n\n  private _handleScroll = () => {\n    if (this._scrollFrame) {\n      cancelAnimationFrame(this._scrollFrame)\n    }\n\n    this._scrollFrame = requestAnimationFrame(() => {\n      this._scrollFrame = 0\n      this._syncScrollState()\n    })\n  }\n\n  private _initObservers() {\n    if (typeof ResizeObserver === 'undefined') {\n      return\n    }\n\n    const layoutAnchor = this._getLayoutAnchor()\n\n    this._actionbarObserver = new ResizeObserver(() => {\n      this._syncGeometry()\n    })\n    this._hostObserver = new ResizeObserver(() => {\n      this._syncGeometry()\n    })\n\n    if (this._actionbar) {\n      this._actionbarObserver.observe(this._actionbar)\n    }\n    this._hostObserver.observe(this)\n    if (layoutAnchor !== this) {\n      this._hostObserver.observe(layoutAnchor)\n    }\n  }\n\n  private _getLayoutAnchor() {\n    return this.parentElement ?? this\n  }\n\n  private _syncGeometry() {\n    const hostRect = this._getLayoutAnchor().getBoundingClientRect()\n    this._barWidth = Math.max(Math.round(hostRect.width), 0)\n    this._barLeft = Math.round(hostRect.left)\n\n    const barHeight = Math.ceil(this._actionbar?.getBoundingClientRect().height || 0)\n    this._barHeight = Math.max(barHeight, 0)\n  }\n\n  private _syncScrollState() {\n    const doc = document.documentElement\n    this._isBottom = Math.ceil(window.scrollY + doc.clientHeight) >= doc.scrollHeight\n  }\n\n  private _bottomPadding() {\n    return isAndroidDevice()\n      ? Math.max(this.padding, 20)\n      : this.padding\n  }\n\n  render() {\n    const actionbarClassName = ['actionbar', !this._isBottom ? 'is-shadow' : '', this.className]\n      .filter(Boolean)\n      .join(' ')\n\n    return html`\n      <div\n        part=\"placeholder\"\n        class=\"placeholder\"\n        style=${styleMap({ height: `${this._barHeight}px` })}\n      >\n        <div\n          part=\"actionbar\"\n          class=${actionbarClassName}\n          style=${styleMap({\n            width: `${this._barWidth}px`,\n            left: `${this._barLeft}px`,\n            padding: `${this.padding}px`,\n            paddingBottom: `calc(env(safe-area-inset-bottom) + ${this._bottomPadding()}px)`,\n          })}\n        >\n          <slot></slot>\n        </div>\n      </div>\n    `\n  }\n}\n"],"names":["isAndroidDevice","QxsFixedActionBar","LitElement","layoutAnchor","hostRect","barHeight","doc","actionbarClassName","html","styleMap","css","__decorateClass","property","state","query","safeCustomElement"],"mappings":"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"}