@primer/react
Version:
An implementation of GitHub's Primer Design System using React
220 lines (216 loc) • 5.37 kB
JavaScript
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 };