@polishd/next 0.2.2-dev.1 → 0.2.2-dev.3

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 (65) hide show
  1. package/CHANGELOG.md +83 -8
  2. package/DATABASE.md +3 -2
  3. package/README.md +19 -4
  4. package/dist/client/design-scan.d.ts +17 -1
  5. package/dist/client/design-scan.d.ts.map +1 -1
  6. package/dist/client/design-scan.js +7 -3
  7. package/dist/client/design-scan.js.map +1 -1
  8. package/dist/dashboard/chrome.d.ts +4 -2
  9. package/dist/dashboard/chrome.d.ts.map +1 -1
  10. package/dist/dashboard/chrome.js +9 -3
  11. package/dist/dashboard/chrome.js.map +1 -1
  12. package/dist/dashboard/color-chip.d.ts +5 -0
  13. package/dist/dashboard/color-chip.d.ts.map +1 -0
  14. package/dist/dashboard/color-chip.js +81 -0
  15. package/dist/dashboard/color-chip.js.map +1 -0
  16. package/dist/dashboard/design-review-card.d.ts.map +1 -1
  17. package/dist/dashboard/design-review-card.js +3 -2
  18. package/dist/dashboard/design-review-card.js.map +1 -1
  19. package/dist/dashboard/design-tokens.d.ts +33 -0
  20. package/dist/dashboard/design-tokens.d.ts.map +1 -0
  21. package/dist/dashboard/design-tokens.js +64 -0
  22. package/dist/dashboard/design-tokens.js.map +1 -0
  23. package/dist/dashboard/design.d.ts.map +1 -1
  24. package/dist/dashboard/design.js +9 -9
  25. package/dist/dashboard/design.js.map +1 -1
  26. package/dist/dashboard/index.d.ts +3 -1
  27. package/dist/dashboard/index.d.ts.map +1 -1
  28. package/dist/dashboard/index.js +23 -11
  29. package/dist/dashboard/index.js.map +1 -1
  30. package/dist/dashboard/installs.d.ts +6 -0
  31. package/dist/dashboard/installs.d.ts.map +1 -0
  32. package/dist/dashboard/installs.js +36 -0
  33. package/dist/dashboard/installs.js.map +1 -0
  34. package/dist/dashboard/overflow-row.d.ts +24 -0
  35. package/dist/dashboard/overflow-row.d.ts.map +1 -0
  36. package/dist/dashboard/overflow-row.js +85 -0
  37. package/dist/dashboard/overflow-row.js.map +1 -0
  38. package/dist/dashboard/telemetry.d.ts +1 -2
  39. package/dist/dashboard/telemetry.d.ts.map +1 -1
  40. package/dist/dashboard/telemetry.js +81 -13
  41. package/dist/dashboard/telemetry.js.map +1 -1
  42. package/dist/dashboard/ui.d.ts +1 -0
  43. package/dist/dashboard/ui.d.ts.map +1 -1
  44. package/dist/dashboard/ui.js +3 -0
  45. package/dist/dashboard/ui.js.map +1 -1
  46. package/dist/dashboard.css +71 -10
  47. package/dist/server/ingest.d.ts +21 -8
  48. package/dist/server/ingest.d.ts.map +1 -1
  49. package/dist/server/ingest.js +45 -15
  50. package/dist/server/ingest.js.map +1 -1
  51. package/dist/server/queries.d.ts +31 -0
  52. package/dist/server/queries.d.ts.map +1 -1
  53. package/dist/server/queries.js +78 -7
  54. package/dist/server/queries.js.map +1 -1
  55. package/dist/server/telemetry.d.ts +15 -8
  56. package/dist/server/telemetry.d.ts.map +1 -1
  57. package/dist/server/telemetry.js +28 -37
  58. package/dist/server/telemetry.js.map +1 -1
  59. package/dist/shared/types.d.ts +9 -7
  60. package/dist/shared/types.d.ts.map +1 -1
  61. package/dist/shared/types.js.map +1 -1
  62. package/dist/telemetry.d.ts.map +1 -1
  63. package/dist/telemetry.js +5 -2
  64. package/dist/telemetry.js.map +1 -1
  65. package/package.json +1 -1
