@burdenoff/website-sdk 2026.1027.1 → 2026.1029.1
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/README.md +186 -1
- package/dist/avatar-live/index.d.mts +11 -0
- package/dist/avatar-live/index.d.ts +11 -0
- package/dist/avatar-live/index.js +120 -0
- package/dist/avatar-live/index.js.map +1 -0
- package/dist/avatar-live/index.mjs +118 -0
- package/dist/avatar-live/index.mjs.map +1 -0
- package/dist/avatar-live-view/index.d.mts +42 -0
- package/dist/avatar-live-view/index.d.ts +42 -0
- package/dist/avatar-live-view/index.js +1422 -0
- package/dist/avatar-live-view/index.js.map +1 -0
- package/dist/avatar-live-view/index.mjs +1420 -0
- package/dist/avatar-live-view/index.mjs.map +1 -0
- package/dist/comparison/index.d.mts +83 -0
- package/dist/comparison/index.d.ts +83 -0
- package/dist/comparison/index.js +116 -0
- package/dist/comparison/index.js.map +1 -0
- package/dist/comparison/index.mjs +109 -0
- package/dist/comparison/index.mjs.map +1 -0
- package/dist/components/explore.d.mts +2 -2
- package/dist/components/explore.d.ts +2 -2
- package/dist/components/explore.js +11 -4
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +11 -4
- package/dist/components/explore.mjs.map +1 -1
- package/dist/components/partners.js.map +1 -1
- package/dist/components/partners.mjs.map +1 -1
- package/dist/content/index.d.mts +1 -1
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +32 -4
- package/dist/content/index.js.map +1 -1
- package/dist/content/index.mjs +32 -5
- package/dist/content/index.mjs.map +1 -1
- package/dist/{explore-BEgq1_0O.d.mts → explore-DUTNYUOm.d.mts} +1 -1
- package/dist/{explore-CHiP9u-4.d.ts → explore-DjQE7Xia.d.ts} +1 -1
- package/dist/explore-avatar-live-config-B171o1Yo.d.ts +283 -0
- package/dist/explore-avatar-live-config-BGsGwbcq.d.mts +283 -0
- package/dist/{explore-types-_9UJu6EA.d.mts → explore-types-Bb2Ih3d8.d.mts} +1 -1
- package/dist/{explore-types-_9UJu6EA.d.ts → explore-types-Bb2Ih3d8.d.ts} +1 -1
- package/dist/hooks/index.d.mts +3 -2
- package/dist/hooks/index.d.ts +3 -2
- package/dist/hooks/index.js +6 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +6 -1
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/{index-CB0Uw1xD.d.ts → index-87BLB-Hj.d.ts} +26 -1
- package/dist/{index-Ctws7kGs.d.mts → index-Chw0pDXS.d.mts} +26 -1
- package/dist/index.d.mts +19 -255
- package/dist/index.d.ts +19 -255
- package/dist/index.js +358 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +352 -41
- package/dist/index.mjs.map +1 -1
- package/dist/types-CndbmBK-.d.mts +68 -0
- package/dist/types-CndbmBK-.d.ts +68 -0
- package/dist/{use-progressive-reveal-C0hkdu_i.d.ts → use-explore-chat-DunjG-3p.d.ts} +10 -36
- package/dist/{use-progressive-reveal-BFPWbEXy.d.mts → use-explore-chat-zRuoAin6.d.mts} +10 -36
- package/dist/use-progressive-reveal-ppicEgzZ.d.mts +35 -0
- package/dist/use-progressive-reveal-ppicEgzZ.d.ts +35 -0
- package/package.json +20 -3
package/dist/index.mjs
CHANGED
|
@@ -6438,6 +6438,11 @@ function ConceptDetail({
|
|
|
6438
6438
|
);
|
|
6439
6439
|
}
|
|
6440
6440
|
|
|
6441
|
+
// src/components/explore-fill.ts
|
|
6442
|
+
function fill(template, values) {
|
|
6443
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
|
|
6444
|
+
}
|
|
6445
|
+
|
|
6441
6446
|
// src/components/explore-i18n.ts
|
|
6442
6447
|
var EXPLORE_LOCALES = ["en", "zh", "hi", "es", "ar", "ta"];
|
|
6443
6448
|
var RTL_LOCALES = /* @__PURE__ */ new Set(["ar"]);
|
|
@@ -7225,9 +7230,6 @@ function resolveExploreLocale(explicit) {
|
|
|
7225
7230
|
function exploreStrings(locale) {
|
|
7226
7231
|
return STRINGS[locale] ?? EN;
|
|
7227
7232
|
}
|
|
7228
|
-
function fill(template, values) {
|
|
7229
|
-
return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
|
|
7230
|
-
}
|
|
7231
7233
|
|
|
7232
7234
|
// src/components/answers-i18n.ts
|
|
7233
7235
|
var EN2 = {
|
|
@@ -11001,6 +11003,10 @@ function useExploreChat(options = {}) {
|
|
|
11001
11003
|
[client, productId]
|
|
11002
11004
|
);
|
|
11003
11005
|
const canEscalate = hasConversation && !isSharedView;
|
|
11006
|
+
const getConversationToken = useCallback(
|
|
11007
|
+
() => conversationTokenRef.current,
|
|
11008
|
+
[]
|
|
11009
|
+
);
|
|
11004
11010
|
return {
|
|
11005
11011
|
phase,
|
|
11006
11012
|
catalog,
|
|
@@ -11025,7 +11031,8 @@ function useExploreChat(options = {}) {
|
|
|
11025
11031
|
escalate,
|
|
11026
11032
|
canEscalate,
|
|
11027
11033
|
createShareLink,
|
|
11028
|
-
isSharedView
|
|
11034
|
+
isSharedView,
|
|
11035
|
+
getConversationToken
|
|
11029
11036
|
};
|
|
11030
11037
|
}
|
|
11031
11038
|
var optimisticCounter = 0;
|
|
@@ -15132,6 +15139,164 @@ var ExploreCta = forwardRef(
|
|
|
15132
15139
|
);
|
|
15133
15140
|
}
|
|
15134
15141
|
);
|
|
15142
|
+
|
|
15143
|
+
// src/components/explore-avatar-live-config.ts
|
|
15144
|
+
var AVATAR_WEB_API_PATH = "/api/web-avatar/v1";
|
|
15145
|
+
var SITE = /^[a-z][a-z0-9-]{1,31}$/;
|
|
15146
|
+
var VERSION = /^[A-Za-z0-9._-]{1,32}$/;
|
|
15147
|
+
var SITE_KEY = /^[A-Za-z0-9_-]{1,128}$/;
|
|
15148
|
+
var LOOPBACK_HOSTS2 = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
15149
|
+
function isAvatarSite(value) {
|
|
15150
|
+
return SITE.test(value);
|
|
15151
|
+
}
|
|
15152
|
+
function isAvatarVersion(value) {
|
|
15153
|
+
return VERSION.test(value);
|
|
15154
|
+
}
|
|
15155
|
+
function avatarApiBase(gatewayUrl) {
|
|
15156
|
+
if (!gatewayUrl) return null;
|
|
15157
|
+
let url;
|
|
15158
|
+
try {
|
|
15159
|
+
url = new URL(gatewayUrl);
|
|
15160
|
+
} catch {
|
|
15161
|
+
return null;
|
|
15162
|
+
}
|
|
15163
|
+
const local = url.protocol === "http:" && LOOPBACK_HOSTS2.has(url.hostname.toLowerCase());
|
|
15164
|
+
if (url.protocol !== "https:" && !local) return null;
|
|
15165
|
+
return `${url.origin}${AVATAR_WEB_API_PATH}`;
|
|
15166
|
+
}
|
|
15167
|
+
function liveConfigComplete(live) {
|
|
15168
|
+
return typeof live.load === "function" && typeof live.site === "string" && isAvatarSite(live.site) && typeof live.manifestVersion === "string" && isAvatarVersion(live.manifestVersion) && typeof live.turnstileSiteKey === "string" && SITE_KEY.test(live.turnstileSiteKey);
|
|
15169
|
+
}
|
|
15170
|
+
var REVIEWED = /* @__PURE__ */ new Set(["en"]);
|
|
15171
|
+
function isAvatarLiveLocaleReviewed(locale) {
|
|
15172
|
+
return REVIEWED.has(locale);
|
|
15173
|
+
}
|
|
15174
|
+
var VIEW_LOAD_TIMEOUT_MS = 8e3;
|
|
15175
|
+
function loadAvatarLiveView() {
|
|
15176
|
+
return import('./avatar-live-view/index.mjs').then(
|
|
15177
|
+
(loaded) => loaded.AvatarLiveView
|
|
15178
|
+
);
|
|
15179
|
+
}
|
|
15180
|
+
function ExploreAvatarLive({
|
|
15181
|
+
live,
|
|
15182
|
+
active,
|
|
15183
|
+
locale,
|
|
15184
|
+
productName,
|
|
15185
|
+
still,
|
|
15186
|
+
fallback,
|
|
15187
|
+
onContinueInChat,
|
|
15188
|
+
loadView = loadAvatarLiveView
|
|
15189
|
+
}) {
|
|
15190
|
+
const T = exploreStrings(locale);
|
|
15191
|
+
const config = useWebSDKConfig();
|
|
15192
|
+
const conversation = useContext(ExploreConversationContext);
|
|
15193
|
+
const base = avatarApiBase(config.gatewayUrl);
|
|
15194
|
+
const headers = useMemo(
|
|
15195
|
+
() => cfAccessHeaders(config.gatewayUrl, config.cfAccess),
|
|
15196
|
+
[config.gatewayUrl, config.cfAccess]
|
|
15197
|
+
);
|
|
15198
|
+
const complete = liveConfigComplete(live);
|
|
15199
|
+
const off = !complete || base === null || conversation === null || conversation.isSharedView || !isAvatarLiveLocaleReviewed(locale);
|
|
15200
|
+
useEffect(() => {
|
|
15201
|
+
if (!complete) {
|
|
15202
|
+
console.warn(
|
|
15203
|
+
"[WebSDK] ExplorePanel: avatar.live needs site, load, turnstileSiteKey and manifestVersion; the live avatar stays off."
|
|
15204
|
+
);
|
|
15205
|
+
}
|
|
15206
|
+
}, [complete]);
|
|
15207
|
+
const [View, setView] = useState(null);
|
|
15208
|
+
const [failed, setFailed] = useState(false);
|
|
15209
|
+
const wanted = active && !off;
|
|
15210
|
+
useEffect(() => {
|
|
15211
|
+
if (!wanted || View !== null) return;
|
|
15212
|
+
let cancelled = false;
|
|
15213
|
+
let loading;
|
|
15214
|
+
try {
|
|
15215
|
+
loading = loadView();
|
|
15216
|
+
} catch (error) {
|
|
15217
|
+
loading = Promise.reject(error);
|
|
15218
|
+
}
|
|
15219
|
+
const patience = setTimeout(() => {
|
|
15220
|
+
if (!cancelled) setFailed(true);
|
|
15221
|
+
}, VIEW_LOAD_TIMEOUT_MS);
|
|
15222
|
+
loading.then(
|
|
15223
|
+
(component) => {
|
|
15224
|
+
if (!cancelled) setView(() => component);
|
|
15225
|
+
},
|
|
15226
|
+
() => {
|
|
15227
|
+
clearTimeout(patience);
|
|
15228
|
+
if (!cancelled) setFailed(true);
|
|
15229
|
+
}
|
|
15230
|
+
);
|
|
15231
|
+
return () => {
|
|
15232
|
+
cancelled = true;
|
|
15233
|
+
clearTimeout(patience);
|
|
15234
|
+
};
|
|
15235
|
+
}, [wanted, View, loadView]);
|
|
15236
|
+
if (View !== null) {
|
|
15237
|
+
return /* @__PURE__ */ jsx(
|
|
15238
|
+
View,
|
|
15239
|
+
{
|
|
15240
|
+
live,
|
|
15241
|
+
active,
|
|
15242
|
+
locale,
|
|
15243
|
+
productName,
|
|
15244
|
+
still,
|
|
15245
|
+
fallback,
|
|
15246
|
+
onContinueInChat,
|
|
15247
|
+
continueInChat: T.continueInChat,
|
|
15248
|
+
off,
|
|
15249
|
+
base,
|
|
15250
|
+
headers,
|
|
15251
|
+
conversation
|
|
15252
|
+
}
|
|
15253
|
+
);
|
|
15254
|
+
}
|
|
15255
|
+
if (off || failed) {
|
|
15256
|
+
return (
|
|
15257
|
+
// `display: contents`: the earlier Avatar view's picture, line and button lay out in the pane exactly as before.
|
|
15258
|
+
/* @__PURE__ */ jsx(
|
|
15259
|
+
"div",
|
|
15260
|
+
{
|
|
15261
|
+
style: { display: "contents" },
|
|
15262
|
+
"data-boff-explore": "avatar-live",
|
|
15263
|
+
"data-phase": off ? "off" : "inert",
|
|
15264
|
+
children: fallback
|
|
15265
|
+
}
|
|
15266
|
+
)
|
|
15267
|
+
);
|
|
15268
|
+
}
|
|
15269
|
+
return /* @__PURE__ */ jsxs(
|
|
15270
|
+
"div",
|
|
15271
|
+
{
|
|
15272
|
+
"data-boff-explore": "avatar-live",
|
|
15273
|
+
"data-phase": "idle",
|
|
15274
|
+
className: "flex max-h-full w-full flex-col items-center gap-4 overflow-y-auto",
|
|
15275
|
+
children: [
|
|
15276
|
+
/* @__PURE__ */ jsx(
|
|
15277
|
+
"img",
|
|
15278
|
+
{
|
|
15279
|
+
src: still.src,
|
|
15280
|
+
alt: still.alt,
|
|
15281
|
+
decoding: "async",
|
|
15282
|
+
width: 128,
|
|
15283
|
+
height: 128,
|
|
15284
|
+
className: "shrink-0 rounded-full border border-border object-cover shadow-sm h-32 w-32"
|
|
15285
|
+
}
|
|
15286
|
+
),
|
|
15287
|
+
/* @__PURE__ */ jsx(
|
|
15288
|
+
"p",
|
|
15289
|
+
{
|
|
15290
|
+
role: "status",
|
|
15291
|
+
"data-boff-explore": "avatar-live-status",
|
|
15292
|
+
className: "text-sm text-muted-foreground"
|
|
15293
|
+
}
|
|
15294
|
+
),
|
|
15295
|
+
/* @__PURE__ */ jsx("div", { "data-boff-explore": "avatar-live-bot-check" })
|
|
15296
|
+
]
|
|
15297
|
+
}
|
|
15298
|
+
);
|
|
15299
|
+
}
|
|
15135
15300
|
var MARK_KEY = "boffExplorePanel";
|
|
15136
15301
|
var POS_KEY = "boffExplorePanelPos";
|
|
15137
15302
|
var DOC_KEY = "boffExplorePanelDoc";
|
|
@@ -15323,15 +15488,15 @@ function ExplorePanel({
|
|
|
15323
15488
|
const rtl = isRtlLocale(resolvedLocale);
|
|
15324
15489
|
const catalogProducts = useContext(ExploreCatalogProductsContext);
|
|
15325
15490
|
const pinnedSlug = pinnedProductSlug(scope, productSlug);
|
|
15326
|
-
const
|
|
15327
|
-
|
|
15328
|
-
const name = productNameFor(
|
|
15491
|
+
const pinnedName = useMemo(
|
|
15492
|
+
() => pinnedSlug === null ? null : productNameFor(
|
|
15329
15493
|
catalogProducts ?? ECOSYSTEM_PRODUCTS,
|
|
15330
15494
|
pinnedSlug,
|
|
15331
15495
|
productName
|
|
15332
|
-
)
|
|
15333
|
-
|
|
15334
|
-
|
|
15496
|
+
),
|
|
15497
|
+
[catalogProducts, pinnedSlug, productName]
|
|
15498
|
+
);
|
|
15499
|
+
const title = pinnedName === null ? T.panelTitle : fill(T.panelTitleProduct, { product: pinnedName });
|
|
15335
15500
|
const uid = useId();
|
|
15336
15501
|
const titleId = `${uid}-title`;
|
|
15337
15502
|
const chatTabId = `${uid}-chat-tab`;
|
|
@@ -15652,6 +15817,32 @@ function ExplorePanel({
|
|
|
15652
15817
|
const tabButton = "rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
15653
15818
|
const expanded = size === "expanded";
|
|
15654
15819
|
const sizeLabel = expanded ? T.exitFullScreen : T.enterFullScreen;
|
|
15820
|
+
const avatarAlt = avatar?.name ? `${avatar.name}, ${T.liveAvatar}` : T.liveAvatar;
|
|
15821
|
+
const comingSoon = avatar ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
15822
|
+
/* @__PURE__ */ jsx(
|
|
15823
|
+
"img",
|
|
15824
|
+
{
|
|
15825
|
+
src: avatar.src,
|
|
15826
|
+
alt: avatarAlt,
|
|
15827
|
+
loading: "lazy",
|
|
15828
|
+
decoding: "async",
|
|
15829
|
+
width: 128,
|
|
15830
|
+
height: 128,
|
|
15831
|
+
className: "h-32 w-32 rounded-full border border-border object-cover shadow-sm"
|
|
15832
|
+
}
|
|
15833
|
+
),
|
|
15834
|
+
/* @__PURE__ */ jsx("p", { className: "text-base font-semibold", children: T.avatarComingSoon }),
|
|
15835
|
+
/* @__PURE__ */ jsx(
|
|
15836
|
+
"button",
|
|
15837
|
+
{
|
|
15838
|
+
type: "button",
|
|
15839
|
+
"data-boff-explore": "panel-continue-chat",
|
|
15840
|
+
className: "inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
15841
|
+
onClick: continueInChat,
|
|
15842
|
+
children: T.continueInChat
|
|
15843
|
+
}
|
|
15844
|
+
)
|
|
15845
|
+
] }) : null;
|
|
15655
15846
|
const tabs = [
|
|
15656
15847
|
{ key: "chat", id: chatTabId, pane: chatPaneId, label: T.tabChat },
|
|
15657
15848
|
{ key: "avatar", id: avatarTabId, pane: avatarPaneId, label: T.tabAvatar }
|
|
@@ -15781,7 +15972,7 @@ function ExplorePanel({
|
|
|
15781
15972
|
)
|
|
15782
15973
|
}
|
|
15783
15974
|
),
|
|
15784
|
-
avatar ? /* @__PURE__ */
|
|
15975
|
+
avatar ? /* @__PURE__ */ jsx(
|
|
15785
15976
|
"div",
|
|
15786
15977
|
{
|
|
15787
15978
|
id: avatarPaneId,
|
|
@@ -15792,31 +15983,18 @@ function ExplorePanel({
|
|
|
15792
15983
|
"absolute inset-0 flex-col items-center justify-center gap-4 overflow-y-auto bg-background p-6 text-center",
|
|
15793
15984
|
view === "avatar" ? "flex" : "hidden"
|
|
15794
15985
|
),
|
|
15795
|
-
children:
|
|
15796
|
-
|
|
15797
|
-
|
|
15798
|
-
|
|
15799
|
-
|
|
15800
|
-
|
|
15801
|
-
|
|
15802
|
-
|
|
15803
|
-
|
|
15804
|
-
|
|
15805
|
-
|
|
15806
|
-
|
|
15807
|
-
),
|
|
15808
|
-
/* @__PURE__ */ jsx("p", { className: "text-base font-semibold", children: T.avatarComingSoon }),
|
|
15809
|
-
/* @__PURE__ */ jsx(
|
|
15810
|
-
"button",
|
|
15811
|
-
{
|
|
15812
|
-
type: "button",
|
|
15813
|
-
"data-boff-explore": "panel-continue-chat",
|
|
15814
|
-
className: "inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
15815
|
-
onClick: continueInChat,
|
|
15816
|
-
children: T.continueInChat
|
|
15817
|
-
}
|
|
15818
|
-
)
|
|
15819
|
-
]
|
|
15986
|
+
children: avatar.live ? /* @__PURE__ */ jsx(
|
|
15987
|
+
ExploreAvatarLive,
|
|
15988
|
+
{
|
|
15989
|
+
live: avatar.live,
|
|
15990
|
+
active: open && view === "avatar",
|
|
15991
|
+
locale: resolvedLocale,
|
|
15992
|
+
productName: pinnedName,
|
|
15993
|
+
still: { src: avatar.src, alt: avatarAlt },
|
|
15994
|
+
fallback: comingSoon,
|
|
15995
|
+
onContinueInChat: continueInChat
|
|
15996
|
+
}
|
|
15997
|
+
) : comingSoon
|
|
15820
15998
|
}
|
|
15821
15999
|
) : null
|
|
15822
16000
|
] })
|
|
@@ -16598,6 +16776,10 @@ function BlogPostPage(props) {
|
|
|
16598
16776
|
] });
|
|
16599
16777
|
}
|
|
16600
16778
|
var CASE_STUDY_TAG = "case-study";
|
|
16779
|
+
function hasCustomerSignOff(page) {
|
|
16780
|
+
const signedAt = page.customerSignOff?.signedAt;
|
|
16781
|
+
return typeof signedAt === "string" && !Number.isNaN(new Date(signedAt).getTime());
|
|
16782
|
+
}
|
|
16601
16783
|
var ANIMATION_STYLES = `
|
|
16602
16784
|
@keyframes csFadeUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
|
|
16603
16785
|
@keyframes csFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
|
|
@@ -16627,6 +16809,9 @@ var CASE_STUDIES_QUERY = `
|
|
|
16627
16809
|
readingTime
|
|
16628
16810
|
featured
|
|
16629
16811
|
category
|
|
16812
|
+
customerSignOff {
|
|
16813
|
+
signedAt
|
|
16814
|
+
}
|
|
16630
16815
|
}
|
|
16631
16816
|
total
|
|
16632
16817
|
hasMore
|
|
@@ -16653,6 +16838,9 @@ var CASE_STUDY_QUERY = `
|
|
|
16653
16838
|
readingTime
|
|
16654
16839
|
featured
|
|
16655
16840
|
category
|
|
16841
|
+
customerSignOff {
|
|
16842
|
+
signedAt
|
|
16843
|
+
}
|
|
16656
16844
|
}
|
|
16657
16845
|
}
|
|
16658
16846
|
`;
|
|
@@ -17023,11 +17211,15 @@ function CaseStudiesListPage(props) {
|
|
|
17023
17211
|
setPosts([]);
|
|
17024
17212
|
return;
|
|
17025
17213
|
}
|
|
17026
|
-
const
|
|
17027
|
-
|
|
17214
|
+
const items = result.data?.publicContentPages?.items || [];
|
|
17215
|
+
const caseStudies = items.filter(
|
|
17216
|
+
(p) => p.tags?.includes(CASE_STUDY_TAG) && hasCustomerSignOff(p)
|
|
17028
17217
|
);
|
|
17029
17218
|
setPosts(caseStudies);
|
|
17030
|
-
|
|
17219
|
+
const dropped = items.length - caseStudies.length;
|
|
17220
|
+
setTotal(
|
|
17221
|
+
Math.max(0, (result.data?.publicContentPages?.total || 0) - dropped)
|
|
17222
|
+
);
|
|
17031
17223
|
setError(null);
|
|
17032
17224
|
} catch {
|
|
17033
17225
|
setError("load-failed");
|
|
@@ -17209,7 +17401,8 @@ function CaseStudyPage(props) {
|
|
|
17209
17401
|
setError(result.errors[0]?.message ?? "Failed to load case study");
|
|
17210
17402
|
return;
|
|
17211
17403
|
}
|
|
17212
|
-
|
|
17404
|
+
const page = result.data?.publicContentPage ?? null;
|
|
17405
|
+
setPost(page && hasCustomerSignOff(page) ? page : null);
|
|
17213
17406
|
setError(null);
|
|
17214
17407
|
} catch {
|
|
17215
17408
|
setError("Failed to load case study");
|
|
@@ -17278,6 +17471,7 @@ function CaseStudyPage(props) {
|
|
|
17278
17471
|
] }) });
|
|
17279
17472
|
}
|
|
17280
17473
|
const formattedDate = formatDate(post.publishedAt || post.lastUpdated);
|
|
17474
|
+
const approvedDate = formatDate(post.customerSignOff?.signedAt);
|
|
17281
17475
|
return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
|
|
17282
17476
|
/* @__PURE__ */ jsx(ProseStyles, {}),
|
|
17283
17477
|
/* @__PURE__ */ jsx(
|
|
@@ -17315,6 +17509,17 @@ function CaseStudyPage(props) {
|
|
|
17315
17509
|
] })
|
|
17316
17510
|
] }) : null
|
|
17317
17511
|
] }),
|
|
17512
|
+
approvedDate && /* @__PURE__ */ jsxs(
|
|
17513
|
+
"p",
|
|
17514
|
+
{
|
|
17515
|
+
className: "-mt-4 mb-8 text-xs text-muted-foreground",
|
|
17516
|
+
"data-cs": "customer-signoff",
|
|
17517
|
+
children: [
|
|
17518
|
+
"Approved for publication by the customer on ",
|
|
17519
|
+
approvedDate
|
|
17520
|
+
]
|
|
17521
|
+
}
|
|
17522
|
+
),
|
|
17318
17523
|
post.thumbnail && /* @__PURE__ */ jsx("div", { className: "mb-10 aspect-[16/9] overflow-hidden rounded-xl", children: /* @__PURE__ */ jsx(
|
|
17319
17524
|
"img",
|
|
17320
17525
|
{
|
|
@@ -20607,6 +20812,112 @@ function shouldRenderSiteFooter(pathname) {
|
|
|
20607
20812
|
return !isFooterlessPath(pathname);
|
|
20608
20813
|
}
|
|
20609
20814
|
|
|
20610
|
-
|
|
20815
|
+
// src/comparison/index.ts
|
|
20816
|
+
var DEFAULT_COMPARISON_MAX_AGE_DAYS = 180;
|
|
20817
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
20818
|
+
var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
20819
|
+
function parseVerifiedAt(value) {
|
|
20820
|
+
if (typeof value !== "string" || !ISO_DATE.test(value)) return null;
|
|
20821
|
+
const date = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
|
|
20822
|
+
if (Number.isNaN(date.getTime())) return null;
|
|
20823
|
+
return date.toISOString().slice(0, 10) === value ? date : null;
|
|
20824
|
+
}
|
|
20825
|
+
function isHttpUrl(value) {
|
|
20826
|
+
try {
|
|
20827
|
+
const url = new URL(value);
|
|
20828
|
+
return url.protocol === "https:" || url.protocol === "http:";
|
|
20829
|
+
} catch {
|
|
20830
|
+
return false;
|
|
20831
|
+
}
|
|
20832
|
+
}
|
|
20833
|
+
function checkComparisonFreshness(claims, options = {}) {
|
|
20834
|
+
const maxAgeDays = options.maxAgeDays ?? DEFAULT_COMPARISON_MAX_AGE_DAYS;
|
|
20835
|
+
const now2 = options.now ?? /* @__PURE__ */ new Date();
|
|
20836
|
+
const issues = [];
|
|
20837
|
+
for (const claim of claims) {
|
|
20838
|
+
const sources = claim.sources ?? [];
|
|
20839
|
+
if (sources.length === 0) {
|
|
20840
|
+
issues.push({
|
|
20841
|
+
path: claim.path,
|
|
20842
|
+
problem: "missing-source",
|
|
20843
|
+
detail: "no source: add { url, verifiedAt } for the vendor page this claim was checked against"
|
|
20844
|
+
});
|
|
20845
|
+
continue;
|
|
20846
|
+
}
|
|
20847
|
+
let newest = null;
|
|
20848
|
+
for (const source of sources) {
|
|
20849
|
+
if (!isHttpUrl(source.url)) {
|
|
20850
|
+
issues.push({
|
|
20851
|
+
path: claim.path,
|
|
20852
|
+
problem: "invalid-url",
|
|
20853
|
+
detail: `source URL is not an http(s) URL: ${JSON.stringify(source.url)}`
|
|
20854
|
+
});
|
|
20855
|
+
}
|
|
20856
|
+
const verified = parseVerifiedAt(source.verifiedAt);
|
|
20857
|
+
if (!verified) {
|
|
20858
|
+
issues.push({
|
|
20859
|
+
path: claim.path,
|
|
20860
|
+
problem: "invalid-date",
|
|
20861
|
+
detail: `verifiedAt must be YYYY-MM-DD, got ${JSON.stringify(source.verifiedAt)}`
|
|
20862
|
+
});
|
|
20863
|
+
continue;
|
|
20864
|
+
}
|
|
20865
|
+
if (verified.getTime() > now2.getTime() + DAY_MS) {
|
|
20866
|
+
issues.push({
|
|
20867
|
+
path: claim.path,
|
|
20868
|
+
problem: "future-date",
|
|
20869
|
+
detail: `verifiedAt ${source.verifiedAt} is in the future`
|
|
20870
|
+
});
|
|
20871
|
+
continue;
|
|
20872
|
+
}
|
|
20873
|
+
if (!newest || verified.getTime() > newest.getTime()) newest = verified;
|
|
20874
|
+
}
|
|
20875
|
+
if (newest) {
|
|
20876
|
+
const ageDays = Math.floor((now2.getTime() - newest.getTime()) / DAY_MS);
|
|
20877
|
+
if (ageDays > maxAgeDays) {
|
|
20878
|
+
issues.push({
|
|
20879
|
+
path: claim.path,
|
|
20880
|
+
problem: "stale",
|
|
20881
|
+
detail: `last verified ${newest.toISOString().slice(0, 10)} (${ageDays} days ago, limit ${maxAgeDays}): re-read the vendor page and update verifiedAt or the claim`
|
|
20882
|
+
});
|
|
20883
|
+
}
|
|
20884
|
+
}
|
|
20885
|
+
}
|
|
20886
|
+
return issues;
|
|
20887
|
+
}
|
|
20888
|
+
function latestVerification(claims) {
|
|
20889
|
+
let latest = null;
|
|
20890
|
+
for (const claim of claims) {
|
|
20891
|
+
for (const source of claim.sources ?? []) {
|
|
20892
|
+
if (parseVerifiedAt(source.verifiedAt) && (!latest || source.verifiedAt > latest)) {
|
|
20893
|
+
latest = source.verifiedAt;
|
|
20894
|
+
}
|
|
20895
|
+
}
|
|
20896
|
+
}
|
|
20897
|
+
return latest;
|
|
20898
|
+
}
|
|
20899
|
+
function oldestVerification(claims) {
|
|
20900
|
+
let oldest = null;
|
|
20901
|
+
for (const claim of claims) {
|
|
20902
|
+
for (const source of claim.sources ?? []) {
|
|
20903
|
+
if (parseVerifiedAt(source.verifiedAt) && (!oldest || source.verifiedAt < oldest)) {
|
|
20904
|
+
oldest = source.verifiedAt;
|
|
20905
|
+
}
|
|
20906
|
+
}
|
|
20907
|
+
}
|
|
20908
|
+
return oldest;
|
|
20909
|
+
}
|
|
20910
|
+
function formatFreshnessReport(issues) {
|
|
20911
|
+
if (issues.length === 0)
|
|
20912
|
+
return "Comparison sources: all claims sourced and fresh.";
|
|
20913
|
+
const lines = issues.map((i) => ` - [${i.problem}] ${i.path}: ${i.detail}`);
|
|
20914
|
+
return [
|
|
20915
|
+
`Comparison sources: ${issues.length} problem(s) found.`,
|
|
20916
|
+
...lines,
|
|
20917
|
+
"Re-check each claim against the vendor's current page, then update the claim and its verifiedAt."
|
|
20918
|
+
].join("\n");
|
|
20919
|
+
}
|
|
20920
|
+
|
|
20921
|
+
export { ANSWERS_PATH, ANSWER_HEADING_SHIFT, ANSWER_PATH_PREFIX, AnswerDetailPage, AnswersPage, BlogListPage, BlogPostPage, Button, CONCEPTS_PATH, CONCEPT_ILLUSTRATION_NOTICE, CONCEPT_PATH_PREFIX, CONCEPT_WORKFLOW_NOTICE, CareersApplyForm, CareersSubmissionForm, CaseStudiesListPage, CaseStudyPage, ChangelogPage, ConceptDetailPage, ConceptsPage, ContactPage, ContentRenderer, ContractsPage, DEFAULT_COMPARISON_MAX_AGE_DAYS, DEFAULT_CONTACT_CATEGORIES, DEFAULT_EXPLORE_EXAMPLE_PROMPTS, DOMAINS_URL, ECOSYSTEM_PRODUCTS, ESCALATE_EXPLORE_CONVERSATION_MUTATION, EXPLORE_CATALOG_QUERY, EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS, EXPLORE_ESCALATION_NOTE_SOFT_MAX, EXPLORE_LOCALES, EXPLORE_MESSAGE_QUERY, EXPLORE_PREFILL_MAX_LENGTH, EXPLORE_RECAPTCHA_ACTION, ElectronDownloadLink, ExploreAnswerBody, ExploreAnswerStyles, ExploreChatProvider, ExploreCta, ExplorePage, ExplorePanel, FALLBACK_EXPLORE_LIMITS, FOOTERLESS_ROUTES, Input, LEGAL_DOCUMENTS, LEGAL_DOCUMENT_KEYS, Label, LaunchCountdown, LegalPage, Markdown, NewsletterForm, NewsletterPage, PRODUCT_SLUG_ALIASES, PRODUCT_SLUG_EMIT, PRODUCT_SLUG_RENAMES, PUBLISHED_ANSWER_FIELDS, PageHead, PartnersPage, PressKitPage, PricingPage, PricingProductKeyError, PricingSection, ProblemsSolvedSection, ProductCard, ProductProvider, ResourceLinks, RybbitAnalytics, SEND_EXPLORE_MESSAGE_MUTATION, Select, SocialLinks, StarRating, StoreBrowsePage, StoreHomePage, StoreProductDetailPage, Textarea, TypeBadge, UnsubscribePage, WaitlistForm, WaitlistPage, WebSDKClient, WebSDKProvider, WebsiteSwitcher, answerPath, answerPlainText, answerSourceHost, answerSpeechText, answerStrings, availablePlanCurrencies, buttonVariants, checkComparisonFreshness, classifyExploreError, cleanPlanDisplayName, cn, conceptPath, detectElectronPlatform, emitProductSlug, exploreQuestionHref, fetchLegalContent, fetchLegalContentPage, fetchPublicJobPosting, fetchPublicJobPostings, fetchPublicJobPostingsForSubmission, fetchPublicProduct, findLegalDocument, formatAnswerDate, formatDownloads, formatFreshnessReport, formatLegalDate, formatPrice2 as formatPrice, getAnswerBySlug, getConceptBySlug, getRecaptchaV3Token, hasCustomerSignOff, inlineImageOrigins, isFooterlessPath, isInlineImageAllowed, isInlineVideoAllowed, isPublishedSourceUrl, isSameProductSlug, isUuidLike, isValidUrl, latestVerification, legacyProductSlug, loadRecaptchaV3, looksLikeDeliverableEmail, normalizeProductSlug, normalizeRoutePath, oldestVerification, parseVerifiedAt, planPriceIn, productSlugVariants, productSlugsByOrigin, resolvePricingProductKey, shouldRenderSiteFooter, speechLocaleOf, splitLeadingHeading, stopSpeaking, useContentPage, useContentPages, useExploreChat, useExploreConversation, useProduct, useProductConfig, useProgressiveReveal, usePublicJobPosting, usePublicJobPostings, usePublicJobPostingsForSubmission, useSpeechOutput, useWebSDK, useWebSDKConfig };
|
|
20611
20922
|
//# sourceMappingURL=index.mjs.map
|
|
20612
20923
|
//# sourceMappingURL=index.mjs.map
|