@burdenoff/website-sdk 2026.703.2 → 2026.709.2

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 (37) hide show
  1. package/dist/components/electron-download.d.mts +32 -0
  2. package/dist/components/electron-download.d.ts +32 -0
  3. package/dist/components/electron-download.js +131 -0
  4. package/dist/components/electron-download.js.map +1 -0
  5. package/dist/components/electron-download.mjs +108 -0
  6. package/dist/components/electron-download.mjs.map +1 -0
  7. package/dist/components/launch-countdown.d.mts +15 -0
  8. package/dist/components/launch-countdown.d.ts +15 -0
  9. package/dist/components/launch-countdown.js +89 -0
  10. package/dist/components/launch-countdown.js.map +1 -0
  11. package/dist/components/launch-countdown.mjs +87 -0
  12. package/dist/components/launch-countdown.mjs.map +1 -0
  13. package/dist/components/problems-solved.d.mts +37 -0
  14. package/dist/components/problems-solved.d.ts +37 -0
  15. package/dist/components/problems-solved.js +157 -0
  16. package/dist/components/problems-solved.js.map +1 -0
  17. package/dist/components/problems-solved.mjs +135 -0
  18. package/dist/components/problems-solved.mjs.map +1 -0
  19. package/dist/components/website-switcher.d.mts +27 -0
  20. package/dist/components/website-switcher.d.ts +27 -0
  21. package/dist/components/website-switcher.js +168 -0
  22. package/dist/components/website-switcher.js.map +1 -0
  23. package/dist/components/website-switcher.mjs +146 -0
  24. package/dist/components/website-switcher.mjs.map +1 -0
  25. package/dist/content/index.d.mts +24 -1
  26. package/dist/content/index.d.ts +24 -1
  27. package/dist/content/index.js +459 -149
  28. package/dist/content/index.js.map +1 -1
  29. package/dist/content/index.mjs +378 -87
  30. package/dist/content/index.mjs.map +1 -1
  31. package/dist/index.d.mts +15 -2
  32. package/dist/index.d.ts +15 -2
  33. package/dist/index.js +817 -86
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +812 -88
  36. package/dist/index.mjs.map +1 -1
  37. package/package.json +3 -1
@@ -1,8 +1,33 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
3
+ var React = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var reactHelmetAsync = require('react-helmet-async');
6
+ var lucideReact = require('lucide-react');
7
+ var reactSlot = require('@radix-ui/react-slot');
8
+ var classVarianceAuthority = require('class-variance-authority');
9
+ var clsx = require('clsx');
10
+ var tailwindMerge = require('tailwind-merge');
11
+
12
+ function _interopNamespace(e) {
13
+ if (e && e.__esModule) return e;
14
+ var n = Object.create(null);
15
+ if (e) {
16
+ Object.keys(e).forEach(function (k) {
17
+ if (k !== 'default') {
18
+ var d = Object.getOwnPropertyDescriptor(e, k);
19
+ Object.defineProperty(n, k, d.get ? d : {
20
+ enumerable: true,
21
+ get: function () { return e[k]; }
22
+ });
23
+ }
24
+ });
25
+ }
26
+ n.default = e;
27
+ return Object.freeze(n);
28
+ }
29
+
30
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
6
31
 
7
32
  var __defProp = Object.defineProperty;
