@salla.sa/twilight-components
Version:
Salla Web Component
202 lines (197 loc) • 8.81 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
import { H as Helper } from './Helper.js';
import { d as defineCustomElement$3 } from './salla-button2.js';
import { d as defineCustomElement$2 } from './salla-price-range2.js';
import { d as defineCustomElement$1 } from './salla-rating-stars2.js';
var FilterOptionTypes;
(function (FilterOptionTypes) {
// CATEGORIES = "categories",
// BRANDs = "brands",
// RATING = "rating",
// PRICE = "price",
// RADIO = "radio",
FilterOptionTypes["VALUES"] = "values";
FilterOptionTypes["VARIANTS"] = "variants";
FilterOptionTypes["MINIMUM"] = "minimum";
FilterOptionTypes["RANGE"] = "range";
})(FilterOptionTypes || (FilterOptionTypes = {}));
var FilterOptionInputType;
(function (FilterOptionInputType) {
FilterOptionInputType["VALUES"] = "values";
FilterOptionInputType["VARIANT"] = "variants";
FilterOptionInputType["RANGE"] = "range";
})(FilterOptionInputType || (FilterOptionInputType = {}));
const sallaFiltersWidgetCss = ":host{display:block}";
const SallaFiltersWidget = /*@__PURE__*/ proxyCustomElement(class SallaFiltersWidget extends HTMLElement {
constructor() {
super();
this.__registerHost();
this.changed = createEvent(this, "changed", 7);
this.initHeight = 195;
this.withLoadMore = undefined;
this.filtersData = undefined;
this.option = undefined;
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.offsetHeight;
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, { class: "s-filters-widget-container" }, h("h3", { class: "s-filters-widget-title", onClick: () => this.toggleWidget() }, h("span", null, this.option.label), h("span", { class: `s-filters-widget-plusminus ${this.isOpen ? 's-filters-widget-plusminus-active' : ''}` })), h("div", { class: "s-filters-widget-content", ref: (el) => this.widgetContent = el }, h("div", { class: "s-filters-widget-values", ref: (el) => this.widgetValues = el }, h("slot", null), 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", { class: "s-filters-widget-more", onClick: () => this.showMore() }, !this.isShowMore ? this.showMoreLabel : this.showLessLabel))));
}
get host() { return this; }
static get style() { return sallaFiltersWidgetCss; }
}, [4, "salla-filters-widget", {
"withLoadMore": [1028, "with-load-more"],
"filtersData": [16],
"option": [16],
"isOpen": [32],
"isShowMore": [32],
"showMoreLabel": [32],
"showLessLabel": [32],
"page": [32],
"setWidgetHeight": [64],
"reset": [64],
"showMore": [64],
"toggleWidget": [64]
}]);
function defineCustomElement() {
if (typeof customElements === "undefined") {
return;
}
const components = ["salla-filters-widget", "salla-button", "salla-price-range", "salla-rating-stars"];
components.forEach(tagName => { switch (tagName) {
case "salla-filters-widget":
if (!customElements.get(tagName)) {
customElements.define(tagName, SallaFiltersWidget);
}
break;
case "salla-button":
if (!customElements.get(tagName)) {
defineCustomElement$3();
}
break;
case "salla-price-range":
if (!customElements.get(tagName)) {
defineCustomElement$2();
}
break;
case "salla-rating-stars":
if (!customElements.get(tagName)) {
defineCustomElement$1();
}
break;
} });
}
export { FilterOptionTypes as F, SallaFiltersWidget as S, defineCustomElement as d };
//# sourceMappingURL=salla-filters-widget2.js.map