@plitzi/sdk-dev-tools 0.38.2 → 0.38.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/dist/components/DevToolsIndicator/DevToolsIndicator.mjs +20 -18
  3. package/dist/components/DevToolsPanel/DevToolsPanel.mjs +35 -33
  4. package/dist/components/DevToolsPanel/tabs/ElementsViewer/components/ElementDetails/ElementDetails.mjs +8 -8
  5. package/dist/components/DevToolsPanel/tabs/QaViewer/QaReplayButton.d.ts +6 -0
  6. package/dist/components/DevToolsPanel/tabs/QaViewer/QaReplayButton.mjs +21 -0
  7. package/dist/components/DevToolsPanel/tabs/QaViewer/QaToolbar.d.ts +4 -1
  8. package/dist/components/DevToolsPanel/tabs/QaViewer/QaToolbar.mjs +27 -19
  9. package/dist/components/DevToolsPanel/tabs/QaViewer/QaViewer.d.ts +4 -3
  10. package/dist/components/DevToolsPanel/tabs/QaViewer/QaViewer.mjs +21 -12
  11. package/dist/components/DevToolsPanel/tabs/QaViewer/QaXray.d.ts +6 -0
  12. package/dist/components/DevToolsPanel/tabs/QaViewer/QaXray.mjs +17 -0
  13. package/dist/components/DevToolsPanel/tabs/QaViewer/QaXrayBoxesRow.d.ts +3 -0
  14. package/dist/components/DevToolsPanel/tabs/QaViewer/QaXrayBoxesRow.mjs +24 -0
  15. package/dist/components/DevToolsPanel/tabs/QaViewer/QaXrayRow.d.ts +7 -0
  16. package/dist/components/DevToolsPanel/tabs/QaViewer/QaXrayRow.mjs +40 -0
  17. package/dist/qa/QaContext.d.ts +4 -0
  18. package/dist/qa/QaContext.mjs +44 -38
  19. package/dist/qa/QaLayer.mjs +99 -47
  20. package/dist/qa/overlays/QaXrayTags.d.ts +12 -0
  21. package/dist/qa/overlays/QaXrayTags.mjs +58 -0
  22. package/dist/qa/qaCss.mjs +19 -18
  23. package/dist/qa/qaSettings.d.ts +11 -3
  24. package/dist/qa/qaSettings.mjs +4 -2
  25. package/dist/qa/xray.d.ts +22 -0
  26. package/dist/qa/xray.mjs +54 -0
  27. package/package.json +29 -5
@@ -1,58 +1,66 @@
1
1
  import e from "./QaDivider.mjs";
2
- import t from "./QaToolChip.mjs";
3
- import n from "./QaVisionSelect.mjs";
4
- import { jsx as r, jsxs as i } from "react/jsx-runtime";
2
+ import t from "./QaReplayButton.mjs";
3
+ import n from "./QaToolChip.mjs";
4
+ import r from "./QaVisionSelect.mjs";
5
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
6
  //#region src/components/DevToolsPanel/tabs/QaViewer/QaToolbar.tsx
