@onesy/ui-react
Version:
UI for React
327 lines (317 loc) • 13.1 kB
JavaScript
import { is, canvasFilterBrightness, canvasFilterContrast, canvasFilterSaturation, canvasFilterFade, canvasFilterInvert, canvasFilterOldPhoto, download, clamp, isEnvironment } from '@onesy/utils';
export { default as currencies } from './currencies';
export function reflow(element) {
return element?.offsetHeight;
}
export const staticClassName = (name, theme) => {
return theme?.ui?.elements?.[`onesy-${name}`]?.className?.static !== undefined ? theme?.ui?.elements?.[`onesy-${name}`]?.className?.static : theme?.ui?.className.static;
};
export const iconSizeToFontSize = value => {
let fontSize = '1.5rem';
if (value === 'very small') fontSize = '0.75rem';else if (value === 'small') fontSize = '1.125rem';else if (value === 'regular') fontSize = '1.5rem';else if (value === 'medium') fontSize = '1.875rem';else if (value === 'large') fontSize = '2.25rem';else if (value === 'very large') fontSize = '2.625rem';else if (value !== undefined) fontSize = value;
return fontSize;
};
// Media query value or value
export const valueBreakpoints = (item, value, breakpoints, theme) => {
// Simple
if (!is('object', item) && item !== undefined) return item;
const breakpointsKeysTheme = Object.keys(theme.breakpoints.media);
const breakpointsKeys = Object.keys(breakpoints || {});
// No breakpoints object
if (is('object', item) && !Object.keys(item).every(prop => ['default', ...breakpointsKeysTheme].includes(prop))) return item;
// Item
if (is('object', item)) {
for (const breakpoint of breakpointsKeys) {
if (breakpoints[breakpoint] && item?.[breakpoint] !== undefined) return item[breakpoint];
}
if (item?.default !== undefined) return item?.default;
}
// Value
if (is('object', value)) {
for (const breakpoint of breakpointsKeys) {
if (breakpoints[breakpoint] && value?.[breakpoint] !== undefined) return value[breakpoint];
}
if (value?.default !== undefined) return value?.default;
}
return value;
};
export const image = uri => new Promise((resolve, reject) => {
const img = document.createElement('img');
const method = () => resolve(img);
img.onload = method;
img.onerror = () => resolve('');
img.src = uri;
});
export const canvasBrightness = (value, mainCanvas, valueCopy) => {
const rootDocument = mainCanvas?.ownerDocument || window.document;
const canvas = rootDocument.createElement('canvas');
canvas.width = valueCopy.width;
canvas.height = valueCopy.height;
const context = canvas.getContext('2d');
context.drawImage(valueCopy, 0, 0);
if (![0, undefined].includes(value)) canvasFilterBrightness(value, canvas);
mainCanvas?.getContext('2d').drawImage(canvas, 0, 0, canvas.width, canvas.height);
return canvas;
};
export const canvasContrast = (value, mainCanvas, valueCopy) => {
const rootDocument = mainCanvas?.ownerDocument || window.document;
const canvas = rootDocument.createElement('canvas');
canvas.width = valueCopy.width;
canvas.height = valueCopy.height;
const context = canvas.getContext('2d');
context.drawImage(valueCopy, 0, 0);
if (![0, undefined].includes(value)) canvasFilterContrast(value, canvas);
mainCanvas?.getContext('2d').drawImage(canvas, 0, 0, canvas.width, canvas.height);
return canvas;
};
export const canvasSaturation = (value, mainCanvas, valueCopy) => {
const rootDocument = mainCanvas?.ownerDocument || window.document;
const canvas = rootDocument.createElement('canvas');
canvas.width = valueCopy.width;
canvas.height = valueCopy.height;
const context = canvas.getContext('2d');
context.drawImage(valueCopy, 0, 0);
if (![0, undefined].includes(value)) canvasFilterSaturation(value, canvas);
mainCanvas?.getContext('2d').drawImage(canvas, 0, 0, canvas.width, canvas.height);
return canvas;
};
export const canvasFade = (value, mainCanvas, valueCopy) => {
const rootDocument = mainCanvas?.ownerDocument || window.document;
const canvas = rootDocument.createElement('canvas');
canvas.width = valueCopy.width;
canvas.height = valueCopy.height;
const context = canvas.getContext('2d');
context.drawImage(valueCopy, 0, 0);
if (![0, undefined].includes(value)) canvasFilterFade(value, canvas);
mainCanvas?.getContext('2d').drawImage(canvas, 0, 0, canvas.width, canvas.height);
return canvas;
};
export const canvasInvert = (value, mainCanvas, valueCopy) => {
const rootDocument = mainCanvas?.ownerDocument || window.document;
const canvas = rootDocument.createElement('canvas');
canvas.width = valueCopy.width;
canvas.height = valueCopy.height;
const context = canvas.getContext('2d');
context.drawImage(valueCopy, 0, 0);
if (![0, undefined].includes(value)) canvasFilterInvert(value, canvas);
mainCanvas?.getContext('2d').drawImage(canvas, 0, 0, canvas.width, canvas.height);
return canvas;
};
export const canvasOldPhoto = (value, mainCanvas, valueCopy) => {
const rootDocument = mainCanvas?.ownerDocument || window.document;
const canvas = rootDocument.createElement('canvas');
canvas.width = valueCopy.width;
canvas.height = valueCopy.height;
const context = canvas.getContext('2d');
context.drawImage(valueCopy, 0, 0);
if (![0, undefined].includes(value)) canvasFilterOldPhoto(value, canvas);
mainCanvas?.getContext('2d').drawImage(canvas, 0, 0, canvas.width, canvas.height);
return canvas;
};
export const print = element => {
const rootDocument = element?.ownerDocument || window.document;
const clone = rootDocument.cloneNode(true);
clone.body.innerHTML = '';
const elementClone = element.cloneNode(true);
clone.body.append(elementClone);
const windowNew = window.open('', 'print');
windowNew.document.head.innerHTML = clone.head.innerHTML;
windowNew.document.body.innerHTML = clone.body.innerHTML;
windowNew.document.close();
windowNew.focus();
windowNew.print();
windowNew.close();
};
export const save = element => {
const rootDocument = element?.ownerDocument || window.document;
const clone = rootDocument.cloneNode(true);
clone.body.innerHTML = '';
const elementClone = element.cloneNode(true);
elementClone.contentEditable = 'false';
clone.body.append(elementClone);
download(`${rootDocument.title}.html`, clone.documentElement.innerHTML, 'text/html');
};
export const matches = value => {
const method = is('element', value) && (value.matches || value['webkitMatchesSelector'] || value['mozMatchesSelector'] || value['oMatchesSelector'] || value['msMatchesSelector']);
if (!method) return () => false;
return method.bind(value);
};
export const angleToCoordinates = (degrees, centerX, centerY, radius) => {
const radians = degrees * Math.PI / 180;
return {
x: centerX + radius * Math.cos(radians),
y: centerY + radius * Math.sin(radians)
};
};
export const line = (pointA, pointB) => {
const lengthX = pointB[0] - pointA[0];
const lengthY = pointB[1] - pointA[1];
return {
length: Math.sqrt(Math.pow(lengthX, 2) + Math.pow(lengthY, 2)),
angle: Math.atan2(lengthY, lengthX)
};
};
export const controlPoint = (current, previous_, next_, reverse = false, smoothRatio = 0.14) => {
const previous = previous_ || current;
const next = next_ || current;
const opposed = line(previous, next);
const angle = opposed.angle + (reverse ? Math.PI : 0);
const length = opposed.length * smoothRatio;
// Bug fix, prevent ties if x are the same
// for previous, and current value
const x = clamp(current[0] + Math.cos(angle) * length, previous[0], next[0]);
const y = current[1] + Math.sin(angle) * length;
return [x, y];
};
export const minMaxBetweenNumbers = (value = 10, min = 0, max = 100) => {
const part = (max - min) / (value - 1);
const values = [min];
for (let i = 0; i < value - 2; i++) values.push(values[values.length - 1] + part);
values.push(max);
return values;
};
export const sanitize = value => {
if (value) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
"/": '/',
"\\": '\',
'*': '*'
};
const reg = /[&<>"'/\\*]/ig;
return value.replace(reg, match => map[match]);
}
};
export const replace = (value, split, join) => {
return value.split(split).join(join);
};
export const importIframeStyles = iframeDocument => {
const styleSheets = window.document.styleSheets;
for (const styleSheet of Array.from(styleSheets)) {
if (!styleSheet.ownerNode.onesy) {
iframeDocument.head.append(styleSheet.ownerNode?.cloneNode(true));
continue;
}
let css = '';
const rules = styleSheet?.cssRules;
for (const rule of Array.from(rules)) css += rule.cssText;
const style = window.document.createElement('style');
style.innerHTML = css;
iframeDocument.head.append(style);
}
};
export const getOverflowParent = (element, vertical = true) => {
if (!element) return;
// height
if (vertical && element.scrollHeight > element.clientHeight) return element;
// width
if (!vertical && element.scrollWidth > element.clientWidth) return element;
return getOverflowParent(element.parentElement, vertical);
};
export const keyboardStandardCommands = ['a', 'c', 'v', 'y', 'z'];
export const keyboardStyleCommands = ['b', 'i', 'u'];
export const caret = {};
if (isEnvironment('browser')) {
if (window.getSelection && document.createRange) {
// Saves caret position(s)
caret.save = function (container) {
const selection = window.getSelection();
if (!(selection && selection.rangeCount > 0)) return;
const range = window.getSelection()?.getRangeAt(0);
if (!range) return;
const preSelectionRange = range.cloneRange();
preSelectionRange.selectNodeContents(container);
preSelectionRange.setEnd(range.startContainer, range.startOffset);
const start = preSelectionRange.toString().length;
return {
start: start,
end: start + range.toString().length
};
};
// Restores caret position(s)
caret.restore = function (container, savedElement) {
let charIndex = 0;
const range = document.createRange();
range.setStart(container, 0);
range.collapse(true);
const nodeStack = [container];
let node;
let foundStart = false;
let stop = false;
// tslint:disable-next-line
while (!stop && (node = nodeStack.pop())) {
if (node.nodeType === 3) {
const nextCharIndex = charIndex + node.length;
if (!foundStart && savedElement.start >= charIndex && savedElement.start <= nextCharIndex) {
range.setStart(node, savedElement.start - charIndex);
foundStart = true;
}
if (foundStart && savedElement.end >= charIndex && savedElement.end <= nextCharIndex) {
range.setEnd(node, savedElement.end - charIndex);
stop = true;
}
charIndex = nextCharIndex;
} else {
let i = node.childNodes.length;
while (i--) {
nodeStack.push(node.childNodes[i]);
}
}
}
const selection = window.getSelection();
selection?.removeAllRanges();
selection?.addRange(range);
};
} else if (process.window && window.document.selection && window.document.body.createTextRange) {
// Saves caret position(s)
caret.save = function (container) {
const selectedTextRange = window.document.selection.createRange();
const preSelectionTextRange = window.document.body.createTextRange();
preSelectionTextRange.moveToElementText(container);
preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
const start = preSelectionTextRange.text.length;
return {
start: start,
end: start + selectedTextRange.text.length
};
};
// Restores caret position(s)
caret.restore = function (container, savedElement) {
const textRange = window.document.body.createTextRange();
textRange.moveToElementText(container);
textRange.collapse(true);
textRange.moveEnd("character", savedElement.end);
textRange.moveStart("character", savedElement.start);
textRange.select();
};
}
}
export const toNumber = (item, valueDefault = 0) => (is('number', item) ? item : +String(item).match(/\d+.?\d+/)?.[0]) || valueDefault;
export const formats = {
entire: 'DD MMM, YYYY [at] h:mm a',
date: 'DD MMM, YYYY',
time: 'h:mm a'
};
export const iconFontSize = 20;
export const decodeHTMLEntities = html => {
const document = new DOMParser().parseFromString(html, 'text/html');
return document.documentElement.textContent || '';
};
export const scrollToMiddleOfParent = element => {
const parent = element.parentElement;
if (!parent) return;
const rects = {
element: element.getBoundingClientRect(),
parent: parent.getBoundingClientRect()
};
const offsetTop = rects.element.top - rects.parent.top + parent.scrollTop;
const top = offsetTop - parent.clientHeight / 2 + element.offsetHeight / 2;
parent.scrollTo({
top,
behavior: 'smooth'
});
};