@@ -0,0 +1,85 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Polishd — a wrapping row that fills the line before it collapses.
5
+ *
6
+ * The Design tab's chip strips (radii, palette) used to hide everything past a
7
+ * fixed count, which meant the sixth chip dropped behind "Show more" while half
8
+ * the row sat empty. The server can't know how many chips fit — that depends on
9
+ * the viewport — so this measures the laid-out row in the browser: everything on
10
+ * the first line stays, the rest is clipped away and counted into the toggle.
11
+ *
12
+ * The overflow items stay in the DOM and keep their layout (the row is clipped
13
+ * with `height`, not `display: none`), so re-measuring after a resize needs no
14
+ * flash of expanded content.
15
+ */
16
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
17
+ /** Measure before paint in the browser; `useLayoutEffect` warns during SSR. */
18
+ const useBeforePaint = typeof window === "undefined" ? useEffect : useLayoutEffect;
19
+ /**
20
+ * Row membership by x-position, not by y: with `items-end` (the radius chips)
21
+ * items on one line share a bottom but not a top, so a top comparison would
22
+ * read a tall chip as its own row. In a wrapping flex row every line restarts
23
+ * at the container's left edge, and that holds whatever the alignment is.
24
+ */
25
+ function measureFirstLine(row) {
26
+ const items = Array.from(row.children);
27
+ // A zero-width row means it isn't laid out (hidden ancestor); every item
28
+ // would read as a wrap onto line two. Nothing measured beats a wrong answer.
29
+ if (items.length === 0 || row.getBoundingClientRect().width === 0)
30
+ return null;
31
+ const rowTop = row.getBoundingClientRect().top;
32
+ const firstLeft = items[0].getBoundingClientRect().left;
33
+ let height = 0;
34
+ for (let i = 0; i < items.length; i++) {
35
+ const box = items[i].getBoundingClientRect();
36
+ if (i > 0 && box.left <= firstLeft + 0.5)
37
+ return { height: Math.ceil(height), hidden: items.length - i };
38
+ height = Math.max(height, box.bottom - rowTop);
39
+ }
40
+ return { height: Math.ceil(height), hidden: 0 };
41
+ }
42
+ export default function OverflowRow({ label, className, rowClassName, children, }) {
43
+ const rowRef = useRef(null);
44
+ const [open, setOpen] = useState(false);
45
+ const [fit, setFit] = useState(null);
46
+ const measure = useCallback(() => {
47
+ if (!rowRef.current)
48
+ return;
49
+ const next = measureFirstLine(rowRef.current);
50
+ if (next === null)
51
+ return;
52
+ // Collapsing shrinks the wrapper, which wakes the observer again — bail on
53
+ // an unchanged result so that echo stops at one render instead of looping.
54
+ setFit((prev) => prev && prev.height === next.height && prev.hidden === next.hidden ? prev : next);
55
+ }, []);
56
+ useBeforePaint(() => {
57
+ measure();
58
+ const row = rowRef.current;
59
+ if (!row || typeof ResizeObserver === "undefined")
60
+ return;
61
+ // The row's own height is pinned while collapsed, so watch the wrapper —
62
+ // it still tracks the viewport.
63
+ const observer = new ResizeObserver(measure);
64
+ if (row.parentElement)
65
+ observer.observe(row.parentElement);
66
+ return () => observer.disconnect();
67
+ }, [measure]);
68
+ // Web fonts land after first paint and change chip widths under us.
69
+ useEffect(() => {
70
+ const fonts = document.fonts;
71
+ if (!fonts)
72
+ return;
73
+ let live = true;
74
+ fonts.ready.then(() => {
75
+ if (live)
76
+ measure();
77
+ });
78
+ return () => {
79
+ live = false;
80
+ };
81
+ }, [measure]);
82
+ const collapsed = fit !== null && fit.hidden > 0 && !open;
83
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: className, children: _jsx("div", { ref: rowRef, className: rowClassName, style: collapsed ? { height: fit.height, overflow: "hidden" } : undefined, children: children }) }), fit !== null && fit.hidden > 0 && (_jsx("div", { className: "mt-4 border-t border-[#2e2e2e] px-4 py-2.5 sm:px-5", children: _jsx("button", { type: "button", onClick: () => setOpen((o) => !o), className: "text-[11px] font-medium text-[#888] transition-colors hover:text-white", children: open ? "Show less ↑" : `Show ${fit.hidden} more ${label} ↓` }) }))] }));
84
+ }
85
+ //# sourceMappingURL=overflow-row.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overflow-row.js","sourceRoot":"","sources":["../../src/dashboard/overflow-row.tsx"],"names":[],"mappings":"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"}
@@ -8,9 +8,8 @@ declare global {
8
8
  * starts the capture singleton once per page load (the listeners are global
9
9
  * and deliberately never torn down — capture suspends off-dashboard instead).
10
10
  */
11
- export declare function PolishdTelemetryEmitter({ endpoint, installId, }: {
11
+ export declare function PolishdTelemetryEmitter({ endpoint }: {
12
12
  endpoint: string;
13
- installId: string;
14
13
  }): null;
15
14
  /**
16
15
  * The one-time opt-in prompt, shown while consent is "unset". Both buttons
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/dashboard/telemetry.tsx"],"names":[],"mappings":"AAsDA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,yBAAyB,CAAC,EAAE,OAAO,CAAC;KACrC;CACF;AAuID;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,QAQA;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,uCAuDtC"}
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/dashboard/telemetry.tsx"],"names":[],"mappings":"AA0DA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,yBAAyB,CAAC,EAAE,OAAO,CAAC;KACrC;CACF;AAqND;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,QAQzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,uCAuDtC"}
@@ -13,9 +13,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  * Everything about the transport differs from the host-site capture layer
14
14
  * because the POST crosses origins:
15
15
  *
16
- * • Identity travels in the body — an anonymous session id minted here (the
17
- * httpOnly session cookie never leaves its origin) plus the stable
18
- * anonymous install id the server resolved from `polishd_meta`.
16
+ * • The session id travels in the body, minted here (the httpOnly session
17
+ * cookie never leaves its origin). The *installation* sends no id at all:
18
+ * the collecting side names it by this page's hostname, taken from the
19
+ * Origin header the browser sets on the cross-origin POST.
19
20
  * • Batches are sent as `text/plain`, which keeps the request inside CORS's
20
21
  * "simple" class — no preflight — and is the only shape `sendBeacon` can
21
22
  * deliver cross-origin anyway. The receiving route parses the body as
@@ -26,14 +27,17 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
26
27
  *
27
28
  * What is captured: page views (tab switches), clicks (with the same
28
29
  * rage/dead classification as the host capture layer, via the shared DOM
29
- * helpers), one viewport sample per session, and session end. Nothing else —
30
- * no scroll depth, no errors, no design scans, and never anything from the
31
- * host site's own pages: capture suspends the moment the URL leaves the
32
- * dashboard's mount path.
30
+ * helpers), scroll depth of the dashboard's own scroll container, JS errors
31
+ * raised while the dashboard is up, one design scan of the dashboard per tab
32
+ * per session, one viewport sample per session, and session end. Everything
33
+ * the full dashboard experience needs on the collecting side — and never
34
+ * anything from the host site's own pages: capture suspends the moment the
35
+ * URL leaves the dashboard's mount path.
33
36
  */
34
37
  import { useRouter } from "next/navigation";
35
38
  import { useEffect, useState, useTransition } from "react";
36
39
  import { componentOf, deviceCategory, hasTextSelection, isInteractive, labelOf, selectorOf, } from "../client/dom";
40
+ import { scheduleDesignScan } from "../client/design-scan";
37
41
  import { denyPolishdTelemetry, grantPolishdTelemetry } from "./telemetry-consent";
38
42
  const PATH_PREFIX = "/~polishd";
39
43
  const SESSION_KEY = "polishd_telemetry_session";
@@ -61,7 +65,7 @@ function sessionId() {
61
65
  return crypto.randomUUID();
62
66
  }
63
67
  }
64
- function start(endpoint, installId) {
68
+ function start(endpoint) {
65
69
  const sid = sessionId();
66
70
  // The route the dashboard is mounted at, learned from where we woke up.
67
71
  // Capture is suspended whenever the URL wanders off it — the listeners
@@ -75,7 +79,7 @@ function start(endpoint, installId) {
75
79
  if (queue.length === 0)
76
80
  return;
77
81
  const batch = queue.splice(0, queue.length);
78
- const body = JSON.stringify({ installId, sessionId: sid, events: batch });
82
+ const body = JSON.stringify({ sessionId: sid, events: batch });
79
83
  if (useBeacon && navigator.sendBeacon) {
80
84
  const ok = navigator.sendBeacon(endpoint, new Blob([body], { type: "text/plain" }));
81
85
  if (!ok)
@@ -127,6 +131,66 @@ function start(endpoint, installId) {
127
131
  push({ type: "click", selector, component, text });
128
132
  }
129
133
  }, { capture: true, passive: true });
134
+ // ---- scroll depth (of whatever actually scrolls) --------------------------
135
+ // The dashboard scrolls inside its own shell container, not the document,
136
+ // so this listens in the capture phase and reads whichever element fired —
137
+ // only meaningfully scrollable ones contribute.
138
+ let maxScrollPct = 0;
139
+ document.addEventListener("scroll", (ev) => {
140
+ if (!onDashboard())
141
+ return;
142
+ const t = ev.target;
143
+ const el = t instanceof Element ? t : document.documentElement;
144
+ const scrollable = el.scrollHeight - el.clientHeight;
145
+ if (scrollable <= 0)
146
+ return;
147
+ const pct = Math.min(100, Math.round((el.scrollTop / scrollable) * 100));
148
+ if (pct > maxScrollPct)
149
+ maxScrollPct = pct;
150
+ }, { capture: true, passive: true });
151
+ /** Report the outgoing tab's depth before the path context changes. */
152
+ const flushScrollDepth = () => {
153
+ if (maxScrollPct <= 0)
154
+ return;
155
+ push({ type: "scroll_depth", value: maxScrollPct });
156
+ maxScrollPct = 0;
157
+ };
158
+ // ---- errors ---------------------------------------------------------------
159
+ addEventListener("error", (ev) => {
160
+ if (!onDashboard())
161
+ return;
162
+ push({
163
+ type: "js_error",
164
+ meta: {
165
+ message: String(ev.message).slice(0, 300),
166
+ source: ev.filename || "",
167
+ line: ev.lineno || 0,
168
+ },
169
+ });
170
+ }, true);
171
+ addEventListener("unhandledrejection", (ev) => {
172
+ if (!onDashboard())
173
+ return;
174
+ const reason = ev.reason;
175
+ push({
176
+ type: "js_error",
177
+ meta: {
178
+ message: String(reason?.message ?? reason).slice(0, 300),
179
+ kind: "unhandledrejection",
180
+ },
181
+ });
182
+ });
183
+ // ---- design scan (the dashboard's own rendered design) --------------------
184
+ // One scan per tab per session, labeled with the telemetry path. On the
185
+ // collecting side this is what feeds the Design tab: the dashboard's design
186
+ // as real installs actually render it.
187
+ const emitDesignScan = () => {
188
+ const path = currentPath;
189
+ scheduleDesignScan(path, (payloadJson, elements) => {
190
+ push({ type: "design_scan", path, meta: { payload: payloadJson, el: elements } });
191
+ flush();
192
+ }, { scanDashboard: true, stillCurrent: () => onDashboard() && telemetryPath() === path });
193
+ };
130
194
  // ---- page views (tab switches ride on the History API) -------------------
131
195
  const onNavigate = () => {
132
196
  if (!onDashboard())
@@ -134,8 +198,10 @@ function start(endpoint, installId) {
134
198
  const next = telemetryPath();
135
199
  if (next === currentPath)
136
200
  return;
201
+ flushScrollDepth();
137
202
  currentPath = next;
138
203
  push({ type: "page_view", path: currentPath });
204
+ emitDesignScan();
139
205
  };
140
206
  const wrapHistory = (method) => {
141
207
  const original = history[method];
@@ -150,6 +216,7 @@ function start(endpoint, installId) {
150
216
  addEventListener("popstate", onNavigate);
151
217
  // ---- lifecycle -----------------------------------------------------------
152
218
  addEventListener("pagehide", () => {
219
+ flushScrollDepth();
153
220
  push({ type: "session_end" });
154
221
  flush(true);
155
222
  });
@@ -163,21 +230,22 @@ function start(endpoint, installId) {
163
230
  push({ type: "viewport", value: w, text: deviceCategory(w) });
164
231
  }
165
232
  push({ type: "page_view", path: currentPath });
233
+ emitDesignScan();
166
234
  }
167
235
  /**
168
236
  * Mounted by the dashboard page only when consent is granted. Renders nothing;
169
237
  * starts the capture singleton once per page load (the listeners are global
170
238
  * and deliberately never torn down — capture suspends off-dashboard instead).
171
239
  */
172
- export function PolishdTelemetryEmitter({ endpoint, installId, }) {
240
+ export function PolishdTelemetryEmitter({ endpoint }) {
173
241
  useEffect(() => {
174
242
  if (window.__polishdTelemetryStarted)
175
243
  return;
176
244
  if (navigator.doNotTrack === "1")
177
245
  return;
178
246
  window.__polishdTelemetryStarted = true;
179
- start(endpoint, installId);
180
- }, [endpoint, installId]);
247
+ start(endpoint);
248
+ }, [endpoint]);
181
249
  return null;
182
250
  }
183
251
  /**
@@ -207,6 +275,6 @@ export function PolishdTelemetryConsent() {
207
275
  }
208
276
  setDismissed(true);
209
277
  });
210
- return (_jsxs("div", { role: "dialog", "aria-label": "Polishd telemetry consent", className: "fixed bottom-4 right-4 z-50 w-[340px] max-w-[calc(100vw-2rem)] rounded-xl border border-[#2e2e2e] bg-[#111] p-4 shadow-2xl", children: [_jsx("p", { className: "text-[13px] font-medium text-white", children: "Help improve polishd?" }), _jsxs("p", { className: "mt-1.5 text-[12px] leading-relaxed text-[#888]", children: ["Share anonymous usage of ", _jsx("span", { className: "text-[#aaa]", children: "this dashboard" }), " \u2014 clicks and tab views inside it, tied to a random install id. Never your site's analytics, never your visitors' data. Opt out any time with", " ", _jsx("code", { className: "font-mono text-[11px] text-[#aaa]", children: "POLISHD_TELEMETRY=off" }), "."] }), _jsxs("div", { className: "mt-3 flex gap-2", children: [_jsx("button", { type: "button", disabled: pending, onClick: () => decide(true), className: "rounded-lg bg-white px-3 py-1.5 text-[12px] font-medium text-black transition-opacity hover:opacity-90 disabled:opacity-50", children: "Share" }), _jsx("button", { type: "button", disabled: pending, onClick: () => decide(false), className: "rounded-lg border border-[#2e2e2e] px-3 py-1.5 text-[12px] text-[#888] transition-colors hover:text-white disabled:opacity-50", children: "No thanks" })] })] }));
278
+ return (_jsxs("div", { role: "dialog", "aria-label": "Polishd telemetry consent", className: "fixed bottom-4 right-4 z-50 w-[340px] max-w-[calc(100vw-2rem)] rounded-xl border border-[#2e2e2e] bg-[#111] p-4 shadow-2xl", children: [_jsx("p", { className: "text-[13px] font-medium text-white", children: "Help improve polishd?" }), _jsxs("p", { className: "mt-1.5 text-[12px] leading-relaxed text-[#888]", children: ["Share anonymous usage of ", _jsx("span", { className: "text-[#aaa]", children: "this dashboard" }), " \u2014 clicks and tab views inside it, reported under your site's domain. Never your site's analytics, never your visitors' data. Opt out any time with", " ", _jsx("code", { className: "font-mono text-[11px] text-[#aaa]", children: "POLISHD_TELEMETRY=off" }), "."] }), _jsxs("div", { className: "mt-3 flex gap-2", children: [_jsx("button", { type: "button", disabled: pending, onClick: () => decide(true), className: "rounded-lg bg-white px-3 py-1.5 text-[12px] font-medium text-black transition-opacity hover:opacity-90 disabled:opacity-50", children: "Share" }), _jsx("button", { type: "button", disabled: pending, onClick: () => decide(false), className: "rounded-lg border border-[#2e2e2e] px-3 py-1.5 text-[12px] text-[#888] transition-colors hover:text-white disabled:opacity-50", children: "No thanks" })] })] }));
211
279
  }
212
280
  //# sourceMappingURL=telemetry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/dashboard/telemetry.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAG3D,OAAO,EACL,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAElF,MAAM,WAAW,GAAG,WAAW,CAAC;AAChC,MAAM,WAAW,GAAG,2BAA2B,CAAC;AAChD,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACjC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,MAAM,cAAc,GAAG,GAAG,CAAC;AAQ3B,2DAA2D;AAC3D,SAAS,aAAa;IACpB,MAAM,GAAG,GAAG,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,GAAG,WAAW,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;AAChD,CAAC;AAED,8EAA8E;AAC9E,SAAS,SAAS;IAChB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACnC,cAAc,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC5C,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;QAC/D,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,QAAgB,EAAE,SAAiB;IAChD,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,wEAAwE;IACxE,uEAAuE;IACvE,0EAA0E;IAC1E,uBAAuB;IACvB,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC;IACpC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,SAAS,CAAC;IAE1D,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,IAAI,WAAW,GAAG,aAAa,EAAE,CAAC;IAElC,MAAM,KAAK,GAAG,CAAC,SAAS,GAAG,KAAK,EAAE,EAAE;QAClC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,IAAI,SAAS,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YACtC,MAAM,EAAE,GAAG,SAAS,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;YACpF,IAAI,CAAC,EAAE;gBAAE,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;YACjC,OAAO;QACT,CAAC;QACD,KAAK,CAAC,QAAQ,EAAE;YACd,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE;YACzC,IAAI;YACJ,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACZ,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,CACX,CAAiF,EACjF,EAAE;QACF,IAAI,CAAC,WAAW,EAAE;YAAE,OAAO;QAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,EAAkB,CAAC,CAAC;QACxE,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS;YAAE,KAAK,EAAE,CAAC;IACzC,CAAC,CAAC;IAEF,6EAA6E;IAE7E,IAAI,SAAS,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAEpD,QAAQ,CAAC,gBAAgB,CACvB,OAAO,EACP,CAAC,EAAE,EAAE,EAAE;QACL,MAAM,MAAM,GAAG,EAAE,CAAC,MAAwB,CAAC;QAC3C,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE;YAAE,OAAO;QACtC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,IAAI,QAAQ,KAAK,SAAS,CAAC,QAAQ,IAAI,GAAG,GAAG,SAAS,CAAC,IAAI,GAAG,cAAc,EAAE,CAAC;YAC7E,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,SAAS,CAAC,IAAI,GAAG,GAAG,CAAC;YACrB,IAAI,SAAS,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBACnC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAChE,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,IAAI,gBAAgB,EAAE;gBAAE,OAAO;YAC/B,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CACjC,CAAC;IAEF,6EAA6E;IAE7E,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,WAAW,EAAE;YAAE,OAAO;QAC3B,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;QAC7B,IAAI,IAAI,KAAK,WAAW;YAAE,OAAO;QACjC,WAAW,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,MAAoC,EAAE,EAAE;QAC3D,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,CAAC,MAAM,CAAC,GAAG,UAAyB,GAAG,IAAsC;YAClF,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACvC,UAAU,EAAE,CAAC;YACb,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;IACJ,CAAC,CAAC;IACF,WAAW,CAAC,WAAW,CAAC,CAAC;IACzB,WAAW,CAAC,cAAc,CAAC,CAAC;IAC5B,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAEzC,6EAA6E;IAE7E,gBAAgB,CAAC,UAAU,EAAE,GAAG,EAAE;QAChC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC,CAAC,CAAC;IACH,gBAAgB,CAAC,kBAAkB,EAAE,GAAG,EAAE;QACxC,IAAI,QAAQ,CAAC,eAAe,KAAK,QAAQ;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IACH,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAEnD,MAAM,CAAC,GAAG,MAAM,CAAC,UAAU,IAAI,QAAQ,CAAC,eAAe,CAAC,WAAW,IAAI,CAAC,CAAC;IACzE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,QAAQ,EACR,SAAS,GAIV;IACC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,CAAC,yBAAyB;YAAE,OAAO;QAC7C,IAAI,SAAS,CAAC,UAAU,KAAK,GAAG;YAAE,OAAO;QACzC,MAAM,CAAC,yBAAyB,GAAG,IAAI,CAAC;QACxC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC7B,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,GAAG,aAAa,EAAE,CAAC;IACnD,IAAI,SAAS;QAAE,OAAO,IAAI,CAAC;IAE3B,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAE,EAAE,CAClC,eAAe,CAAC,KAAK,IAAI,EAAE;QACzB,IAAI,CAAC;YACH,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,qBAAqB,EAAE,CAAC;gBAC9B,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,MAAM,oBAAoB,EAAE,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;YACrE,oDAAoD;QACtD,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IAEL,OAAO,CACL,eACE,IAAI,EAAC,QAAQ,gBACF,2BAA2B,EACtC,SAAS,EAAC,4HAA4H,aAEtI,YAAG,SAAS,EAAC,oCAAoC,sCAA0B,EAC3E,aAAG,SAAS,EAAC,gDAAgD,0CAClC,eAAM,SAAS,EAAC,aAAa,+BAAsB,wJAE5B,GAAG,EACnD,eAAM,SAAS,EAAC,mCAAmC,sCAA6B,SAC9E,EACJ,eAAK,SAAS,EAAC,iBAAiB,aAC9B,iBACE,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAC3B,SAAS,EAAC,4HAA4H,sBAG/H,EACT,iBACE,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAC5B,SAAS,EAAC,+HAA+H,0BAGlI,IACL,IACF,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/dashboard/telemetry.tsx"],"names":[],"mappings":"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"}
@@ -25,6 +25,7 @@ export declare function RefreshIcon({ spinning }: {
25
25
  export declare function GearIcon(): import("react").JSX.Element;
26
26
  export declare function ChartIcon(): import("react").JSX.Element;
27
27
  export declare function DropletIcon(): import("react").JSX.Element;
28
+ export declare function GlobeIcon(): import("react").JSX.Element;
28
29
  /** The tab rail's in-flight marker: same 13px box as the icon it replaces. */
29
30
  export declare function SpinnerIcon(): import("react").JSX.Element;
30
31
  //# sourceMappingURL=ui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/dashboard/ui.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,MAAM,qBAAqB,CAAC;AACzC,eAAO,MAAM,IAAI,oDAA6C,CAAC;AAC/D,eAAO,MAAM,OAAO,8BAAuB,CAAC;AAC5C,eAAO,MAAM,QAAQ,oEAAoE,CAAC;AAC1F,eAAO,MAAM,QAAQ,wJACkI,CAAC;AACxJ,eAAO,MAAM,UAAU,2JACmI,CAAC;AAC3J,eAAO,MAAM,QAAQ,oLAC8J,CAAC;AACpL,eAAO,MAAM,OAAO,mMAC8K,CAAC;AAEnM,4EAA4E;AAC5E,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAQ1C;AAID,wBAAgB,WAAW,CAAC,EAAE,QAAgB,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,+BAkBvE;AAED,wBAAgB,QAAQ,gCAiBvB;AAED,wBAAgB,SAAS,gCAkBxB;AAED,wBAAgB,WAAW,gCAgB1B;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,gCAiB1B"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/dashboard/ui.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,MAAM,qBAAqB,CAAC;AACzC,eAAO,MAAM,IAAI,oDAA6C,CAAC;AAC/D,eAAO,MAAM,OAAO,8BAAuB,CAAC;AAC5C,eAAO,MAAM,QAAQ,oEAAoE,CAAC;AAC1F,eAAO,MAAM,QAAQ,wJACkI,CAAC;AACxJ,eAAO,MAAM,UAAU,2JACmI,CAAC;AAC3J,eAAO,MAAM,QAAQ,oLAC8J,CAAC;AACpL,eAAO,MAAM,OAAO,mMAC8K,CAAC;AAEnM,4EAA4E;AAC5E,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAQ1C;AAID,wBAAgB,WAAW,CAAC,EAAE,QAAgB,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,+BAkBvE;AAED,wBAAgB,QAAQ,gCAiBvB;AAED,wBAAgB,SAAS,gCAkBxB;AAED,wBAAgB,WAAW,gCAgB1B;AAED,wBAAgB,SAAS,gCAkBxB;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,gCAiB1B"}
@@ -44,6 +44,9 @@ export function ChartIcon() {
44
44
  export function DropletIcon() {
45
45
  return (_jsx("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: _jsx("path", { d: "M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" }) }));
46
46
  }
47
+ export function GlobeIcon() {
48
+ return (_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("line", { x1: "2", y1: "12", x2: "22", y2: "12" }), _jsx("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" })] }));
49
+ }
47
50
  /** The tab rail's in-flight marker: same 13px box as the icon it replaces. */
48
51
  export function SpinnerIcon() {
49
52
  return (_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", className: "animate-spin", "aria-hidden": true, children: [_jsx("circle", { cx: "12", cy: "12", r: "9", opacity: "0.25" }), _jsx("path", { d: "M21 12a9 9 0 0 0-9-9" })] }));
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/dashboard/ui.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/dashboard/ui.tsx"],"names":[],"mappings":"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"}
@@ -92,7 +92,6 @@
92
92
  --color-purple-300: oklch(82.7% .119 306.383);
93
93
  --color-purple-400: oklch(71.4% .203 305.504);
94
94
  --color-purple-500: oklch(62.7% .265 303.9);
95
- --color-purple-950: oklch(29.1% .149 302.717);
96
95
  --color-black: #000;
97
96
  --color-white: #fff;
98
97
  --spacing: .25rem;
@@ -282,6 +281,10 @@
282
281
  inset-inline: 0;
283
282
  }
284
283
 
284
+ .polishd-root.polishd-root .inset-y-0 {
285
+ inset-block: 0;
286
+ }
287
+
285
288
  .polishd-root.polishd-root .top-0 {
286
289
  top: 0;
287
290
  }
@@ -848,8 +851,8 @@
848
851
  min-width: 0;
849
852
  }
850
853
 
851
- .polishd-root.polishd-root .min-w-\[160px\] {
852
- min-width: 160px;
854
+ .polishd-root.polishd-root .min-w-\[280px\] {
855
+ min-width: 280px;
853
856
  }
854
857
 
855
858
  .polishd-root.polishd-root .min-w-\[420px\] {
@@ -864,8 +867,12 @@
864
867
  min-width: 560px;
865
868
  }
866
869
 
867
- .polishd-root.polishd-root .min-w-\[700px\] {
868
- min-width: 700px;
870
+ .polishd-root.polishd-root .min-w-\[640px\] {
871
+ min-width: 640px;
872
+ }
873
+
874
+ .polishd-root.polishd-root .min-w-\[820px\] {
875
+ min-width: 820px;
869
876
  }
870
877
 
871
878
  .polishd-root.polishd-root .flex-1 {
@@ -945,6 +952,10 @@
945
952
  cursor: pointer;
946
953
  }
947
954
 
955
+ .polishd-root.polishd-root .resize {
956
+ resize: both;
957
+ }
958
+
948
959
  .polishd-root.polishd-root .resize-y {
949
960
  resize: vertical;
950
961
  }
@@ -1137,6 +1148,10 @@
1137
1148
  border-radius: .25rem;
1138
1149
  }
1139
1150
 
1151
+ .polishd-root.polishd-root .rounded-\[2px\] {
1152
+ border-radius: 2px;
1153
+ }
1154
+
1140
1155
  .polishd-root.polishd-root .rounded-\[5px\] {
1141
1156
  border-radius: 5px;
1142
1157
  }
@@ -1271,6 +1286,16 @@
1271
1286
  border-color: var(--color-white);
1272
1287
  }
1273
1288
 
1289
+ .polishd-root.polishd-root .border-white\/20 {
1290
+ border-color: #fff3;
1291
+ }
1292
+
1293
+ @supports (color: color-mix(in lab, red, red)) {
1294
+ .polishd-root.polishd-root .border-white\/20 {
1295
+ border-color: color-mix(in oklab, var(--color-white) 20%, transparent);
1296
+ }
1297
+ }
1298
+
1274
1299
  .polishd-root.polishd-root .bg-\[\#0a0a0a\] {
1275
1300
  background-color: #0a0a0a;
1276
1301
  }
@@ -1287,6 +1312,10 @@
1287
1312
  background-color: #1a1a1a;
1288
1313
  }
1289
1314
 
1315
+ .polishd-root.polishd-root .bg-\[\#1c1c1c\] {
1316
+ background-color: #1c1c1c;
1317
+ }
1318
+
1290
1319
  .polishd-root.polishd-root .bg-\[\#2e2e2e\] {
1291
1320
  background-color: #2e2e2e;
1292
1321
  }
@@ -1319,6 +1348,10 @@
1319
1348
  background-color: #666;
1320
1349
  }
1321
1350
 
1351
+ .polishd-root.polishd-root .bg-\[\#777\] {
1352
+ background-color: #777;
1353
+ }
1354
+
1322
1355
  .polishd-root.polishd-root .bg-\[\#050505\] {
1323
1356
  background-color: #050505;
1324
1357
  }
@@ -1433,6 +1466,10 @@
1433
1466
  background-color: currentColor;
1434
1467
  }
1435
1468
 
1469
+ .polishd-root.polishd-root .bg-emerald-500 {
1470
+ background-color: var(--color-emerald-500);
1471
+ }
1472
+
1436
1473
  .polishd-root.polishd-root .bg-emerald-950 {
1437
1474
  background-color: var(--color-emerald-950);
1438
1475
  }
@@ -1455,10 +1492,6 @@
1455
1492
  background-color: var(--color-purple-500);
1456
1493
  }