8
33
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -144,9 +169,9 @@ var _WebSDKClient = class _WebSDKClient {
144
169
  __publicField(_WebSDKClient, "CACHE_TTL", 5 * 60 * 1e3);
145
170
  // 5 minutes
146
171
  __publicField(_WebSDKClient, "MAX_CACHE_ENTRIES", 100);
147
- var WebSDKContext = react.createContext(null);
172
+ var WebSDKContext = React.createContext(null);
148
173
  function useWebSDK() {
149
- const client = react.useContext(WebSDKContext);
174
+ const client = React.useContext(WebSDKContext);
150
175
  if (!client) {
151
176
  throw new Error("useWebSDK must be used within a WebSDKProvider");
152
177
  }
@@ -156,7 +181,7 @@ function useWebSDKConfig() {
156
181
  const client = useWebSDK();
157
182
  return client.getConfig();
158
183
  }
159
- var ProductContext = react.createContext({
184
+ var ProductContext = React.createContext({
160
185
  product: null,
161
186
  loading: true,
162
187
  error: null,
@@ -165,7 +190,7 @@ var ProductContext = react.createContext({
165
190
  }
166
191
  });
167
192
  function useProduct() {
168
- return react.useContext(ProductContext);
193
+ return React.useContext(ProductContext);
169
194
  }
170
195
  var PUBLIC_CONTENT_PAGE_QUERY = `
171
196
  query PublicContentPage($slug: String!, $productId: String) {
@@ -241,10 +266,10 @@ function useContentPage(slug, options) {
241
266
  const config = useWebSDKConfig();
242
267
  const { product } = useProduct();
243
268
  const resolvedProductId = product?.id || config.productId;
244
- const [data, setData] = react.useState(null);
245
- const [loading, setLoading] = react.useState(true);
246
- const [error, setError] = react.useState(null);
247
- const fetchPage = react.useCallback(async () => {
269
+ const [data, setData] = React.useState(null);
270
+ const [loading, setLoading] = React.useState(true);
271
+ const [error, setError] = React.useState(null);
272
+ const fetchPage = React.useCallback(async () => {
248
273
  if (!resolvedProductId) return;
249
274
  setLoading(true);
250
275
  setError(null);
@@ -271,7 +296,7 @@ function useContentPage(slug, options) {
271
296
  setLoading(false);
272
297
  }
273
298
  }, [client, resolvedProductId, slug, options?.resolve]);
274
- react.useEffect(() => {
299
+ React.useEffect(() => {
275
300
  fetchPage();
276
301
  }, [fetchPage]);
277
302
  return { data, loading, error, refetch: fetchPage };
@@ -279,10 +304,10 @@ function useContentPage(slug, options) {
279
304
  function useContentPages(options) {
280
305
  const client = useWebSDK();
281
306
  const config = useWebSDKConfig();
282
- const [data, setData] = react.useState(null);
283
- const [loading, setLoading] = react.useState(true);
284
- const [error, setError] = react.useState(null);
285
- const fetchPages = react.useCallback(async () => {
307
+ const [data, setData] = React.useState(null);
308
+ const [loading, setLoading] = React.useState(true);
309
+ const [error, setError] = React.useState(null);
310
+ const fetchPages = React.useCallback(async () => {
286
311
  setLoading(true);
287
312
  setError(null);
288
313
  try {
@@ -306,7 +331,7 @@ function useContentPages(options) {
306
331
  setLoading(false);
307
332
  }
308
333
  }, [client, config.productId, options?.limit, options?.offset]);
309
- react.useEffect(() => {
334
+ React.useEffect(() => {
310
335
  fetchPages();
311
336
  }, [fetchPages]);
312
337
  return { data, loading, error, refetch: fetchPages };
@@ -482,7 +507,7 @@ function BlogCard({
482
507
  month: "long",
483
508
  day: "numeric"
484
509
  }) : "";
485
- const [imgError, setImgError] = react.useState(false);
510
+ const [imgError, setImgError] = React.useState(false);
486
511
  return /* @__PURE__ */ jsxRuntime.jsxs(
487
512
  "a",
488
513
  {
@@ -552,13 +577,13 @@ function BlogListPage(props) {
552
577
  const config = useWebSDKConfig();
553
578
  const { product } = useProduct();
554
579
  const resolvedProductId = product?.id || config.productId;
555
- const [posts, setPosts] = react.useState([]);
556
- const [total, setTotal] = react.useState(0);
557
- const [loading, setLoading] = react.useState(true);
558
- const [error, setError] = react.useState(null);
559
- const [offset, setOffset] = react.useState(0);
580
+ const [posts, setPosts] = React.useState([]);
581
+ const [total, setTotal] = React.useState(0);
582
+ const [loading, setLoading] = React.useState(true);
583
+ const [error, setError] = React.useState(null);
584
+ const [offset, setOffset] = React.useState(0);
560
585
  const limit = 12;
561
- const fetchPosts = react.useCallback(async () => {
586
+ const fetchPosts = React.useCallback(async () => {
562
587
  if (!resolvedProductId) return;
563
588
  setLoading(true);
564
589
  try {
@@ -583,7 +608,7 @@ function BlogListPage(props) {
583
608
  setLoading(false);
584
609
  }
585
610
  }, [client, resolvedProductId, offset]);
586
- react.useEffect(() => {
611
+ React.useEffect(() => {
587
612
  fetchPosts();
588
613
  }, [fetchPosts]);
589
614
  const featuredPosts = posts.filter((p) => p.featured);
@@ -668,11 +693,11 @@ function BlogPostPage(props) {
668
693
  const config = useWebSDKConfig();
669
694
  const { product } = useProduct();
670
695
  const resolvedProductId = product?.id || config.productId;
671
- const [post, setPost] = react.useState(null);
672
- const [loading, setLoading] = react.useState(true);
673
- const [error, setError] = react.useState(null);
696
+ const [post, setPost] = React.useState(null);
697
+ const [loading, setLoading] = React.useState(true);
698
+ const [error, setError] = React.useState(null);
674
699
  const slug = typeof window !== "undefined" ? window.location.pathname.split("/").pop() || "" : "";
675
- react.useEffect(() => {
700
+ React.useEffect(() => {
676
701
  if (!slug || !resolvedProductId) return;
677
702
  async function fetchPost() {
678
703
  setLoading(true);
@@ -831,7 +856,7 @@ function CaseStudyCard({
831
856
  month: "long",
832
857
  day: "numeric"
833
858
  }) : "";
834
- const [imgError, setImgError] = react.useState(false);
859
+ const [imgError, setImgError] = React.useState(false);
835
860
  return /* @__PURE__ */ jsxRuntime.jsxs(
836
861
  "a",
837
862
  {
@@ -901,13 +926,13 @@ function CaseStudiesListPage(props) {
901
926
  const config = useWebSDKConfig();
902
927
  const { product } = useProduct();
903
928
  const resolvedProductId = product?.id || config.productId;
904
- const [posts, setPosts] = react.useState([]);
905
- const [total, setTotal] = react.useState(0);
906
- const [loading, setLoading] = react.useState(true);
907
- const [error, setError] = react.useState(null);
908
- const [offset, setOffset] = react.useState(0);
929
+ const [posts, setPosts] = React.useState([]);
930
+ const [total, setTotal] = React.useState(0);
931
+ const [loading, setLoading] = React.useState(true);
932
+ const [error, setError] = React.useState(null);
933
+ const [offset, setOffset] = React.useState(0);
909
934
  const limit = 12;
910
- const fetchPosts = react.useCallback(async () => {
935
+ const fetchPosts = React.useCallback(async () => {
911
936
  if (!resolvedProductId) return;
912
937
  setLoading(true);
913
938
  try {
@@ -932,7 +957,7 @@ function CaseStudiesListPage(props) {
932
957
  setLoading(false);
933
958
  }
934
959
  }, [client, resolvedProductId, offset]);
935
- react.useEffect(() => {
960
+ React.useEffect(() => {
936
961
  fetchPosts();
937
962
  }, [fetchPosts]);
938
963
  const featuredPosts = posts.filter((p) => p.featured);
@@ -1017,11 +1042,11 @@ function CaseStudyPage(props) {
1017
1042
  const config = useWebSDKConfig();
1018
1043
  const { product } = useProduct();
1019
1044
  const resolvedProductId = product?.id || config.productId;
1020
- const [post, setPost] = react.useState(null);
1021
- const [loading, setLoading] = react.useState(true);
1022
- const [error, setError] = react.useState(null);
1045
+ const [post, setPost] = React.useState(null);
1046
+ const [loading, setLoading] = React.useState(true);
1047
+ const [error, setError] = React.useState(null);
1023
1048
  const slug = typeof window !== "undefined" ? window.location.pathname.split("/").pop() || "" : "";
1024
- react.useEffect(() => {
1049
+ React.useEffect(() => {
1025
1050
  if (!slug || !resolvedProductId) return;
1026
1051
  async function fetchPost() {
1027
1052
  setLoading(true);
@@ -1123,6 +1148,65 @@ function CaseStudyPage(props) {
1123
1148
  ] })
1124
1149
  ] });
1125
1150
  }
1151
+ function cn(...inputs) {
1152
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
1153
+ }
1154
+ var buttonVariants = classVarianceAuthority.cva(
1155
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1156
+ {
1157
+ variants: {
1158
+ variant: {
1159
+ default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
1160
+ destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
1161
+ outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
1162
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
1163
+ ghost: "hover:bg-accent hover:text-accent-foreground",
1164
+ link: "text-primary underline-offset-4 hover:underline"
1165
+ },
1166
+ size: {
1167
+ default: "h-9 px-4 py-2",
1168
+ sm: "h-8 rounded-md px-3 text-xs",
1169
+ lg: "h-10 rounded-md px-8",
1170
+ icon: "h-9 w-9"
1171
+ }
1172
+ },
1173
+ defaultVariants: {
1174
+ variant: "default",
1175
+ size: "default"
1176
+ }
1177
+ }
1178
+ );
1179
+ var Button = React__namespace.forwardRef(
1180
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
1181
+ const Comp = asChild ? reactSlot.Slot : "button";
1182
+ return /* @__PURE__ */ jsxRuntime.jsx(
1183
+ Comp,
1184
+ {
1185
+ className: cn(buttonVariants({ variant, size, className })),
1186
+ ref,
1187
+ ...props
1188
+ }
1189
+ );
1190
+ }
1191
+ );
1192
+ Button.displayName = "Button";
1193
+ var Input = React__namespace.forwardRef(
1194
+ ({ className, type, ...props }, ref) => {
1195
+ return /* @__PURE__ */ jsxRuntime.jsx(
1196
+ "input",
1197
+ {
1198
+ type,
1199
+ className: cn(
1200
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1201
+ className
1202
+ ),
1203
+ ref,
1204
+ ...props
1205
+ }
1206
+ );
1207
+ }
1208
+ );
1209
+ Input.displayName = "Input";
1126
1210
  var CHANGELOG_TAG = "changelog";
1127
1211
  var CHANGELOG_LIST_QUERY = `
1128
1212
  query ChangelogList($productId: String!, $limit: Int, $offset: Int) {
@@ -1168,30 +1252,29 @@ function sortByDateDesc(a, b) {
1168
1252
  const db = new Date(b.publishedAt || b.lastUpdated || 0).getTime();
1169
1253
  return db - da;
1170
1254
  }
1171
- function ChangelogPage(props) {
1172
- const {
1173
- productName,
1174
- heroEyebrow = "What's new",
1175
- heroTitle = "Changelog",
1176
- heroSubtitle = "Platform updates, improvements, and announcements \u2014 newest first.",
1177
- ctaTitle,
1178
- ctaSubtitle,
1179
- ctaHref,
1180
- ctaLabel,
1181
- className = "",
1182
- seoTitle,
1183
- seoDescription,
1184
- seoKeywords
1185
- } = props;
1255
+ function normalize(value) {
1256
+ return value.toLowerCase().trim();
1257
+ }
1258
+ function paginate(items, page, pageSize) {
1259
+ const start = (page - 1) * pageSize;
1260
+ return items.slice(start, start + pageSize);
1261
+ }
1262
+ function parseEntryDate(date) {
1263
+ return new Date(date).getTime();
1264
+ }
1265
+ function useCmsChangelog() {
1186
1266
  const client = useWebSDK();
1187
1267
  const config = useWebSDKConfig();
1188
1268
  const { product } = useProduct();
1189
1269
  const resolvedProductId = product?.id || config.productId;
1190
- const [entries, setEntries] = react.useState([]);
1191
- const [loading, setLoading] = react.useState(true);
1192
- const [error, setError] = react.useState(null);
1193
- const fetchEntries = react.useCallback(async () => {
1194
- if (!resolvedProductId) return;
1270
+ const [entries, setEntries] = React.useState([]);
1271
+ const [loading, setLoading] = React.useState(true);
1272
+ const [error, setError] = React.useState(null);
1273
+ const fetchEntries = React.useCallback(async () => {
1274
+ if (!resolvedProductId) {
1275
+ setLoading(false);
1276
+ return;
1277
+ }
1195
1278
  setLoading(true);
1196
1279
  try {
1197
1280
  const listResult = await client.query(CHANGELOG_LIST_QUERY, {
@@ -1230,96 +1313,323 @@ function ChangelogPage(props) {
1230
1313
  setLoading(false);
1231
1314
  }
1232
1315
  }, [client, resolvedProductId]);
1233
- react.useEffect(() => {
1316
+ React.useEffect(() => {
1234
1317
  fetchEntries();
1235
1318
  }, [fetchEntries]);
1319
+ return { entries, loading, error };
1320
+ }
1321
+ function CmsTimeline(props) {
1322
+ const { entries, loading, error } = props;
1323
+ if (loading) {
1324
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-3xl mx-auto space-y-12", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxRuntime.jsx(
1325
+ "div",
1326
+ {
1327
+ className: "rounded-2xl border border-border/40 bg-card overflow-hidden animate-pulse",
1328
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 sm:p-8 space-y-4", children: [
1329
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 bg-muted rounded w-1/3" }),
1330
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 bg-muted rounded w-2/3" }),
1331
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded" }),
1332
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-5/6" })
1333
+ ] })
1334
+ },
1335
+ i
1336
+ )) });
1337
+ }
1338
+ if (error) {
1339
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: error }) });
1340
+ }
1341
+ if (entries.length === 0) {
1342
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "No changelog entries yet. Check back soon!" }) });
1343
+ }
1344
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-3xl mx-auto space-y-12", children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs(
1345
+ "article",
1346
+ {
1347
+ id: entry.slug,
1348
+ className: "rounded-2xl border border-border/40 bg-card overflow-hidden scroll-mt-24",
1349
+ children: [
1350
+ entry.thumbnail && /* @__PURE__ */ jsxRuntime.jsx(
1351
+ "img",
1352
+ {
1353
+ src: entry.thumbnail,
1354
+ alt: "",
1355
+ width: 1024,
1356
+ height: 576,
1357
+ loading: "lazy",
1358
+ decoding: "async",
1359
+ className: "w-full aspect-video object-cover border-b border-border/40"
1360
+ }
1361
+ ),
1362
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 sm:p-8", children: [
1363
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground mb-2", children: [
1364
+ entry.publishedAt && /* @__PURE__ */ jsxRuntime.jsx("time", { dateTime: entry.publishedAt, children: formatDate(entry.publishedAt || entry.lastUpdated) }),
1365
+ entry.author && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1366
+ " \xB7 ",
1367
+ entry.author
1368
+ ] })
1369
+ ] }),
1370
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl sm:text-2xl font-bold text-foreground mb-4", children: entry.title }),
1371
+ entry.content ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose prose-sm prose-gray dark:prose-invert max-w-none", children: /* @__PURE__ */ jsxRuntime.jsx(
1372
+ ContentRenderer,
1373
+ {
1374
+ content: entry.content,
1375
+ format: entry.contentFormat
1376
+ }
1377
+ ) }) : entry.excerpt && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: entry.excerpt })
1378
+ ] })
1379
+ ]
1380
+ },
1381
+ entry.id
1382
+ )) });
1383
+ }
1384
+ function EntryContent({ content }) {
1385
+ if (typeof content === "string") {
1386
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose prose-sm prose-gray dark:prose-invert max-w-none", children: /* @__PURE__ */ jsxRuntime.jsx(ContentRenderer, { content, format: "markdown" }) });
1387
+ }
1388
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose prose-sm max-w-none", children: content });
1389
+ }
1390
+ function EntriesTimeline(props) {
1391
+ const { entries, pageSize, productName } = props;
1392
+ const [query, setQuery] = React.useState("");
1393
+ const [selectedCategory, setSelectedCategory] = React.useState(null);
1394
+ const [page, setPage] = React.useState(1);
1395
+ const categories = React.useMemo(
1396
+ () => Array.from(new Set(entries.map((e) => e.category))).sort(),
1397
+ [entries]
1398
+ );
1399
+ const filtered = React.useMemo(() => {
1400
+ const normalized = normalize(query);
1401
+ return entries.filter((entry) => {
1402
+ if (selectedCategory && entry.category !== selectedCategory) {
1403
+ return false;
1404
+ }
1405
+ if (!normalized) return true;
1406
+ const haystack = [
1407
+ entry.title,
1408
+ entry.version,
1409
+ entry.category,
1410
+ ...entry.tags ?? [],
1411
+ typeof entry.content === "string" ? entry.content : ""
1412
+ ].join(" ").toLowerCase();
1413
+ return haystack.includes(normalized);
1414
+ }).sort((a, b) => parseEntryDate(b.date) - parseEntryDate(a.date));
1415
+ }, [entries, query, selectedCategory]);
1416
+ const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
1417
+ const safePage = Math.min(page, totalPages);
1418
+ const pageItems = paginate(filtered, safePage, pageSize);
1419
+ React.useEffect(() => {
1420
+ setPage(1);
1421
+ }, [query, selectedCategory]);
1422
+ if (entries.length === 0) {
1423
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "No changelog entries yet. Check back soon!" }) });
1424
+ }
1425
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl mx-auto", children: [
1426
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-8 space-y-4", children: [
1427
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1428
+ /* @__PURE__ */ jsxRuntime.jsx(
1429
+ lucideReact.Search,
1430
+ {
1431
+ className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground",
1432
+ "aria-hidden": "true"
1433
+ }
1434
+ ),
1435
+ /* @__PURE__ */ jsxRuntime.jsx(
1436
+ Input,
1437
+ {
1438
+ type: "search",
1439
+ placeholder: "Search releases, features, fixes\u2026",
1440
+ value: query,
1441
+ onChange: (e) => setQuery(e.target.value),
1442
+ className: "pl-9",
1443
+ "aria-label": "Search changelog"
1444
+ }
1445
+ )
1446
+ ] }),
1447
+ categories.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
1448
+ /* @__PURE__ */ jsxRuntime.jsx(
1449
+ "button",
1450
+ {
1451
+ type: "button",
1452
+ onClick: () => setSelectedCategory(null),
1453
+ className: cn(
1454
+ "px-3 py-1 rounded-full text-xs font-medium border transition-colors",
1455
+ selectedCategory === null ? "bg-primary text-primary-foreground border-primary" : "bg-background text-muted-foreground border-border/60 hover:border-primary/40"
1456
+ ),
1457
+ children: "All"
1458
+ }
1459
+ ),
1460
+ categories.map((category) => /* @__PURE__ */ jsxRuntime.jsx(
1461
+ "button",
1462
+ {
1463
+ type: "button",
1464
+ onClick: () => setSelectedCategory(category),
1465
+ className: cn(
1466
+ "px-3 py-1 rounded-full text-xs font-medium border transition-colors",
1467
+ selectedCategory === category ? "bg-primary text-primary-foreground border-primary" : "bg-background text-muted-foreground border-border/60 hover:border-primary/40"
1468
+ ),
1469
+ children: category
1470
+ },
1471
+ category
1472
+ ))
1473
+ ] })
1474
+ ] }),
1475
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1476
+ /* @__PURE__ */ jsxRuntime.jsx(
1477
+ "div",
1478
+ {
1479
+ className: "absolute left-[1.125rem] top-3 bottom-3 w-px bg-border/60 hidden sm:block",
1480
+ "aria-hidden": "true"
1481
+ }
1482
+ ),
1483
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-8", children: pageItems.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs(
1484
+ "article",
1485
+ {
1486
+ className: "relative sm:pl-12",
1487
+ children: [
1488
+ /* @__PURE__ */ jsxRuntime.jsx(
1489
+ "div",
1490
+ {
1491
+ className: "hidden sm:flex absolute left-2 top-2 h-5 w-5 items-center justify-center rounded-full border-2 border-background bg-primary ring-1 ring-border/40",
1492
+ "aria-hidden": "true",
1493
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full bg-primary-foreground" })
1494
+ }
1495
+ ),
1496
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-2xl border border-border/40 bg-card overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 sm:p-8", children: [
1497
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2 mb-3", children: [
1498
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center rounded-md bg-primary/10 px-2 py-1 text-xs font-medium text-primary", children: entry.category }),
1499
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center rounded-md bg-muted px-2 py-1 text-xs font-mono font-medium text-muted-foreground", children: [
1500
+ "v",
1501
+ entry.version
1502
+ ] }),
1503
+ /* @__PURE__ */ jsxRuntime.jsx(
1504
+ "time",
1505
+ {
1506
+ className: "text-xs text-muted-foreground",
1507
+ dateTime: entry.date,
1508
+ children: formatDate(entry.date)
1509
+ }
1510
+ )
1511
+ ] }),
1512
+ entry.tags && entry.tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1.5 mb-3", children: entry.tags.map((tag) => /* @__PURE__ */ jsxRuntime.jsx(
1513
+ "span",
1514
+ {
1515
+ className: "text-[10px] uppercase tracking-wide text-muted-foreground bg-background border border-border/40 px-1.5 py-0.5 rounded",
1516
+ children: tag
1517
+ },
1518
+ tag
1519
+ )) }),
1520
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl sm:text-2xl font-bold text-foreground mb-4", children: entry.title }),
1521
+ /* @__PURE__ */ jsxRuntime.jsx(EntryContent, { content: entry.content })
1522
+ ] }) })
1523
+ ]
1524
+ },
1525
+ `${entry.version}-${entry.date}`
1526
+ )) })
1527
+ ] }),
1528
+ pageItems.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "No entries match your filters." }) }),
1529
+ totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-10 flex items-center justify-between", children: [
1530
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
1531
+ "Page ",
1532
+ safePage,
1533
+ " of ",
1534
+ totalPages,
1535
+ " \xB7 ",
1536
+ filtered.length,
1537
+ " entries"
1538
+ ] }),
1539
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1540
+ /* @__PURE__ */ jsxRuntime.jsx(
1541
+ Button,
1542
+ {
1543
+ variant: "outline",
1544
+ size: "sm",
1545
+ onClick: () => setPage((p) => Math.max(1, p - 1)),
1546
+ disabled: safePage <= 1,
1547
+ "aria-label": "Previous page",
1548
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" })
1549
+ }
1550
+ ),
1551
+ /* @__PURE__ */ jsxRuntime.jsx(
1552
+ Button,
1553
+ {
1554
+ variant: "outline",
1555
+ size: "sm",
1556
+ onClick: () => setPage((p) => Math.min(totalPages, p + 1)),
1557
+ disabled: safePage >= totalPages,
1558
+ "aria-label": "Next page",
1559
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4" })
1560
+ }
1561
+ )
1562
+ ] })
1563
+ ] }),
1564
+ productName && pageItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("script", { type: "application/ld+json", children: JSON.stringify({
1565
+ "@context": "https://schema.org",
1566
+ "@type": "ItemList",
1567
+ name: `${productName} Changelog`,
1568
+ itemListElement: pageItems.map((entry, index) => ({
1569
+ "@type": "ListItem",
1570
+ position: (safePage - 1) * pageSize + index + 1,
1571
+ name: entry.title,
1572
+ description: typeof entry.content === "string" ? entry.content.slice(0, 200) : void 0,
1573
+ datePublished: entry.date
1574
+ }))
1575
+ }) })
1576
+ ] });
1577
+ }
1578
+ function ChangelogPage(props) {
1579
+ const {
1580
+ productName,
1581
+ heroEyebrow = "What's new",
1582
+ heroTitle = "Changelog",
1583
+ heroSubtitle = "Platform updates, improvements, and announcements \u2014 newest first.",
1584
+ ctaTitle,
1585
+ ctaSubtitle,
1586
+ ctaHref,
1587
+ ctaLabel,
1588
+ className = "",
1589
+ seoTitle,
1590
+ seoDescription,
1591
+ seoKeywords,
1592
+ entries,
1593
+ pageSize = 10
1594
+ } = props;
1595
+ const { product } = useProduct();
1596
+ const resolvedProductName = productName || product?.name;
1597
+ const cms = useCmsChangelog();
1236
1598
  const showCta = Boolean(ctaHref && ctaLabel);
1599
+ const isPropDriven = entries != null;
1237
1600
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `w-full ${className}`, children: [
1238
- seoTitle && /* @__PURE__ */ jsxRuntime.jsx(
1601
+ /* @__PURE__ */ jsxRuntime.jsx(
1239
1602
  PageHead,
1240
1603
  {
1241
- title: seoTitle,
1604
+ title: seoTitle || heroTitle,
1242
1605
  description: seoDescription || heroSubtitle,
1243
- productName,
1606
+ productName: resolvedProductName,
1244
1607
  keywords: seoKeywords
1245
1608
  }
1246
1609
  ),
1247
1610
  /* @__PURE__ */ jsxRuntime.jsx("section", { className: "py-16 md:py-20 px-4 sm:px-6 lg:px-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl mx-auto", children: [
1248
1611
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-primary/10 border border-primary/20 text-xs font-medium text-primary mb-6", children: [
1249
- /* @__PURE__ */ jsxRuntime.jsx(
1250
- "svg",
1251
- {
1252
- className: "h-3.5 w-3.5",
1253
- fill: "none",
1254
- viewBox: "0 0 24 24",
1255
- stroke: "currentColor",
1256
- children: /* @__PURE__ */ jsxRuntime.jsx(
1257
- "path",
1258
- {
1259
- strokeLinecap: "round",
1260
- strokeLinejoin: "round",
1261
- strokeWidth: 2,
1262
- d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
1263
- }
1264
- )
1265
- }
1266
- ),
1612
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1267
1613
  heroEyebrow
1268
1614
  ] }),
1269
1615
  /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl sm:text-5xl font-bold text-foreground mb-4", children: heroTitle }),
1270
1616
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg text-muted-foreground", children: heroSubtitle })
1271
1617
  ] }) }),
