{"version":3,"file":"BqDrawer-Ct5jW7n0.cjs","names":[],"sources":["../src/components/drawer/BqDrawer.ts"],"sourcesContent":["/**\r\n * Drawer / side panel overlay.\r\n * @element bq-drawer\r\n * @prop {boolean} open\r\n * @prop {string}  title\r\n * @prop {string}  placement - right | left | top | bottom\r\n * @prop {string}  size      - sm | md | lg | full\r\n * @slot        - Drawer body\r\n * @slot footer - Footer actions\r\n * @fires bq-close\r\n */\r\nimport type { ComponentDefinition } from '@bquery/bquery/component';\r\nimport { component, html } from '@bquery/bquery/component';\r\nimport { escapeHtml } from '@bquery/bquery/security';\r\nimport { t } from '../../i18n/index.js';\r\nimport type { OverlayFocusState } from '../../utils/dom.js';\r\nimport {\r\n  cleanupOverlayFocus,\r\n  getAnimationTimeoutMs,\r\n  uniqueId,\r\n  updateOverlayFocus,\r\n} from '../../utils/dom.js';\r\nimport { getBaseStyles } from '../../utils/styles.js';\r\n\r\ntype BqDrawerProps = {\r\n  open: boolean;\r\n  title: string;\r\n  placement: string;\r\n  size: string;\r\n};\r\ntype BqDrawerState = { titleId: string };\r\nconst NORMAL_DURATION = '200ms';\r\n\r\nconst definition: ComponentDefinition<BqDrawerProps, BqDrawerState> = {\r\n  props: {\r\n    open: { type: Boolean, default: false },\r\n    title: { type: String, default: '' },\r\n    placement: { type: String, default: 'right' },\r\n    size: { type: String, default: 'md' },\r\n  },\r\n  state: {\r\n    titleId: '',\r\n  },\r\n  styles: `\r\n    ${getBaseStyles()}\r\n    *, *::before, *::after { box-sizing: border-box; }\r\n    :host { display: block; }\r\n    :host(:not([open])) .backdrop { display: none; }\r\n    .backdrop {\r\n      position: fixed; inset: 0; z-index: var(--bq-z-overlay,300);\r\n      background: rgba(0,0,0,0.5);\r\n      animation: fadeIn var(--bq-duration-normal) var(--bq-easing-decelerate);\r\n    }\r\n    @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }\r\n    .drawer {\r\n      position: fixed; z-index: calc(var(--bq-z-overlay,300) + 1);\r\n      background: var(--bq-bg-base,#fff); box-shadow: var(--bq-shadow-xl);\r\n      display: flex; flex-direction: column;\r\n      font-family: var(--bq-font-family-sans);\r\n    }\r\n    .drawer[data-placement=\"right\"]  { right: 0; top: 0; bottom: 0; animation: slideInRight var(--bq-duration-normal) var(--bq-easing-decelerate); }\r\n    .drawer[data-placement=\"left\"]   { left: 0; top: 0; bottom: 0; animation: slideInLeft var(--bq-duration-normal) var(--bq-easing-decelerate); }\r\n    .drawer[data-placement=\"top\"]    { top: 0; left: 0; right: 0; animation: slideInTop var(--bq-duration-normal) var(--bq-easing-decelerate); }\r\n    .drawer[data-placement=\"bottom\"] { bottom: 0; left: 0; right: 0; animation: slideInBottom var(--bq-duration-normal) var(--bq-easing-decelerate); }\r\n    .drawer[data-placement=\"right\"][data-size=\"sm\"],  .drawer[data-placement=\"left\"][data-size=\"sm\"]  { width: 20rem; }\r\n    .drawer[data-placement=\"right\"][data-size=\"md\"],  .drawer[data-placement=\"left\"][data-size=\"md\"]  { width: 28rem; }\r\n    .drawer[data-placement=\"right\"][data-size=\"lg\"],  .drawer[data-placement=\"left\"][data-size=\"lg\"]  { width: 40rem; }\r\n    .drawer[data-placement=\"right\"][data-size=\"full\"],.drawer[data-placement=\"left\"][data-size=\"full\"] { width: 100vw; }\r\n    .drawer[data-placement=\"top\"][data-size=\"sm\"],    .drawer[data-placement=\"bottom\"][data-size=\"sm\"]    { height: 16rem; }\r\n    .drawer[data-placement=\"top\"][data-size=\"md\"],    .drawer[data-placement=\"bottom\"][data-size=\"md\"]    { height: 22rem; }\r\n    .drawer[data-placement=\"top\"][data-size=\"lg\"],    .drawer[data-placement=\"bottom\"][data-size=\"lg\"]    { height: 36rem; }\r\n    @keyframes slideInRight  { from { transform: translateX(100%); } to { transform: translateX(0); } }\r\n    @keyframes slideInLeft   { from { transform: translateX(-100%); } to { transform: translateX(0); } }\r\n    @keyframes slideInTop    { from { transform: translateY(-100%); } to { transform: translateY(0); } }\r\n    @keyframes slideInBottom { from { transform: translateY(100%); } to { transform: translateY(0); } }\r\n    :host([data-closing]) .backdrop { animation: drwFadeOut var(--bq-duration-normal) var(--bq-easing-accelerate) forwards; }\r\n    :host([data-closing]) .drawer[data-placement=\"right\"]  { animation: slideOutRight var(--bq-duration-normal) var(--bq-easing-accelerate) forwards; }\r\n    :host([data-closing]) .drawer[data-placement=\"left\"]   { animation: slideOutLeft var(--bq-duration-normal) var(--bq-easing-accelerate) forwards; }\r\n    :host([data-closing]) .drawer[data-placement=\"top\"]    { animation: slideOutTop var(--bq-duration-normal) var(--bq-easing-accelerate) forwards; }\r\n    :host([data-closing]) .drawer[data-placement=\"bottom\"] { animation: slideOutBottom var(--bq-duration-normal) var(--bq-easing-accelerate) forwards; }\r\n    @keyframes drwFadeOut { to { opacity: 0; } }\r\n    @keyframes slideOutRight  { to { transform: translateX(100%); } }\r\n    @keyframes slideOutLeft   { to { transform: translateX(-100%); } }\r\n    @keyframes slideOutTop    { to { transform: translateY(-100%); } }\r\n    @keyframes slideOutBottom { to { transform: translateY(100%); } }\r\n    .header { display: flex; align-items: center; justify-content: space-between; padding: var(--bq-space-5,1.25rem) var(--bq-space-6,1.5rem); border-bottom: 1px solid var(--bq-border-base,#e2e8f0); flex-shrink: 0; }\r\n    .title { font-size: var(--bq-font-size-lg,1.125rem); font-weight: var(--bq-font-weight-semibold,600); color: var(--bq-text-base,#0f172a); margin: 0; flex: 1; }\r\n    .close-btn { display: inline-flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; background: none; border: none; cursor: pointer; color: var(--bq-text-muted,#475569); border-radius: var(--bq-radius-md,0.375rem); font-size: 1rem; transition: background var(--bq-duration-fast); }\r\n    .close-btn:hover { background: var(--bq-bg-muted,#f1f5f9); }\r\n    .close-btn:focus-visible { outline: 2px solid transparent; box-shadow: var(--bq-focus-ring); }\r\n    .body { padding: var(--bq-space-6,1.5rem); overflow-y: auto; flex: 1; }\r\n    .footer { padding: var(--bq-space-4,1rem) var(--bq-space-6,1.5rem); border-top: 1px solid var(--bq-border-base,#e2e8f0); display: flex; gap: var(--bq-space-3,0.75rem); justify-content: flex-end; flex-shrink: 0; background: var(--bq-bg-subtle,#f8fafc); }\r\n    @media (prefers-reduced-motion: reduce) {\r\n      .backdrop, .drawer { animation: none !important; }\r\n      .close-btn { transition: none; }\r\n    }\r\n  `,\r\n  connected() {\r\n    type BQEl = HTMLElement & {\r\n      setState(k: 'titleId', v: string): void;\r\n      getState<T>(k: string): T;\r\n    };\r\n    const self = this as unknown as BQEl;\r\n    const record = self as unknown as Record<string, unknown>;\r\n    if (!self.getState<string>('titleId'))\r\n      self.setState('titleId', uniqueId('bq-drawer-title'));\r\n    const close = () => {\r\n      if (self.hasAttribute('data-closing')) return;\r\n      const clearCloseTimer = () => {\r\n        const closeTimer = record['_closeTimer'] as\r\n          | ReturnType<typeof setTimeout>\r\n          | undefined;\r\n        if (closeTimer) {\r\n          clearTimeout(closeTimer);\r\n          delete record['_closeTimer'];\r\n        }\r\n      };\r\n      const reducedMotion = self.ownerDocument.defaultView?.matchMedia?.(\r\n        '(prefers-reduced-motion: reduce)'\r\n      )?.matches;\r\n      const finalize = () => {\r\n        clearCloseTimer();\r\n        self.removeAttribute('data-closing');\r\n        self.removeAttribute('open');\r\n        self.dispatchEvent(\r\n          new CustomEvent('bq-close', { bubbles: true, composed: true })\r\n        );\r\n      };\r\n      if (reducedMotion) {\r\n        finalize();\r\n      } else {\r\n        self.setAttribute('data-closing', '');\r\n        const drawer = self.shadowRoot?.querySelector('.drawer');\r\n        const timeoutMs = drawer\r\n          ? getAnimationTimeoutMs(drawer, NORMAL_DURATION)\r\n          : 0;\r\n        if (timeoutMs <= 0) {\r\n          finalize();\r\n        } else {\r\n          record['_closeTimer'] = setTimeout(finalize, Math.ceil(timeoutMs) + 20);\r\n        }\r\n      }\r\n    };\r\n    const kh = (e: Event) => {\r\n      if ((e as KeyboardEvent).key === 'Escape' && self.hasAttribute('open'))\r\n        close();\r\n    };\r\n    const bh = (e: Event) => {\r\n      if ((e.target as Element).classList.contains('backdrop')) close();\r\n    };\r\n    const ch = (e: Event) => {\r\n      if ((e.target as Element).closest('.close-btn')) close();\r\n    };\r\n    const s = self as unknown as Record<string, unknown>;\r\n    s['_kh'] = kh;\r\n    s['_bh'] = bh;\r\n    s['_ch'] = ch;\r\n    document.addEventListener('keydown', kh);\r\n    self.shadowRoot?.addEventListener('click', bh);\r\n    self.shadowRoot?.addEventListener('click', ch);\r\n  },\r\n  disconnected() {\r\n    const s = this as unknown as Record<string, unknown>;\r\n    cleanupOverlayFocus(s as unknown as OverlayFocusState);\r\n    const kh = s['_kh'] as EventListener | undefined;\r\n    if (kh) document.removeEventListener('keydown', kh);\r\n    const bh = s['_bh'] as EventListener | undefined;\r\n    if (bh) this.shadowRoot?.removeEventListener('click', bh);\r\n    const ch = s['_ch'] as EventListener | undefined;\r\n    if (ch) this.shadowRoot?.removeEventListener('click', ch);\r\n    const closeTimer = s['_closeTimer'] as ReturnType<typeof setTimeout> | undefined;\r\n    if (closeTimer) {\r\n      clearTimeout(closeTimer);\r\n      delete s['_closeTimer'];\r\n      this.removeAttribute('data-closing');\r\n      this.removeAttribute('open');\r\n    }\r\n  },\r\n  updated() {\r\n    updateOverlayFocus(this, this as unknown as OverlayFocusState, '.drawer');\r\n  },\r\n  render({ props, state }) {\r\n    const titleId = state.titleId || 'bq-drawer-title';\r\n    return html`\r\n      <div class=\"backdrop\" part=\"backdrop\" role=\"presentation\">\r\n        <div\r\n          class=\"drawer\"\r\n          part=\"drawer\"\r\n          data-placement=\"${escapeHtml(props.placement)}\"\r\n          data-size=\"${escapeHtml(props.size)}\"\r\n          role=\"dialog\"\r\n          aria-modal=\"true\"\r\n          aria-labelledby=\"${escapeHtml(titleId)}\"\r\n          tabindex=\"-1\"\r\n        >\r\n          <div class=\"header\" part=\"header\">\r\n            <h2 class=\"title\" id=\"${escapeHtml(titleId)}\" part=\"title\">\r\n              ${escapeHtml(props.title)}\r\n            </h2>\r\n            <button\r\n              class=\"close-btn\"\r\n              type=\"button\"\r\n              aria-label=\"${t('drawer.close')}\"\r\n              part=\"close\"\r\n            >\r\n              &#10005;\r\n            </button>\r\n          </div>\r\n          <div class=\"body\" part=\"body\"><slot></slot></div>\r\n          <div class=\"footer\" part=\"footer\"><slot name=\"footer\"></slot></div>\r\n        </div>\r\n      </div>\r\n    `;\r\n  },\r\n};\r\n\r\ncomponent<BqDrawerProps, BqDrawerState>('bq-drawer', definition);\r\n"],"mappings":"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"}