1457
1494
 
1458
- .polishd-root.polishd-root .bg-purple-950 {
1459
- background-color: var(--color-purple-950);
1460
- }
1461
-
1462
1495
  .polishd-root.polishd-root .bg-red-500 {
1463
1496
  background-color: var(--color-red-500);
1464
1497
  }
@@ -1503,6 +1536,10 @@
1503
1536
  padding: calc(var(--spacing) * 5);
1504
1537
  }
1505
1538
 
1539
+ .polishd-root.polishd-root .px-1 {
1540
+ padding-inline: var(--spacing);
1541
+ }
1542
+
1506
1543
  .polishd-root.polishd-root .px-1\.5 {
1507
1544
  padding-inline: calc(var(--spacing) * 1.5);
1508
1545
  }
@@ -1611,6 +1648,10 @@
1611
1648
  padding-block: 76px;
1612
1649
  }
1613
1650
 
1651
+ .polishd-root.polishd-root .py-px {
1652
+ padding-block: 1px;
1653
+ }
1654
+
1614
1655
  .polishd-root.polishd-root .pt-4 {
1615
1656
  padding-top: calc(var(--spacing) * 4);
1616
1657
  }
@@ -2276,11 +2317,23 @@
2276
2317
  color: var(--color-white);
2277
2318
  }