1272
- /* @__PURE__ */ jsxRuntime.jsx("section", { className: "px-4 sm:px-6 lg:px-8 pb-20", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-3xl mx-auto space-y-12", children: loading ? [1, 2, 3].map((i) => /* @__PURE__ */ jsxRuntime.jsx(
1273
- "div",
1618
+ /* @__PURE__ */ jsxRuntime.jsx("section", { className: "px-4 sm:px-6 lg:px-8 pb-20", children: isPropDriven ? /* @__PURE__ */ jsxRuntime.jsx(
1619
+ EntriesTimeline,
1274
1620
  {
1275
- className: "rounded-2xl border border-border/40 bg-card overflow-hidden animate-pulse",
1276
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 sm:p-8 space-y-4", children: [
1277
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 bg-muted rounded w-1/3" }),
1278
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 bg-muted rounded w-2/3" }),
1279
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded" }),
1280
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-5/6" })
1281
- ] })
1282
- },
1283
- i
1284
- )) : error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: error }) }) : entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "No changelog entries yet. Check back soon!" }) }) : entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs(
1285
- "article",
1621
+ entries,
1622
+ pageSize,
1623
+ productName: resolvedProductName
1624
+ }
1625
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1626
+ CmsTimeline,
1286
1627
  {
1287
- id: entry.slug,
1288
- className: "rounded-2xl border border-border/40 bg-card overflow-hidden scroll-mt-24",
1289
- children: [
1290
- entry.thumbnail && /* @__PURE__ */ jsxRuntime.jsx(
1291
- "img",
1292
- {
1293
- src: entry.thumbnail,
1294
- alt: "",
1295
- width: 1024,
1296
- height: 576,
1297
- loading: "lazy",
1298
- decoding: "async",
1299
- className: "w-full aspect-video object-cover border-b border-border/40"
1300
- }
1301
- ),
1302
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 sm:p-8", children: [
1303
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground mb-2", children: [
1304
- entry.publishedAt && /* @__PURE__ */ jsxRuntime.jsx("time", { dateTime: entry.publishedAt, children: formatDate(entry.publishedAt || entry.lastUpdated) }),
1305
- entry.author && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1306
- " \xB7 ",
1307
- entry.author
1308
- ] })
1309
- ] }),
1310
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl sm:text-2xl font-bold text-foreground mb-4", children: entry.title }),
1311
- entry.content ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose prose-sm prose-gray dark:prose-invert max-w-none", children: /* @__PURE__ */ jsxRuntime.jsx(
1312
- ContentRenderer,
1313
- {
1314
- content: entry.content,
1315
- format: entry.contentFormat
1316
- }
1317
- ) }) : entry.excerpt && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: entry.excerpt })
1318
- ] })
1319
- ]
1320
- },
1321
- entry.id
1322
- )) }) }),
1628
+ entries: cms.entries,
1629
+ loading: cms.loading,
1630
+ error: cms.error
1631
+ }
1632
+ ) }),
1323
1633
  showCta && /* @__PURE__ */ jsxRuntime.jsx("section", { className: "py-14 px-4 sm:px-6 lg:px-8 bg-primary/5 border-t border-border/40", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-2xl mx-auto text-center", children: [
1324
1634
  ctaTitle && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold text-foreground mb-3", children: ctaTitle }),
1325
1635
  ctaSubtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mb-7", children: ctaSubtitle }),
@@ -1442,7 +1752,7 @@ function PressKitLightbox({
1442
1752
  asset,
1443
1753
  onClose
1444
1754
  }) {
1445
- react.useEffect(() => {
1755
+ React.useEffect(() => {
1446
1756
  if (!asset) return;
1447
1757
  const onKey = (e) => {
1448
1758
  if (e.key === "Escape") onClose();
@@ -1567,7 +1877,7 @@ function AssetCard({
1567
1877
  }) : "";
1568
1878
  const ext = (asset.mimeType || "file").split("/").pop()?.toUpperCase() || "FILE";
1569
1879
  const size = formatBytes(asset.fileSize);
1570
- const [imgError, setImgError] = react.useState(false);
1880
+ const [imgError, setImgError] = React.useState(false);
1571
1881
  const thumb = asset.thumbnailUrl && !imgError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] overflow-hidden bg-muted/30", children: /* @__PURE__ */ jsxRuntime.jsx(
1572
1882
  "img",
1573
1883
  {
@@ -1680,7 +1990,7 @@ function PressReleaseCard({
1680
1990
  month: "long",
1681
1991
  day: "numeric"
1682
1992
  }) : "";
1683
- const [imgError, setImgError] = react.useState(false);
1993
+ const [imgError, setImgError] = React.useState(false);
1684
1994
  return /* @__PURE__ */ jsxRuntime.jsxs(
1685
1995
  "a",
1686
1996
  {
@@ -1755,14 +2065,14 @@ function PressKitPage(props) {
1755
2065
  const { product } = useProduct();
1756
2066
  const resolvedProductId = product?.id || config.productId;
1757
2067
  const contactEmail = mediaContactEmail || product?.contactEmail || void 0;
1758
- const [assets, setAssets] = react.useState([]);
1759
- const [loading, setLoading] = react.useState(true);
1760
- const [error, setError] = react.useState(null);
1761
- const [activeCategory, setActiveCategory] = react.useState("ALL");
1762
- const [releases, setReleases] = react.useState([]);
1763
- const [releasesLoading, setReleasesLoading] = react.useState(true);
1764
- const [preview, setPreview] = react.useState(null);
1765
- const fetchAssets = react.useCallback(async () => {
2068
+ const [assets, setAssets] = React.useState([]);
2069
+ const [loading, setLoading] = React.useState(true);
2070
+ const [error, setError] = React.useState(null);
2071
+ const [activeCategory, setActiveCategory] = React.useState("ALL");
2072
+ const [releases, setReleases] = React.useState([]);
2073
+ const [releasesLoading, setReleasesLoading] = React.useState(true);
2074
+ const [preview, setPreview] = React.useState(null);
2075
+ const fetchAssets = React.useCallback(async () => {
1766
2076
  if (!resolvedProductId) {
1767
2077
  setLoading(false);
1768
2078
  return;
@@ -1797,10 +2107,10 @@ function PressKitPage(props) {
1797
2107
  setLoading(false);
1798
2108
  }
1799
2109
  }, [client, resolvedProductId]);
1800
- react.useEffect(() => {
2110
+ React.useEffect(() => {
1801
2111
  fetchAssets();
1802
2112
  }, [fetchAssets]);
1803
- const fetchReleases = react.useCallback(async () => {
2113
+ const fetchReleases = React.useCallback(async () => {
1804
2114
  if (!resolvedProductId || !showPressReleases) {
1805
2115
  setReleasesLoading(false);
1806
2116
  return;
@@ -1839,7 +2149,7 @@ function PressKitPage(props) {
1839
2149
  setReleasesLoading(false);
1840
2150
  }
1841
2151
  }, [client, resolvedProductId, showPressReleases]);
1842
- react.useEffect(() => {
2152
+ React.useEffect(() => {
1843
2153
  fetchReleases();
1844
2154
  }, [fetchReleases]);
1845
2155
  const presentCategories = CATEGORY_ORDER.filter(
@@ -2010,10 +2320,10 @@ function ContractsPage(props) {
2010
2320
  const { product } = useProduct();
2011
2321
  const resolvedProductId = product?.id || config.productId;
2012
2322
  const displayName = productName ?? product?.name ?? config.productId;
2013
- const [contracts, setContracts] = react.useState([]);
2014
- const [loading, setLoading] = react.useState(true);
2015
- const [error, setError] = react.useState(null);
2016
- const fetchContracts = react.useCallback(async () => {
2323
+ const [contracts, setContracts] = React.useState([]);
2324
+ const [loading, setLoading] = React.useState(true);
2325
+ const [error, setError] = React.useState(null);
2326
+ const fetchContracts = React.useCallback(async () => {
2017
2327
  if (!resolvedProductId) {
2018
2328
  setLoading(false);
2019
2329
  return;
@@ -2051,7 +2361,7 @@ function ContractsPage(props) {
2051
2361
  setLoading(false);
2052
2362
  }
2053
2363
  }, [client, resolvedProductId]);
2054
- react.useEffect(() => {
2364
+ React.useEffect(() => {
2055
2365
  fetchContracts();
2056
2366
  }, [fetchContracts]);
2057
2367
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen bg-background ${className}`, children: [