6
- var a = () => /* @__PURE__ */ i("div", {
7
+ var o = () => /* @__PURE__ */ a("div", {
7
8
  className: "flex shrink-0 flex-wrap items-center gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-700",
8
9
  children: [
9
- /* @__PURE__ */ r(t, {
10
+ /* @__PURE__ */ i(n, {
10
11
  setting: "inspect",
11
12
  label: "Inspect",
12
13
  icon: "fa-solid fa-arrow-pointer",
13
14
  title: "Point at an element for its box and style; click to keep it here; hold Alt over another to measure. Esc stops.",
14
15
  primary: !0
15
16
  }),
16
- /* @__PURE__ */ r(e, {}),
17
- /* @__PURE__ */ r(t, {
17
+ /* @__PURE__ */ i(e, {}),
18
+ /* @__PURE__ */ i(n, {
18
19
  setting: "grid",
19
20
  label: "Grid",
20
21
  icon: "fa-solid fa-table-columns",
21
22
  title: "The page's 12, 8 or 4 columns"
22
23
  }),
23
- /* @__PURE__ */ r(t, {
24
- setting: "outlines",
25
- label: "Outlines",
26
- icon: "fa-regular fa-square",
27
- title: "Every element's box"
24
+ /* @__PURE__ */ i(n, {
25
+ setting: "xray",
26
+ label: "X-ray",
27
+ icon: "fa-solid fa-x-ray",
28
+ title: "Every element's box, its type and id when pointed at — and what is bound to data, shown on a condition, runs a flow, moves or sits behind a flag, named on the page"
28
29
  }),
29
- /* @__PURE__ */ r(t, {
30
+ /* @__PURE__ */ i(n, {
30
31
  setting: "tabOrder",
31
32
  label: "Tab order",
32
33
  icon: "fa-solid fa-arrow-right-to-bracket",
33
34
  title: "The order the Tab key walks the controls in"
34
35
  }),
35
- /* @__PURE__ */ r(t, {
36
+ /* @__PURE__ */ i(n, {
36
37
  setting: "viewport",
37
38
  label: "Viewport",
38
39
  icon: "fa-solid fa-ruler-horizontal",
39
40
  title: "The window's size and the breakpoint showing"
40
41
  }),
41
- /* @__PURE__ */ r(e, {}),
42
- /* @__PURE__ */ r(t, {
42
+ /* @__PURE__ */ i(e, {}),
43
+ /* @__PURE__ */ i(n, {
43
44
  setting: "paused",
44
45
  label: "Pause",
45
46
  icon: "fa-solid fa-pause",
46
47
  title: "Hold every animation where it is"
47
48
  }),
48
- /* @__PURE__ */ r(t, {
49
+ /* @__PURE__ */ i(n, {
50
+ setting: "slowMotion",
51
+ label: "Slow",
52
+ icon: "fa-solid fa-gauge-simple",
53
+ title: "Every animation at a quarter of its speed"
54
+ }),
55
+ /* @__PURE__ */ i(t, {}),
56
+ /* @__PURE__ */ i(n, {
49
57
  setting: "reducedMotion",
50
58
  label: "Reduced motion",
51
59
  icon: "fa-solid fa-person-walking",
52
60
  title: "The page as a visitor who asked for less motion gets it"
53
61
  }),
54
- /* @__PURE__ */ r(n, {})
62
+ /* @__PURE__ */ i(r, {})
55
63
  ]
56
64
  });
57
65
  //#endregion
58
- export { a as default };
66
+ export { o as default };
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Tools for checking a build in the browser it will be used in — a pre-production deployment, say — rather than in the
3
- * builder: an inspector for any element, what lines things up, motion, colour, and the checks a tester runs on every
4
- * page. The bar on top; the checks and the inspector side by side below, one over the other when the panel is narrow.
5
- * All of it stays on while the panel is folded away, and in this browser only.
3
+ * builder: an inspector for any element, what lines things up, what the document wires to each element, motion and
4
+ * colour, and the checks a tester runs on every page. The bar on top; the x-ray's legend and the checks beside the
5
+ * inspector below, one over the other when the panel is narrow. All of it stays on while the panel is folded away, and
6
+ * in this browser only.
6
7
  */
7
8
  declare const QaViewer: () => import('react').JSX.Element;
8
9
  export default QaViewer;
@@ -1,14 +1,23 @@
1
- import e from "./QaChecks.mjs";
2
- import t from "./QaInspectorPanel.mjs";
3
- import n from "./QaToolbar.mjs";
4
- import { jsx as r, jsxs as i } from "react/jsx-runtime";
1
+ import e from "../../../../qa/QaContext.mjs";
2
+ import t from "./QaChecks.mjs";
3
+ import n from "./QaInspectorPanel.mjs";
4
+ import r from "./QaToolbar.mjs";
5
+ import i from "./QaXray.mjs";
6
+ import { use as a } from "react";
7
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
5
8
  //#region src/components/DevToolsPanel/tabs/QaViewer/QaViewer.tsx
6
- var a = () => /* @__PURE__ */ i("div", {
7
- className: "@container flex h-full min-h-0 w-full flex-col",
8
- children: [/* @__PURE__ */ r(n, {}), /* @__PURE__ */ i("div", {
9
- className: "grid min-h-0 grow grid-cols-1 content-start gap-3 overflow-y-auto p-3 @3xl:grid-cols-[minmax(0,0.85fr)_minmax(0,1.15fr)]",
10
- children: [/* @__PURE__ */ r(e, {}), /* @__PURE__ */ r(t, {})]
11
- })]
12
- });
9
+ var c = () => {
10
+ let { settings: c } = a(e);
11
+ return /* @__PURE__ */ s("div", {
12
+ className: "@container flex h-full min-h-0 w-full flex-col",
13
+ children: [/* @__PURE__ */ o(r, {}), /* @__PURE__ */ s("div", {
14
+ className: "grid min-h-0 grow grid-cols-1 content-start gap-3 overflow-y-auto p-3 @3xl:grid-cols-[minmax(0,0.85fr)_minmax(0,1.15fr)]",
15
+ children: [/* @__PURE__ */ s("div", {
16
+ className: "flex min-w-0 flex-col gap-3",
17
+ children: [c.xray && /* @__PURE__ */ o(i, {}), /* @__PURE__ */ o(t, {})]
18
+ }), /* @__PURE__ */ o(n, {})]
19
+ })]
20
+ });
21
+ };
13
22
  //#endregion
14
- export { a as default };
23
+ export { c as default };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * What the x-ray marks on the page, in its colours, with how many of each the page has — one picked to see only it, or
3
+ * the boxes alone.
4
+ */
5
+ declare const QaXray: () => import('react').JSX.Element;
6
+ export default QaXray;
@@ -0,0 +1,17 @@
1
+ import { XRAY_MARKS as e } from "../../../../qa/xray.mjs";
2
+ import t from "./QaXrayBoxesRow.mjs";
3
+ import n from "./QaXrayRow.mjs";
4
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
+ //#region src/components/DevToolsPanel/tabs/QaViewer/QaXray.tsx
6
+ var a = () => /* @__PURE__ */ i("section", {
7
+ className: "flex min-w-0 flex-col gap-1.5",
8
+ children: [/* @__PURE__ */ i("div", {
9
+ className: "flex items-center gap-2 text-[10px] font-semibold tracking-wider text-zinc-400 uppercase dark:text-zinc-500",
10
+ children: [/* @__PURE__ */ r("i", { className: "fa-solid fa-x-ray" }), "X-ray"]
11
+ }), /* @__PURE__ */ i("div", {
12
+ className: "overflow-hidden rounded border border-zinc-200 dark:border-zinc-700",
13
+ children: [/* @__PURE__ */ r(t, {}), e.map((e) => /* @__PURE__ */ r(n, { mark: e }, e))]
14
+ })]
15
+ });
16
+ //#endregion
17
+ export { a as default };
@@ -0,0 +1,3 @@
1
+ /** The boxes alone, picked: every element's box with its type and id, and no wiring marked over them. */
2
+ declare const QaXrayBoxesRow: () => import('react').JSX.Element;
3
+ export default QaXrayBoxesRow;
@@ -0,0 +1,24 @@
1
+ import e from "../../../../qa/QaContext.mjs";
2
+ import t from "clsx";
3
+ import { use as n, useCallback as r } from "react";
4
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ //#region src/components/DevToolsPanel/tabs/QaViewer/QaXrayBoxesRow.tsx
6
+ var o = () => {
7
+ let { settings: o, setSetting: s } = n(e), c = o.xrayFilter === "none", l = r(() => s("xrayFilter", c ? "all" : "none"), [s, c]);
8
+ return /* @__PURE__ */ a("button", {
9
+ type: "button",
10
+ "aria-pressed": c,
11
+ title: "Every element's box, its type and id when pointed at — and no wiring. Click again to mark it all.",
12
+ className: t("flex w-full cursor-pointer items-center gap-2 border-b border-zinc-100 px-2.5 py-1.5 text-left dark:border-zinc-800", {
13
+ "bg-violet-500/10": c,
14
+ "hover:bg-zinc-50 dark:hover:bg-zinc-800/60": !c
15
+ }),
16
+ onClick: l,
17
+ children: [/* @__PURE__ */ i("span", { className: "h-2.5 w-2.5 shrink-0 rounded-sm border border-dashed border-violet-500" }), /* @__PURE__ */ i("span", {
18
+ className: "min-w-0 truncate font-medium text-zinc-800 dark:text-zinc-200",
19
+ children: "Boxes only"
20
+ })]
21
+ });
22
+ };
23
+ //#endregion
24
+ export { o as default };
@@ -0,0 +1,7 @@
1
+ import { XrayMark } from '../../../../qa/xray';
2
+ export type QaXrayRowProps = {
3
+ mark: XrayMark;
4
+ };
5
+ /** One kind of wiring: how many elements of the page carry it — and, picked, the only one the x-ray shows. */
6
+ declare const QaXrayRow: ({ mark }: QaXrayRowProps) => import('react').JSX.Element;
7
+ export default QaXrayRow;
@@ -0,0 +1,40 @@
1
+ import { XRAY as e } from "../../../../qa/xray.mjs";
2
+ import t from "../../../../qa/QaContext.mjs";
3
+ import n from "clsx";
4
+ import { use as r, useCallback as i } from "react";
5
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
+ //#region src/components/DevToolsPanel/tabs/QaViewer/QaXrayRow.tsx
7
+ var s = ({ mark: s }) => {
8
+ let { settings: c, setSetting: l, xrayCounts: u } = r(t), { label: d, description: f, colour: p } = e[s], m = c.xrayFilter === s, h = i(() => l("xrayFilter", m ? "all" : s), [
9
+ l,
10
+ m,
11
+ s
12
+ ]);
13
+ return /* @__PURE__ */ o("button", {
14
+ type: "button",
15
+ "aria-pressed": m,
16
+ title: `${f}. Click to show only these; again for all.`,
17
+ className: n("flex w-full cursor-pointer items-center gap-2 border-b border-zinc-100 px-2.5 py-1.5 text-left last:border-b-0 dark:border-zinc-800", {
18
+ "bg-violet-500/10": m,
19
+ "hover:bg-zinc-50 dark:hover:bg-zinc-800/60": !m,
20
+ "opacity-50": c.xrayFilter !== "all" && !m
21
+ }),
22
+ onClick: h,
23
+ children: [
24
+ /* @__PURE__ */ a("span", {
25
+ className: "h-2.5 w-2.5 shrink-0 rounded-full",
26
+ style: { backgroundColor: p }
27
+ }),
28
+ /* @__PURE__ */ a("span", {
29
+ className: "min-w-0 truncate font-medium text-zinc-800 dark:text-zinc-200",
30
+ children: d
31
+ }),
32
+ /* @__PURE__ */ a("span", {
33
+ className: "ml-auto rounded-full bg-zinc-100 px-1.5 text-[10px] font-semibold text-zinc-600 tabular-nums dark:bg-zinc-800 dark:text-zinc-300",
34
+ children: u[s]
35
+ })
36
+ ]
37
+ });
38
+ };
39
+ //#endregion
40
+ export { s as default };
@@ -1,5 +1,6 @@
1
1
  import { QaFindings } from './findings';
2
2
  import { QaCheck, QaSettings } from './qaSettings';
3
+ import { XrayCounts } from './xray';
3
4
  import { ReactNode, RefObject } from 'react';
4
5
  export interface QaContextValue {
5
6
  settings: QaSettings;
@@ -8,6 +9,9 @@ export interface QaContextValue {
8
9
  /** What the checks that are on found, the last time they looked. */
9
10
  findings: QaFindings;
10
11
  setFindings: (findings: QaFindings) => void;
12
+ /** How many elements of the page the x-ray marked, by mark, the last time it looked. */
13
+ xrayCounts: XrayCounts;
14
+ setXrayCounts: (counts: XrayCounts) => void;
11
15
  /** Bumped to make the checks look again. */
12
16
  round: number;
13
17
  rescan: () => void;
@@ -1,73 +1,79 @@
1
1
  import { NO_FINDINGS as e } from "./findings.mjs";
2
2
  import { QA_DEFAULTS as t } from "./qaSettings.mjs";
3
- import n from "@plitzi/plitzi-ui/hooks/useStorage";
4
- import { createContext as r, useCallback as i, useEffect as a, useMemo as o, useState as s } from "react";
5
- import { jsx as c } from "react/jsx-runtime";
3
+ import { NO_XRAY_COUNTS as n } from "./xray.mjs";
4
+ import r from "@plitzi/plitzi-ui/hooks/useStorage";
5
+ import { createContext as i, useCallback as a, useEffect as o, useMemo as s, useState as c } from "react";
6
+ import { jsx as l } from "react/jsx-runtime";
6
7
  //#region src/qa/QaContext.tsx
7
- var l = r({
8
+ var u = i({
8
9
  settings: t,
9
10
  setSetting: () => void 0,
10
11
  setCheck: () => void 0,
11
12
  findings: e,
12
13
  setFindings: () => void 0,
14
+ xrayCounts: n,
15
+ setXrayCounts: () => void 0,
13
16
  round: 0,
14
17
  rescan: () => void 0,
15
18
  pageRef: { current: null },
16
19
  pinned: void 0,
17
20
  setPinned: () => void 0
18
21
  });
19
- l.displayName = "QaContext";
20
- var u = ({ children: r, pageRef: u, collapsed: d }) => {
21
- let [f, p] = n("plitzi-sdk-dev-tools-qa", t), [m, h] = s(e), [g, _] = s(0), [v, y] = s(), b = o(() => ({
22
+ u.displayName = "QaContext";
23
+ var d = ({ children: i, pageRef: d, collapsed: f }) => {
24
+ let [p, m] = r("plitzi-sdk-dev-tools-qa", t), [h, g] = c(e), [_, v] = c(n), [y, b] = c(0), [x, S] = c(), C = s(() => ({
22
25
  ...t,
23
- ...f,
26
+ ...p,
24
27
  checks: {
25
28
  ...t.checks,
26
- ...f.checks
29
+ ...p.checks
27
30
  }
28
- }), [f]), x = i((e, t) => p((n) => ({
31
+ }), [p]), w = a((e, t) => m((n) => ({
29
32
  ...n,
30
33
  [e]: t
31
- })), [p]), S = i((e, n) => p((r) => ({
34
+ })), [m]), T = a((e, n) => m((r) => ({
32
35
  ...r,
33
36
  checks: {
34
37
  ...t.checks,
35
38
  ...r.checks,
36
39
  [e]: n
37
40
  }
38
- })), [p]), C = i(() => _((e) => e + 1), []);
39
- a(() => {
40
- d && (p((e) => ({
41
+ })), [m]), E = a(() => b((e) => e + 1), []);
42
+ o(() => {
43
+ f && (m((e) => ({
41
44
  ...e,
42
45
  inspect: !1,
43
46
  checks: t.checks
44
- })), y(void 0));
45
- }, [d, p]);
46
- let w = o(() => ({
47
- settings: b,
48
- setSetting: x,
49
- setCheck: S,
50
- findings: m,
51
- setFindings: h,
52
- round: g,
53
- rescan: C,
54
- pageRef: u,
55
- pinned: v,
56
- setPinned: y
47
+ })), S(void 0));
48
+ }, [f, m]);
49
+ let D = s(() => ({
50
+ settings: C,
51
+ setSetting: w,
52
+ setCheck: T,
53
+ findings: h,
54
+ setFindings: g,
55
+ xrayCounts: _,
56
+ setXrayCounts: v,
57
+ round: y,
58
+ rescan: E,
59
+ pageRef: d,
60
+ pinned: x,
61
+ setPinned: S
57
62
  }), [
58
- b,
59
- x,
60
- S,
61
- m,
62
- g,
63
63
  C,
64
- u,
65
- v
64
+ w,
65
+ T,
66
+ h,
67
+ _,
68
+ y,
69
+ E,
70
+ d,
71
+ x
66
72
  ]);
67
- return /* @__PURE__ */ c(l, {
68
- value: w,
69
- children: r
73
+ return /* @__PURE__ */ l(u, {
74
+ value: D,
75
+ children: i
70
76
  });
71
77
  };
72
78
  //#endregion
73
- export { u as QaProvider, l as default };
79
+ export { d as QaProvider, u as default };
@@ -1,69 +1,121 @@
1
1
  import { NO_FINDINGS as e } from "./findings.mjs";
2
2
  import { QA_CHECKS as t, QA_FINDING_ATTRIBUTE as n, QA_PAGE_ATTRIBUTE as r, REDUCED_MOTION_CLASS as i, isQaActive as a } from "./qaSettings.mjs";
3
- import o from "./QaContext.mjs";
4
- import { CHECKS as s } from "./checks/index.mjs";
5
- import c from "./overlays/QaGrid.mjs";
6
- import l from "./overlays/QaInspector.mjs";
7
- import u from "./overlays/QaTabOrder.mjs";
8
- import d from "./overlays/QaViewport.mjs";
9
- import { VISION_MATRIX as f, qaCss as p, visionFilterId as m } from "./qaCss.mjs";
10
- import h from "./usePageBox.mjs";
11
- import { use as g, useEffect as _, useMemo as v } from "react";
12
- import { useCommonStore as y } from "@plitzi/sdk-shared/store";
13
- import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
3
+ import { NO_XRAY_COUNTS as o, XRAY_ATTRIBUTE as s, xrayMarksOf as c } from "./xray.mjs";
4
+ import l from "./QaContext.mjs";
5
+ import { CHECKS as u } from "./checks/index.mjs";
6
+ import d from "./overlays/QaGrid.mjs";
7
+ import f from "./overlays/QaInspector.mjs";
8
+ import p from "./overlays/QaTabOrder.mjs";
9
+ import m from "./overlays/QaViewport.mjs";
10
+ import h from "./overlays/QaXrayTags.mjs";
11
+ import { VISION_MATRIX as g, qaCss as _, visionFilterId as v } from "./qaCss.mjs";
12
+ import y from "./usePageBox.mjs";
13
+ import { use as b, useEffect as x, useMemo as S } from "react";
14
+ import { useCommonStore as C } from "@plitzi/sdk-shared/store";
15
+ import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
16
+ import { treeOf as D } from "@plitzi/sdk-schema/helpers/components";
14
17
  //#region src/qa/QaLayer.tsx
15
- var C = "http://www.w3.org/2000/svg", w = 250, T = 1e3, E = () => {
16
- let { settings: E, pageRef: D, round: O, setFindings: k } = g(o), [A] = y("navigation.currentPageId"), j = h(D), M = a(E), N = v(() => p(E), [E]), P = v(() => t.filter((e) => E.checks[e]).join(" "), [E.checks]);
17
- return _(() => {
18
- let e = D.current;
19
- if (e && M) return e.setAttribute(r, ""), () => e.removeAttribute(r);
20
- }, [M, D]), _(() => {
21
- if (!N) return;
18
+ var O = "http://www.w3.org/2000/svg", k = 250, A = 1e3, j = 200, M = .25, N = () => {
19
+ let { settings: N, pageRef: P, round: F, setFindings: I, setXrayCounts: L } = b(l), [[R, z, B]] = C([
20
+ "navigation.currentPageId",
21
+ "schema.flat",
22
+ "schema.components"
23
+ ]), V = y(P), H = a(N), U = S(() => _(N), [N]), W = S(() => t.filter((e) => N.checks[e]).join(" "), [N.checks]);
24
+ return x(() => {
25
+ let e = P.current;
26
+ if (e && H) return e.setAttribute(r, ""), () => e.removeAttribute(r);
27
+ }, [H, P]), x(() => {
28
+ if (!U) return;
22
29
  let e = document.createElement("style");
23
- return e.setAttribute("data-plitzi-qa", ""), e.textContent = N, document.head.append(e), () => e.remove();
24
- }, [N]), _(() => {
25
- if (E.reducedMotion) return document.documentElement.classList.add(i), () => document.documentElement.classList.remove(i);
26
- }, [E.reducedMotion]), _(() => {
27
- let e = E.vision;
30
+ return e.setAttribute("data-plitzi-qa", ""), e.textContent = U, document.head.append(e), () => e.remove();
31
+ }, [U]), x(() => {
32
+ if (N.reducedMotion) return document.documentElement.classList.add(i), () => document.documentElement.classList.remove(i);
33
+ }, [N.reducedMotion]), x(() => {
34
+ let e = N.vision;
28
35
  if (e !== "protanopia" && e !== "deuteranopia" && e !== "tritanopia") return;
29
- let t = document.createElementNS(C, "svg");
36
+ let t = document.createElementNS(O, "svg");
30
37
  t.setAttribute("aria-hidden", "true"), t.setAttribute("style", "position: absolute; width: 0; height: 0");
31
- let n = document.createElementNS(C, "filter");
32
- n.setAttribute("id", m(e));
33
- let r = document.createElementNS(C, "feColorMatrix");
34
- return r.setAttribute("type", "matrix"), r.setAttribute("values", f[e]), n.append(r), t.append(n), document.body.append(t), () => t.remove();
35
- }, [E.vision]), _(() => {
36
- let r = D.current, i = t.filter((e) => P.split(" ").includes(e));
38
+ let n = document.createElementNS(O, "filter");
39
+ n.setAttribute("id", v(e));
40
+ let r = document.createElementNS(O, "feColorMatrix");
41
+ return r.setAttribute("type", "matrix"), r.setAttribute("values", g[e]), n.append(r), t.append(n), document.body.append(t), () => t.remove();
42
+ }, [N.vision]), x(() => {
43
+ let e = P.current;
44
+ if (!e || !N.xray) {
45
+ L(o);
46
+ return;
47
+ }
48
+ let t, n = () => {
49
+ let t = { ...o };
50
+ e.querySelectorAll("[data-plitzi-el]").forEach((e) => {
51
+ let n = e.getAttribute("data-plitzi-el") ?? "", r = D({
52
+ flat: z,
53
+ components: B
54
+ }, n)?.flat[n]?.definition, i = r ? c(r) : [];
55
+ i.forEach((e) => {
56
+ t[e] += 1;
57
+ }), i.length === 0 ? e.removeAttribute(s) : e.getAttribute("data-plitzi-qa-xray") !== i.join(" ") && e.setAttribute(s, i.join(" "));
58
+ }), L(t);
59
+ }, r = () => {
60
+ clearTimeout(t), t = setTimeout(n, j);
61
+ };
62
+ n();
63
+ let i = new MutationObserver(r);
64
+ return i.observe(e, {
65
+ childList: !0,
66
+ subtree: !0
67
+ }), () => {
68
+ clearTimeout(t), i.disconnect(), e.querySelectorAll(`[${s}]`).forEach((e) => e.removeAttribute(s));
69
+ };
70
+ }, [
71
+ N.xray,
72
+ P,
73
+ z,
74
+ B,
75
+ R,
76
+ L
77
+ ]), x(() => {
78
+ let e = P.current;
79
+ if (!e || !N.slowMotion) return;
80
+ let t = (t) => e.getAnimations({ subtree: !0 }).forEach((e) => {
81
+ e.playbackRate = t;
82
+ }), n = () => t(M);
83
+ return n(), e.addEventListener("animationstart", n), e.addEventListener("transitionrun", n), () => {
84
+ e.removeEventListener("animationstart", n), e.removeEventListener("transitionrun", n), t(1);
85
+ };
86
+ }, [N.slowMotion, P]), x(() => {
87
+ let r = P.current, i = t.filter((e) => W.split(" ").includes(e));
37
88
  if (!r || i.length === 0) {
38
- k(e);
89
+ I(e);
39
90
  return;
40
91
  }
41
92
  let a = [], o = () => {
42
93
  a.forEach((e) => e.removeAttribute(n));
43
94
  let t = { ...e };
44
- for (let e of i) t[e] = s[e].run(r);
95
+ for (let e of i) t[e] = u[e].run(r);
45
96
  let o = /* @__PURE__ */ new Map();
46
- i.forEach((e) => t[e].forEach(({ element: t }) => o.set(t, [...o.get(t) ?? [], e]))), o.forEach((e, t) => t.setAttribute(n, e.join(" "))), a = [...o.keys()], k(t);
47
- }, c, l, u = () => {
48
- typeof requestIdleCallback == "function" ? l = requestIdleCallback(o, { timeout: T }) : o();
97
+ i.forEach((e) => t[e].forEach(({ element: t }) => o.set(t, [...o.get(t) ?? [], e]))), o.forEach((e, t) => t.setAttribute(n, e.join(" "))), a = [...o.keys()], I(t);
98
+ }, s, c, l = () => {
99
+ typeof requestIdleCallback == "function" ? c = requestIdleCallback(o, { timeout: A }) : o();
49
100
  }, d = () => {
50
- clearTimeout(c), l !== void 0 && typeof cancelIdleCallback == "function" && cancelIdleCallback(l), c = setTimeout(u, w);
101
+ clearTimeout(s), c !== void 0 && typeof cancelIdleCallback == "function" && cancelIdleCallback(c), s = setTimeout(l, k);
51
102
  };
52
103
  return d(), window.addEventListener("resize", d), () => {
53
- clearTimeout(c), l !== void 0 && typeof cancelIdleCallback == "function" && cancelIdleCallback(l), window.removeEventListener("resize", d), a.forEach((e) => e.removeAttribute(n));
104
+ clearTimeout(s), c !== void 0 && typeof cancelIdleCallback == "function" && cancelIdleCallback(c), window.removeEventListener("resize", d), a.forEach((e) => e.removeAttribute(n));
54
105
  };
55
106
  }, [
107
+ W,
56
108
  P,
57
- D,
58
- O,
59
- A,
60
- k
61
- ]), /* @__PURE__ */ S(b, { children: [
62
- E.grid && /* @__PURE__ */ x(c, { box: j }),
63
- E.tabOrder && /* @__PURE__ */ x(u, {}),
64
- E.inspect && /* @__PURE__ */ x(l, {}),
65
- E.viewport && /* @__PURE__ */ x(d, { box: j })
109
+ F,
110
+ R,
111
+ I
112
+ ]), /* @__PURE__ */ E(w, { children: [
113
+ N.grid && /* @__PURE__ */ T(d, { box: V }),
114
+ N.xray && N.xrayFilter !== "none" && /* @__PURE__ */ T(h, { filter: N.xrayFilter }),
115
+ N.tabOrder && /* @__PURE__ */ T(p, {}),
116
+ N.inspect && /* @__PURE__ */ T(f, {}),
117
+ N.viewport && /* @__PURE__ */ T(m, { box: V })
66
118
  ] });
67
119
  };
68
120
  //#endregion
69
- export { E as default };
121
+ export { N as default };
@@ -0,0 +1,12 @@
1
+ import { XrayFilter } from '../xray';
2
+ /** What there are tags for: the boxes alone carry none. */
3
+ type TaggedFilter = Exclude<XrayFilter, 'none'>;
4
+ export type QaXrayTagsProps = {
5
+ filter: TaggedFilter;
6
+ };
7
+ /**
8
+ * Every element the x-ray marked, named on its corner with a dot for each thing wired to it — so the page says which of
9
+ * its parts are bound, conditional, interactive or moving without pointing at each one.
10
+ */
11
+ declare const QaXrayTags: ({ filter }: QaXrayTagsProps) => import('react').JSX.Element;
12
+ export default QaXrayTags;
@@ -0,0 +1,58 @@
1
+ import { XRAY as e, XRAY_ATTRIBUTE as t, XRAY_MARKS as n } from "../xray.mjs";
2
+ import r from "../QaContext.mjs";
3
+ import { use as i, useEffect as a, useState as o } from "react";
4
+ import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ //#region src/qa/overlays/QaXrayTags.tsx
6
+ var u = 150, d = 16, f = (e) => n.some((t) => t === e), p = (e, n) => {
7
+ let r = [], i = /* @__PURE__ */ new Set();
8
+ for (let a of e.querySelectorAll(`[${t}]`)) {
9
+ if (r.length >= u) break;
10
+ let e = (a.getAttribute("data-plitzi-qa-xray") ?? "").split(" ").filter(f);
11
+ if (n !== "all" && !e.includes(n)) continue;
12
+ let t = a.getBoundingClientRect();
13
+ if (t.width === 0 || t.bottom < 0 || t.top > window.innerHeight) continue;
14
+ let o = (e) => `${String(Math.round(t.left))}:${String(Math.round(e))}`, s = t.top >= d ? t.top - d + 1 : Math.max(t.top, 0);
15
+ for (let e = 0; e < 3 && i.has(o(s)); e += 1) s += d;
16
+ i.has(o(s)) || (i.add(o(s)), r.push({
17
+ id: a.getAttribute("data-plitzi-el") ?? "",
18
+ marks: e,
19
+ left: t.left,
20
+ top: s
21
+ }));
22
+ }
23
+ return r;
24
+ }, m = ({ filter: n }) => {
25
+ let { pageRef: u } = i(r), [d, f] = o([]);
26
+ return a(() => {
27
+ let e = u.current;
28
+ if (!e) return;
29
+ let r = 0, i = () => {
30
+ cancelAnimationFrame(r), r = requestAnimationFrame(() => f(p(e, n)));
31
+ };
32
+ i();
33
+ let a = new MutationObserver(i);
34
+ return a.observe(e, {
35
+ subtree: !0,
36
+ attributes: !0,
37
+ attributeFilter: [t]
38
+ }), document.addEventListener("scroll", i, !0), window.addEventListener("resize", i), () => {
39
+ cancelAnimationFrame(r), a.disconnect(), document.removeEventListener("scroll", i, !0), window.removeEventListener("resize", i);
40
+ };
41
+ }, [u, n]), /* @__PURE__ */ c(s, { children: d.map(({ id: t, marks: n, left: r, top: i }) => /* @__PURE__ */ l("span", {
42
+ className: "pointer-events-none fixed z-[999998] flex h-[15px] max-w-56 items-center gap-1 rounded-sm bg-zinc-900/85 px-1 font-mono text-[10px] leading-none text-white shadow-sm",
43
+ style: {
44
+ left: r,
45
+ top: i
46
+ },
47
+ children: [n.map((t) => /* @__PURE__ */ c("span", {
48
+ title: e[t].label,
49
+ className: "h-1.5 w-1.5 shrink-0 rounded-full",
50
+ style: { backgroundColor: e[t].colour }
51
+ }, t)), /* @__PURE__ */ c("span", {
52
+ className: "truncate",
53
+ children: t
54
+ })]
55
+ }, `${t}-${String(r)}-${String(i)}`)) });
56
+ };
57
+ //#endregion
58
+ export { m as default };