UNPKG

@cbpds/web-components

Version:
476 lines (475 loc) 20.7 kB
/*! * CPB Design System web components - built with Stencil */ import { Host, h } from "@stencil/core"; import { setCSSProps, createNamespaceKey } from "../../utils/utils"; export class CbpSlider { constructor() { this.formFields = []; this.valueFields = []; this.fieldId = createNamespaceKey('cbp-slider'); this.value = undefined; this.gap = 0; this.variant = "single"; this.min = 0; this.max = 100; this.step = 1; this.hideMinmax = undefined; this.hideInput = undefined; this.error = false; this.disabled = false; this.context = undefined; this.sx = {}; } async reset() { this.value = this.initialValue != undefined ? this.initialValue : ''; if (this.variant == 'range') this.initRangeSlider(); if (!this.hideInput) { if (this.variant == 'range') { this.valueFields.forEach((item, index) => { !isNaN(this.initialValue[index]) ? item.setAttribute("value", this.initialValue[index]) : item.removeAttribute("value"); }); } else !isNaN(this.initialValue) ? this.valueField1.setAttribute("value", this.initialValue) : this.valueField1.removeAttribute("value"); } this.setSliderBar(); } watchDisabledHandler(newValue) { this.formFields.forEach((item) => { (newValue) ? item.setAttribute('disabled', '') : item.removeAttribute('disabled'); }); } handleChange(e, i = 0) { var _a, _b, _c, _d; let newValue = (!isNaN(e.target.value) && !isNaN(parseFloat(e.target.value))) ? e.target.value : this.min; if (i == 1) { const Min = Number(((_a = this.value) === null || _a === void 0 ? void 0 : _a[0]) || this.min) + this.gap; if (newValue < Min) newValue = Min; } else if (newValue < this.min) newValue = this.min; if (i == 0 && this.formFields.length > 1) { const Max = Number(((_b = this.value) === null || _b === void 0 ? void 0 : _b[1]) || this.max) - this.gap; if (newValue > Max) newValue = Max; } else if (newValue > this.max) newValue = this.max; this.formFields[i].value = newValue; if (!!this.valueFields[i]) this.valueFields[i].value = newValue; if (this.variant == 'single') this.value = newValue; else { this.value = [ i == 0 ? newValue : ((_c = this.value) === null || _c === void 0 ? void 0 : _c[0]) || undefined, i == 1 ? newValue : ((_d = this.value) === null || _d === void 0 ? void 0 : _d[1]) || undefined, ]; this.updateRangeBoundaries(); } this.valueChange.emit({ host: this.host, nativeElement: this.formFields[i], value: this.value, nativeEvent: e }); this.setSliderBar(); } setSliderBar() { var _a, _b, _c; if (this.variant == 'single') { let newValuePercent = (Number(this.value) - this.min) / (this.max - this.min); this.host.style.setProperty('--cbp-slider-track-selection-size', `${newValuePercent || 0}`); } else { let newValuePercent = ((((_a = this.value) === null || _a === void 0 ? void 0 : _a[1]) - ((_b = this.value) === null || _b === void 0 ? void 0 : _b[0])) / (this.max - this.min)) || 0; let newValueOffsetPercent = (((((_c = this.value) === null || _c === void 0 ? void 0 : _c[0]) - this.min) / (this.max - this.min)) * 100) || 0; this.host.style.setProperty('--cbp-slider-track-selection-size', `${newValuePercent}`); this.host.style.setProperty('--cbp-slider-track-selection-offset', `${newValueOffsetPercent}%`); } } initRangeSlider() { this.variant = "range"; let value; if (typeof this.value == 'string') { value = this.value.split(',').map(Number); value.forEach((item, index) => { if (isNaN(item)) value[index] = ''; }); this.value = [...value]; } } updateRangeBoundaries() { if (!this.hideInput) { this.valueFields.forEach((item, index) => { if (index == 0) { item === null || item === void 0 ? void 0 : item.setAttribute('max', `${Number(this.value[1] || this.max) - this.gap}`); } if (index == 1) { item === null || item === void 0 ? void 0 : item.setAttribute('min', `${Number(this.value[0] || this.min) + this.gap}`); } }); } } componentWillLoad() { this.formFields = Array.from(this.host.querySelectorAll('input[type=range]')); if (this.formFields.length > 1) { this.initRangeSlider(); } if (typeof this.sx == 'string') { this.sx = JSON.parse(this.sx) || {}; } setCSSProps(this.host, Object.assign({}, this.sx)); } componentDidLoad() { this.valueFields = this.variant == 'range' ? [this.valueField1, this.valueField2] : [this.valueField1]; this.formFields.forEach((item, index) => { if (!!item.getAttribute('id')) { this.fieldId = item.getAttribute('id'); } else { if (this.variant == 'single') { item.setAttribute('id', `${this.fieldId}`); } else { item.setAttribute('id', `${this.fieldId}${index == 1 ? '-end' : ''}`); } } if (this.value) item.setAttribute('value', this.variant == 'range' ? this.value[index] : this.value); if (this.min) item.setAttribute('min', `${this.min}`); if (this.max) item.setAttribute('max', `${this.max}`); if (this.step) item.setAttribute('step', `${this.step}`); if (this.disabled) item.setAttribute('disabled', ''); if (index == 1) item.setAttribute('aria-labelledby', `${this.fieldId}-label`); if (this.variant == "range") { if (document.querySelector(`${this.fieldId}-description`)) item.setAttribute('aria-describedby', `${this.fieldId}-description`); else item.setAttribute('aria-description', index == 0 ? 'Range start' : 'Range end'); } if (this.value != undefined) { this.setSliderBar(); } item.addEventListener('click', () => item.focus()); item.addEventListener('input', (e) => this.handleChange(e, index)); this.initialValue = this.value; }); } componentDidRender() { this.valueFields.forEach(item => { item === null || item === void 0 ? void 0 : item.removeAttribute('aria-describedby'); }); } render() { var _a, _b; return (h(Host, { key: '271858cc4f7d313c271df3b67210bb63e1584851' }, !this.hideInput && this.variant == 'range' && h("input", { key: '6fbbdc8c31d45d02d3677d5afe98bd00cea39ee8', type: "number", min: this.min, max: this.max, step: this.step, value: this.variant == 'range' ? (_a = this.value) === null || _a === void 0 ? void 0 : _a[0] : `${this.value}`, disabled: this.disabled, "aria-labelledby": `${this.fieldId}-label`, "aria-description": "Slider 1 value", "aria-invalid": this.error, ref: (el) => this.valueField1 = el, onChange: (e) => this.handleChange(e, 0) }), (!this.hideMinmax || this.host.querySelector('[slot="cpb-slider-before"]')) && h("span", { key: '858b7daa8791a18800727812c21641f004f26939' }, !this.hideMinmax && this.min, h("slot", { key: '8db542532da0e625a673ec34f6307e24277deec5', name: "cpb-slider-before" })), h("div", { key: '88ea8a6e653d9428ac361e6fef4df25e4acca623', class: "cbp-slider-wrapper" }, h("span", { key: '39fe9f424a979c2f51c2cdc3100ef20a3f9fc3e5', class: "cbp-slider-selection" }), h("slot", { key: '906d92a1c78c279afa32c76a6c3c002d22e2d4e8' })), (!this.hideMinmax || this.host.querySelector('[slot="cpb-slider-after"]')) && h("span", { key: 'c9e3650f1dceda9a94520a5928fe14da0af12e76' }, h("slot", { key: 'd5fc7e843885bcfa6712b3fe7469800e46820aba', name: "cpb-slider-after" }), !this.hideMinmax && this.max), !this.hideInput && h("input", { key: 'bddd64c541d6c381c49163a328da53e55b0f667a', type: "number", min: this.min, max: this.max, step: this.step, value: this.variant == 'range' ? (_b = this.value) === null || _b === void 0 ? void 0 : _b[1] : `${this.value}`, disabled: this.disabled, "aria-labelledby": `${this.fieldId}-label`, "aria-description": `Slider ${this.variant == 'range' ? 2 : 1} value`, "aria-invalid": this.error, ref: (el) => this.variant == 'range' ? this.valueField2 = el : this.valueField1 = el, onChange: (e) => this.handleChange(e, this.variant == 'range' ? 1 : 0) }))); } static get is() { return "cbp-slider"; } static get originalStyleUrls() { return { "$": ["cbp-slider.scss"] }; } static get styleUrls() { return { "$": ["cbp-slider.css"] }; } static get properties() { return { "fieldId": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Optionally specify the ID of the visible control here, which is used to generate related pattern node IDs and associate everything for accessibility. \nFor range sliders, \"-start\" and \"-end\" are appended to the specified/generated value automatically." }, "attribute": "field-id", "reflect": false, "defaultValue": "createNamespaceKey('cbp-slider')" }, "value": { "type": "any", "mutable": true, "complexType": { "original": "number | number[] | string | string[]", "resolved": "number | number[] | string | string[]", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies the value of the slider and numeric entry field.\nThis prop should be set on this component rather than (or in addition to) the slotted `input type=\"range\"`." }, "attribute": "value", "reflect": true }, "gap": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies the minimum difference in values in a range slider. If a non-zero value is specified, keep in mind the interaction with the \"step\" property." }, "attribute": "gap", "reflect": false, "defaultValue": "0" }, "variant": { "type": "string", "mutable": true, "complexType": { "original": "\"single\" | \"range\"", "resolved": "\"range\" | \"single\"", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies whether the control is a single slider or a range with two values (can be auto-detected by the number of slotted `input[type=range]` tags)." }, "attribute": "variant", "reflect": true, "defaultValue": "\"single\"" }, "min": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies the minimum value of the slider and numeric entry field (defaults to 0). \nThis prop should be set on this component rather than (or in addition to) the slotted `input type=\"range\"`." }, "attribute": "min", "reflect": false, "defaultValue": "0" }, "max": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies the maximum value of the slider and numeric entry field (defaults to 100). \nThis prop should be set on this component rather than (or in addition to) the slotted `input type=\"range\"`." }, "attribute": "max", "reflect": false, "defaultValue": "100" }, "step": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies the step value of the slider and numeric entry field (defaults to 1). \nThis prop should be set on this component rather than (or in addition to) the slotted `input type=\"range\"`." }, "attribute": "step", "reflect": false, "defaultValue": "1" }, "hideMinmax": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies whether the min/max values are hidden (shown by default)." }, "attribute": "hide-minmax", "reflect": false }, "hideInput": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies whether the numeric input is hidden (shown by default)." }, "attribute": "hide-input", "reflect": false }, "error": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies that the field has an error (and sets aria-invalid accordingly). Primarily controlled by the parent `cbp-form-field` component." }, "attribute": "error", "reflect": true, "defaultValue": "false" }, "disabled": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies that the field is disabled. Primarily controlled by the parent `cbp-form-field` component." }, "attribute": "disabled", "reflect": true, "defaultValue": "false" }, "context": { "type": "string", "mutable": false, "complexType": { "original": "'light-inverts' | 'light-always' | 'dark-inverts' | 'dark-always'", "resolved": "\"dark-always\" | \"dark-inverts\" | \"light-always\" | \"light-inverts\"", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies the context of the component as it applies to the visual design and whether it inverts when light/dark mode is toggled. Default behavior is \"light-inverts\" and does not have to be specified." }, "attribute": "context", "reflect": true }, "sx": { "type": "any", "mutable": false, "complexType": { "original": "any", "resolved": "any", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Supports adding inline styles as an object" }, "attribute": "sx", "reflect": false, "defaultValue": "{}" } }; } static get events() { return [{ "method": "valueChange", "name": "valueChange", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "A custom event fired when the menu is opened or closed." }, "complexType": { "original": "any", "resolved": "any", "references": {} } }]; } static get methods() { return { "reset": { "complexType": { "signature": "() => Promise<void>", "parameters": [], "references": { "Promise": { "location": "global", "id": "global::Promise" } }, "return": "Promise<void>" }, "docs": { "text": "A custom method to reset the Slider component to its initial state and value since it does not update \nproperly on a native form reset. This method may be called manually, but is automatically called on \nform reset when using the `cbp-form` component.", "tags": [] } } }; } static get elementRef() { return "host"; } static get watchers() { return [{ "propName": "disabled", "methodName": "watchDisabledHandler" }]; } } //# sourceMappingURL=cbp-slider.js.map