{"version":3,"file":"alert.cjs","names":[],"sources":["../src/feedback/alert/alert.ts"],"sourcesContent":["import { define, getHost, html, prop, useEmit, useSlots } from '@vielzeug/ore';\n\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\n\nimport '../../content/icon/icon';\nimport { awaitExit } from '../../overlay/shared/await-exit';\nimport { roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  forcedColorsMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport componentStyles from './alert.css?inline';\n\nexport type OreAlertEvents = {\n  dismiss: { originalEvent: MouseEvent };\n};\n\nexport type OreAlertProps = {\n  /** Show a left accent border (for flat/bordered variants) */\n  accented?: boolean;\n  /** Theme color */\n  color?: ThemeColor;\n  /** Show a dismissible (×) button */\n  dismissible?: boolean;\n  /** Heading text shown above the content */\n  heading?: string;\n  /** Position action buttons to the right instead of below */\n  horizontal?: boolean;\n  /** Border radius */\n  rounded?: RoundedSize | '';\n  /** Alert size */\n  size?: ComponentSize;\n  /** Visual style variant */\n  variant?: 'solid' | 'flat' | 'bordered';\n};\n\n/**\n * A status/feedback banner with optional heading, icon slot, and dismiss button.\n *\n * @element ore-alert\n *\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual style: 'flat' | 'solid' | 'bordered'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} heading - Bold heading text above the content\n * @attr {boolean} dismissible - Show a close (×) button\n * @attr {boolean} accented - Add a left accent border (flat/bordered only)\n * @attr {boolean} horizontal - Position action buttons to the right instead of below\n *\n * @fires dismiss - Fired when the alert is dismissed. detail: { originalEvent: MouseEvent }\n *\n * @slot - Default slot for the alert message content\n * @slot icon - Icon on the left side\n * @slot meta - Metadata displayed alongside the heading (lighter, right-aligned)\n * @slot actions - Action buttons shown below the message\n *\n * @cssprop --alert-bg - Background color\n * @cssprop --alert-color - Text/icon color\n * @cssprop --alert-border-color - Border color\n * @cssprop --alert-shadow - Box shadow\n * @cssprop --alert-radius - Border radius\n * @cssprop --alert-padding - Padding\n * @cssprop --alert-gap - Gap between icon, body, and close button\n * @cssprop --alert-font-size - Font size\n *\n * @part alert - Alert root container.\n * @part icon - Icon container.\n * @part header - Header container.\n * @part heading - Heading text element.\n * @part meta - Meta text container.\n * @part body - Body content container.\n * @part content - Content container.\n * @part actions - Actions slot container.\n * @part close - Close action control.\n * @example\n * ```html\n * <ore-alert color=\"success\">Your changes have been saved.</ore-alert>\n * <ore-alert color=\"error\" variant=\"solid\" dismissible heading=\"Something went wrong\">\n *   Please try again later.\n * </ore-alert>\n * ```\n */\nexport const ALERT_TAG = 'ore-alert' as const;\ndefine<OreAlertProps>(ALERT_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...roundableBundle,\n    accented: prop.bool(false),\n    dismissible: prop.bool(false),\n    heading: prop.string(),\n    horizontal: prop.bool(false),\n    variant: prop.string<'solid' | 'flat' | 'bordered'>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreAlertEvents>();\n    const slots = useSlots();\n\n    let announceEl: HTMLElement | null = null;\n\n    const announce = (message: string) => {\n      if (!announceEl) return;\n\n      announceEl.textContent = '';\n      requestAnimationFrame(() => {\n        if (announceEl) announceEl.textContent = message;\n      });\n    };\n\n    const handleDismiss = (e: MouseEvent) => {\n      if (!props.dismissible.value) return;\n\n      el.setAttribute('dismissing', '');\n      awaitExit(el, () => {\n        el.removeAttribute('dismissing');\n        el.setAttribute('dismissed', '');\n        announce('Alert dismissed');\n        emit('dismiss', { originalEvent: e });\n      });\n    };\n\n    const alertRole = () => (props.color.value === 'error' ? 'alert' : 'status');\n\n    return html`\n      <span\n        class=\"sr-announce\"\n        aria-live=\"polite\"\n        aria-atomic=\"true\"\n        ref=\"${(ref: HTMLElement) => {\n          announceEl = ref;\n        }}\"></span>\n      <div class=\"alert\" role=\"${alertRole}\" part=\"alert\">\n        <span class=\"icon\" part=\"icon\" aria-hidden=\"true\" ?hidden=\"${() => !slots.has('icon').value}\">\n          <slot name=\"icon\"></slot>\n        </span>\n        <div class=\"header\" part=\"header\" ?hidden=\"${() => !props.heading.value}\">\n          <span class=\"heading\" part=\"heading\">${props.heading}</span>\n          <span class=\"meta\" part=\"meta\">\n            <slot name=\"meta\"></slot>\n          </span>\n        </div>\n        <div class=\"body\" part=\"body\">\n          <div class=\"content\" part=\"content\">\n            <slot></slot>\n          </div>\n        </div>\n        <div class=\"actions\" part=\"actions\" ?hidden=\"${() => !slots.has('actions').value}\">\n          <slot name=\"actions\"></slot>\n        </div>\n        <button\n          class=\"close\"\n          part=\"close\"\n          type=\"button\"\n          aria-label=\"Dismiss alert\"\n          ?hidden=\"${() => !props.dismissible.value}\"\n          @click=\"${handleDismiss}\">\n          <ore-icon name=\"x\" size=\"16\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n        </button>\n      </div>\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    coarsePointerMixin,\n    reducedMotionMixin,\n    roundedVariantMixin,\n    forcedColorsMixin,\n    sizeVariantMixin({\n      lg: { '--_padding': 'var(--size-4) var(--size-5)', fontSize: 'var(--text-base)', gap: 'var(--size-3-5)' },\n      sm: { '--_padding': 'var(--size-2) var(--size-3)', fontSize: 'var(--text-xs)', gap: 'var(--size-2)' },\n    }),\n    componentStyles,\n  ],\n});\n"],"mappings":"iXAuFA,IAAa,EAAY,aACzB,EAAA,EAAA,OAAA,CAAsB,EAAW,CAC/B,MAAO,CACL,GAAG,EAAA,eACH,GAAG,EAAA,cACH,GAAG,EAAA,gBACH,SAAU,EAAA,KAAK,KAAK,EAAK,EACzB,YAAa,EAAA,KAAK,KAAK,EAAK,EAC5B,QAAS,EAAA,KAAK,OAAO,EACrB,WAAY,EAAA,KAAK,KAAK,EAAK,EAC3B,QAAS,EAAA,KAAK,OAAsC,CACtD,EACA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,GAAA,EAAO,EAAA,QAAA,CAAwB,EAC/B,GAAA,EAAQ,EAAA,SAAA,CAAS,EAEnB,EAAiC,KAE/B,EAAY,GAAoB,CAC/B,IAEL,EAAW,YAAc,GACzB,0BAA4B,CACtB,IAAY,EAAW,YAAc,EAC3C,CAAC,EACH,EAgBA,MAAO,GAAA,IAAI;;;;;eAKC,GAAqB,CAC3B,EAAa,CACf,EAAE;qCATmB,EAAM,MAAM,QAAU,QAAU,QAAU,SAU5B;yEACgC,CAAC,EAAM,IAAI,MAAM,CAAC,CAAC,MAAM;;;yDAGzC,CAAC,EAAM,QAAQ,MAAM;iDAC/B,EAAM,QAAQ;;;;;;;;;;2DAUF,CAAC,EAAM,IAAI,SAAS,CAAC,CAAC,MAAM;;;;;;;;yBAQ9D,CAAC,EAAM,YAAY,MAAM;oBA7CzB,GAAkB,CAClC,EAAM,YAAY,QAEvB,EAAG,aAAa,aAAc,EAAE,EAChC,EAAA,UAAU,MAAU,CAClB,EAAG,gBAAgB,YAAY,EAC/B,EAAG,aAAa,YAAa,EAAE,EAC/B,EAAS,iBAAiB,EAC1B,EAAK,UAAW,CAAE,cAAe,CAAE,CAAC,CACtC,CAAC,EACH,EAoC8B;;;;KAKhC,EACA,OAAQ,CACN,EAAA,gBACA,EAAA,mBACA,EAAA,mBACA,EAAA,oBACA,EAAA,kBACA,EAAA,iBAAiB,CACf,GAAI,CAAE,aAAc,8BAA+B,SAAU,mBAAoB,IAAK,iBAAkB,EACxG,GAAI,CAAE,aAAc,8BAA+B,SAAU,iBAAkB,IAAK,eAAgB,CACtG,CAAC,EACD,EAAA,OACF,CACF,CAAC"}