2278
2319
 
2279
- .polishd-root.polishd-root .group-hover\/tip\:opacity-100:is(:where(.group\/tip):hover *) {
2320
+ .polishd-root.polishd-root .group-hover\/chip\:opacity-0:is(:where(.group\/chip):hover *) {
2321
+ opacity: 0;
2322
+ }
2323
+
2324
+ .polishd-root.polishd-root .group-hover\/chip\:opacity-100:is(:where(.group\/chip):hover *), .polishd-root.polishd-root .group-hover\/tip\:opacity-100:is(:where(.group\/tip):hover *) {
2280
2325
  opacity: 1;
2281
2326
  }
2282
2327
  }
2283
2328
 
2329
+ .polishd-root.polishd-root .group-focus-visible\/chip\:opacity-0:is(:where(.group\/chip):focus-visible *) {
2330
+ opacity: 0;
2331
+ }
2332
+
2333
+ .polishd-root.polishd-root .group-focus-visible\/chip\:opacity-100:is(:where(.group\/chip):focus-visible *) {
2334
+ opacity: 1;
2335
+ }
2336
+
2284
2337
  .polishd-root.polishd-root .placeholder\:text-\[\#555\]::placeholder {
2285
2338
  color: #555;
2286
2339
  }
@@ -2307,6 +2360,10 @@
2307
2360
  background-color: #1a1a1a;
