@liiift-studio/sanity-visitor-insights 0.8.1 → 0.9.0
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.
- package/dist/index.js +218 -52
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +203 -47
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/studio/Figure.tsx +239 -43
- package/src/studio/VisitorInsightsTool.tsx +15 -0
- package/src/studio/panels.test.tsx +110 -3
- package/src/studio/panels.tsx +20 -6
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -51,7 +61,7 @@ var import_sanity2 = require("sanity");
|
|
|
51
61
|
var import_icons = require("@liiift-studio/sanity-ui-compat/icons");
|
|
52
62
|
|
|
53
63
|
// src/studio/VisitorInsightsTool.tsx
|
|
54
|
-
var
|
|
64
|
+
var import_react3 = require("react");
|
|
55
65
|
var import_sanity_ui_compat3 = require("@liiift-studio/sanity-ui-compat");
|
|
56
66
|
|
|
57
67
|
// src/studio/useReport.ts
|
|
@@ -106,6 +116,7 @@ function useReport({ apiBaseUrl, report, range }) {
|
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
// src/studio/Figure.tsx
|
|
119
|
+
var import_react2 = __toESM(require("react"));
|
|
109
120
|
var import_sanity_ui_compat = require("@liiift-studio/sanity-ui-compat");
|
|
110
121
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
111
122
|
var REASON_TEXT = {
|
|
@@ -141,7 +152,7 @@ function ComparisonBar({ label, metric, max, tone = "default" }) {
|
|
|
141
152
|
const value = metric.status === "unavailable" ? null : metric.value;
|
|
142
153
|
const width = value !== null && max > 0 ? Math.max(2, value / max * 100) : 0;
|
|
143
154
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_sanity_ui_compat.Stack, { space: 2, children: [
|
|
144
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
155
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: barHeader, children: [
|
|
145
156
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Text, { size: 1, weight: "medium", children: label }),
|
|
146
157
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetricFigure, { metric, label, size: 1 })
|
|
147
158
|
] }),
|
|
@@ -164,24 +175,69 @@ function ComparisonBar({ label, metric, max, tone = "default" }) {
|
|
|
164
175
|
)
|
|
165
176
|
] });
|
|
166
177
|
}
|
|
178
|
+
var chartFrame = { position: "relative", width: "100%" };
|
|
179
|
+
var readout = {
|
|
180
|
+
position: "absolute",
|
|
181
|
+
top: 0,
|
|
182
|
+
right: 0,
|
|
183
|
+
padding: "6px 10px",
|
|
184
|
+
borderRadius: 3,
|
|
185
|
+
background: "var(--card-bg-color, rgba(0,0,0,0.55))",
|
|
186
|
+
border: "1px solid var(--card-border-color, rgba(128,128,128,0.35))",
|
|
187
|
+
pointerEvents: "none",
|
|
188
|
+
maxWidth: "70%"
|
|
189
|
+
};
|
|
190
|
+
var barHeader = {
|
|
191
|
+
display: "flex",
|
|
192
|
+
alignItems: "center",
|
|
193
|
+
justifyContent: "space-between",
|
|
194
|
+
gap: 12,
|
|
195
|
+
flexWrap: "wrap"
|
|
196
|
+
};
|
|
197
|
+
var legendRow = {
|
|
198
|
+
display: "flex",
|
|
199
|
+
gap: 12,
|
|
200
|
+
alignItems: "center",
|
|
201
|
+
flexWrap: "wrap"
|
|
202
|
+
};
|
|
203
|
+
var noticeRow = {
|
|
204
|
+
display: "flex",
|
|
205
|
+
gap: 12,
|
|
206
|
+
alignItems: "flex-start",
|
|
207
|
+
flexWrap: "wrap"
|
|
208
|
+
};
|
|
209
|
+
var noticeBadge = { flex: "0 0 auto" };
|
|
167
210
|
function NoticeList({ notices }) {
|
|
168
211
|
if (notices.length === 0) return null;
|
|
169
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "grid", gap: 8 }, children: notices.map((notice) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Card, { padding: 3, radius: 2, tone: "caution", border: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
170
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Badge, { tone: "caution", fontSize: 0, children: "Caveat" }),
|
|
212
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "grid", gap: 8 }, children: notices.map((notice) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Card, { padding: 3, radius: 2, tone: "caution", border: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: noticeRow, children: [
|
|
213
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: noticeBadge, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Badge, { tone: "caution", fontSize: 0, children: "Caveat" }) }),
|
|
171
214
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Text, { size: 1, children: notice })
|
|
172
215
|
] }) }) }, notice)) });
|
|
173
216
|
}
|
|
217
|
+
var CHART = { w: 760, h: 240, left: 52, right: 12, top: 16, bottom: 30 };
|
|
218
|
+
function niceCeiling(value) {
|
|
219
|
+
if (value <= 0) return 1;
|
|
220
|
+
const magnitude = 10 ** Math.floor(Math.log10(value));
|
|
221
|
+
const normalised = value / magnitude;
|
|
222
|
+
const step = normalised <= 1 ? 1 : normalised <= 2 ? 2 : normalised <= 5 ? 5 : 10;
|
|
223
|
+
return step * magnitude;
|
|
224
|
+
}
|
|
225
|
+
function shortDate(iso) {
|
|
226
|
+
const parsed = /* @__PURE__ */ new Date(`${iso}T00:00:00Z`);
|
|
227
|
+
if (Number.isNaN(parsed.getTime())) return iso;
|
|
228
|
+
return `${parsed.getUTCDate()} ${parsed.toLocaleString("en-GB", { month: "short", timeZone: "UTC" })}`;
|
|
229
|
+
}
|
|
174
230
|
function TrendChart({ points, label = "Daily pageviews, GA4 against Vercel" }) {
|
|
231
|
+
const [hovered, setHovered] = import_react2.default.useState(null);
|
|
175
232
|
if (points.length < 3) return null;
|
|
176
|
-
const W = 720;
|
|
177
|
-
const H = 132;
|
|
178
|
-
const PAD = 4;
|
|
179
233
|
const values = points.flatMap((p) => [p.ga4, p.vercel]).filter((v) => typeof v === "number");
|
|
180
234
|
if (values.length === 0) return null;
|
|
181
|
-
const max = Math.max(...values, 1);
|
|
182
|
-
const
|
|
183
|
-
const
|
|
184
|
-
const
|
|
235
|
+
const max = niceCeiling(Math.max(...values, 1));
|
|
236
|
+
const plotW = CHART.w - CHART.left - CHART.right;
|
|
237
|
+
const plotH = CHART.h - CHART.top - CHART.bottom;
|
|
238
|
+
const x = (i) => CHART.left + i / Math.max(1, points.length - 1) * plotW;
|
|
239
|
+
const y = (v) => CHART.top + plotH - v / max * plotH;
|
|
240
|
+
const line = (pick) => {
|
|
185
241
|
let d = "";
|
|
186
242
|
let penDown = false;
|
|
187
243
|
points.forEach((p, i) => {
|
|
@@ -195,40 +251,145 @@ function TrendChart({ points, label = "Daily pageviews, GA4 against Vercel" }) {
|
|
|
195
251
|
});
|
|
196
252
|
return d.trim();
|
|
197
253
|
};
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
"
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
254
|
+
const bands = [];
|
|
255
|
+
let run = [];
|
|
256
|
+
const flushRun = () => {
|
|
257
|
+
if (run.length > 1) {
|
|
258
|
+
const top = run.map((i) => `${x(i).toFixed(1)} ${y(points[i].vercel).toFixed(1)}`);
|
|
259
|
+
const bottom = [...run].reverse().map((i) => `${x(i).toFixed(1)} ${y(points[i].ga4).toFixed(1)}`);
|
|
260
|
+
bands.push(`M${top.join(" L")} L${bottom.join(" L")} Z`);
|
|
261
|
+
}
|
|
262
|
+
run = [];
|
|
263
|
+
};
|
|
264
|
+
points.forEach((p, i) => {
|
|
265
|
+
if (typeof p.ga4 === "number" && typeof p.vercel === "number") run.push(i);
|
|
266
|
+
else flushRun();
|
|
267
|
+
});
|
|
268
|
+
flushRun();
|
|
269
|
+
const ticks = [0, 0.25, 0.5, 0.75, 1].map((f) => ({ value: max * f, y: y(max * f) }));
|
|
270
|
+
const labelEvery = Math.max(1, Math.ceil(points.length / 6));
|
|
271
|
+
const dateTicks = points.map((p, i) => ({ i, date: p.date })).filter(({ i }) => i % labelEvery === 0 || i === points.length - 1);
|
|
272
|
+
const active = hovered !== null ? points[hovered] : null;
|
|
273
|
+
const activeGap = active && typeof active.ga4 === "number" && typeof active.vercel === "number" && active.vercel > 0 ? (active.vercel - active.ga4) / active.vercel : null;
|
|
274
|
+
const onKeyDown = (event) => {
|
|
275
|
+
const last = points.length - 1;
|
|
276
|
+
const current = hovered ?? 0;
|
|
277
|
+
const move = (next) => {
|
|
278
|
+
event.preventDefault();
|
|
279
|
+
setHovered(Math.max(0, Math.min(last, next)));
|
|
280
|
+
};
|
|
281
|
+
if (event.key === "ArrowRight") return move(hovered === null ? 0 : current + 1);
|
|
282
|
+
if (event.key === "ArrowLeft") return move(hovered === null ? last : current - 1);
|
|
283
|
+
if (event.key === "Home") return move(0);
|
|
284
|
+
if (event.key === "End") return move(last);
|
|
285
|
+
if (event.key === "Escape") {
|
|
286
|
+
setHovered(null);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
const onMove = (event) => {
|
|
291
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
292
|
+
if (box.width === 0) return;
|
|
293
|
+
const svgX = (event.clientX - box.left) / box.width * CHART.w;
|
|
294
|
+
const ratio = (svgX - CHART.left) / plotW;
|
|
295
|
+
const index = Math.round(ratio * (points.length - 1));
|
|
296
|
+
setHovered(index >= 0 && index < points.length ? index : null);
|
|
297
|
+
};
|
|
298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_sanity_ui_compat.Stack, { space: 3, children: [
|
|
299
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: chartFrame, children: [
|
|
300
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
301
|
+
"svg",
|
|
302
|
+
{
|
|
303
|
+
viewBox: `0 0 ${CHART.w} ${CHART.h}`,
|
|
304
|
+
width: "100%",
|
|
305
|
+
style: { display: "block", height: "auto" },
|
|
306
|
+
role: "img",
|
|
307
|
+
"aria-label": `${label}, ${points[0]?.date} to ${points[points.length - 1]?.date}. Peak ${formatCount(max)} pageviews in a day.`,
|
|
308
|
+
onMouseMove: onMove,
|
|
309
|
+
onMouseLeave: () => setHovered(null),
|
|
310
|
+
onKeyDown,
|
|
311
|
+
onBlur: () => setHovered(null),
|
|
312
|
+
tabIndex: 0,
|
|
313
|
+
"aria-describedby": active ? "trend-readout" : void 0,
|
|
314
|
+
children: [
|
|
315
|
+
ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { children: [
|
|
316
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
317
|
+
"line",
|
|
318
|
+
{
|
|
319
|
+
x1: CHART.left,
|
|
320
|
+
x2: CHART.w - CHART.right,
|
|
321
|
+
y1: tick.y,
|
|
322
|
+
y2: tick.y,
|
|
323
|
+
stroke: "currentColor",
|
|
324
|
+
strokeOpacity: tick.value === 0 ? 0.35 : 0.12,
|
|
325
|
+
strokeWidth: "1"
|
|
326
|
+
}
|
|
327
|
+
),
|
|
328
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
329
|
+
"text",
|
|
330
|
+
{
|
|
331
|
+
x: CHART.left - 8,
|
|
332
|
+
y: tick.y + 4,
|
|
333
|
+
textAnchor: "end",
|
|
334
|
+
fontSize: "11",
|
|
335
|
+
fill: "currentColor",
|
|
336
|
+
fillOpacity: "0.55",
|
|
337
|
+
children: formatCount(tick.value)
|
|
338
|
+
}
|
|
339
|
+
)
|
|
340
|
+
] }, tick.value)),
|
|
341
|
+
dateTicks.map(({ i, date }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
342
|
+
"text",
|
|
343
|
+
{
|
|
344
|
+
x: x(i),
|
|
345
|
+
y: CHART.h - 10,
|
|
346
|
+
textAnchor: "middle",
|
|
347
|
+
fontSize: "11",
|
|
348
|
+
fill: "currentColor",
|
|
349
|
+
fillOpacity: "0.55",
|
|
350
|
+
children: shortDate(date)
|
|
351
|
+
},
|
|
352
|
+
date
|
|
353
|
+
)),
|
|
354
|
+
bands.map((d) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d, fill: "currentColor", fillOpacity: "0.09", stroke: "none" }, d.slice(0, 24))),
|
|
355
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: line((p) => p.vercel), fill: "none", stroke: "currentColor", strokeOpacity: "0.9", strokeWidth: "2" }),
|
|
356
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: line((p) => p.ga4), fill: "none", stroke: "currentColor", strokeOpacity: "0.9", strokeWidth: "2", strokeDasharray: "5 3" }),
|
|
357
|
+
hovered !== null && active && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { children: [
|
|
358
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
359
|
+
"line",
|
|
360
|
+
{
|
|
361
|
+
x1: x(hovered),
|
|
362
|
+
x2: x(hovered),
|
|
363
|
+
y1: CHART.top,
|
|
364
|
+
y2: CHART.top + plotH,
|
|
365
|
+
stroke: "currentColor",
|
|
366
|
+
strokeOpacity: "0.4",
|
|
367
|
+
strokeWidth: "1"
|
|
368
|
+
}
|
|
369
|
+
),
|
|
370
|
+
typeof active.vercel === "number" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: x(hovered), cy: y(active.vercel), r: "4", fill: "currentColor" }),
|
|
371
|
+
typeof active.ga4 === "number" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: x(hovered), cy: y(active.ga4), r: "4", fill: "currentColor" })
|
|
372
|
+
] })
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
),
|
|
376
|
+
active && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: readout, id: "trend-readout", role: "status", "aria-live": "polite", children: [
|
|
377
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Text, { size: 1, weight: "medium", children: shortDate(active.date) }),
|
|
378
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_sanity_ui_compat.Text, { size: 1, muted: true, children: [
|
|
379
|
+
"Vercel ",
|
|
380
|
+
typeof active.vercel === "number" ? formatCount(active.vercel) : "\u2014",
|
|
381
|
+
" \xB7 ",
|
|
382
|
+
"GA4 ",
|
|
383
|
+
typeof active.ga4 === "number" ? formatCount(active.ga4) : "\u2014",
|
|
384
|
+
activeGap !== null ? ` \xB7 gap ${formatPercent(activeGap, 0)}` : ""
|
|
385
|
+
] })
|
|
386
|
+
] })
|
|
387
|
+
] }),
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: legendRow, children: [
|
|
220
389
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Text, { size: 0, muted: true, children: "\u2501\u2501 Vercel" }),
|
|
221
390
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Text, { size: 0, muted: true, children: "\u2504\u2504 GA4" }),
|
|
222
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
223
|
-
|
|
224
|
-
" to ",
|
|
225
|
-
last
|
|
226
|
-
] }),
|
|
227
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_sanity_ui_compat.Text, { size: 0, muted: true, children: [
|
|
228
|
-
"peak ",
|
|
229
|
-
formatCount(max),
|
|
230
|
-
"/day"
|
|
231
|
-
] })
|
|
391
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Text, { size: 0, muted: true, children: "shaded band is the gap" }),
|
|
392
|
+
!active && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sanity_ui_compat.Text, { size: 0, muted: true, children: "hover, or focus and use arrow keys, for a day" })
|
|
232
393
|
] })
|
|
233
394
|
] });
|
|
234
395
|
}
|
|
@@ -243,6 +404,11 @@ function maxOf(metrics) {
|
|
|
243
404
|
return metrics.reduce((max, metric) => metric.status === "unavailable" ? max : Math.max(max, metric.value), 0);
|
|
244
405
|
}
|
|
245
406
|
var tableWrap = { overflowX: "auto", width: "100%" };
|
|
407
|
+
var cardGrid = {
|
|
408
|
+
display: "grid",
|
|
409
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(min(14rem, 100%), 1fr))",
|
|
410
|
+
gap: 16
|
|
411
|
+
};
|
|
246
412
|
var table = { width: "100%", borderCollapse: "collapse", minWidth: 420 };
|
|
247
413
|
var cell = { padding: "8px 12px", textAlign: "left", borderBottom: "1px solid var(--card-border-color)" };
|
|
248
414
|
var numericCell = { ...cell, textAlign: "right" };
|
|
@@ -267,7 +433,7 @@ function MeasurementHealthPanel({ data }) {
|
|
|
267
433
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sanity_ui_compat2.Stack, { space: 3, children: [
|
|
268
434
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Heading, { size: 1, children: "Context" }),
|
|
269
435
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Text, { size: 1, muted: true, children: "Different units to the figures above, and to each other. Shown for scale, never differenced." }),
|
|
270
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
436
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: cardGrid, children: [
|
|
271
437
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Card, { padding: 3, radius: 2, tone: "transparent", border: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sanity_ui_compat2.Stack, { space: 3, children: [
|
|
272
438
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Label, { size: 1, muted: true, children: "GA4 sessions" }),
|
|
273
439
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MetricFigure, { metric: data.ga4Sessions, label: "GA4 sessions" })
|
|
@@ -286,7 +452,7 @@ function MeasurementHealthPanel({ data }) {
|
|
|
286
452
|
}
|
|
287
453
|
function AcquisitionPanel({ data }) {
|
|
288
454
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sanity_ui_compat2.Stack, { space: 4, children: [
|
|
289
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
455
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: cardGrid, children: [
|
|
290
456
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Card, { padding: 3, radius: 2, tone: "transparent", border: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sanity_ui_compat2.Stack, { space: 3, children: [
|
|
291
457
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Label, { size: 1, muted: true, children: "Sessions" }),
|
|
292
458
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Text, { size: 4, children: formatCount(data.totalSessions) })
|
|
@@ -308,7 +474,7 @@ function AcquisitionPanel({ data }) {
|
|
|
308
474
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { scope: "col", style: numericCell, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Label, { size: 1, muted: true, children: "Sessions" }) })
|
|
309
475
|
] }) }),
|
|
310
476
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { children: (data.rows ?? []).map((row) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("tr", { children: [
|
|
311
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { scope: "row", style: cell, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
477
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { scope: "row", style: cell, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }, children: [
|
|
312
478
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Text, { size: 1, children: row.source }),
|
|
313
479
|
row.designIndustry && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Badge, { tone: "primary", fontSize: 0, children: "design industry" }),
|
|
314
480
|
row.unattributed && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Badge, { tone: "caution", fontSize: 0, children: "unattributed" })
|
|
@@ -412,8 +578,8 @@ var PANELS = [
|
|
|
412
578
|
{ report: "diagnostics", label: "Diagnostics", blurb: "What to fix before trusting the numbers above" }
|
|
413
579
|
];
|
|
414
580
|
function RangeSelector({ value, onChange }) {
|
|
415
|
-
const refs = (0,
|
|
416
|
-
const onKeyDown = (0,
|
|
581
|
+
const refs = (0, import_react3.useRef)([]);
|
|
582
|
+
const onKeyDown = (0, import_react3.useCallback)(
|
|
417
583
|
(event) => {
|
|
418
584
|
const currentIndex = RANGES.findIndex((r) => r.key === value);
|
|
419
585
|
let nextIndex = null;
|
|
@@ -469,8 +635,8 @@ function SourceStatusRow({ sources }) {
|
|
|
469
635
|
] }) });
|
|
470
636
|
}
|
|
471
637
|
function PanelTabs({ value, onChange }) {
|
|
472
|
-
const refs = (0,
|
|
473
|
-
const onKeyDown = (0,
|
|
638
|
+
const refs = (0, import_react3.useRef)([]);
|
|
639
|
+
const onKeyDown = (0, import_react3.useCallback)(
|
|
474
640
|
(event) => {
|
|
475
641
|
const currentIndex = PANELS.findIndex((p) => p.report === value);
|
|
476
642
|
let nextIndex = null;
|
|
@@ -546,8 +712,8 @@ function ReportPanel({ report, apiBaseUrl, range }) {
|
|
|
546
712
|
function VisitorInsightsTool(props) {
|
|
547
713
|
const apiBaseUrl = props.tool?.options?.apiBaseUrl ?? props.apiBaseUrl ?? "";
|
|
548
714
|
const siteLabel = props.tool?.options?.siteLabel ?? props.siteLabel ?? "";
|
|
549
|
-
const [range, setRange] = (0,
|
|
550
|
-
const [activePanel, setActivePanel] = (0,
|
|
715
|
+
const [range, setRange] = (0, import_react3.useState)("week");
|
|
716
|
+
const [activePanel, setActivePanel] = (0, import_react3.useState)("measurement-health");
|
|
551
717
|
const active = PANELS.find((p) => p.report === activePanel) ?? PANELS[0];
|
|
552
718
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sanity_ui_compat3.Container, { width: 4, padding: 4, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sanity_ui_compat3.Stack, { space: 5, children: [
|
|
553
719
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sanity_ui_compat3.Flex, { align: "flex-start", justify: "space-between", gap: 4, wrap: "wrap", children: [
|