{"version":3,"file":"card.cjs","names":[],"sources":["../src/content/card/card.ts"],"sourcesContent":["import { bind, define, getHost, html, prop, useEmit, useSlots, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { createInteraction } from '../../core';\nimport { disablableBundle, loadableBundle, themableBundle } from '../../shared';\nimport {\n  colorThemeMixin,\n  elevationMixin,\n  frostVariantMixin,\n  paddingMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n} from '../../styles';\nimport type { ElevationLevel, PaddingSize, ThemeColor } from '../../types';\nimport componentStyles from './card.css?inline';\n\nconst INTERACTIVE_DESCENDANT_SELECTOR =\n  'button, a[href], input, select, textarea, summary, [role=\"button\"], [role=\"link\"], [contenteditable=\"\"], [contenteditable=\"true\"]';\n\nfunction isNestedInteractiveTarget(host: HTMLElement, event: Event): boolean {\n  for (const node of event.composedPath()) {\n    if (!(node instanceof HTMLElement)) continue;\n\n    if (node === host) return false;\n\n    if (node.matches(INTERACTIVE_DESCENDANT_SELECTOR) || node.closest(INTERACTIVE_DESCENDANT_SELECTOR)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n/** Card component properties */\n\nexport type OreCardEvents = {\n  activate: { originalEvent: MouseEvent | KeyboardEvent; trigger: 'pointer' | 'keyboard' };\n};\n\nexport type OreCardProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Shadow elevation level (0-5) */\n  elevation?: ElevationLevel;\n  /** Make the card interactive (role=button, keyboard nav, emits activate) */\n  interactive?: boolean;\n  /** Show a loading progress bar */\n  loading?: boolean;\n  /** Card orientation */\n  orientation?: 'horizontal';\n  /** Internal padding size */\n  padding?: PaddingSize;\n  /** Visual style variant */\n  variant?: 'solid' | 'flat' | 'glass' | 'frost';\n};\n\n/**\n * A versatile card container with semantic slots for media, header, body, footer, and actions.\n *\n * @element ore-card\n *\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'glass' | 'frost'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} padding - Internal padding: 'none' | 'sm' | 'md' | 'lg' | 'xl'\n * @attr {string} elevation - Shadow elevation: '0' | '1' | '2' | '3' | '4' | '5'\n * @attr {string} orientation - Card layout: 'horizontal'\n * @attr {boolean} interactive - Enable pointer/keyboard activation\n * @attr {boolean} disabled - Disable card interaction\n * @attr {boolean} loading - Show loading progress bar\n *\n * @fires activate - Emitted when an interactive card is activated. detail: { originalEvent: MouseEvent | KeyboardEvent; trigger: 'pointer' | 'keyboard' }\n *\n * @slot media - Media content displayed at top/left\n * @slot header - Card header (title, subtitle)\n * @slot - Main card content\n * @slot footer - Card footer content\n * @slot actions - Action buttons or links\n *\n * @cssprop --card-bg - Background color\n * @cssprop --card-color - Text color\n * @cssprop --card-border - Border width\n * @cssprop --card-border-color - Border color\n * @cssprop --card-radius - Border radius\n * @cssprop --card-padding - Internal padding\n * @cssprop --card-shadow - Box shadow\n * @cssprop --card-hover-shadow - Shadow on hover\n *\n * @part card - Card root container.\n * @part loading-bar - Loading progress bar.\n * @part media - Media slot container.\n * @part body - Body content container.\n * @part header - Header container.\n * @part content - Content container.\n * @part footer - Footer container.\n * @part actions - Actions slot container.\n * @example\n * ```html\n * <ore-card elevation=\"2\"><h3 slot=\"header\">Title</h3><p>Content</p></ore-card>\n * <ore-card interactive color=\"primary\"><h3 slot=\"header\">Click me</h3></ore-card>\n * <ore-card variant=\"frost\" color=\"secondary\">Frosted card</ore-card>\n * ```\n */\nexport const CARD_TAG = 'ore-card' as const;\ndefine<OreCardProps>(CARD_TAG, {\n  props: {\n    ...themableBundle,\n    ...disablableBundle,\n    ...loadableBundle,\n    elevation: prop.number<ElevationLevel>(),\n    interactive: prop.bool(false),\n    orientation: prop.string<'horizontal'>(),\n    padding: prop.string<PaddingSize>(),\n    variant: prop.string<'solid' | 'flat' | 'glass' | 'frost'>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreCardEvents>();\n    const slots = useSlots();\n    const watch = watchEffect;\n\n    bind({\n      attr: {\n        ariaBusy: () => (props.loading.value ? 'true' : 'false'),\n        ariaDisabled: () => (props.interactive.value ? String(props.disabled.value) : null),\n        role: () => (props.interactive.value ? 'button' : null),\n      },\n    });\n\n    watch(() => {\n      if (props.interactive.value) {\n        el.setAttribute('tabindex', props.disabled.value ? '-1' : '0');\n      } else {\n        el.removeAttribute('tabindex');\n      }\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Event Handlers\n    // ────────────────────────────────────────────────────────────────\n\n    const pressControl = createInteraction({\n      disabled: computed(() => !props.interactive.value || Boolean(props.disabled.value)),\n      onPress: (originalEvent, trigger) => {\n        emit('activate', { originalEvent, trigger });\n      },\n    });\n\n    const handleClick = (e: MouseEvent) => {\n      if (!props.interactive.value || props.disabled.value) return;\n\n      if (isNestedInteractiveTarget(el, e)) return;\n\n      pressControl.handleClick(e);\n    };\n\n    const handleKeydown = (e: KeyboardEvent) => {\n      pressControl.handleKeydown(e);\n    };\n\n    bind({\n      on: {\n        click: (e: MouseEvent) => handleClick(e),\n        keydown: (e: KeyboardEvent) => handleKeydown(e),\n      },\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Template\n    // ────────────────────────────────────────────────────────────────\n\n    return html`\n      <div class=\"card\" part=\"card\">\n        <div class=\"loading-bar\" part=\"loading-bar\"></div>\n        <div class=\"card-media\" part=\"media\" ?hidden=\"${() => !slots.has('media').value}\">\n          <slot name=\"media\"></slot>\n        </div>\n        <div class=\"card-body\" part=\"body\">\n          <div class=\"card-header\" part=\"header\" ?hidden=\"${() => !slots.has('header').value}\">\n            <slot name=\"header\"></slot>\n          </div>\n          <div class=\"card-content\" part=\"content\" ?hidden=\"${() => !slots.has().value}\">\n            <slot></slot>\n          </div>\n          <div class=\"card-footer\" part=\"footer\" ?hidden=\"${() => !slots.has('footer').value}\">\n            <slot name=\"footer\"></slot>\n          </div>\n          <div class=\"card-actions\" part=\"actions\" ?hidden=\"${() => !slots.has('actions').value}\">\n            <slot name=\"actions\"></slot>\n          </div>\n        </div>\n      </div>\n    `;\n  },\n\n  styles: [\n    colorThemeMixin,\n    elevationMixin,\n    paddingMixin,\n    roundedVariantMixin,\n    frostVariantMixin('.card'),\n    reducedMotionMixin,\n    componentStyles,\n  ],\n});\n"],"mappings":"8aAeA,IAAM,EACJ,oIAEF,SAAS,EAA0B,EAAmB,EAAuB,CAC3E,IAAK,IAAM,KAAQ,EAAM,aAAa,EAC9B,gBAAgB,YAEtB,IAAI,IAAS,EAAM,MAAO,GAE1B,GAAI,EAAK,QAAQ,CAA+B,GAAK,EAAK,QAAQ,CAA+B,EAC/F,MAAO,EAHiB,CAO5B,MAAO,EACT,CAyEA,IAAa,EAAW,YACxB,EAAA,EAAA,OAAA,CAAqB,EAAU,CAC7B,MAAO,CACL,GAAG,EAAA,eACH,GAAG,EAAA,iBACH,GAAG,EAAA,eACH,UAAW,EAAA,KAAK,OAAuB,EACvC,YAAa,EAAA,KAAK,KAAK,EAAK,EAC5B,YAAa,EAAA,KAAK,OAAqB,EACvC,QAAS,EAAA,KAAK,OAAoB,EAClC,QAAS,EAAA,KAAK,OAA6C,CAC7D,EAEA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,GAAA,EAAO,EAAA,QAAA,CAAuB,EAC9B,GAAA,EAAQ,EAAA,SAAA,CAAS,EACjB,EAAQ,EAAA,aAEd,EAAA,EAAA,KAAA,CAAK,CACH,KAAM,CACJ,aAAiB,EAAM,QAAQ,MAAQ,OAAS,QAChD,iBAAqB,EAAM,YAAY,MAAQ,OAAO,EAAM,SAAS,KAAK,EAAI,KAC9E,SAAa,EAAM,YAAY,MAAQ,SAAW,IACpD,CACF,CAAC,EAED,MAAY,CACN,EAAM,YAAY,MACpB,EAAG,aAAa,WAAY,EAAM,SAAS,MAAQ,KAAO,GAAG,EAE7D,EAAG,gBAAgB,UAAU,CAEjC,CAAC,EAMD,IAAM,EAAe,EAAA,kBAAkB,CACrC,UAAA,EAAU,EAAA,SAAA,KAAe,CAAC,EAAM,YAAY,OAAS,EAAQ,EAAM,SAAS,KAAM,EAClF,SAAU,EAAe,IAAY,CACnC,EAAK,WAAY,CAAE,gBAAe,SAAQ,CAAC,CAC7C,CACF,CAAC,EAEK,EAAe,GAAkB,CACjC,CAAC,EAAM,YAAY,OAAS,EAAM,SAAS,OAE3C,EAA0B,EAAI,CAAC,GAEnC,EAAa,YAAY,CAAC,CAC5B,EAEM,EAAiB,GAAqB,CAC1C,EAAa,cAAc,CAAC,CAC9B,EAaA,OAXA,EAAA,EAAA,KAAA,CAAK,CACH,GAAI,CACF,MAAQ,GAAkB,EAAY,CAAC,EACvC,QAAU,GAAqB,EAAc,CAAC,CAChD,CACF,CAAC,EAMM,EAAA,IAAI;;;4DAG+C,CAAC,EAAM,IAAI,OAAO,CAAC,CAAC,MAAM;;;;gEAItB,CAAC,EAAM,IAAI,QAAQ,CAAC,CAAC,MAAM;;;kEAGzB,CAAC,EAAM,IAAI,CAAC,CAAC,MAAM;;;gEAGrB,CAAC,EAAM,IAAI,QAAQ,CAAC,CAAC,MAAM;;;kEAGzB,CAAC,EAAM,IAAI,SAAS,CAAC,CAAC,MAAM;;;;;KAM9F,EAEA,OAAQ,CACN,EAAA,gBACA,EAAA,eACA,EAAA,aACA,EAAA,oBACA,EAAA,kBAAkB,OAAO,EACzB,EAAA,mBACA,EAAA,OACF,CACF,CAAC"}