@liiift-studio/sanity-visitor-insights 0.53.0 → 0.55.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 CHANGED
@@ -1461,9 +1461,8 @@ function CrossSourceTimeline({ series, markers = [], currency, onBrush }) {
1461
1461
  x2: at,
1462
1462
  y1: TOP_PAD,
1463
1463
  y2: height - AXIS_HEIGHT + 4,
1464
- stroke: "currentColor",
1465
- strokeWidth: 1,
1466
- opacity: 0.18
1464
+ stroke: mark("chart.grid"),
1465
+ strokeWidth: 1
1467
1466
  },
1468
1467
  `grid-${date}`
1469
1468
  );
@@ -1495,7 +1494,7 @@ function CrossSourceTimeline({ series, markers = [], currency, onBrush }) {
1495
1494
  const stems = row.mark === "events" ? row.points.filter((p) => p.value !== null && p.value !== 0) : [];
1496
1495
  const zeroes = row.mark === "events" && pitch >= 6 ? row.points.filter((p) => p.value === 0) : [];
1497
1496
  const gap = row.shortfall ? gapGen(row.points) ?? "" : "";
1498
- const shortfallLine = row.shortfall && revealed ? lineGen(shortfallPoints) ?? "" : "";
1497
+ const shortfallLine = row.shortfall ? lineGen(shortfallPoints) ?? "" : "";
1499
1498
  const clipId = `${instanceId}-row-${rowIndex}`;
1500
1499
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
1501
1500
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("clipPath", { id: clipId, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: GUTTER, y: plotTop, width: plotWidth, height: Math.max(1, bottom - plotTop) }) }) }),
@@ -1514,21 +1513,29 @@ function CrossSourceTimeline({ series, markers = [], currency, onBrush }) {
1514
1513
  {
1515
1514
  d: ghost,
1516
1515
  fill: "none",
1517
- stroke: "currentColor",
1516
+ stroke: mark("chart.ghost"),
1518
1517
  strokeWidth: 1,
1519
- strokeDasharray: "2 3",
1520
- opacity: 0.35
1518
+ strokeDasharray: "2 3"
1521
1519
  }
1522
1520
  ),
1523
1521
  gap && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1524
1522
  "path",
1525
1523
  {
1526
1524
  d: gap,
1527
- fill: shortfallStroke ? seriesFill(colorFor(row.shortfall.source, row.unit, row.shortfall.color), 0.3) : "currentColor",
1525
+ fill: shortfallStroke ? seriesFill(colorFor(row.shortfall.source, row.unit, row.shortfall.color), MARKS["chart.region"].alpha) : "currentColor",
1528
1526
  opacity: shortfallStroke ? 1 : 0.48
1529
1527
  }
1530
1528
  ),
1531
- shortfallLine && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: shortfallLine, fill: "none", stroke: shortfallStroke ?? "currentColor", strokeWidth: 1.5, strokeDasharray: "6 4", opacity: 0.8 }),
1529
+ shortfallLine && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1530
+ "path",
1531
+ {
1532
+ d: shortfallLine,
1533
+ fill: "none",
1534
+ stroke: mark("chart.regionEdge"),
1535
+ strokeWidth: 1.5,
1536
+ strokeDasharray: "6 4"
1537
+ }
1538
+ ),
1532
1539
  zeroes.map((p) => {
1533
1540
  const cx = at(p);
1534
1541
  if (!Number.isFinite(cx)) return null;
@@ -1539,8 +1546,7 @@ function CrossSourceTimeline({ series, markers = [], currency, onBrush }) {
1539
1546
  y: zeroY - 3,
1540
1547
  width: stemWidth,
1541
1548
  height: 3,
1542
- fill: stroke,
1543
- opacity: 0.7
1549
+ fill: stroke
1544
1550
  },
1545
1551
  `zero-${p.date}`
1546
1552
  );
@@ -1556,8 +1562,7 @@ function CrossSourceTimeline({ series, markers = [], currency, onBrush }) {
1556
1562
  y: Math.min(headY, zeroY),
1557
1563
  width: stemWidth,
1558
1564
  height: Math.max(1.5, Math.abs(zeroY - headY)),
1559
- fill: stroke,
1560
- opacity: 0.9
1565
+ fill: stroke
1561
1566
  },
1562
1567
  p.date
1563
1568
  );
@@ -1569,8 +1574,7 @@ function CrossSourceTimeline({ series, markers = [], currency, onBrush }) {
1569
1574
  fill: "none",
1570
1575
  stroke,
1571
1576
  strokeWidth: 2,
1572
- strokeDasharray: row.complete ? void 0 : "6 4",
1573
- opacity: row.complete ? 0.95 : 0.7
1577
+ strokeDasharray: row.complete ? void 0 : "6 4"
1574
1578
  }
