{"version":3,"file":"accordion.cjs","names":[],"sources":["../src/disclosure/accordion/accordion.ts"],"sourcesContent":["import { bind, createContext, define, getHost, html, onCleanup, prop, provide, useEmit } from '@vielzeug/ore';\nimport { computed, type Readable } from '@vielzeug/ripple';\nimport { createListControl, lifecycleSignal } from '../../core';\nimport type { ComponentSize, SurfaceVariant } from '../../types';\nimport styles from './accordion.css?inline';\n\n/** Context provided by ore-accordion to its ore-accordion-item children. */\nexport type AccordionContext = {\n  selectionMode: Readable<'single' | 'multiple' | undefined>;\n  size: Readable<ComponentSize | undefined>;\n  variant: Readable<SurfaceVariant | undefined>;\n};\n/** Injection key for the accordion context. */\nexport const ACCORDION_CTX = createContext<AccordionContext>('AccordionContext');\n\n/** Accordion component properties */\n\nexport type OreAccordionEvents = {\n  change: { expandedItem: HTMLElement };\n};\n\nexport type OreAccordionProps = {\n  /** Selection mode (single = only one opens, multiple = multiple can be open) */\n  selectionMode?: 'single' | 'multiple';\n  /** Size for all items (propagated via context) */\n  size?: ComponentSize;\n  /** Visual variant for all items (propagated via context) */\n  variant?: SurfaceVariant;\n};\n\n/**\n * A container for accordion items with single or multiple selection modes.\n *\n * @element ore-accordion\n * @element ore-accordion-item - Child element for each collapsible panel\n *\n * @attr {string} selection-mode - Selection mode: 'single' | 'multiple'\n * @attr {string} size - Size for all items: 'sm' | 'md' | 'lg' (propagated to children)\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'text' | 'glass' | 'frost' (propagated to children)\n *\n * @fires expand - Emitted when an item expands. detail: { expanded: boolean; item: HTMLElement }\n * @fires change - Emitted when selection changes (single mode). detail: { expandedItem: HTMLElement }\n *\n * @slot - `ore-accordion-item` elements\n *\n * @cssprop --accordion-bg - Container background color (solid/flat/glass/frost variants)\n * @cssprop --accordion-border-color - Container border color (solid/flat variants)\n * @cssprop --accordion-divider-color - Divider color between items (text variant)\n * @cssprop --accordion-shadow - Container box shadow\n * @example\n * ```html\n * <ore-accordion selection-mode=\"single\">\n *   <ore-accordion-item>\n *     <span slot=\"title\">What is Refine?</span>\n *     <p>Refine is a headless web component library.</p>\n *   </ore-accordion-item>\n *   <ore-accordion-item>\n *     <span slot=\"title\">How do I install it?</span>\n *     <p>Run <code>npm install @vielzeug/refine</code>.</p>\n *   </ore-accordion-item>\n * </ore-accordion>\n * <ore-accordion variant=\"bordered\" selection-mode=\"multiple\">\n *   <ore-accordion-item expanded><span slot=\"title\">Open by default</span><p>Content</p></ore-accordion-item>\n * </ore-accordion>\n * ```\n */\n\nexport const ACCORDION_TAG = 'ore-accordion' as const;\ndefine<OreAccordionProps>(ACCORDION_TAG, {\n  props: {\n    selectionMode: prop.string<'single' | 'multiple'>(),\n    size: prop.string<ComponentSize>(),\n    variant: prop.string<SurfaceVariant>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreAccordionEvents>();\n\n    const handleSelectionMode = (expandedItem: HTMLElement) => {\n      if (props.selectionMode.value !== 'single') return;\n\n      el.querySelectorAll(':scope > ore-accordion-item[expanded]').forEach((item) => {\n        if (item !== expandedItem && item.hasAttribute('expanded')) {\n          item.removeAttribute('expanded');\n        }\n      });\n\n      emit('change', { expandedItem });\n    };\n\n    const getAccordionItems = () => {\n      return [...el.querySelectorAll<HTMLElement>(':scope > ore-accordion-item:not([disabled])')];\n    };\n\n    const getSummaryElements = () => {\n      return getAccordionItems()\n        .map((item) => item.shadowRoot?.querySelector<HTMLElement>('summary'))\n        .filter(Boolean) as HTMLElement[];\n    };\n\n    const listControl = createListControl({\n      getItems: () => getAccordionItems(),\n      loop: true,\n      onNavigate: ({ index }) => {\n        const summaries = getSummaryElements();\n\n        summaries[index]?.focus();\n      },\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    provide(ACCORDION_CTX, {\n      selectionMode: computed(() => props.selectionMode.value),\n      size: props.size,\n      variant: props.variant,\n    });\n\n    // Group-level event and keyboard handling for WAI-ARIA Accordion pattern\n\n    bind({\n      on: {\n        expand: (event: Event) => {\n          const eventTarget = event.composedPath().find((node): node is HTMLElement => node instanceof HTMLElement);\n          const expandedItem = (event as CustomEvent<{ item?: HTMLElement }>).detail?.item ?? eventTarget;\n\n          if (expandedItem?.localName !== 'ore-accordion-item') return;\n\n          // Guard: only respond to accordion-items that belong to THIS accordion instance\n          if (expandedItem.closest('ore-accordion') !== el) return;\n\n          handleSelectionMode(expandedItem);\n        },\n        keydown: (evt: KeyboardEvent) => {\n          const summaries = getSummaryElements();\n\n          if (!summaries.length) return;\n\n          const activeSummary = evt\n            .composedPath()\n            .find((node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'summary');\n          const focused = activeSummary ? summaries.indexOf(activeSummary) : -1;\n\n          if (focused === -1) return; // focus is not on a summary — let native handling proceed\n\n          listControl.set(focused);\n          listControl.handleKeydown(evt);\n        },\n      },\n    });\n\n    return html`\n      <slot></slot>\n    `;\n  },\n\n  styles: [styles],\n});\n"],"mappings":"oPAaA,IAAa,GAAA,EAAgB,EAAA,cAAA,CAAgC,kBAAkB,EAsDlE,EAAgB,iBAC7B,EAAA,EAAA,OAAA,CAA0B,EAAe,CACvC,MAAO,CACL,cAAe,EAAA,KAAK,OAA8B,EAClD,KAAM,EAAA,KAAK,OAAsB,EACjC,QAAS,EAAA,KAAK,OAAuB,CACvC,EAEA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,GAAA,EAAO,EAAA,QAAA,CAA4B,EAEnC,EAAuB,GAA8B,CACrD,EAAM,cAAc,QAAU,WAElC,EAAG,iBAAiB,uCAAuC,CAAC,CAAC,QAAS,GAAS,CACzE,IAAS,GAAgB,EAAK,aAAa,UAAU,GACvD,EAAK,gBAAgB,UAAU,CAEnC,CAAC,EAED,EAAK,SAAU,CAAE,cAAa,CAAC,EACjC,EAEM,MACG,CAAC,GAAG,EAAG,iBAA8B,6CAA6C,CAAC,EAGtF,MACG,EAAkB,CAAC,CACvB,IAAK,GAAS,EAAK,YAAY,cAA2B,SAAS,CAAC,CAAC,CACrE,OAAO,OAAO,EAGb,EAAc,EAAA,kBAAkB,CACpC,aAAgB,EAAkB,EAClC,KAAM,GACN,YAAa,CAAE,WAAY,CAGzB,EAAA,CAAA,CAAU,EAAM,EAAE,MAAM,CAC1B,EACA,OAAQ,EAAA,gBAAgB,EAAA,SAAS,CACnC,CAAC,EAyCD,OAvCA,EAAA,EAAA,QAAA,CAAQ,EAAe,CACrB,eAAA,EAAe,EAAA,SAAA,KAAe,EAAM,cAAc,KAAK,EACvD,KAAM,EAAM,KACZ,QAAS,EAAM,OACjB,CAAC,GAID,EAAA,EAAA,KAAA,CAAK,CACH,GAAI,CACF,OAAS,GAAiB,CACxB,IAAM,EAAc,EAAM,aAAa,CAAC,CAAC,KAAM,GAA8B,aAAgB,WAAW,EAClG,EAAgB,EAA8C,QAAQ,MAAQ,EAEhF,GAAc,YAAc,sBAG5B,EAAa,QAAQ,eAAe,IAAM,GAE9C,EAAoB,CAAY,CAClC,EACA,QAAU,GAAuB,CAC/B,IAAM,EAAY,EAAmB,EAErC,GAAI,CAAC,EAAU,OAAQ,OAEvB,IAAM,EAAgB,EACnB,aAAa,CAAC,CACd,KAAM,GAA8B,aAAgB,aAAe,EAAK,YAAc,SAAS,EAC5F,EAAU,EAAgB,EAAU,QAAQ,CAAa,EAAI,GAE/D,IAAY,KAEhB,EAAY,IAAI,CAAO,EACvB,EAAY,cAAc,CAAG,EAC/B,CACF,CACF,CAAC,EAEM,EAAA,IAAI;;KAGb,EAEA,OAAQ,CAAC,EAAA,OAAM,CACjB,CAAC"}