import { html, nothing } from 'lit'; import { property } from 'lit/decorators.js'; import { BootstrapElement, defineElement } from '@bootstrap-wc/core'; /** * `` — single slide inside ``. Host carries * `.carousel-item` (+ `.active` and the transient `.carousel-item-next`, * `.carousel-item-prev`, `.carousel-item-start`, `.carousel-item-end` * classes during animation) so Bootstrap's transform / opacity selectors * match across the slot boundary. * * @slot - Slide content. Pass an `` (or freeform * layout) and optionally a `` at the end matching Bootstrap's structure. * If you slot anything into the optional `caption` slot, it is * wrapped in a default `.carousel-caption d-none d-md-block` div for * convenience. * @slot caption - Optional caption shorthand: wraps the slot content in * `.carousel-caption d-none d-md-block` automatically. */ export class BsCarouselItem extends BootstrapElement { @property({ type: Boolean, reflect: true }) active = false; /** Internal: applied by parent carousel during animation. */ @property({ type: String, attribute: 'transition-state', reflect: true }) transitionState: '' | 'next' | 'prev' | 'start' | 'end' | 'next-start' | 'prev-end' = ''; protected override hostClasses(): string { const parts = ['carousel-item']; if (this.active) parts.push('active'); switch (this.transitionState) { case 'next': parts.push('carousel-item-next'); break; case 'prev': parts.push('carousel-item-prev'); break; case 'next-start': parts.push('carousel-item-next', 'carousel-item-start'); break; case 'prev-end': parts.push('carousel-item-prev', 'carousel-item-end'); break; case 'start': parts.push('carousel-item-start'); break; case 'end': parts.push('carousel-item-end'); break; } return parts.join(' '); } override render() { const hasCaption = !!this.querySelector('[slot="caption"]'); return html`${hasCaption ? html`` : nothing}`; } } defineElement('bs-carousel-item', BsCarouselItem); declare global { interface HTMLElementTagNameMap { 'bs-carousel-item': BsCarouselItem; } }