{"version":3,"file":"tab-panel.cjs","names":[],"sources":["../src/disclosure/tab-panel/tab-panel.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, onMounted, prop, ref, styleMap, watchEffect, when } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport { setAriaReflection } from '../../core';\nimport { reducedMotionMixin } from '../../styles';\nimport { TABS_CTX } from '../tabs/tabs';\nimport styles from './tab-panel.css?inline';\n\nconst TAB_PANEL_PADDING_PRESET: Record<string, string> = {\n  '2xl': 'var(--size-12)',\n  lg: 'var(--size-6)',\n  md: 'var(--size-4)',\n  none: '0',\n  sm: 'var(--size-2)',\n  xl: 'var(--size-8)',\n  xs: 'var(--size-1)',\n};\n\nexport type OreTabPanelProps = {\n  /** Active state (managed by ore-tabs) */\n  active?: boolean;\n  /** When true, the panel content is not rendered until first activation (preserves resources) */\n  lazy?: boolean;\n  /** Panel padding size: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' (default: 'md' = var(--size-4)) */\n  padding?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n  /** Must match the `value` of its corresponding ore-tab-item */\n  value: string;\n};\n\n/**\n * Content panel for a tab. Shown when its `value` matches the selected tab.\n *\n * @element ore-tab-panel\n *\n * @attr {string} value - Must match the corresponding ore-tab-item value\n * @attr {boolean} active - Toggled by the parent ore-tabs\n * @attr {string} padding - Panel padding: 'none' | 'xs' | 'sm' | 'md' (default) | 'lg' | 'xl' | '2xl'\n *\n * @slot - Panel content\n *\n * @cssprop --tab-panel-padding - Inner padding of the panel content area\n * @cssprop --tab-panel-font-size - Font size of the panel content\n * @part panel - Panel container.\n * @example\n * ```html\n * <ore-tab-panel value=\"overview\"><p>Overview content here</p></ore-tab-panel>\n * <ore-tab-panel value=\"settings\" padding=\"lg\"><p>Large padding</p></ore-tab-panel>\n * <ore-tab-panel value=\"code\" padding=\"none\"><pre>No padding for code</pre></ore-tab-panel>\n * ```\n */\nexport const TAB_PANEL_TAG = 'ore-tab-panel' as const;\ndefine<OreTabPanelProps>(TAB_PANEL_TAG, {\n  props: {\n    active: prop.bool(false),\n    lazy: prop.bool(false),\n    padding: prop.oneOf(['none', 'xs', 'sm', 'md', 'lg', 'xl', '2xl'] as const, 'md'),\n    value: prop.string(''),\n  },\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    const tabsCtx = inject(TABS_CTX);\n    const isActive = computed(() =>\n      tabsCtx ? !!tabsCtx.value.value && tabsCtx.value.value === props.value.value : props.active.value,\n    );\n\n    bind({\n      attr: {\n        active: () => (isActive.value ? true : undefined),\n      },\n    });\n\n    // Map padding prop to CSS variable\n    const paddingValue = computed(() => {\n      const key = props.padding.value ?? 'md';\n\n      return TAB_PANEL_PADDING_PRESET[key] ?? TAB_PANEL_PADDING_PRESET.md;\n    });\n    // Track whether the panel has ever been active (for lazy rendering)\n    const hasBeenActive = signal(false);\n\n    watch(() => {\n      if (isActive.value) hasBeenActive.value = true;\n    });\n\n    // shouldRender: true if not lazy OR has been active at least once\n    const shouldRender = computed(() => !props.lazy.value || hasBeenActive.value);\n    const panelStyle = styleMap({ '--tab-panel-padding': paddingValue });\n    const panelId = () => `tabpanel-${props.value.value}`;\n    const panelRef = ref<HTMLElement>();\n\n    // `aria-labelledby` as a plain IDREF attribute cannot resolve across shadow-tree boundaries\n    // (the matching `id` lives inside <ore-tab-item>'s own shadow root) — see\n    // `setAriaReflection()`'s doc comment. Deferred to `onMounted()`: sibling custom elements\n    // (including the peer `<ore-tab-item>`) connect in tree order within the same synchronous\n    // insertion, so a sibling's shadow content may not exist yet during this element's own\n    // `setup()` — `onMounted()`'s microtask runs after the whole subtree has connected.\n    onMounted(() => {\n      watch(() => {\n        const panel = panelRef.value;\n        const value = props.value.value;\n\n        if (!panel) return;\n\n        const tabsEl = value ? el.closest('ore-tabs') : null;\n        const tabEl = tabsEl?.querySelector<HTMLElement>(`:scope > ore-tab-item[value=\"${value}\"]`);\n        const button = tabEl?.shadowRoot?.querySelector<HTMLElement>('[role=\"tab\"]') ?? null;\n\n        setAriaReflection(panel, 'ariaLabelledByElements', button ? [button] : []);\n      });\n    });\n\n    return html`\n      <div\n        class=\"panel\"\n        part=\"panel\"\n        role=\"tabpanel\"\n        ref=\"${panelRef}\"\n        id=\"${panelId}\"\n        aria-hidden=\"${() => String(!isActive.value)}\"\n        style=\"${panelStyle}\"\n        tabindex=\"0\">\n        ${when(\n          shouldRender,\n          () => html`\n            <slot></slot>\n          `,\n        )}\n      </div>\n    `;\n  },\n  styles: [reducedMotionMixin, styles],\n});\n"],"mappings":"+SAQA,IAAM,EAAmD,CACvD,MAAO,iBACP,GAAI,gBACJ,GAAI,gBACJ,KAAM,IACN,GAAI,gBACJ,GAAI,gBACJ,GAAI,eACN,EAkCa,EAAgB,iBAC7B,EAAA,EAAA,OAAA,CAAyB,EAAe,CACtC,MAAO,CACL,OAAQ,EAAA,KAAK,KAAK,EAAK,EACvB,KAAM,EAAA,KAAK,KAAK,EAAK,EACrB,QAAS,EAAA,KAAK,MAAM,CAAC,OAAQ,KAAM,KAAM,KAAM,KAAM,KAAM,KAAK,EAAY,IAAI,EAChF,MAAO,EAAA,KAAK,OAAO,EAAE,CACvB,EACA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,EAAQ,EAAA,YAER,GAAA,EAAU,EAAA,OAAA,CAAO,EAAA,QAAQ,EACzB,GAAA,EAAW,EAAA,SAAA,KACf,EAAU,CAAC,CAAC,EAAQ,MAAM,OAAS,EAAQ,MAAM,QAAU,EAAM,MAAM,MAAQ,EAAM,OAAO,KAC9F,GAEA,EAAA,EAAA,KAAA,CAAK,CACH,KAAM,CACJ,WAAe,EAAS,MAAQ,GAAO,IAAA,EACzC,CACF,CAAC,EAGD,IAAM,GAAA,EAAe,EAAA,SAAA,KAGZ,EAFK,EAAM,QAAQ,OAAS,OAEK,EAAyB,EAClE,EAEK,GAAA,EAAgB,EAAA,OAAA,CAAO,EAAK,EAElC,MAAY,CACN,EAAS,QAAO,EAAc,MAAQ,GAC5C,CAAC,EAGD,IAAM,GAAA,EAAe,EAAA,SAAA,KAAe,CAAC,EAAM,KAAK,OAAS,EAAc,KAAK,EACtE,GAAA,EAAa,EAAA,SAAA,CAAS,CAAE,sBAAuB,CAAa,CAAC,EAC7D,MAAgB,YAAY,EAAM,MAAM,QACxC,GAAA,EAAW,EAAA,IAAA,CAAiB,EAuBlC,OAfA,EAAA,EAAA,UAAA,KAAgB,CACd,MAAY,CACV,IAAM,EAAQ,EAAS,MACjB,EAAQ,EAAM,MAAM,MAE1B,GAAI,CAAC,EAAO,OAIZ,IAAM,IAFS,EAAQ,EAAG,QAAQ,UAAU,EAAI,KAAA,EAC1B,cAA2B,gCAAgC,EAAM,GAAG,EAAA,EACpE,YAAY,cAA2B,cAAc,GAAK,KAEhF,EAAA,kBAAkB,EAAO,yBAA0B,EAAS,CAAC,CAAM,EAAI,CAAC,CAAC,CAC3E,CAAC,CACH,CAAC,EAEM,EAAA,IAAI;;;;;eAKA,EAAS;cACV,EAAQ;2BACO,OAAO,CAAC,EAAS,KAAK,EAAE;iBACpC,EAAW;;WAElB,EAAA,EAAA,KAAA,CACA,MACM,EAAA,IAAI;;WAGZ,EAAE;;KAGR,EACA,OAAQ,CAAC,EAAA,mBAAoB,EAAA,OAAM,CACrC,CAAC"}