@postnord/web-components
Version:
PostNord Web Components
190 lines (184 loc) • 6.59 kB
JavaScript
/*!
* Built with Stencil
* By PostNord.
*/
const byteToHex = [];
for (let i = 0; i < 256; ++i) {
byteToHex.push((i + 0x100).toString(16).slice(1));
}
function unsafeStringify(arr, offset = 0) {
return (byteToHex[arr[offset + 0]] +
byteToHex[arr[offset + 1]] +
byteToHex[arr[offset + 2]] +
byteToHex[arr[offset + 3]] +
'-' +
byteToHex[arr[offset + 4]] +
byteToHex[arr[offset + 5]] +
'-' +
byteToHex[arr[offset + 6]] +
byteToHex[arr[offset + 7]] +
'-' +
byteToHex[arr[offset + 8]] +
byteToHex[arr[offset + 9]] +
'-' +
byteToHex[arr[offset + 10]] +
byteToHex[arr[offset + 11]] +
byteToHex[arr[offset + 12]] +
byteToHex[arr[offset + 13]] +
byteToHex[arr[offset + 14]] +
byteToHex[arr[offset + 15]]).toLowerCase();
}
let getRandomValues;
const rnds8 = new Uint8Array(16);
function rng() {
if (!getRandomValues) {
if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
}
getRandomValues = crypto.getRandomValues.bind(crypto);
}
return getRandomValues(rnds8);
}
const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
const native = { randomUUID };
function v4(options, buf, offset) {
if (native.randomUUID && !buf && !options) {
return native.randomUUID();
}
options = options || {};
const rnds = options.random ?? options.rng?.() ?? rng();
if (rnds.length < 16) {
throw new Error('Random bytes length must be >= 16');
}
rnds[6] = (rnds[6] & 0x0f) | 0x40;
rnds[8] = (rnds[8] & 0x3f) | 0x80;
if (buf) {
offset = offset || 0;
if (offset < 0 || offset + 16 > buf.length) {
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
}
for (let i = 0; i < 16; ++i) {
buf[offset + i] = rnds[i];
}
return buf;
}
return unsafeStringify(rnds);
}
const SE = 'SE';
const DK = 'DK';
const FI = 'FI';
const NO = 'NO';
const sv = 'sv';
const en = 'en';
const da = 'da';
const fi = 'fi';
const no = 'no';
const markets = [SE, DK, FI, NO];
const languages = [sv, en, da, fi, no];
const marketMap = {
SE: [sv, en],
DK: [da, en],
FI: [fi, sv, en],
NO: [no, en],
};
const humanReadableFileSize = {
KB: 1024,
MB: 1024 * 1024,
GB: 1024 * 1024,
TB: 1024 * 1024 * 1024,
};
const getBytesFromHumanReadableFileSize = function (sizeString) {
const fileSizeChecker = /(\d+\.?\d*)\s?([a-zA-Z]{2})?$/;
if (fileSizeChecker.test(sizeString)) {
const matches = sizeString.match(fileSizeChecker);
const unit = (matches[2] || '').toLocaleUpperCase();
const size = parseInt(matches[1]);
if (unit && humanReadableFileSize[unit]) {
const baseSize = humanReadableFileSize[unit];
return size * baseSize;
}
return size;
}
return 0;
};
function isSmallScreen() {
return window.innerWidth / 16 < 55;
}
const uuidv4 = () => v4();
function getTopbarHeight() {
return document?.querySelector('pn-topbar')?.offsetHeight || 0;
}
function getMenuHeight() {
return isSmallScreen() ? document?.querySelector('pn-side-menu')?.offsetHeight || 0 : 0;
}
function getTotalHeightOffset() {
const totalOffset = getTopbarHeight() + getMenuHeight();
return totalOffset > window.scrollY ? totalOffset - window.scrollY : 0;
}
/**
* @param {HTMLElement} host Use the `this.hostElement` property.
*
* @description The `awaitTopbar` function can be used to wait for the topbar to be available.
*
* The function will also setup listeners for any market/language changes from the topbar and updates the host element with the `setAttribute` function.
*
* Remember to use a Stencil `@Prop` named `market` and/or `language` to take advantage of the auto update feature.
*
* @returns The pnTopbar object.
*/
async function awaitTopbar(host) {
const topbar = () => window.pnTopbar;
function finishSetup(fallBack) {
const data = fallBack || topbar();
host.market = data.market;
host.language = data.language;
if (data.hasLoaded) {
topbar().onChangeMarket = (market) => (host.market = market);
topbar().onChangeLanguage = (language) => (host.language = language);
}
return data;
}
return await new Promise(resolve => {
// If the pntopbar script does not exist. Resolve with default values.
if (!document.querySelector('pn-topbar'))
return resolve(finishSetup({ hasLoaded: false, market: host.market || SE, language: host.language || en }));
if (topbar()?.hasLoaded)
return resolve(finishSetup());
window.addEventListener('topbarLoaded', () => resolve(finishSetup()));
});
}
/**
* @description Apply the Ripple effect quick and easy.
*
* @example
* ```css
* // CSS
* pn-component-name { `@include pn-ripple($blue700) }
* ```
*
* ```js
* // tsx
* onClick((e) => ripple(e, this.hostElement, '.pn-ripple-container'))
* ```
* @param event The MouseEvent from a onClick handler.
* @param host The hostElement of the component (root element).
* @param rippleClass Append the ripple event to this selector instead of the host element.
*/
const ripple = (event, host, rippleClass) => {
const { left, top, width, height } = host.getBoundingClientRect();
const { clientX = 0, clientY = 0 } = event || {};
const elSize = width > height ? width : height;
const element = document.createElement('div');
element.classList.add('pn-ripple');
element.style.height = `${elSize * 2}px`;
element.style.width = `${elSize * 2}px`;
element.style.left = clientX > 0 ? `${clientX - left}px` : `50%`;
element.style.top = clientY > 0 ? `${clientY - top}px` : `50%`;
if (rippleClass)
host.querySelector(rippleClass).appendChild(element);
else
host.appendChild(element);
setTimeout(() => element.remove(), 400);
};
export { DK as D, FI as F, NO as N, SE as S, marketMap as a, getTopbarHeight as b, getMenuHeight as c, da as d, en as e, fi as f, getBytesFromHumanReadableFileSize as g, getTotalHeightOffset as h, isSmallScreen as i, awaitTopbar as j, languages as l, markets as m, no as n, ripple as r, sv as s, uuidv4 as u };
//# sourceMappingURL=helpers.js.map