@postnord/web-components
Version:
PostNord Web Components
141 lines (136 loc) • 10.3 kB
JavaScript
/*!
* Built with Stencil
* By PostNord.
*/
'use strict';
var index = require('./index-DWu-2oJc.js');
var arrow_left = require('./arrow_left-Crkz484c.js');
var arrow_right = require('./arrow_right-CABi9Wkp.js');
const pnSegmentedControlCss = () => `${index.transformTag("pn-segmented-control")}{position:relative;display:inline-block;max-width:100%;overflow:hidden;border-radius:3em;transform:translateZ(0);transition-property:outline-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)} (prefers-reduced-motion: reduce){${index.transformTag("pn-segmented-control")}{transition-duration:0s;transition-delay:0s}}${index.transformTag("pn-segmented-control")}{outline:0.2rem solid transparent;outline-offset:0.2rem}${index.transformTag("pn-segmented-control")}:focus-within,${index.transformTag("pn-segmented-control")}:active{outline-color:#005d92}${index.transformTag("pn-segmented-control")} .pn-segmented-control{display:flex;align-items:center;border-radius:3em;min-height:3em;padding:0.25em;background:#f3f2f2;position:relative;overflow-x:auto;scroll-snap-type:x mandatory}${index.transformTag("pn-segmented-control")} .pn-segmented-control:hover .pn-sc-bg[data-hover]{opacity:1}${index.transformTag("pn-segmented-control")} .pn-segmented-control::-webkit-scrollbar{display:none}${index.transformTag("pn-segmented-control")} .pn-segmented-control .pn-sc-bg{position:absolute;top:50%;transform:translateY(-50%);will-change:transform;left:0;border-radius:inherit;transition-property:width, transform, background-color, opacity, box-shadow;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)} (prefers-reduced-motion: reduce){${index.transformTag("pn-segmented-control")} .pn-segmented-control .pn-sc-bg{transition-duration:0s;transition-delay:0s}}${index.transformTag("pn-segmented-control")} .pn-segmented-control .pn-sc-bg[data-active]{box-shadow:0px 0.3px 0.9px rgba(0, 0, 0, 0.1), 0px 1.6px 3.6px rgba(0, 0, 0, 0.13);border:0.0625em solid #005d92;background-color:#ffffff;z-index:1}${index.transformTag("pn-segmented-control")} .pn-segmented-control .pn-sc-bg[data-hover]{background-color:#e0f8ff;opacity:0;border:0.25em solid transparent;z-index:0}${index.transformTag("pn-segmented-control")} .pn-segmented-control .pn-sc-bg[data-hover][data-disabled]{border-color:#e9e6e5;background-color:#e9e6e5}${index.transformTag("pn-segmented-control")} .pn-segmented-control .pn-sc-bg[data-disabled]{border-color:#e9e6e5;background-color:#e9e6e5}${index.transformTag("pn-segmented-control")} .pn-sc-arrows{position:absolute;top:50%;transform:translateY(-50%);left:0;height:100%;width:100%;z-index:3;display:flex;justify-content:space-between;align-items:center;pointer-events:none}${index.transformTag("pn-segmented-control")} .pn-sc-arrows svg{width:1.5em}${index.transformTag("pn-segmented-control")} .pn-sc-arrows svg.pn-icon-svg path{fill:#005d92}${index.transformTag("pn-segmented-control")} .pn-sc-arrows>.pn-sc-arrow{cursor:pointer;pointer-events:all;width:2.5em;height:2.5em;background:#ffffff;border:none;outline:none;display:flex;align-items:center;justify-content:center;opacity:0;will-change:transform;-webkit-tap-highlight-color:transparent;transition-property:transform, opacity, background-color, box-shadow;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)} (prefers-reduced-motion: reduce){${index.transformTag("pn-segmented-control")} .pn-sc-arrows>.pn-sc-arrow{transition-duration:0s;transition-delay:0s}}${index.transformTag("pn-segmented-control")} .pn-sc-arrows>.pn-sc-arrow.pn-sc-arrow-left{transform:translateX(-100%);border-radius:0 50% 50% 0;padding:0 0.3em 0 0;box-shadow:0.2rem 0.3rem 0.2rem rgba(0, 0, 0, 0.4)}${index.transformTag("pn-segmented-control")} .pn-sc-arrows>.pn-sc-arrow.pn-sc-arrow-right{transform:translateX(100%);border-radius:50% 0 0 50%;box-shadow:-0.2rem 0.3rem 0.2rem rgba(0, 0, 0, 0.4)}${index.transformTag("pn-segmented-control")} .pn-sc-arrows[data-left] .pn-sc-arrow-left,${index.transformTag("pn-segmented-control")} .pn-sc-arrows[data-right] .pn-sc-arrow-right{opacity:1;transform:translateX(0)}`;
const PnSegmentedControl = class {
constructor(hostRef) {
index.registerInstance(this, hostRef);
}
mo;
segmentContainer;
segments = [];
activeBg;
hoverBg;
scrollRegistered = false;
get hostElement() { return index.getElement(this); }
showScrollArrows = false;
showLeftArrow = false;
showRightArrow = false;
/** This is the name of the radio buttons inside the controller. @deprecated Set the name in the nested `pn-segment` components. */
name;
/** Currently active segment value. */
value;
valueHandler() {
this.setActiveSegment();
}
changeHandler(event) {
const target = event.target;
this.value = target.value;
this.setActiveSegment();
}
handleResize() {
this.rerender();
}
handleHover(event) {
const { target } = event.detail;
this.calcHighlight(target, true);
}
connectedCallback() {
this.mo = new MutationObserver(() => {
index.forceUpdate(this.hostElement);
this.setSegments();
});
this.mo.observe(this.hostElement, { childList: true, subtree: true });
}
disconnectedCallback() {
if (this.mo)
this.mo.disconnect();
}
componentDidLoad() {
this.setSegments();
}
setSegments() {
const segmentTag = index.transformTag('pn-segment');
const list = this.hostElement.querySelectorAll(segmentTag);
this.segments = Array.from(list);
this.setActiveSegment();
}
setActiveSegment() {
this.segments.forEach(segmentEl => {
if (this.value === segmentEl.value)
segmentEl.setAttribute('selected', 'true');
else
segmentEl.removeAttribute('selected');
});
this.rerender();
}
rerender() {
requestAnimationFrame(() => {
this.calcHighlight();
this.scrollArrowRender();
});
}
/*---------------------------------------HIGHLIGHT LOGIC-------------------------------------------*/
calcHighlight(element, hover) {
const chip = hover ? this.hoverBg : this.activeBg;
requestAnimationFrame(() => {
const el = element || this.segments.find(({ value }) => value === this.value);
const segmentTag = index.transformTag('pn-segment');
const elSegment = el?.closest(segmentTag);
if (!elSegment)
return;
const elRect = elSegment.getBoundingClientRect();
const { left: hostLeft } = this.segmentContainer.getBoundingClientRect();
const { left: segmentLeft, height: segmentHeight, width: segmentWidth } = elRect;
const offset = segmentLeft - hostLeft + this.segmentContainer.scrollLeft;
chip.style.setProperty('transform', `translate(${offset}px, -50%`);
chip.style.setProperty('width', `${segmentWidth}px`);
chip.style.setProperty('height', `${segmentHeight}px`);
el.disabled ? (chip.dataset.disabled = '') : delete chip.dataset.disabled;
});
}
/*---------------------------------------/HIGHLIGHT LOGIC-------------------------------------------*/
/*---------------------------------------SCROLL ARROW LOGIC-------------------------------------------*/
scrollArrowRender() {
if (this.segmentContainer.scrollWidth > this.segmentContainer.clientWidth) {
this.showScrollArrows = true;
if (!this.scrollRegistered) {
this.segmentContainer.addEventListener('scroll', this.scrollArrowRender.bind(this));
this.scrollRegistered = true;
}
const amountScrolled = Math.round(this.segmentContainer.scrollWidth - this.segmentContainer.scrollLeft);
const distanceToEnd = amountScrolled - this.segmentContainer.clientWidth;
const distanceToStart = this.segmentContainer.scrollLeft;
this.showLeftArrow = distanceToStart > 0;
this.showRightArrow = distanceToEnd > 0;
}
else {
this.showLeftArrow = false;
this.showRightArrow = false;
this.showScrollArrows = false;
}
}
scroll(val) {
let amount = this.segmentContainer.scrollLeft + val;
this.segmentContainer.scroll({
left: amount,
behavior: 'smooth',
});
}
/*---------------------------------------/SCROLL ARROW LOGIC-------------------------------------------*/
render() {
return (index.h(index.Host, { key: 'e50018a767b5280ce0144544f3fb213b8f025944' }, index.h("div", { key: '8f9f4beedc7b07d2431fde84456a96d501bdbf15', class: "pn-segmented-control", ref: el => (this.segmentContainer = el) }, index.h("slot", { key: '1caffca6e2cd27adcb2c5bfa5b45f52043c85829' }), index.h("div", { key: '3ef184c6e26f194aa3b5e3ef284313f73aa03a6e', class: "pn-sc-bg", "data-active": true, ref: el => (this.activeBg = el) }), index.h("div", { key: '90c56a3f631557e062f70b4ef98231eafc1f46d7', class: "pn-sc-bg", "data-hover": true, ref: el => (this.hoverBg = el) })), index.h("div", { key: '371d10511a314e69613a195858dba3073f7ca920', class: "pn-sc-arrows", "data-left": this.showLeftArrow, "data-right": this.showRightArrow, hidden: !this.showScrollArrows }, index.h("button", { key: 'e698d859b989e8fde8864185d3fdce81584280da', "aria-label": "Left", class: "pn-sc-arrow pn-sc-arrow-left", onClick: () => this.scroll(-120), tabindex: "-1" }, index.h("pn-icon", { key: 'e82f3b0257bd48dc281a6c113cecbd0cb551fd53', icon: arrow_left.arrow_left })), index.h("button", { key: '8eba509c3c48304c372d543e51edecaaf41cf564', "aria-label": "Right", class: "pn-sc-arrow pn-sc-arrow-right", onClick: () => this.scroll(120), tabindex: "-1" }, index.h("pn-icon", { key: '0ed1d7cd2b88a619f21e2ee8075c864f9bdcf561', icon: arrow_right.arrow_right })))));
}
static get watchers() { return {
"value": [{
"valueHandler": 0
}]
}; }
};
PnSegmentedControl.style = pnSegmentedControlCss();
exports.pn_segmented_control = PnSegmentedControl;