{"version":3,"file":"ngwr-compare.mjs","sources":["../../../projects/lib/compare/compare.ts","../../../projects/lib/compare/compare.html","../../../projects/lib/compare/ngwr-compare.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 { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ElementRef, ViewEncapsulation, computed, inject, input, model } from '@angular/core';\n\nimport { clamp } from 'ngwr/utils';\n\n/**\n * Before/after comparison slider. Works with any content — project two\n * pieces of markup with `wrCompareBefore` and `wrCompareAfter` attributes;\n * the component stacks them in the same cell and clips the \"after\" side\n * with a draggable divider.\n *\n * @example\n * ```html\n * <wr-compare [(position)]=\"pos\">\n *   <img wrCompareBefore src=\"before.jpg\" alt=\"\" />\n *   <img wrCompareAfter src=\"after.jpg\" alt=\"\" />\n * </wr-compare>\n *\n * <wr-compare orientation=\"vertical\">\n *   <pre wrCompareBefore>{{ oldCode }}</pre>\n *   <pre wrCompareAfter>{{ newCode }}</pre>\n * </wr-compare>\n * ```\n *\n * @see https://ngwr.dev/components/compare\n */\n@Component({\n  selector: 'wr-compare',\n  templateUrl: './compare.html',\n  encapsulation: ViewEncapsulation.None,\n  host: { '[class]': 'classes()' },\n})\nexport class WrCompare {\n  /** Divider position as a percentage (0–100). Two-way bindable. @default 50 */\n  readonly position = model(50);\n\n  /**\n   * Divider direction:\n   * - `'horizontal'` — divider line is vertical, drags left/right.\n   * - `'vertical'`   — divider line is horizontal, drags up/down.\n   * @default 'horizontal'\n   */\n  readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\n\n  /** Show the round drag handle on the divider. @default true */\n  readonly showHandle = input(true, { transform: coerceBooleanProperty });\n\n  /** Disable interaction (divider stays put). @default false */\n  readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n  /** Initial position transform — accepts any number / numeric string. */\n  readonly minPosition = input(0, { transform: (v: unknown): number => coerceNumberProperty(v, 0) });\n  readonly maxPosition = input(100, { transform: (v: unknown): number => coerceNumberProperty(v, 100) });\n\n  private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n  private dragging = false;\n\n  protected readonly classes = computed(() => {\n    const parts = ['wr-compare', `wr-compare--${this.orientation()}`];\n    if (this.disabled()) parts.push('wr-compare--disabled');\n    return parts.join(' ');\n  });\n\n  /** Clip path applied to the \"after\" layer so the divider reveals it. */\n  protected readonly clipPath = computed(() => {\n    const p = clamp(this.position(), 0, 100);\n    if (this.orientation() === 'horizontal') {\n      // Show from `p%` to the right edge.\n      return `inset(0 0 0 ${p}%)`;\n    }\n    return `inset(${p}% 0 0 0)`;\n  });\n\n  // Pointer handlers\n\n  protected onPointerDown(event: PointerEvent): void {\n    if (this.disabled()) return;\n    event.preventDefault();\n    this.dragging = true;\n    (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\n    this.updateFromPointer(event);\n  }\n\n  protected onPointerMove(event: PointerEvent): void {\n    if (!this.dragging) return;\n    this.updateFromPointer(event);\n  }\n\n  protected onPointerUp(event: PointerEvent): void {\n    if (!this.dragging) return;\n    this.dragging = false;\n    (event.currentTarget as HTMLElement).releasePointerCapture(event.pointerId);\n  }\n\n  protected onKeydown(event: KeyboardEvent): void {\n    if (this.disabled()) return;\n    const step = event.shiftKey ? 10 : 1;\n    let next: number | null = null;\n    if (this.orientation() === 'horizontal') {\n      if (event.key === 'ArrowLeft') next = this.position() - step;\n      else if (event.key === 'ArrowRight') next = this.position() + step;\n    } else {\n      if (event.key === 'ArrowUp') next = this.position() - step;\n      else if (event.key === 'ArrowDown') next = this.position() + step;\n    }\n    if (event.key === 'Home') next = this.minPosition();\n    else if (event.key === 'End') next = this.maxPosition();\n    if (next === null) return;\n    event.preventDefault();\n    this.position.set(clamp(next, this.minPosition(), this.maxPosition()));\n  }\n\n  private updateFromPointer(event: PointerEvent): void {\n    const rect = this.host.nativeElement.getBoundingClientRect();\n    const raw =\n      this.orientation() === 'horizontal'\n        ? ((event.clientX - rect.left) / rect.width) * 100\n        : ((event.clientY - rect.top) / rect.height) * 100;\n    this.position.set(clamp(raw, this.minPosition(), this.maxPosition()));\n  }\n}\n","<div\n  class=\"wr-compare__surface\"\n  role=\"slider\"\n  aria-label=\"Comparison divider\"\n  [attr.aria-orientation]=\"orientation()\"\n  [attr.aria-valuemin]=\"minPosition()\"\n  [attr.aria-valuemax]=\"maxPosition()\"\n  [attr.aria-valuenow]=\"position()\"\n  [attr.aria-disabled]=\"disabled() || null\"\n  [attr.tabindex]=\"disabled() ? -1 : 0\"\n  (pointerdown)=\"onPointerDown($event)\"\n  (pointermove)=\"onPointerMove($event)\"\n  (pointerup)=\"onPointerUp($event)\"\n  (pointercancel)=\"onPointerUp($event)\"\n  (keydown)=\"onKeydown($event)\"\n>\n  <div class=\"wr-compare__layers\">\n    <div class=\"wr-compare__layer wr-compare__layer--before\">\n      <ng-content select=\"[wrCompareBefore]\" />\n    </div>\n    <div class=\"wr-compare__layer wr-compare__layer--after\" [style.clip-path]=\"clipPath()\">\n      <ng-content select=\"[wrCompareAfter]\" />\n    </div>\n  </div>\n\n  <div\n    class=\"wr-compare__divider\"\n    [style.left.%]=\"orientation() === 'horizontal' ? position() : null\"\n    [style.top.%]=\"orientation() === 'vertical' ? position() : null\"\n    aria-hidden=\"true\"\n  >\n    @if (showHandle()) {\n      <span class=\"wr-compare__handle\">\n        @if (orientation() === 'horizontal') {\n          <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n            <path\n              d=\"M5 4 L1 8 L5 12 M11 4 L15 8 L11 12\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-width=\"1.5\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n            />\n          </svg>\n        } @else {\n          <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n            <path\n              d=\"M4 5 L8 1 L12 5 M4 11 L8 15 L12 11\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-width=\"1.5\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n            />\n          </svg>\n        }\n      </span>\n    }\n  </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}