@salla.sa/twilight-components
Version:
Salla Web Component
148 lines (147 loc) • 5 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
import { Host, h } from "@stencil/core";
export class SallaProductCardEmbed {
constructor() {
this.loading = false;
this.hasError = false;
this.productData = null;
}
async componentWillLoad() {
await salla.onReady();
await this.fetchProduct();
}
componentDidLoad() {
this.ensureParentContainsFloats();
}
componentDidRender() {
this.renderCardNode();
}
/**
* The host floats for `align="left"|"right"`. If the parent is a plain
* block element with visible overflow it won't contain those floats,
* letting them spill into following siblings (e.g. a comments section).
* Promote such parents to a block formatting context.
*/
ensureParentContainsFloats() {
if (this.align !== 'left' && this.align !== 'right')
return;
const parent = this.hostEl?.parentElement;
if (!parent)
return;
const cs = getComputedStyle(parent);
if (cs.display === 'block' && cs.overflow === 'visible' && cs.float === 'none') {
parent.style.display = 'flow-root';
}
}
fetchProduct() {
if (!this.productId) {
this.productData = null;
this.loading = false;
this.hasError = false;
return;
}
this.loading = true;
this.hasError = false;
return salla.api
.withoutNotifier(() => salla.product.api.getDetails(this.productId))
.then((response) => {
const data = response.data;
this.productData = data ?? null;
this.hasError = !data;
})
.catch((_error) => {
this.productData = null;
this.hasError = true;
})
.finally(() => {
this.loading = false;
});
}
renderCardNode() {
if (!this.cardContainer)
return;
this.cardContainer.textContent = '';
if (!this.productData || this.loading || this.hasError)
return;
const tag = window.customElements.get('custom-salla-product-card')
? 'custom-salla-product-card'
: 'salla-product-card';
const card = document.createElement(tag);
card.product = this.productData;
this.cardContainer.appendChild(card);
}
render() {
const cardClasses = {
's-product-card-embed-card': true,
's-product-card-embed-card-align-left': this.align === 'left',
's-product-card-embed-card-align-right': this.align === 'right',
's-product-card-embed-card-align-center': this.align === 'center',
};
return (h(Host, { key: '4fcd0b6e5da26ac976b0f3c5c031b614dc9d04b1' }, this.hasError && h("span", { key: '55b4a2649d4912b61f6b75e3c2437bfaee7863e0', class: "s-product-card-embed-fallback" }), h("div", { key: 'ac5882e5dd36ac28cc6e5a24186156c7cadda820', class: cardClasses, ref: (el) => {
this.cardContainer = el;
} })));
}
static get is() { return "salla-product-card-embed"; }
static get originalStyleUrls() {
return {
"$": ["salla-product-card-embed.scss"]
};
}
static get styleUrls() {
return {
"$": ["salla-product-card-embed.css"]
};
}
static get properties() {
return {
"productId": {
"type": "any",
"attribute": "product-id",
"mutable": false,
"complexType": {
"original": "string | number",
"resolved": "number | string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Product identifier used to fetch product details."
},
"getter": false,
"setter": false,
"reflect": false
},
"align": {
"type": "string",
"attribute": "align",
"mutable": false,
"complexType": {
"original": "'left' | 'right' | 'center'",
"resolved": "\"center\" | \"left\" | \"right\"",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Optional alignment for the embedded card."
},
"getter": false,
"setter": false,
"reflect": true
}
};
}
static get states() {
return {
"loading": {},
"hasError": {},
"productData": {}
};
}
static get elementRef() { return "hostEl"; }
}