var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { html, LitElement, nothing } from 'lit';
import { property, query, queryAssignedElements, state, } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { styleMap } from 'lit/directives/style-map.js';
import { addThemingController } from '../../theming/theming-controller.js';
import { addKeybindings, arrowDown, arrowLeft, arrowRight, arrowUp, endKey, homeKey, pageDownKey, pageUpKey, } from '../common/controllers/key-bindings.js';
import { blazorDeepImport } from '../common/decorators/blazorDeepImport.js';
import { watch } from '../common/decorators/watch.js';
import { addSafeEventListener, asNumber, asPercent, clamp, formatString, isDefined, isLTR, } from '../common/util.js';
import { styles as shared } from './themes/shared/slider.common.css.js';
import { styles } from './themes/slider.base.css.js';
import { all } from './themes/themes.js';
let IgcSliderBaseComponent = class IgcSliderBaseComponent extends LitElement {
    get hasLabels() {
        return this.labels?.length > 0;
    }
    get distance() {
        return this.max - this.min;
    }
    set min(value) {
        if (!isDefined(value) || value > this.max) {
            return;
        }
        this._min = this.hasLabels ? 0 : value;
        if (isDefined(this._lowerBound) && this._lowerBound < value) {
            this._lowerBound = value;
        }
    }
    get min() {
        return this._min;
    }
    set max(value) {
        if (!isDefined(value) || value < this._min) {
            return;
        }
        this._max = this.hasLabels ? this.labels.length - 1 : value;
        if (isDefined(this._upperBound) && this._upperBound > value) {
            this._upperBound = value;
        }
    }
    get max() {
        return this._max;
    }
    set lowerBound(value) {
        if (!isDefined(value))
            return;
        this._lowerBound = Math.min(this._upperBound ?? value, value);
    }
    get lowerBound() {
        const current = this._lowerBound ?? this._min;
        const upper = Math.min(this._upperBound ?? this._max, this._max);
        return clamp(current, this._min, upper);
    }
    set upperBound(value) {
        if (!isDefined(value))
            return;
        this._upperBound = Math.max(this._lowerBound ?? value, value);
    }
    get upperBound() {
        const current = this._upperBound ?? this._max;
        const lower = Math.max(this._lowerBound ?? this._min, this.min);
        return clamp(current, lower, this._max);
    }
    set step(value) {
        this._step = this.hasLabels ? 1 : asNumber(value, this._step);
    }
    get step() {
        return this._step;
    }
    constraintsChange() {
        this.normalizeValue();
    }
    constructor() {
        super();
        this._min = 0;
        this._max = 100;
        this._step = 1;
        this.pointerCaptured = false;
        this.thumbLabelsVisible = false;
        this.labels = [];
        this.disabled = false;
        this.discreteTrack = false;
        this.hideTooltip = false;
        this.primaryTicks = 0;
        this.secondaryTicks = 0;
        this.tickOrientation = 'end';
        this.hidePrimaryLabels = false;
        this.hideSecondaryLabels = false;
        this.locale = 'en';
        this.tickLabelRotation = 0;
        addThemingController(this, all);
        addSafeEventListener(this, 'pointerdown', this.pointerDown);
        addSafeEventListener(this, 'pointermove', this.pointerMove);
        addSafeEventListener(this, 'lostpointercapture', this.lostPointerCapture);
        addSafeEventListener(this, 'keyup', this.handleKeyUp);
        addKeybindings(this, {
            skip: () => this.disabled,
        })
            .set(arrowLeft, () => this.handleArrowKeys(isLTR(this) ? -1 : 1))
            .set(arrowRight, () => this.handleArrowKeys(isLTR(this) ? 1 : -1))
            .set(arrowUp, () => this.handleArrowKeys(1))
            .set(arrowDown, () => this.handleArrowKeys(-1))
            .set(homeKey, () => this.handleKeyboardIncrement(this.lowerBound - this.activeValue))
            .set(endKey, () => this.handleKeyboardIncrement(this.upperBound - this.activeValue))
            .set(pageUpKey, () => this.handlePageKeys(1))
            .set(pageDownKey, () => this.handlePageKeys(-1));
    }
    handleArrowKeys(delta) {
        const step = this.step ? this.step : 1;
        this.handleKeyboardIncrement(step * delta);
    }
    handlePageKeys(delta) {
        const step = this.step ? this.step : 1;
        this.handleKeyboardIncrement(delta * Math.max((this.upperBound - this.lowerBound) / 10, step));
    }
    handleKeyboardIncrement(increment) {
        if (increment) {
            const updated = this.updateValue(increment);
            this.showThumbLabels();
            this.hideThumbLabels();
            if (updated) {
                this.emitChangeEvent();
            }
        }
    }
    handleKeyUp() {
        this.activeThumb?.part.add('focused');
    }
    handleSlotChange() {
        this.labels = this.labelElements.map((label) => label.textContent ?? '');
        if (this.hasLabels) {
            this.min = 0;
            this.max = this.labels.length - 1;
            this.step = 1;
        }
    }
    get activeValue() {
        return 0;
    }
    normalizeValue() { }
    getTrackStyle() {
        return {};
    }
    updateValue(_increment) {
        return false;
    }
    renderThumbs() {
        return html ``;
    }
    emitInputEvent() { }
    emitChangeEvent() { }
    validateValue(value) {
        return this.normalizeByStep(clamp(value, this.lowerBound, this.upperBound));
    }
    formatValue(value) {
        const strValue = value.toLocaleString(this.locale, this.valueFormatOptions);
        return this.valueFormat
            ? formatString(this.valueFormat, strValue)
            : strValue;
    }
    normalizeByStep(value) {
        return this.step ? value - ((value - this.lowerBound) % this.step) : value;
    }
    closestHandle(_event) {
        return this.thumb;
    }
    totalTickCount() {
        const primaryTicks = this.hasLabels
            ? this.primaryTicks > 0
                ? this.labels.length
                : 0
            : this.primaryTicks === 1
                ? 2
                : this.primaryTicks;
        return primaryTicks > 0
            ? (primaryTicks - 1) * this.secondaryTicks + primaryTicks
            : this.secondaryTicks > 0
                ? this.secondaryTicks
                : 0;
    }
    tickValue(idx) {
        const tickCount = this.totalTickCount();
        const distance = this.distance;
        const labelStep = tickCount > 1 ? distance / (tickCount - 1) : distance;
        const labelVal = labelStep * idx;
        return this.min + labelVal;
    }
    isPrimary(idx) {
        return this.primaryTicks <= 0
            ? false
            : idx % (this.secondaryTicks + 1) === 0;
    }
    showThumbLabels() {
        if (this.disabled || this.hideTooltip) {
            return;
        }
        if (this.thumbHoverTimer) {
            clearTimeout(this.thumbHoverTimer);
            this.thumbHoverTimer = null;
        }
        this.thumbLabelsVisible = true;
    }
    hideThumbLabels() {
        if (this.pointerCaptured || !this.thumbLabelsVisible) {
            return;
        }
        this.thumbHoverTimer = setTimeout(() => {
            this.thumbLabelsVisible = false;
        }, 750);
    }
    calculateTrackUpdate(mouseX) {
        const { width, left } = this.activeThumb.getBoundingClientRect();
        const { width: trackWidth } = this.base.getBoundingClientRect();
        const thumbX = left + width / 2;
        const scale = trackWidth / this.distance;
        const change = isLTR(this) ? mouseX - thumbX : thumbX - mouseX;
        if (this.step) {
            const stepDistance = scale * this.step;
            if (Math.abs(change) < stepDistance / 2) {
                return 0;
            }
            return Math.round(change / stepDistance) * this.step;
        }
        return change / scale;
    }
    updateSlider(mouseX) {
        if (this.disabled || !this.activeThumb) {
            return;
        }
        const increment = this.calculateTrackUpdate(mouseX);
        if (increment !== 0) {
            this.updateValue(increment);
        }
    }
    pointerDown(event) {
        const thumb = this.closestHandle(event);
        thumb.focus();
        this.startValue = this.activeValue;
        this.updateSlider(event.clientX);
        this.setPointerCapture(event.pointerId);
        this.pointerCaptured = true;
        this.showThumbLabels();
        event.preventDefault();
        this.activeThumb?.part.remove('focused');
    }
    pointerMove(event) {
        if (this.pointerCaptured) {
            this.updateSlider(event.clientX);
        }
    }
    lostPointerCapture() {
        this.pointerCaptured = false;
        this.hideThumbLabels();
        if (this.startValue !== this.activeValue) {
            this.emitChangeEvent();
        }
        this.startValue = undefined;
    }
    handleThumbFocus(event) {
        this.activeThumb = event.target;
    }
    handleThumbBlur() {
        this.activeThumb?.part.remove('focused');
        this.activeThumb = undefined;
    }
    *_renderTicks() {
        const total = this.totalTickCount();
        const secondaryTicks = this.secondaryTicks + 1;
        for (let i = 0; i < total; i++) {
            const primary = this.isPrimary(i);
            const shown = primary ? this.hidePrimaryLabels : this.hideSecondaryLabels;
            const labelInner = this.hasLabels
                ? primary
                    ? this.labels[Math.round(i / secondaryTicks)]
                    : nothing
                : this.formatValue(this.tickValue(i));
            yield html `<div part="tick-group">
        <div part="tick" data-primary=${primary}>
          ${shown
                ? nothing
                : html `
                <div part="tick-label">
                  <span part="tick-label-inner">${labelInner}</span>
                </div>
              `}
        </div>
      </div>`;
        }
    }
    renderTicks() {
        return html `<div part="ticks">${this._renderTicks()}</div>`;
    }
    renderThumb(value, ariaLabel, thumbId) {
        const percent = `${asPercent(value - this.min, this.distance)}%`;
        const thumbStyles = { insetInlineStart: percent };
        const tooltipStyles = {
            insetInlineStart: percent,
            opacity: this.thumbLabelsVisible ? 1 : 0,
        };
        const textValue = this.hasLabels
            ? this.labels[value]
            : this.valueFormat || this.valueFormatOptions
                ? this.formatValue(value)
                : undefined;
        return html `
      <div
        part="thumb"
        id=${ifDefined(thumbId)}
        tabindex=${this.disabled ? -1 : 0}
        style=${styleMap(thumbStyles)}
        role="slider"
        aria-valuemin=${this.lowerBound}
        aria-valuemax=${this.upperBound}
        aria-valuenow=${value}
        aria-valuetext=${ifDefined(textValue)}
        aria-label=${ifDefined(ariaLabel)}
        aria-disabled=${this.disabled}
        @pointerenter=${this.showThumbLabels}
        @pointerleave=${this.hideThumbLabels}
        @focus=${this.handleThumbFocus}
        @blur=${this.handleThumbBlur}
      ></div>
      ${this.hideTooltip
            ? nothing
            : html `
            <div part="thumb-label" style=${styleMap(tooltipStyles)}>
              <div part="thumb-label-inner">
                ${this.hasLabels ? this.labels[value] : this.formatValue(value)}
              </div>
            </div>
          `}
    `;
    }
    renderSteps() {
        if (!this.discreteTrack || !this.step) {
            return nothing;
        }
        const interval = (100 * Math.SQRT2 * this.step) / this.distance;
        return html `
      <div part="steps">
        <svg width="100%" height="100%" style="display: flex">
          <line
            x1="0"
            y1="1"
            x2="100%"
            y2="1"
            stroke="currentColor"
            stroke-dasharray="0, calc(${interval}%)"
            stroke-linecap="round"
            stroke-width="2px"
          ></line>
        </svg>
      </div>
    `;
    }
    render() {
        const isStart = this.tickOrientation === 'start';
        const isMirrored = this.tickOrientation === 'mirror';
        return html `
      <div part="base">
        ${isStart || isMirrored ? html `${this.renderTicks()}` : nothing}
        <div part="track">
          <div part="inactive"></div>
          <div part="fill" style=${styleMap(this.getTrackStyle())}></div>
          ${this.renderSteps()}
        </div>
        ${!isStart ? html `${this.renderTicks()}` : nothing}
        <div part="thumbs">${this.renderThumbs()}</div>
        <slot @slotchange=${this.handleSlotChange}></slot>
      </div>
    `;
    }
};
IgcSliderBaseComponent.styles = [styles, shared];
__decorate([
    query(`[part~='thumb']`)
], IgcSliderBaseComponent.prototype, "thumb", void 0);
__decorate([
    query(`[part='base']`, true)
], IgcSliderBaseComponent.prototype, "base", void 0);
__decorate([
    queryAssignedElements({ selector: 'igc-slider-label' })
], IgcSliderBaseComponent.prototype, "labelElements", void 0);
__decorate([
    state()
], IgcSliderBaseComponent.prototype, "thumbLabelsVisible", void 0);
__decorate([
    state()
], IgcSliderBaseComponent.prototype, "labels", void 0);
__decorate([
    property({ type: Number })
], IgcSliderBaseComponent.prototype, "min", null);
__decorate([
    property({ type: Number })
], IgcSliderBaseComponent.prototype, "max", null);
__decorate([
    property({ type: Number, attribute: 'lower-bound' })
], IgcSliderBaseComponent.prototype, "lowerBound", null);
__decorate([
    property({ type: Number, attribute: 'upper-bound' })
], IgcSliderBaseComponent.prototype, "upperBound", null);
__decorate([
    property({ type: Boolean, reflect: true })
], IgcSliderBaseComponent.prototype, "disabled", void 0);
__decorate([
    property({ type: Boolean, attribute: 'discrete-track' })
], IgcSliderBaseComponent.prototype, "discreteTrack", void 0);
__decorate([
    property({ type: Boolean, attribute: 'hide-tooltip' })
], IgcSliderBaseComponent.prototype, "hideTooltip", void 0);
__decorate([
    property({ type: Number })
], IgcSliderBaseComponent.prototype, "step", null);
__decorate([
    property({ type: Number, attribute: 'primary-ticks' })
], IgcSliderBaseComponent.prototype, "primaryTicks", void 0);
__decorate([
    property({ type: Number, attribute: 'secondary-ticks' })
], IgcSliderBaseComponent.prototype, "secondaryTicks", void 0);
__decorate([
    property({ attribute: 'tick-orientation' })
], IgcSliderBaseComponent.prototype, "tickOrientation", void 0);
__decorate([
    property({ type: Boolean, attribute: 'hide-primary-labels' })
], IgcSliderBaseComponent.prototype, "hidePrimaryLabels", void 0);
__decorate([
    property({ type: Boolean, attribute: 'hide-secondary-labels' })
], IgcSliderBaseComponent.prototype, "hideSecondaryLabels", void 0);
__decorate([
    property()
], IgcSliderBaseComponent.prototype, "locale", void 0);
__decorate([
    property({ attribute: 'value-format' })
], IgcSliderBaseComponent.prototype, "valueFormat", void 0);
__decorate([
    property({ attribute: false })
], IgcSliderBaseComponent.prototype, "valueFormatOptions", void 0);
__decorate([
    property({ type: Number, reflect: true, attribute: 'tick-label-rotation' })
], IgcSliderBaseComponent.prototype, "tickLabelRotation", void 0);
__decorate([
    watch('min', { waitUntilFirstUpdate: true }),
    watch('max', { waitUntilFirstUpdate: true }),
    watch('lowerBound', { waitUntilFirstUpdate: true }),
    watch('upperBound', { waitUntilFirstUpdate: true }),
    watch('step', { waitUntilFirstUpdate: true })
], IgcSliderBaseComponent.prototype, "constraintsChange", null);
IgcSliderBaseComponent = __decorate([
    blazorDeepImport
], IgcSliderBaseComponent);
export { IgcSliderBaseComponent };
//# sourceMappingURL=slider-base.js.map