igniteui-webcomponents
Version:
Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.
461 lines • 16.8 kB
JavaScript
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 { LitElement, html, 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 { themes } from '../../theming/theming-decorator.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 { blazorTypeOverride } from '../common/decorators/blazorTypeOverride.js';
import { watch } from '../common/decorators/watch.js';
import { 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;
this.addEventListener('pointerdown', this.pointerDown);
this.addEventListener('pointermove', this.pointerMove);
this.addEventListener('lostpointercapture', this.lostPointerCapture);
this.addEventListener('keyup', this.handleKeyUp);
addKeybindings(this, {
skip: () => this.disabled,
bindingDefaults: { preventDefault: true },
})
.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 ? 'true' : 'false'}
=${this.showThumbLabels}
=${this.hideThumbLabels}
=${this.handleThumbFocus}
=${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 =${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' }),
blazorTypeOverride('TickLabelRotation', true)
], 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([
themes(all),
blazorDeepImport
], IgcSliderBaseComponent);
export { IgcSliderBaseComponent };
//# sourceMappingURL=slider-base.js.map