@liiift-studio/sanity-visitor-insights 0.78.1 → 0.79.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.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +83 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +83 -0
- package/dist/index.mjs.map +1 -1
- package/dist/{ranges-BgcKmdw3.d.mts → ranges-C7y7-GWi.d.mts} +47 -1
- package/dist/{ranges-BgcKmdw3.d.ts → ranges-C7y7-GWi.d.ts} +47 -1
- package/dist/server.d.mts +4 -4
- package/dist/server.d.ts +4 -4
- package/dist/server.js +112 -4
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +112 -4
- package/dist/server.mjs.map +1 -1
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{vercel-D0tEOU9d.d.mts → vercel-5mnf2RIU.d.mts} +0 -8
- package/dist/{vercel-D0tEOU9d.d.ts → vercel-5mnf2RIU.d.ts} +0 -8
- package/package.json +1 -1
- package/src/core/siteConfig.ts +8 -0
- package/src/reportData.ts +30 -0
- package/src/server/orders.ts +211 -3
- package/src/server/reports/reports.test.ts +184 -1
- package/src/server/reports/typefaceInterest.ts +23 -2
- package/src/studio/panels.test.tsx +131 -0
- package/src/studio/panels.tsx +139 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as sanity from 'sanity';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { R as ReportEnvelope, a as ReportName, b as RangeKey, M as MetricValue, A as AcquisitionData, c as MeasurementHealthData, D as DiagnosticReport, J as JourneyData, T as TypefaceInterestData } from './ranges-
|
|
4
|
-
export { C as CaptureBasis, d as CaptureEstimate, e as CaptureModel, f as CheckStatus, g as Coverage, h as CrossSourceDay, i as DateRange, j as DiagnosticCheck, E as EmailCampaign, k as EventCutover, l as JourneyOutcome, m as JourneySegment, n as JourneyStep, L as LandingPage, o as LicenceTierRow, P as PREEXISTING,
|
|
3
|
+
import { R as ReportEnvelope, a as ReportName, b as RangeKey, M as MetricValue, A as AcquisitionData, c as MeasurementHealthData, D as DiagnosticReport, J as JourneyData, T as TypefaceInterestData } from './ranges-C7y7-GWi.mjs';
|
|
4
|
+
export { C as CaptureBasis, d as CaptureEstimate, e as CaptureModel, f as CheckStatus, g as Coverage, h as CrossSourceDay, i as DateRange, j as DiagnosticCheck, E as EmailCampaign, k as EventCutover, l as JourneyOutcome, m as JourneySegment, n as JourneyStep, L as LandingPage, o as LibraryCoverageData, p as LicenceTierRow, P as PREEXISTING, q as REPORT_NAMES, r as ReportError, S as SiteAnalyticsConfig, s as SourceName, t as SourceRow, u as SourceStatus, v as StyleDemandData, w as TimelineEvent, x as TypefaceInterestRow, U as UnavailableReason, y as coverageForRange, z as estimated, B as isReportName, F as ok, G as partial, H as previousRange, I as resolveRange, K as unavailable, N as validateSiteConfig, O as valueOrNull } from './ranges-C7y7-GWi.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Data hook for the Studio panels.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as sanity from 'sanity';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { R as ReportEnvelope, a as ReportName, b as RangeKey, M as MetricValue, A as AcquisitionData, c as MeasurementHealthData, D as DiagnosticReport, J as JourneyData, T as TypefaceInterestData } from './ranges-
|
|
4
|
-
export { C as CaptureBasis, d as CaptureEstimate, e as CaptureModel, f as CheckStatus, g as Coverage, h as CrossSourceDay, i as DateRange, j as DiagnosticCheck, E as EmailCampaign, k as EventCutover, l as JourneyOutcome, m as JourneySegment, n as JourneyStep, L as LandingPage, o as LicenceTierRow, P as PREEXISTING,
|
|
3
|
+
import { R as ReportEnvelope, a as ReportName, b as RangeKey, M as MetricValue, A as AcquisitionData, c as MeasurementHealthData, D as DiagnosticReport, J as JourneyData, T as TypefaceInterestData } from './ranges-C7y7-GWi.js';
|
|
4
|
+
export { C as CaptureBasis, d as CaptureEstimate, e as CaptureModel, f as CheckStatus, g as Coverage, h as CrossSourceDay, i as DateRange, j as DiagnosticCheck, E as EmailCampaign, k as EventCutover, l as JourneyOutcome, m as JourneySegment, n as JourneyStep, L as LandingPage, o as LibraryCoverageData, p as LicenceTierRow, P as PREEXISTING, q as REPORT_NAMES, r as ReportError, S as SiteAnalyticsConfig, s as SourceName, t as SourceRow, u as SourceStatus, v as StyleDemandData, w as TimelineEvent, x as TypefaceInterestRow, U as UnavailableReason, y as coverageForRange, z as estimated, B as isReportName, F as ok, G as partial, H as previousRange, I as resolveRange, K as unavailable, N as validateSiteConfig, O as valueOrNull } from './ranges-C7y7-GWi.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Data hook for the Studio panels.
|
package/dist/index.js
CHANGED
|
@@ -3172,6 +3172,22 @@ function visitorsPerOrder(data) {
|
|
|
3172
3172
|
}
|
|
3173
3173
|
return ok(Math.round(visitors / orders));
|
|
3174
3174
|
}
|
|
3175
|
+
var WEIGHTS_SHOWN = 12;
|
|
3176
|
+
function leadingFamily(demand) {
|
|
3177
|
+
if (demand.licences <= 0) return null;
|
|
3178
|
+
const ranked = Object.entries(demand.familyLicences).sort((a, b) => b[1] - a[1]);
|
|
3179
|
+
const top = ranked[0];
|
|
3180
|
+
if (!top) return null;
|
|
3181
|
+
return { family: top[0], share: top[1] / demand.licences };
|
|
3182
|
+
}
|
|
3183
|
+
function styleDemandSubtitle(demand) {
|
|
3184
|
+
return `${formatCount(demand.licences)} style licences across ${formatCount(demand.orders)} orders \u2014 your whole order history, not the range above, because a month of style-level counts is too thin to rank.`;
|
|
3185
|
+
}
|
|
3186
|
+
function libraryCoverageSubtitle(coverage) {
|
|
3187
|
+
const unreleasedStyles = coverage.unreleased.reduce((sum, f) => sum + f.styles, 0);
|
|
3188
|
+
const released = coverage.styles - unreleasedStyles;
|
|
3189
|
+
return `${formatCount(coverage.everLicensed)} of ${formatCount(released)} released styles have been licensed at least once.`;
|
|
3190
|
+
}
|
|
3175
3191
|
function TypefaceInterestPanel({ data }) {
|
|
3176
3192
|
const benchmark = catalogueRate(data.rows ?? []);
|
|
3177
3193
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: panelStack, children: [
|
|
@@ -3314,6 +3330,73 @@ function TypefaceInterestPanel({ data }) {
|
|
|
3314
3330
|
}
|
|
3315
3331
|
)
|
|
3316
3332
|
] }),
|
|
3333
|
+
(data.styleDemand?.weights.length ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3334
|
+
Section,
|
|
3335
|
+
{
|
|
3336
|
+
title: "Which weights sell",
|
|
3337
|
+
subtitle: styleDemandSubtitle(data.styleDemand),
|
|
3338
|
+
children: [
|
|
3339
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3340
|
+
ProportionChart,
|
|
3341
|
+
{
|
|
3342
|
+
bars: (data.styleDemand?.weights ?? []).slice(0, WEIGHTS_SHOWN).map((row) => ({
|
|
3343
|
+
key: row.weight,
|
|
3344
|
+
label: row.weight,
|
|
3345
|
+
sublabel: row.families === 1 ? "one family only" : `across ${formatCount(row.families)} families`,
|
|
3346
|
+
value: row.licences
|
|
3347
|
+
})),
|
|
3348
|
+
format: (value) => `${formatCount(value)} licences`,
|
|
3349
|
+
totalLabel: "Style licences in the weights shown"
|
|
3350
|
+
}
|
|
3351
|
+
),
|
|
3352
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: stackPair, children: [
|
|
3353
|
+
(data.styleDemand?.weights.length ?? 0) > WEIGHTS_SHOWN && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sanity_ui_compat3.Text, { size: 0, muted: true, children: [
|
|
3354
|
+
formatCount(data.styleDemand.weights.length - WEIGHTS_SHOWN),
|
|
3355
|
+
" quieter",
|
|
3356
|
+
" ",
|
|
3357
|
+
"weights are not shown."
|
|
3358
|
+
] }),
|
|
3359
|
+
leadingFamily(data.styleDemand) && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sanity_ui_compat3.Text, { size: 1, children: [
|
|
3360
|
+
leadingFamily(data.styleDemand)?.family,
|
|
3361
|
+
" accounts for",
|
|
3362
|
+
" ",
|
|
3363
|
+
formatPercent(leadingFamily(data.styleDemand)?.share ?? 0, 0),
|
|
3364
|
+
" of every style ever licensed."
|
|
3365
|
+
] }),
|
|
3366
|
+
(data.styleDemand?.orders ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sanity_ui_compat3.Text, { size: 0, muted: true, children: [
|
|
3367
|
+
formatPercent(data.styleDemand.singleStyleOrders / data.styleDemand.orders, 0),
|
|
3368
|
+
" ",
|
|
3369
|
+
"of orders licensed exactly one style."
|
|
3370
|
+
] })
|
|
3371
|
+
] })
|
|
3372
|
+
]
|
|
3373
|
+
}
|
|
3374
|
+
),
|
|
3375
|
+
data.libraryCoverage && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3376
|
+
Section,
|
|
3377
|
+
{
|
|
3378
|
+
title: "What the library holds",
|
|
3379
|
+
tone: "secondary",
|
|
3380
|
+
subtitle: libraryCoverageSubtitle(data.libraryCoverage),
|
|
3381
|
+
children: [
|
|
3382
|
+
data.libraryCoverage.gaps.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sanity_ui_compat3.Text, { size: 1, children: [
|
|
3383
|
+
"Never licensed, in families that sell:",
|
|
3384
|
+
" ",
|
|
3385
|
+
data.libraryCoverage.gaps.map((g) => `${g.family} (${formatCount(g.styles)})`).join(", "),
|
|
3386
|
+
"."
|
|
3387
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sanity_ui_compat3.Text, { size: 1, children: "Every style in every selling family has been licensed at least once." }),
|
|
3388
|
+
data.libraryCoverage.unreleased.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sanity_ui_compat3.Text, { size: 0, muted: true, children: [
|
|
3389
|
+
"Not counted above:",
|
|
3390
|
+
" ",
|
|
3391
|
+
data.libraryCoverage.unreleased.map((u) => `${u.family} (${formatCount(u.styles)} styles)`).join(", "),
|
|
3392
|
+
" ",
|
|
3393
|
+
"\u2014 no style from ",
|
|
3394
|
+
data.libraryCoverage.unreleased.length === 1 ? "it" : "them",
|
|
3395
|
+
" has ever sold, which reads as unreleased rather than unwanted."
|
|
3396
|
+
] })
|
|
3397
|
+
]
|
|
3398
|
+
}
|
|
3399
|
+
),
|
|
3317
3400
|
(data.licences?.length ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: stackBlock, children: [
|
|
3318
3401
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SectionTitle, { title: "How licences sell" }),
|
|
3319
3402
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sanity_ui_compat3.Text, { size: 1, muted: true, children: "From your orders, so exact. Bars are orders; the money beside them is that order total split evenly across the licences on it, so it is a share rather than a price." }),
|