UNPKG

@salla.sa/twilight-components

Version:
316 lines (315 loc) 14.2 kB
/*! * Crafted with ❤ by Salla */ import { Host, h } from "@stencil/core"; import Helper from "../../Helpers/Helper"; import { FilterOptionTypes } from "../salla-filters/interfaces"; export class SallaFiltersWidget { constructor() { this.initHeight = 195; this.isOpen = true; this.isShowMore = false; this.showMoreLabel = "عرض المزيد"; this.showLessLabel = "عرض أقل"; this.page = salla.config.get('page'); } connectedCallback() { //lets be smart and don't show 5 and more link for 8 options this.withLoadMore = this.option.key != 'price' && Array.isArray(this.option.values) && this.option.values.length > 8; salla.onReady(() => { this.page = salla.config.get('page'); }); salla.lang.onLoaded(() => { this.showMoreLabel = salla.lang.getWithDefault('common.titles.more', this.showMoreLabel); this.showLessLabel = salla.lang.getWithDefault('common.elements.show_less', this.showLessLabel); }); } componentDidLoad() { this.widgetValues.scrollHeight < this.initHeight && (this.withLoadMore = false); (this.withLoadMore && this.widgetValues) && (this.widgetValues.style.maxHeight = `${this.initHeight}px`); this.widgetContent.style.height = `${this.widgetContent.scrollHeight}px`; } /** * Asynchronously sets the height of a widget element to its current height, allowing for smooth transitions. * This function is often used in scenarios where the widget's content changes dynamically, and animating * the height adjustment is desired for a smoother user experience. * * @param {number} [delay=250] - Optional. The delay (in milliseconds) before updating the widget height. * Defaults to 250 milliseconds. * * @returns {Promise<void>} - A Promise that resolves once the widget height is set after the specified delay. * * @example * // Set widget height with the default delay (250 milliseconds) * await setWidgetHeight(); * * // Set widget height with a custom delay (e.g., 500 milliseconds) * await setWidgetHeight(500); */ async setWidgetHeight(delay = 250) { this.widgetContent.removeAttribute('style'); setTimeout(() => { let currentWidgetHeight = this.widgetContent.scrollHeight; this.widgetContent.style.height = currentWidgetHeight + 'px'; }, delay); } /** * Reset selected filter options. */ async reset() { if (this.option.type === FilterOptionTypes.RANGE) { this.priceRange.reset(); } Array.from(this.host.querySelectorAll('input')).forEach(input => input.checked = false); } /** * Action to show more or less filter options. */ async showMore() { this.isShowMore = !this.isShowMore; this.widgetContent.style.height = 'auto'; this.widgetValues.style.maxHeight = this.isShowMore ? `${this.widgetValues.scrollHeight}px` : `${this.initHeight}px`; setTimeout(() => { this.widgetContent.style.height = `${this.widgetContent.scrollHeight}px`; }, 400); // get height after time of collapse animtion (duration-300) } /** * Action to toggle widget open or closed (expand/ collapse). */ async toggleWidget() { this.isOpen = !this.isOpen; Helper.toggleElementClassIf(this.widgetContent, 's-filters-widget-opened', 's-filters-widget-closed', () => this.isOpen); } renderFilterOption(option) { if (![FilterOptionTypes.VALUES, FilterOptionTypes.MINIMUM, FilterOptionTypes.VARIANTS].includes(option.type)) { return ''; } //@ts-ignore return option.values.map((filterOption, index) => { let value = typeof filterOption == 'number' ? filterOption : (filterOption.key || filterOption.value); return h("label", { class: "s-filters-label", htmlFor: `${option.key}-option-${value}`, key: `${option.key}-option-${value}` }, h("input", { id: `${option.key}-option-${value}`, name: option.key, type: "radio", checked: this.isSelectedOption(option, value), class: `s-filters-radio`, onChange: event => this.changed.emit({ event, option, value }) }), this.getOptionLabel(option, filterOption)); }); } isSelectedOption(option, value) { if (option.type === FilterOptionTypes.MINIMUM) { return this.filtersData[option.key] == value; } if (option.type === FilterOptionTypes.VARIANTS) { return this.filtersData[option.type] && this.filtersData[option.type][Object.keys(this.filtersData[option.type])[0]] == value; } if (option.type === FilterOptionTypes.RANGE) { return this.filtersData[option.key] && this.filtersData[option.key].min == value.min && this.filtersData[option.key].max == value.max; } if (option.type === FilterOptionTypes.VALUES) { return this.filtersData[option.key] && Number(this.filtersData[option.key]) == Number(value); } return false; } getOptionLabel(option, filterOption) { if (option.key == 'rating') { //in amazon has stars & up, should we add it, to avoid those people who will come to say I selected 4 why I see 5 sars products return h("salla-rating-stars", { size: "small", value: filterOption }); } let label = filterOption.value || 'null'; //label+=filterOption.count ? ` (${salla.helpers.number(filterOption.count)})` : ''; return h("span", { class: "s-filters-option-name" }, label); } render() { return (h(Host, { key: 'faa16285c7c2dcd248f00230aa4b1eebc1814fdd', class: "s-filters-widget-container" }, h("h3", { key: '019354d300116c2d567b75e5cc93d0d1dfc4785b', class: "s-filters-widget-title", onClick: () => this.toggleWidget() }, h("span", { key: '8ce2bc6a789a0f5d82308afad47cbae58467439a' }, this.option.label), h("span", { key: 'a5dcaa63ad18d41a324b499f36c82780c0670d4f', class: `s-filters-widget-plusminus ${this.isOpen ? 's-filters-widget-plusminus-active' : ''}` })), h("div", { key: 'bef8427341d94bb6eb6e37d9736f9ca3e9503058', class: "s-filters-widget-content", ref: (el) => this.widgetContent = el }, h("div", { key: '451025fa922e84970107fe6ab2752db780effd86', class: "s-filters-widget-values", ref: (el) => this.widgetValues = el }, h("slot", { key: 'cbea119413f48c302684ae52c81786dcb69c6f29' }), this.option.type !== FilterOptionTypes.RANGE ? this.renderFilterOption(this.option) : h("salla-price-range", { onChanged: (event) => { this.changed.emit(event.detail); }, ref: price => this.priceRange = price, filtersData: this.filtersData, option: this.option })), this.withLoadMore && h("a", { key: '6b2e1b91b27509b445ad4af9367b4cc464bd2d4e', class: "s-filters-widget-more", onClick: () => this.showMore() }, !this.isShowMore ? this.showMoreLabel : this.showLessLabel)))); } static get is() { return "salla-filters-widget"; } static get originalStyleUrls() { return { "$": ["salla-filters-widget.scss"] }; } static get styleUrls() { return { "$": ["salla-filters-widget.css"] }; } static get properties() { return { "withLoadMore": { "type": "boolean", "attribute": "with-load-more", "mutable": true, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Show more or less filter options." }, "getter": false, "setter": false, "reflect": false }, "filtersData": { "type": "unknown", "attribute": "filters-data", "mutable": false, "complexType": { "original": "object", "resolved": "object", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Selected filter options value." }, "getter": false, "setter": false }, "option": { "type": "unknown", "attribute": "option", "mutable": false, "complexType": { "original": "Filter", "resolved": "Filter", "references": { "Filter": { "location": "import", "path": "../salla-filters/interfaces", "id": "src/components/salla-filters/interfaces.ts::Filter" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Filter option along with possible values." }, "getter": false, "setter": false } }; } static get states() { return { "isOpen": {}, "isShowMore": {}, "showMoreLabel": {}, "showLessLabel": {}, "page": {} }; } static get events() { return [{ "method": "changed", "name": "changed", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Custom event emitted up on filter option selection changes." }, "complexType": { "original": "any", "resolved": "any", "references": {} } }]; } static get methods() { return { "setWidgetHeight": { "complexType": { "signature": "(delay?: number) => Promise<void>", "parameters": [{ "name": "delay", "type": "number", "docs": "- Optional. The delay (in milliseconds) before updating the widget height.\n Defaults to 250 milliseconds." }], "references": { "Promise": { "location": "global", "id": "global::Promise" } }, "return": "Promise<void>" }, "docs": { "text": "Asynchronously sets the height of a widget element to its current height, allowing for smooth transitions.\nThis function is often used in scenarios where the widget's content changes dynamically, and animating\nthe height adjustment is desired for a smoother user experience.", "tags": [{ "name": "param", "text": "delay - Optional. The delay (in milliseconds) before updating the widget height.\n Defaults to 250 milliseconds." }, { "name": "returns", "text": "- A Promise that resolves once the widget height is set after the specified delay." }, { "name": "example", "text": "// Set widget height with the default delay (250 milliseconds)\nawait setWidgetHeight();\n\n// Set widget height with a custom delay (e.g., 500 milliseconds)\nawait setWidgetHeight(500);" }] } }, "reset": { "complexType": { "signature": "() => Promise<void>", "parameters": [], "references": { "Promise": { "location": "global", "id": "global::Promise" } }, "return": "Promise<void>" }, "docs": { "text": "Reset selected filter options.", "tags": [] } }, "showMore": { "complexType": { "signature": "() => Promise<void>", "parameters": [], "references": { "Promise": { "location": "global", "id": "global::Promise" } }, "return": "Promise<void>" }, "docs": { "text": "Action to show more or less filter options.", "tags": [] } }, "toggleWidget": { "complexType": { "signature": "() => Promise<void>", "parameters": [], "references": { "Promise": { "location": "global", "id": "global::Promise" } }, "return": "Promise<void>" }, "docs": { "text": "Action to toggle widget open or closed (expand/ collapse).", "tags": [] } } }; } static get elementRef() { return "host"; } } //# sourceMappingURL=salla-filters-widget.js.map