{"version":3,"file":"ngwr-carousel.mjs","sources":["../../../projects/lib/carousel/carousel-slide.ts","../../../projects/lib/carousel/carousel.ts","../../../projects/lib/carousel/carousel.html","../../../projects/lib/carousel/ngwr-carousel.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Component, ViewEncapsulation } from '@angular/core';\n\n/**\n * One slide in a {@link WrCarousel}. Holds whatever content you\n * project — image, card, video, anything.\n */\n@Component({\n  selector: 'wr-carousel-slide',\n  template: '<ng-content />',\n  encapsulation: ViewEncapsulation.None,\n  host: { class: 'wr-carousel-slide', role: 'group', 'aria-roledescription': 'slide' },\n})\nexport class WrCarouselSlide {}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n  Component,\n  DestroyRef,\n  ViewEncapsulation,\n  computed,\n  contentChildren,\n  effect,\n  inject,\n  input,\n  model,\n  signal,\n} from '@angular/core';\n\nimport { WrCarouselSlide } from './carousel-slide';\n\n/**\n * Slide carousel. Project `<wr-carousel-slide>` children — the carousel\n * snaps between them with prev/next buttons and optional dots / autoplay.\n *\n * @example\n * ```html\n * <wr-carousel [(active)]=\"i\" autoplay>\n *   <wr-carousel-slide><img src=\"a.jpg\" /></wr-carousel-slide>\n *   <wr-carousel-slide><img src=\"b.jpg\" /></wr-carousel-slide>\n *   <wr-carousel-slide><img src=\"c.jpg\" /></wr-carousel-slide>\n * </wr-carousel>\n * ```\n *\n * @see https://ngwr.dev/components/carousel\n */\n@Component({\n  selector: 'wr-carousel',\n  templateUrl: './carousel.html',\n  encapsulation: ViewEncapsulation.None,\n  host: { class: 'wr-carousel' },\n})\nexport class WrCarousel {\n  /** Active slide index. Two-way bindable. @default 0 */\n  readonly active = model(0);\n\n  /** Show prev / next arrow buttons. @default true */\n  readonly showArrows = input(true, { transform: coerceBooleanProperty });\n\n  /** Show dot indicators below the slides. @default true */\n  readonly showDots = input(true, { transform: coerceBooleanProperty });\n\n  /** Auto-advance slides. @default false */\n  readonly autoplay = input(false, { transform: coerceBooleanProperty });\n\n  /** Autoplay interval (ms). @default 4000 */\n  readonly intervalMs = input(4000, {\n    transform: (v: unknown): number => Math.max(500, coerceNumberProperty(v, 4000)),\n  });\n\n  /** Wrap around at the ends. @default true */\n  readonly loop = input(true, { transform: coerceBooleanProperty });\n\n  protected readonly slides = contentChildren(WrCarouselSlide);\n  protected readonly count = computed(() => this.slides().length);\n\n  /** Live horizontal drag offset (px) during a touch swipe. */\n  protected readonly dragX = signal(0);\n  protected readonly dragging = signal(false);\n\n  /** CSS transform for the track — the per-slide offset plus any live drag. */\n  protected readonly trackStyle = computed(() => {\n    const base = -this.active() * 100;\n    const drag = this.dragX();\n    return drag === 0 ? `translateX(${base}%)` : `translateX(calc(${base}% + ${drag}px))`;\n  });\n\n  private timer: ReturnType<typeof setInterval> | null = null;\n  private readonly paused = signal(false);\n  private readonly destroyRef = inject(DestroyRef);\n\n  constructor() {\n    effect(() => {\n      if (this.timer) clearInterval(this.timer);\n      this.timer = null;\n      if (!this.autoplay() || this.paused() || this.count() < 2) return;\n      const interval = this.intervalMs();\n      this.timer = setInterval(() => this.next(), interval);\n    });\n\n    this.destroyRef.onDestroy(() => {\n      if (this.timer) clearInterval(this.timer);\n    });\n  }\n\n  protected onMouseEnter(): void {\n    this.paused.set(true);\n  }\n\n  protected onMouseLeave(): void {\n    this.paused.set(false);\n  }\n\n  // Imperative\n\n  goTo(index: number): void {\n    const max = this.count() - 1;\n    if (max < 0) return;\n    if (this.loop()) {\n      const next = ((index % this.count()) + this.count()) % this.count();\n      this.active.set(next);\n    } else {\n      this.active.set(Math.min(Math.max(0, index), max));\n    }\n  }\n\n  next(): void {\n    this.goTo(this.active() + 1);\n  }\n\n  prev(): void {\n    this.goTo(this.active() - 1);\n  }\n\n  // Swipe navigation — the track follows the finger; releasing past ~20% of the\n  // viewport advances a slide (left = next, right = prev), otherwise snaps back.\n\n  private swipeStartX = 0;\n\n  protected onSwipeStart(event: TouchEvent): void {\n    const touch = event.touches[0];\n    if (!touch) return;\n    this.swipeStartX = touch.clientX;\n    this.dragging.set(true);\n    this.paused.set(true); // hold autoplay while dragging\n  }\n\n  protected onSwipeMove(event: TouchEvent): void {\n    if (!this.dragging()) return;\n    const touch = event.touches[0];\n    if (!touch) return;\n    this.dragX.set(touch.clientX - this.swipeStartX);\n  }\n\n  protected onSwipeEnd(event: TouchEvent, viewport: HTMLElement): void {\n    if (!this.dragging()) return;\n    this.dragging.set(false);\n    const dx = this.dragX();\n    this.dragX.set(0);\n    this.paused.set(false);\n    const threshold = (viewport.offsetWidth || 0) * 0.2;\n    if (dx <= -threshold) this.next();\n    else if (dx >= threshold) this.prev();\n  }\n}\n","<div\n  #viewport\n  class=\"wr-carousel__viewport\"\n  aria-roledescription=\"carousel\"\n  (mouseenter)=\"onMouseEnter()\"\n  (mouseleave)=\"onMouseLeave()\"\n  (touchstart)=\"onSwipeStart($event)\"\n  (touchmove)=\"onSwipeMove($event)\"\n  (touchend)=\"onSwipeEnd($event, viewport)\"\n  (touchcancel)=\"onSwipeEnd($event, viewport)\"\n>\n  <div class=\"wr-carousel__track\" [style.transform]=\"trackStyle()\" [style.transition]=\"dragging() ? 'none' : null\">\n    <ng-content />\n  </div>\n</div>\n\n@if (showArrows() && count() > 1) {\n  <button type=\"button\" class=\"wr-carousel__nav wr-carousel__nav--prev\" aria-label=\"Previous slide\" (click)=\"prev()\">\n    <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n      <path d=\"M9 2 L4 7 L9 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n    </svg>\n  </button>\n  <button type=\"button\" class=\"wr-carousel__nav wr-carousel__nav--next\" aria-label=\"Next slide\" (click)=\"next()\">\n    <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n      <path d=\"M5 2 L10 7 L5 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n    </svg>\n  </button>\n}\n\n@if (showDots() && count() > 1) {\n  <div class=\"wr-carousel__dots\" role=\"group\" aria-label=\"Carousel pagination\">\n    @for (slide of slides(); track $index) {\n      <button\n        type=\"button\"\n        class=\"wr-carousel__dot\"\n        [class.wr-carousel__dot--active]=\"$index === active()\"\n        [attr.aria-current]=\"$index === active() ? 'true' : null\"\n        [attr.aria-label]=\"`Go to slide ${$index + 1}`\"\n        (click)=\"goTo($index)\"\n      ></button>\n    }\n  </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}