mirror of
https://github.com/livebook-dev/livebook.git
synced 2024-11-17 13:27:50 +08:00
117 lines
2.7 KiB
JavaScript
117 lines
2.7 KiB
JavaScript
import md5 from "crypto-js/md5";
|
|
import encBase64 from "crypto-js/enc-base64";
|
|
|
|
export function isMacOS() {
|
|
return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);
|
|
}
|
|
|
|
export function isEditableElement(element) {
|
|
return (
|
|
["input", "textarea"].includes(element.tagName.toLowerCase()) ||
|
|
element.contentEditable === "true"
|
|
);
|
|
}
|
|
|
|
export function clamp(n, x, y) {
|
|
return Math.min(Math.max(n, x), y);
|
|
}
|
|
|
|
export function getLineHeight(element) {
|
|
const computedStyle = window.getComputedStyle(element);
|
|
const lineHeight = parseInt(computedStyle.lineHeight, 10);
|
|
|
|
if (Number.isNaN(lineHeight)) {
|
|
const clone = element.cloneNode();
|
|
clone.innerHTML = "<br>";
|
|
element.appendChild(clone);
|
|
const singleLineHeight = clone.clientHeight;
|
|
clone.innerHTML = "<br><br>";
|
|
const doubleLineHeight = clone.clientHeight;
|
|
element.removeChild(clone);
|
|
const lineHeight = doubleLineHeight - singleLineHeight;
|
|
return lineHeight;
|
|
} else {
|
|
return lineHeight;
|
|
}
|
|
}
|
|
|
|
export function selectElementContent(element) {
|
|
const selection = window.getSelection();
|
|
const range = document.createRange();
|
|
range.selectNodeContents(element);
|
|
selection.removeAllRanges();
|
|
selection.addRange(range);
|
|
}
|
|
|
|
export function smoothlyScrollToElement(element) {
|
|
const { height } = element.getBoundingClientRect();
|
|
|
|
if (height < window.innerHeight) {
|
|
element.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
} else {
|
|
element.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transforms a UTF8 string into base64 encoding.
|
|
*/
|
|
export function encodeBase64(string) {
|
|
return btoa(unescape(encodeURIComponent(string)));
|
|
}
|
|
|
|
/**
|
|
* Transforms base64 encoding into UTF8 string.
|
|
*/
|
|
export function decodeBase64(binary) {
|
|
return decodeURIComponent(escape(atob(binary)));
|
|
}
|
|
|
|
/**
|
|
* Generates a random string.
|
|
*/
|
|
export function randomId() {
|
|
const array = new Uint8Array(24);
|
|
crypto.getRandomValues(array);
|
|
const byteString = String.fromCharCode(...array);
|
|
return btoa(byteString);
|
|
}
|
|
|
|
/**
|
|
* Calculates MD5 of the given string and returns
|
|
* the base64 encoded binary.
|
|
*/
|
|
export function md5Base64(string) {
|
|
return md5(string).toString(encBase64);
|
|
}
|
|
|
|
/**
|
|
* A simple throttle version that ensures
|
|
* the given function is called at most once
|
|
* within the given time window.
|
|
*/
|
|
export function throttle(fn, windowMs) {
|
|
let ignore = false;
|
|
|
|
return (...args) => {
|
|
if (!ignore) {
|
|
fn(...args);
|
|
ignore = true;
|
|
setTimeout(() => {
|
|
ignore = false;
|
|
}, windowMs);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function findChildOrThrow(element, selector) {
|
|
const child = element.querySelector(selector);
|
|
|
|
if (!child) {
|
|
throw new Error(
|
|
`expected a child matching ${selector}, but none was found`
|
|
);
|
|
}
|
|
|
|
return child;
|
|
}
|