@sanity/ui-workshop
Version:
An environment for designing, reviewing, and quality-testing React components.
315 lines (314 loc) • 11.1 kB
JavaScript
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
import { c } from "react/compiler-runtime";
import { TrashIcon, PlayIcon } from "@sanity/icons";
import { Box, Text, Stack, Card, Flex, Button } from "@sanity/ui";
import { createContext, useContext, useRef, memo, Profiler, useEffect, useState } from "react";
import { useWorkshop } from "@sanity/ui-workshop";
const PerfContext = createContext(null);
function usePerf() {
const perf = useContext(PerfContext);
if (!perf)
throw new Error("Perf: missing context value");
return perf;
}
function usePerfTest(props) {
const $ = c(18), {
name,
title,
description,
run
} = props, {
activeTest,
addRenderResult,
registerTest
} = usePerf(), active = activeTest === name, ref = useRef(null);
let t0, t1;
$[0] !== description || $[1] !== name || $[2] !== run || $[3] !== title ? (t1 = {
description,
name,
ref,
run,
title
}, $[0] = description, $[1] = name, $[2] = run, $[3] = title, $[4] = t1) : t1 = $[4], t0 = t1;
const test = t0;
let t2;
$[5] !== addRenderResult || $[6] !== name ? (t2 = (id, phase, actualDuration, baseDuration, startTime, commitTime) => {
const result = {
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime,
interactions: /* @__PURE__ */ new Set()
};
setTimeout(() => {
console.log("@todo: render", {
addRenderResult,
name,
result
});
}, 0);
}, $[5] = addRenderResult, $[6] = name, $[7] = t2) : t2 = $[7];
const handleRender = t2;
let t3, t4;
$[8] !== active || $[9] !== handleRender || $[10] !== name ? (t4 = memo(function(t52) {
const {
children
} = t52;
return active ? /* @__PURE__ */ jsx(Profiler, { id: name, onRender: handleRender, children }) : /* @__PURE__ */ jsx(Fragment, { children });
}), $[8] = active, $[9] = handleRender, $[10] = name, $[11] = t4) : t4 = $[11], t3 = t4;
const Wrapper = t3;
let t5, t6;
$[12] !== registerTest || $[13] !== test ? (t5 = () => registerTest(test), t6 = [registerTest, test], $[12] = registerTest, $[13] = test, $[14] = t5, $[15] = t6) : (t5 = $[14], t6 = $[15]), useEffect(t5, t6);
let t7, t8;
return $[16] !== Wrapper ? (t8 = {
ref,
Wrapper
}, $[16] = Wrapper, $[17] = t8) : t8 = $[17], t7 = t8, t7;
}
const PerfInspector = memo(function() {
const $ = c(12), {
clearResults,
results,
runTest,
testDetails
} = usePerf();
if (testDetails.length === 0) {
let t02;
return $[0] === Symbol.for("react.memo_cache_sentinel") ? (t02 = /* @__PURE__ */ jsx(Box, { padding: 2, children: /* @__PURE__ */ jsx(Box, { padding: 2, children: /* @__PURE__ */ jsx(Text, { muted: !0, size: [2, 2, 1], children: "No tests" }) }) }), $[0] = t02) : t02 = $[0], t02;
}
let t0;
if ($[1] !== clearResults || $[2] !== results || $[3] !== runTest || $[4] !== testDetails) {
let t12;
$[6] !== clearResults || $[7] !== results || $[8] !== runTest ? (t12 = (detail) => {
const testResults = results.filter((r) => r.name === detail.name);
return /* @__PURE__ */ jsxs(Card, { border: !0, overflow: "hidden", radius: 2, style: {
lineHeight: 0
}, children: [
/* @__PURE__ */ jsxs(Flex, { children: [
/* @__PURE__ */ jsxs(Stack, { flex: 1, padding: 2, space: 2, children: [
/* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", children: detail.title || detail.name }),
detail.description && /* @__PURE__ */ jsx(Text, { muted: !0, size: 1, children: detail.description })
] }),
/* @__PURE__ */ jsx(Flex, { align: "flex-start", gap: 1, padding: 1, children: /* @__PURE__ */ jsx(Button, { "aria-label": "Clear results", fontSize: 1, icon: TrashIcon, mode: "bleed", onClick: () => clearResults(detail.name), padding: 1 }) })
] }),
/* @__PURE__ */ jsxs(Stack, { children: [
testResults.map(_temp2),
/* @__PURE__ */ jsx(Card, { borderTop: !0, children: /* @__PURE__ */ jsx(Stack, { children: /* @__PURE__ */ jsx(Button, { "aria-label": "Run", fontSize: 1, icon: PlayIcon, mode: "bleed", onClick: () => runTest(detail.name), padding: 2, radius: 0 }) }) })
] })
] }, detail.name);
}, $[6] = clearResults, $[7] = results, $[8] = runTest, $[9] = t12) : t12 = $[9], t0 = testDetails.map(t12), $[1] = clearResults, $[2] = results, $[3] = runTest, $[4] = testDetails, $[5] = t0;
} else
t0 = $[5];
let t1;
return $[10] !== t0 ? (t1 = /* @__PURE__ */ jsx(Stack, { padding: 2, space: 2, children: t0 }), $[10] = t0, $[11] = t1) : t1 = $[11], t1;
});
function _temp$1(r_0, rIdx) {
return /* @__PURE__ */ jsx(Card, { children: r_0.phase }, rIdx);
}
function _temp2(result, resultIndex) {
return /* @__PURE__ */ jsxs(Card, { borderTop: !0, children: [
/* @__PURE__ */ jsx(Stack, { children: result.renders.map(_temp$1) }),
/* @__PURE__ */ jsxs(Flex, { padding: 2, children: [
/* @__PURE__ */ jsx(Box, { flex: 1, children: /* @__PURE__ */ jsxs(Text, { muted: !0, size: 1, children: [
result.timing?.runs,
" runs"
] }) }),
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { size: 1, children: [
"Avg. ",
result.timing?.avgDuration.toFixed(3),
"ms"
] }) })
] })
] }, resultIndex);
}
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function _runTest(test, target) {
performance.clearMarks(), performance.clearMeasures();
for (let i = 0; i < 1; i += 1)
performance.mark(`start:${test.name}`), await test.run({
target
}), performance.mark(`end:${test.name}`), performance.measure(test.name, `start:${test.name}`, `end:${test.name}`), await delay(100);
const sumDuration = performance.getEntriesByName(test.name).reduce((t, e) => t + e.duration, 0);
return {
avgDuration: sumDuration / 1,
sumDuration,
runs: 1
};
}
function perfReducer(state, msg) {
if (msg.type === "workshop/perf/clearResults")
return {
...state,
results: state.results.filter((d) => d.name !== msg.name)
};
if (msg.type === "workshop/perf/registerTest")
return {
...state,
testDetails: state.testDetails.concat([{
description: msg.description,
name: msg.name,
title: msg.title
}])
};
if (msg.type === "workshop/perf/unregisterTest")
return {
...state,
testDetails: state.testDetails.filter((d) => d.name !== msg.name)
};
if (msg.type === "workshop/perf/runTest")
return {
...state,
activeTest: msg.name,
results: state.results.concat([{
name: msg.name,
renders: []
}])
};
if (msg.type === "workshop/perf/addResult") {
if (state.activeTest === msg.name) {
const result = state.results.filter((r) => r.name === msg.name), lastResult = result[result.length - 1];
if (lastResult)
return {
...state,
results: state.results.map((r) => r === lastResult ? {
...r,
timing: msg.result
} : r)
};
}
return state;
}
if (msg.type === "workshop/perf/addRenderResult") {
if (state.activeTest === msg.name) {
const result = state.results.filter((r) => r.name === msg.name), lastResult = result[result.length - 1];
if (lastResult)
return {
...state,
results: state.results.map((r) => r === lastResult ? {
...r,
renders: r.renders.concat([msg.result])
} : r)
};
}
return state;
}
return state;
}
const PerfProvider = memo(function(props) {
const $ = c(26), {
children
} = props, {
broadcast,
channel
} = useWorkshop();
let t0;
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = {
results: [],
testDetails: [],
tests: []
}, $[0] = t0) : t0 = $[0];
const [t1, setState] = useState(t0), {
activeTest,
results,
testDetails,
tests
} = t1;
let t2;
$[1] !== broadcast ? (t2 = (name, result) => {
broadcast({
type: "workshop/perf/addRenderResult",
name,
result
});
}, $[1] = broadcast, $[2] = t2) : t2 = $[2];
const addRenderResult = t2;
let t3;
$[3] !== broadcast ? (t3 = (name_0) => {
broadcast({
type: "workshop/perf/clearResults",
name: name_0
});
}, $[3] = broadcast, $[4] = t3) : t3 = $[4];
const clearResults = t3;
let t4;
$[5] !== broadcast ? (t4 = (test) => (broadcast({
type: "workshop/perf/registerTest",
description: test.description,
title: test.title,
name: test.name
}), setState((s) => ({
...s,
tests: s.tests.concat([test])
})), () => {
broadcast({
type: "workshop/perf/unregisterTest",
name: test.name
}), setState((s_0) => ({
...s_0,
tests: s_0.tests.filter((t) => t !== test)
}));
}), $[5] = broadcast, $[6] = t4) : t4 = $[6];
const registerTest = t4;
let t5;
$[7] !== broadcast ? (t5 = (testName) => {
broadcast({
type: "workshop/perf/runTest",
name: testName
});
}, $[7] = broadcast, $[8] = t5) : t5 = $[8];
const runTest = t5;
let t6, t7;
$[9] !== activeTest || $[10] !== addRenderResult || $[11] !== clearResults || $[12] !== registerTest || $[13] !== results || $[14] !== runTest || $[15] !== testDetails || $[16] !== tests ? (t7 = {
activeTest,
addRenderResult,
clearResults,
registerTest,
results,
runTest,
testDetails,
tests
}, $[9] = activeTest, $[10] = addRenderResult, $[11] = clearResults, $[12] = registerTest, $[13] = results, $[14] = runTest, $[15] = testDetails, $[16] = tests, $[17] = t7) : t7 = $[17], t6 = t7;
const perf = t6;
let t8, t9;
$[18] !== broadcast || $[19] !== channel || $[20] !== tests ? (t8 = () => channel.subscribe((msg) => {
if (setState((s_1) => perfReducer(s_1, msg)), msg.type === "workshop/perf/runTest") {
setTimeout(() => {
const test_0 = tests.find((t_0) => t_0.name === msg.name);
if (test_0) {
const container = test_0.ref.current;
container !== null && _runTest(test_0, container).then((result_0) => {
broadcast({
type: "workshop/perf/addResult",
name: test_0.name,
result: result_0
});
}).catch(_temp);
}
}, 0);
return;
}
}), t9 = [broadcast, channel, tests], $[18] = broadcast, $[19] = channel, $[20] = tests, $[21] = t8, $[22] = t9) : (t8 = $[21], t9 = $[22]), useEffect(t8, t9);
let t10;
return $[23] !== children || $[24] !== perf ? (t10 = /* @__PURE__ */ jsx(PerfContext.Provider, { value: perf, children }), $[23] = children, $[24] = perf, $[25] = t10) : t10 = $[25], t10;
});
function _temp(err) {
console.error(err);
}
function perfPlugin() {
return {
name: "perf",
title: "Performance",
inspector: PerfInspector,
provider: PerfProvider
};
}
export {
perfPlugin,
usePerf,
usePerfTest
};
//# sourceMappingURL=plugin-perf.js.map