import Big from "big.js"; import { fromUnixTime, intlFormat } from "date-fns"; import { createMemo, JSX } from "solid-js"; export const sleep = (timeout: number) => new Promise((res) => setTimeout(res, timeout)); // Source: https://stackoverflow.com/a/34591063 export const roundToStep = (value: number, step = 1.0) => { const inv = new Big(1.0).div(step); return inv.mul(value).round().div(inv).toNumber(); }; export const getDisplayDate = function (date: Date) { return intlFormat( date, { day: "2-digit", month: "2-digit", year: "numeric", }, { locale: "de-CH", } ); }; export const getDisplayDateFromUnix = function (unix: number) { return getDisplayDate(fromUnixTime(unix)); }; export const resetInput = (defaultValue: any, eventName = "input") => (evt: FocusEvent) => { const el = evt.target as HTMLInputElement | null; if (!el) { return; } if (el.value !== "") { return; } el.value = defaultValue; const event = new Event(eventName, { bubbles: true }); el.dispatchEvent(event); }; export const getDomain = () => import.meta.env.SSR ? process.env.DOMAIN || "localhost" : location.hostname; export const getHost = () => `https://${getDomain()}`; export const onClickFocus: JSX.EventHandlerUnion< HTMLAnchorElement, MouseEvent > = (evt) => { const el = evt.currentTarget!; const id = el.getAttribute("href"); if (id == null) { return; } const targetEl = document.querySelector(id); if (targetEl == null) { return; } targetEl.focus(); }; export const externalLink = { target: "_blank", rel: "noopener" }; export const createOptionalNumberInputHandler = ( onInput: (v: number | undefined) => void ) => { return (e: InputEvent & { currentTarget: HTMLInputElement }) => { if (e.currentTarget.validity.badInput) { return; } let value = e.currentTarget.value == "" ? undefined : parseNumberInput(e.currentTarget.value); if (Number.isNaN(value)) { return; } onInput(value); }; }; const parseNumberInput = (v: string): number => parseFloat(v.replace(",", ".")); export const createNativeInputValue = ( getEl: () => HTMLInputElement, signal: () => any ) => createMemo(function (prev) { const value = signal(); const el = getEl(); if (!el) { return value != null ? value : ""; } const elValue = parseNumberInput(el.value); // If the element value and signal value are equal, we can skip triggering the memo change by reusing the prev value let result = elValue == value ? prev : value; // NaN is always != NaN in js, we have to replace it with a value which has a proper identity if (Number.isNaN(result)) { result = undefined; } if (result == null) { result = ""; } // If both the value and prev value are the same, but the element value is different, we have to update it manually if (value === prev && elValue != value) { el.value = result; } return result; });