Buckets:
| import { createContext, createSignal, splitProps, useContext } from "solid-js" | |
| import type { JSX } from "solid-js/jsx-runtime" | |
| import { makeResizeObserver } from "@solid-primitives/resize-observer" | |
| import { IconCheckCircle, IconHashtag } from "../icons" | |
| export type ShareMessages = { locale: string } & Record<string, string> | |
| const shareContext = createContext<ShareMessages>() | |
| export function ShareI18nProvider(props: { messages: ShareMessages; children: JSX.Element }) { | |
| return <shareContext.Provider value={props.messages}>{props.children}</shareContext.Provider> | |
| } | |
| export function useShareMessages() { | |
| const value = useContext(shareContext) | |
| if (value) { | |
| return value | |
| } | |
| throw new Error("ShareI18nProvider is required") | |
| } | |
| export function normalizeLocale(locale: string) { | |
| return locale === "root" ? "en" : locale | |
| } | |
| export function formatNumber(value: number, locale: string) { | |
| return new Intl.NumberFormat(normalizeLocale(locale)).format(value) | |
| } | |
| export function formatCurrency(value: number, locale: string) { | |
| return new Intl.NumberFormat(normalizeLocale(locale), { | |
| style: "currency", | |
| currency: "USD", | |
| minimumFractionDigits: 2, | |
| maximumFractionDigits: 2, | |
| }).format(value) | |
| } | |
| export function formatCount(value: number, locale: string, singular: string, plural: string) { | |
| const unit = value === 1 ? singular : plural | |
| return `${formatNumber(value, locale)} ${unit}` | |
| } | |
| interface AnchorProps extends JSX.HTMLAttributes<HTMLDivElement> { | |
| id: string | |
| } | |
| export function AnchorIcon(props: AnchorProps) { | |
| const [local, rest] = splitProps(props, ["id", "children"]) | |
| const [copied, setCopied] = createSignal(false) | |
| const messages = useShareMessages() | |
| return ( | |
| <div {...rest} data-element-anchor title={messages.link_to_message} data-status={copied() ? "copied" : ""}> | |
| <a | |
| href={`#${local.id}`} | |
| onClick={(e) => { | |
| e.preventDefault() | |
| const anchor = e.currentTarget | |
| const hash = anchor.getAttribute("href") || "" | |
| const { origin, pathname, search } = window.location | |
| navigator.clipboard | |
| .writeText(`${origin}${pathname}${search}${hash}`) | |
| .catch((err) => console.error("Copy failed", err)) | |
| setCopied(true) | |
| setTimeout(() => setCopied(false), 3000) | |
| }} | |
| > | |
| {local.children} | |
| <IconHashtag width={18} height={18} /> | |
| <IconCheckCircle width={18} height={18} /> | |
| </a> | |
| <span data-element-tooltip>{messages.copied}</span> | |
| </div> | |
| ) | |
| } | |
| export function createOverflow() { | |
| const [overflow, setOverflow] = createSignal(false) | |
| return { | |
| get status() { | |
| return overflow() | |
| }, | |
| ref(el: HTMLElement) { | |
| const sync = () => { | |
| setOverflow(el.scrollHeight > el.clientHeight + 1) | |
| } | |
| const obs = makeResizeObserver(sync) | |
| obs.observe(el) | |
| sync() | |
| }, | |
| } | |
| } | |
| export function formatDuration(ms: number, locale: string): string { | |
| const normalized = normalizeLocale(locale) | |
| const ONE_SECOND = 1000 | |
| const ONE_MINUTE = 60 * ONE_SECOND | |
| if (ms >= ONE_MINUTE) { | |
| return new Intl.NumberFormat(normalized, { | |
| style: "unit", | |
| unit: "minute", | |
| unitDisplay: "narrow", | |
| maximumFractionDigits: 0, | |
| }).format(Math.floor(ms / ONE_MINUTE)) | |
| } | |
| if (ms >= ONE_SECOND) { | |
| return new Intl.NumberFormat(normalized, { | |
| style: "unit", | |
| unit: "second", | |
| unitDisplay: "narrow", | |
| maximumFractionDigits: 0, | |
| }).format(Math.floor(ms / ONE_SECOND)) | |
| } | |
| return new Intl.NumberFormat(normalized, { | |
| style: "unit", | |
| unit: "millisecond", | |
| unitDisplay: "narrow", | |
| maximumFractionDigits: 0, | |
| }).format(ms) | |
| } | |
Xet Storage Details
- Size:
- 3.7 kB
- Xet hash:
- ca357ca7e078abc1033e003cd9a763efb6b5dd39d4e841752f23a93c6ba2238c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.