2308
2361
  }
2309
2362
 
2363
+ .polishd-root.polishd-root .hover\:bg-\[\#1f1f1f\]:hover {
2364
+ background-color: #1f1f1f;
2365
+ }
2366
+
2310
2367
  .polishd-root.polishd-root .hover\:bg-\[\#111\]:hover {
2311
2368
  background-color: #111;
2312
2369
  }
@@ -2345,6 +2402,10 @@
2345
2402
  outline-style: none;
2346
2403
  }
2347
2404
 
2405
+ .polishd-root.polishd-root .focus-visible\:border-\[\#777\]:focus-visible {
2406
+ border-color: #777;
2407
+ }
2408
+
2348
2409
  .polishd-root.polishd-root .disabled\:cursor-not-allowed:disabled {
2349
2410
  cursor: not-allowed;
2350
2411
  }
@@ -42,24 +42,37 @@ export declare function sessionIdFromCookie(cookieValue: string | undefined): st
42
42
  * they do in the browser. It falls back to the defaults when omitted.
43
43
  */
44
44
  export declare function ingest(body: unknown, cookieValue: string | undefined, config?: Partial<PolishdConfig>): Promise<IngestResult>;
45
+ /**
46
+ * Derive the reporting installation's identity — its hostname — from request
47
+ * headers.
48
+ *
49
+ * The `Origin` header is the honest source: the browser sets it on every
50
+ * cross-origin POST and page script cannot forge it, so it names the site the
51
+ * dashboard actually runs on. A request without one (same-origin in some
52
+ * browsers, server-to-server) falls back to `Host`. A *malformed* Origin gets
53
+ * no fallback — a client that sends the header wrong is not one to guess for.
54
+ * Returns null when no acceptable hostname can be derived; ports are dropped
55
+ * so one install's dev server isn't split across restarts.
56
+ */
57
+ export declare function telemetryInstallId(origin: string | null, host: string | null): string | null;
45
58
  /**
46
59
  * Ingest a telemetry batch from a *remote* polishd installation.
47
60
  *
48
61
  * This differs from first-party {@link ingest} in exactly three ways, each a
49
62
  * consequence of the request crossing origins:
50
63
  *
51
- * 1. Identity travels in the body. The session cookie is httpOnly and
52
- * first-party, so it never arrives here; the emitter mints an anonymous
53
- * session id itself and sends it alongside a stable `installId`. Both are
54
- * validated by shape only — there is nothing to verify them against, and
55
- * the worst a forger achieves is polluting telemetry, same as any public
56
- * ingest endpoint.
64
+ * 1. Identity is split between body and headers. The session cookie is
65
+ * httpOnly and first-party, so it never arrives here; the emitter mints
66
+ * an anonymous session id itself, and the *installation* is identified by
67
+ * `installId` — the hostname the route derived from the Origin header via
68
+ * {@link telemetryInstallId}. It is validated by shape only; the worst a
69
+ * forger achieves is polluting telemetry, same as any public endpoint.
57
70
  * 2. Every stored row is tagged with the `installId`, so one shared database
58
- * can tell installations apart.
71
+ * can tell installations apart — and name them by domain.
59
72
  * 3. Dashboard paths are NOT dropped. Recording how the dashboard itself is
60
73
  * used is the entire point of this channel; the emitter is expected to
61
74
  * namespace its paths so they can't collide with the receiving site's own
62
75
  * first-party events.
63
76
  */
64
- export declare function ingestTelemetry(body: unknown, config?: Partial<PolishdConfig>): Promise<IngestResult>;
77
+ export declare function ingestTelemetry(body: unknown, installId: string | null, config?: Partial<PolishdConfig>): Promise<IngestResult>;
65
78
  //# sourceMappingURL=ingest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/server/ingest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAenB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AAExD,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AA+BD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAElF;AAkCD;;;;;;GAMG;AACH,wBAAsB,MAAM,CAC1B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,YAAY,CAAC,CA4BvB;AAWD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,OAAO,EACb,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,YAAY,CAAC,CAyBvB"}
1
+ {"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/server/ingest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAenB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AAExD,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AA+BD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAElF;AAkCD;;;;;;GAMG;AACH,wBAAsB,MAAM,CAC1B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,YAAY,CAAC,CA4BvB;AAcD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAc5F;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,YAAY,CAAC,CAsBvB"}