1575
1579
  )
1576
1580
  ] })
@@ -2040,7 +2044,6 @@ function OverviewPanel({ data, previous, onBrush }) {
2040
2044
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2041
2045
  ChartData,
2042
2046
  {
2043
- note: "A negative miss means GA4 counted more than Vercel that day \u2014 usually a tag firing twice, not extra traffic.",
2044
2047
  label: "Show these figures as a table",
2045
2048
  rows: data.crossSource ?? [],
2046
2049
  rowKey: (d) => d.date,
@@ -2384,7 +2387,11 @@ function AcquisitionPanel({ data, previous }) {
2384
2387
  filterOn: (row) => `${row.source} ${row.channel} ${row.medium ?? ""} ${row.campaign ?? ""}`,
2385
2388
  filterPlaceholder: "Filter sources",
2386
2389
  exportName: "traffic-sources",
2387
- truncatedNote: data.rowsTruncated ? "GA4 held more source rows than are shown here, so this is the top of a longer list \u2014 for a foundry, the tail of small design blogs is often the referral story." : void 0,
2390
+ truncatedNote: shortListNote(
2391
+ Boolean(data.rowsTruncated),
2392
+ Boolean(data.rowsWithheld),
2393
+ "For a foundry the tail of small design blogs is often the referral story."
2394
+ ),
2388
2395
  columns: [
2389
2396
  {
2390
2397
  key: "source",
@@ -2500,8 +2507,7 @@ function AcquisitionPanel({ data, previous }) {
2500
2507
  " of those sales; the rest came from sources outside this list, so this column does not add up to the whole."
2501
2508
  ] })
2502
2509
  ] })
2503
- ] }),
2504
- data.rowsWithheld && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NoticeList, { notices: ["GA4 withheld some low-traffic rows for privacy, so this list is shorter than reality."] })
2510
+ ] })
2505
2511
  ] });
2506
2512
  }
2507
2513
  function firstStepRate(steps) {
@@ -2526,6 +2532,11 @@ function spread(segments) {
2526
2532
  if (ratio < RATIO) return null;
2527
2533
  return `${worst.label} reaches the second step at ${formatPercent(worst.rate, 2)} against ${best.label}'s ${formatPercent(best.rate, 2)} \u2014 about ${Math.round(ratio)} times worse, on ${formatCount(worst.users)} visitors. The combined funnel above averages the two and describes neither.`;
2528
2534
  }
2535
+ function shortListNote(truncated, withheld, tail) {
2536
+ if (!truncated && !withheld) return void 0;
2537
+ const cause = truncated && withheld ? "GA4 returned only its top rows, and withheld others with too few people to report" : truncated ? "GA4 returned only its top rows" : "GA4 withheld rows with too few people to report";
2538
+ return `${cause}, so this list is shorter than reality. ${tail}`;
2539
+ }
2529
2540
  function JourneyPanel({ data }) {
2530
2541
  const [segmentKey, setSegmentKey] = import_react4.default.useState(null);
2531
2542
  const segments = data.segments ?? [];
@@ -2723,7 +2734,11 @@ function TypefaceInterestPanel({ data }) {
2723
2734
  filterOn: (row) => row.typeface,
2724
2735
  filterPlaceholder: "Filter typefaces",
2725
2736
  exportName: "typeface-interest",
2726
- truncatedNote: data.rowsTruncated ? "GA4 returned only its top rows, so families past the cap show as unknown rather than as zero. For a foundry the long tail is most of the catalogue." : void 0,
2737
+ truncatedNote: shortListNote(
2738
+ Boolean(data.rowsTruncated),
2739
+ Boolean(data.rowsWithheld),
2740
+ "A family missing from this table has not necessarily gone quiet \u2014 and for a foundry the long tail is most of the catalogue."
2741
+ ),
2727
2742
  columns: [
2728
2743
  {
2729
2744
  key: "typeface",
@@ -2858,7 +2873,6 @@ function TypefaceInterestPanel({ data }) {
2858
2873
  }
2859
2874
  )
2860
2875
  ] }),
2861
- data.rowsWithheld && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NoticeList, { notices: ["GA4 withheld some low-count rows for privacy. A family missing from this table has not necessarily gone quiet."] }),
2862
2876
  data.revenueIsApportioned && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sanity_ui_compat3.Text, { size: 0, muted: true, children: "Revenue is apportioned: an order covering several families or licences is split evenly between them, because the order documents carry no per-line value." })
2863
2877
  ] });
2864
2878
  }