UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

220 lines (216 loc) • 5.37 kB
import { c } from 'react-compiler-runtime'; import { clsx } from 'clsx'; import { useState, useEffect } from 'react'; import classes from './Spinner.module.css.js'; import { useMedia } from '../hooks/useMedia.js'; import { jsxs, jsx } from 'react/jsx-runtime'; import { useId } from '../hooks/useId.js'; import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden.js'; const ANIMATION_DURATION_MS = 1000; const sizeMap = { small: '16px', medium: '32px', large: '64px' }; function Spinner(t0) { var _ariaLabel; const $ = c(35); let ariaLabel; let className; let props; let style; let t1; let t2; let t3; if ($[0] !== t0) { ({ size: t1, srText: t2, "aria-label": ariaLabel, className, style, delay: t3, ...props } = t0); $[0] = t0; $[1] = ariaLabel; $[2] = className; $[3] = props; $[4] = style; $[5] = t1; $[6] = t2; $[7] = t3; } else { ariaLabel = $[1]; className = $[2]; props = $[3]; style = $[4]; t1 = $[5]; t2 = $[6]; t3 = $[7]; } const sizeKey = t1 === undefined ? "medium" : t1; const srText = t2 === undefined ? "Loading" : t2; const delay = t3 === undefined ? false : t3; const noMotionPreference = useMedia("(prefers-reduced-motion: no-preference)", false); const size = sizeMap[sizeKey]; const hasHiddenLabel = srText !== null && ariaLabel === undefined; const labelId = useId(); let t4; if ($[8] !== delay) { t4 = () => ({ isVisible: !delay, syncDelay: !delay ? computeSyncDelay() : 0 }); $[8] = delay; $[9] = t4; } else { t4 = $[9]; } const [t5, setVisibleState] = useState(t4); const { isVisible, syncDelay } = t5; let t6; let t7; if ($[10] !== delay) { t6 = () => { if (delay) { const delayDuration = typeof delay === "number" ? delay : delay === "short" ? 300 : 1000; const timeoutId = setTimeout(() => { setVisibleState({ isVisible: true, syncDelay: computeSyncDelay() }); }, delayDuration); return () => clearTimeout(timeoutId); } }; t7 = [delay]; $[10] = delay; $[11] = t6; $[12] = t7; } else { t6 = $[11]; t7 = $[12]; } useEffect(t6, t7); if (!isVisible) { return null; } let t8; if ($[13] !== noMotionPreference || $[14] !== style || $[15] !== syncDelay) { t8 = noMotionPreference ? { ...style, animationDelay: `${syncDelay}ms` } : style; $[13] = noMotionPreference; $[14] = style; $[15] = syncDelay; $[16] = t8; } else { t8 = $[16]; } const mergedStyle = t8; const t9 = (_ariaLabel = ariaLabel) !== null && _ariaLabel !== void 0 ? _ariaLabel : undefined; const t10 = hasHiddenLabel ? labelId : undefined; let t11; if ($[17] !== className) { t11 = clsx(className, classes.SpinnerAnimation); $[17] = className; $[18] = t11; } else { t11 = $[18]; } let t12; let t13; if ($[19] === Symbol.for("react.memo_cache_sentinel")) { t12 = /*#__PURE__*/jsx("circle", { cx: "8", cy: "8", r: "7", stroke: "currentColor", strokeOpacity: "0.25", strokeWidth: "2", vectorEffect: "non-scaling-stroke" }); t13 = /*#__PURE__*/jsx("path", { d: "M15 8a7.002 7.002 0 00-7-7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", vectorEffect: "non-scaling-stroke" }); $[19] = t12; $[20] = t13; } else { t12 = $[19]; t13 = $[20]; } let t14; if ($[21] !== mergedStyle || $[22] !== props || $[23] !== size || $[24] !== t10 || $[25] !== t11 || $[26] !== t9) { t14 = /*#__PURE__*/jsxs("svg", { height: size, width: size, viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, "aria-label": t9, "aria-labelledby": t10, className: t11, style: mergedStyle, ...props, children: [t12, t13] }); $[21] = mergedStyle; $[22] = props; $[23] = size; $[24] = t10; $[25] = t11; $[26] = t9; $[27] = t14; } else { t14 = $[27]; } let t15; if ($[28] !== hasHiddenLabel || $[29] !== labelId || $[30] !== srText) { t15 = hasHiddenLabel ? /*#__PURE__*/jsx(VisuallyHidden, { id: labelId, children: srText }) : null; $[28] = hasHiddenLabel; $[29] = labelId; $[30] = srText; $[31] = t15; } else { t15 = $[31]; } let t16; if ($[32] !== t14 || $[33] !== t15) { t16 = /*#__PURE__*/jsxs("span", { className: classes.Box, children: [t14, t15] }); $[32] = t14; $[33] = t15; $[34] = t16; } else { t16 = $[34]; } return t16; } Spinner.displayName = 'Spinner'; /** * Computes a negative animation-delay so all spinners land at the same * rotation angle regardless of when they mount. Because every instance * references the same clock (performance.now()), the CSS animation engine * keeps them visually in sync without any Web Animations API calls * (getAnimations, element.animate, startTime), which are significantly * slower in Safari/WebKit. */ function computeSyncDelay() { const now = typeof performance !== 'undefined' ? performance.now() : 0; return -(now % ANIMATION_DURATION_MS); } export { Spinner as default };