{"version":3,"file":"BqDialog-oenJBBqr.cjs","names":[],"sources":["../src/components/dialog/BqDialog.ts"],"sourcesContent":["/**\r\n * Dialog / modal overlay.\r\n * @element bq-dialog\r\n * @prop {boolean} open\r\n * @prop {string}  title\r\n * @prop {string}  size        - sm | md | lg | xl | full\r\n * @prop {boolean} dismissible - Show close button\r\n * @slot        - Dialog body\r\n * @slot footer - Dialog 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 BqDialogProps = {\r\n  open: boolean;\r\n  title: string;\r\n  size: string;\r\n  dismissible: boolean;\r\n};\r\ntype BqDialogState = { titleId: string };\r\nconst NORMAL_DURATION = '200ms';\r\n\r\nconst definition: ComponentDefinition<BqDialogProps, BqDialogState> = {\r\n  props: {\r\n    open: { type: Boolean, default: false },\r\n    title: { type: String, default: '' },\r\n    size: { type: String, default: 'md' },\r\n    dismissible: { type: Boolean, default: true },\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])) .overlay { display: none; }\r\n    .overlay {\r\n      position: fixed; inset: 0; z-index: var(--bq-z-modal,400);\r\n      background: rgba(0,0,0,0.5);\r\n      display: flex; align-items: center; justify-content: center;\r\n      padding: var(--bq-space-4,1rem);\r\n      animation: fadeIn var(--bq-duration-normal,200ms) var(--bq-easing-decelerate);\r\n    }\r\n    @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }\r\n    .dialog {\r\n      background: var(--bq-bg-base,#fff); border-radius: var(--bq-radius-xl,0.75rem);\r\n      box-shadow: var(--bq-shadow-xl); width: 100%;\r\n      max-height: calc(100vh - 4rem); display: flex; flex-direction: column;\r\n      animation: scaleIn var(--bq-duration-normal,200ms) var(--bq-easing-spring);\r\n      font-family: var(--bq-font-family-sans); overflow: hidden;\r\n    }\r\n    @keyframes scaleIn { from { transform: scale(0.95); opacity: 0; } to { transform: scale(1); opacity: 1; } }\r\n    :host([data-closing]) .overlay { animation: dlgFadeOut var(--bq-duration-normal,200ms) var(--bq-easing-accelerate) forwards; }\r\n    :host([data-closing]) .dialog { animation: dlgScaleOut var(--bq-duration-normal,200ms) var(--bq-easing-accelerate) forwards; }\r\n    @keyframes dlgFadeOut { to { opacity: 0; } }\r\n    @keyframes dlgScaleOut { to { transform: scale(0.95); opacity: 0; } }\r\n    .dialog[data-size=\"sm\"] { max-width: 28rem; }\r\n    .dialog[data-size=\"md\"] { max-width: 36rem; }\r\n    .dialog[data-size=\"lg\"] { max-width: 48rem; }\r\n    .dialog[data-size=\"xl\"] { max-width: 64rem; }\r\n    .dialog[data-size=\"full\"] { max-width: 100vw; max-height: 100vh; border-radius: 0; }\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    .header-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; flex-shrink: 0; 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; color: var(--bq-text-muted,#475569); font-size: var(--bq-font-size-md,1rem); line-height: var(--bq-line-height-relaxed,1.625); }\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; align-items: center; justify-content: flex-end; gap: var(--bq-space-3,0.75rem); flex-shrink: 0; background: var(--bq-bg-subtle,#f8fafc); }\r\n    @media (prefers-reduced-motion: reduce) {\r\n      .overlay, .dialog { 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-dlg-title'));\r\n    // Escape key handler\r\n    const kh = (e: Event) => {\r\n      if ((e as KeyboardEvent).key === 'Escape' && self.hasAttribute('open'))\r\n        close();\r\n    };\r\n    // Click-outside handler\r\n    const oh = (e: Event) => {\r\n      if ((e.target as Element).classList.contains('overlay')) close();\r\n    };\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 overlay = self.shadowRoot?.querySelector('.overlay');\r\n        const timeoutMs = overlay\r\n          ? getAnimationTimeoutMs(overlay, 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 ch = (e: Event) => {\r\n      if ((e.target as Element).closest('.close-btn')) close();\r\n    };\r\n    (self as unknown as Record<string, unknown>)['_kh'] = kh;\r\n    (self as unknown as Record<string, unknown>)['_oh'] = oh;\r\n    (self as unknown as Record<string, unknown>)['_ch'] = ch;\r\n    document.addEventListener('keydown', kh);\r\n    self.shadowRoot?.addEventListener('click', oh);\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 oh = s['_oh'] as EventListener | undefined;\r\n    if (oh) this.shadowRoot?.removeEventListener('click', oh);\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, '.dialog');\r\n  },\r\n  render({ props, state }) {\r\n    const titleId = state.titleId || 'bq-dlg-title';\r\n    return html`\r\n      <div part=\"overlay\" class=\"overlay\" role=\"presentation\">\r\n        <div\r\n          part=\"dialog\"\r\n          class=\"dialog\"\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=\"header-title\" id=\"${escapeHtml(titleId)}\" part=\"title\">\r\n              ${escapeHtml(props.title)}\r\n            </h2>\r\n            ${props.dismissible\r\n              ? `<button class=\"close-btn\" type=\"button\" aria-label=\"${t('dialog.close')}\" part=\"close\">&#10005;</button>`\r\n              : ''}\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<BqDialogProps, BqDialogState>('bq-dialog', definition);\r\n"],"mappings":";;;;;;;AA+BA,IAAM,kBAAkB;AAwKxB,2BAAA,EAAwC,aAAa;CArKnD,OAAO;EACL,MAAM;GAAE,MAAM;GAAS,SAAS;GAAO;EACvC,OAAO;GAAE,MAAM;GAAQ,SAAS;GAAI;EACpC,MAAM;GAAE,MAAM;GAAQ,SAAS;GAAM;EACrC,aAAa;GAAE,MAAM;GAAS,SAAS;GAAM;EAC9C;CACD,OAAO,EACL,SAAS,IACV;CACD,QAAQ;MACJ,eAAA,eAAe,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCpB,YAAY;EAKV,MAAM,OAAO;EACb,MAAM,SAAS;AACf,MAAI,CAAC,KAAK,SAAiB,UAAU,CACnC,MAAK,SAAS,WAAW,YAAA,SAAS,eAAe,CAAC;EAEpD,MAAM,MAAM,MAAa;AACvB,OAAK,EAAoB,QAAQ,YAAY,KAAK,aAAa,OAAO,CACpE,QAAO;;EAGX,MAAM,MAAM,MAAa;AACvB,OAAK,EAAE,OAAmB,UAAU,SAAS,UAAU,CAAE,QAAO;;EAElE,MAAM,cAAc;AAClB,OAAI,KAAK,aAAa,eAAe,CAAE;GACvC,MAAM,wBAAwB;IAC5B,MAAM,aAAa,OAAO;AAG1B,QAAI,YAAY;AACd,kBAAa,WAAW;AACxB,YAAO,OAAO;;;GAGlB,MAAM,gBAAgB,KAAK,cAAc,aAAa,aACpD,mCACD,EAAE;GACH,MAAM,iBAAiB;AACrB,qBAAiB;AACjB,SAAK,gBAAgB,eAAe;AACpC,SAAK,gBAAgB,OAAO;AAC5B,SAAK,cACH,IAAI,YAAY,YAAY;KAAE,SAAS;KAAM,UAAU;KAAM,CAAC,CAC/D;;AAEH,OAAI,cACF,WAAU;QACL;AACL,SAAK,aAAa,gBAAgB,GAAG;IACrC,MAAM,UAAU,KAAK,YAAY,cAAc,WAAW;IAC1D,MAAM,YAAY,UACd,YAAA,sBAAsB,SAAS,gBAAgB,GAC/C;AACJ,QAAI,aAAa,EACf,WAAU;QAEV,QAAO,iBAAiB,WAAW,UAAU,KAAK,KAAK,UAAU,GAAG,GAAG;;;EAI7E,MAAM,MAAM,MAAa;AACvB,OAAK,EAAE,OAAmB,QAAQ,aAAa,CAAE,QAAO;;AAEzD,OAA4C,SAAS;AACrD,OAA4C,SAAS;AACrD,OAA4C,SAAS;AACtD,WAAS,iBAAiB,WAAW,GAAG;AACxC,OAAK,YAAY,iBAAiB,SAAS,GAAG;AAC9C,OAAK,YAAY,iBAAiB,SAAS,GAAG;;CAEhD,eAAe;EACb,MAAM,IAAI;AACV,cAAA,oBAAoB,EAAkC;EACtD,MAAM,KAAK,EAAE;AACb,MAAI,GAAI,UAAS,oBAAoB,WAAW,GAAG;EACnD,MAAM,KAAK,EAAE;AACb,MAAI,GAAI,MAAK,YAAY,oBAAoB,SAAS,GAAG;EACzD,MAAM,KAAK,EAAE;AACb,MAAI,GAAI,MAAK,YAAY,oBAAoB,SAAS,GAAG;EACzD,MAAM,aAAa,EAAE;AACrB,MAAI,YAAY;AACd,gBAAa,WAAW;AACxB,UAAO,EAAE;AACT,QAAK,gBAAgB,eAAe;AACpC,QAAK,gBAAgB,OAAO;;;CAGhC,UAAU;AACR,cAAA,mBAAmB,MAAM,MAAsC,UAAU;;CAE3E,OAAO,EAAE,OAAO,SAAS;EACvB,MAAM,UAAU,MAAM,WAAW;AACjC,SAAO,2BAAA,CAAI;;;;;uBAKQ,2BAAA,GAAW,MAAM,KAAK,CAAC;;;6BAGjB,2BAAA,GAAW,QAAQ,CAAC;;;;2CAIN,2BAAA,GAAW,QAAQ,CAAC;gBAC/C,2BAAA,GAAW,MAAM,MAAM,CAAC;;cAE1B,MAAM,cACJ,uDAAuD,aAAA,EAAE,eAAe,CAAC,oCACzE,GAAG;;;;;;;;CAUkC,CAAW"}