@burdenoff/website-sdk 2026.522.6 → 2026.524.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.
@@ -159,4 +159,29 @@ interface PressKitPageProps {
159
159
  }
160
160
  declare function PressKitPage(props: PressKitPageProps): react_jsx_runtime.JSX.Element;
161
161
 
162
- export { BlogListPage, type BlogListPageProps, BlogPostPage, type BlogPostPageProps, type ContentPageData, type ContentPageListData, type ContentPageListItem, ContentRenderer, type PressKitAsset, type PressKitAssetCategory, PressKitPage, type PressKitPageProps, type UseContentPageOptions, useContentPage, useContentPages };
162
+ interface ContractAsset {
163
+ id: string;
164
+ title: string;
165
+ slug: string;
166
+ description?: string | null;
167
+ fileUrl: string;
168
+ fileName?: string | null;
169
+ fileSize?: number | null;
170
+ mimeType?: string | null;
171
+ version?: string | null;
172
+ tags: string[];
173
+ sortOrder: number;
174
+ updatedAt: string;
175
+ }
176
+ interface ContractsPageProps {
177
+ productName?: string;
178
+ heroTitle?: string;
179
+ heroSubtitle?: string;
180
+ className?: string;
181
+ seoTitle?: string;
182
+ seoDescription?: string;
183
+ seoKeywords?: string;
184
+ }
185
+ declare function ContractsPage(props: ContractsPageProps): react_jsx_runtime.JSX.Element;
186
+
187
+ export { BlogListPage, type BlogListPageProps, BlogPostPage, type BlogPostPageProps, type ContentPageData, type ContentPageListData, type ContentPageListItem, ContentRenderer, type ContractAsset, ContractsPage, type ContractsPageProps, type PressKitAsset, type PressKitAssetCategory, PressKitPage, type PressKitPageProps, type UseContentPageOptions, useContentPage, useContentPages };
@@ -159,4 +159,29 @@ interface PressKitPageProps {
159
159
  }
160
160
  declare function PressKitPage(props: PressKitPageProps): react_jsx_runtime.JSX.Element;
161
161
 
162
- export { BlogListPage, type BlogListPageProps, BlogPostPage, type BlogPostPageProps, type ContentPageData, type ContentPageListData, type ContentPageListItem, ContentRenderer, type PressKitAsset, type PressKitAssetCategory, PressKitPage, type PressKitPageProps, type UseContentPageOptions, useContentPage, useContentPages };
162
+ interface ContractAsset {
163
+ id: string;
164
+ title: string;
165
+ slug: string;
166
+ description?: string | null;
167
+ fileUrl: string;
168
+ fileName?: string | null;
169
+ fileSize?: number | null;
170
+ mimeType?: string | null;
171
+ version?: string | null;
172
+ tags: string[];
173
+ sortOrder: number;
174
+ updatedAt: string;
175
+ }
176
+ interface ContractsPageProps {
177
+ productName?: string;
178
+ heroTitle?: string;
179
+ heroSubtitle?: string;
180
+ className?: string;
181
+ seoTitle?: string;
182
+ seoDescription?: string;
183
+ seoKeywords?: string;
184
+ }
185
+ declare function ContractsPage(props: ContractsPageProps): react_jsx_runtime.JSX.Element;
186
+
187
+ export { BlogListPage, type BlogListPageProps, BlogPostPage, type BlogPostPageProps, type ContentPageData, type ContentPageListData, type ContentPageListItem, ContentRenderer, type ContractAsset, ContractsPage, type ContractsPageProps, type PressKitAsset, type PressKitAssetCategory, PressKitPage, type PressKitPageProps, type UseContentPageOptions, useContentPage, useContentPages };
@@ -774,6 +774,42 @@ function BlogPostPage(props) {
774
774
  ] })
775
775
  ] });
776
776
  }
777
+
778
+ // src/content/utils.ts
779
+ function formatBytes(bytes) {
780
+ if (bytes == null) return "";
781
+ if (bytes < 1024) return `${bytes} B`;
782
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
783
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
784
+ }
785
+ function fileExt(file) {
786
+ const name = file.fileName || file.fileUrl.split("/").pop()?.split("?")[0] || "";
787
+ const ext = name.split(".").pop();
788
+ return ext && ext !== name ? ext.toUpperCase() : "FILE";
789
+ }
790
+ async function downloadFile(e, file) {
791
+ e.preventDefault();
792
+ const openInTab = () => window.open(file.fileUrl, "_blank", "noopener,noreferrer");
793
+ const name = file.fileName || file.fileUrl.split("/").pop()?.split("?")[0] || file.title || "download";
794
+ try {
795
+ const res = await fetch(file.fileUrl, { mode: "cors" });
796
+ if (!res.ok) {
797
+ openInTab();
798
+ return;
799
+ }
800
+ const blob = await res.blob();
801
+ const objUrl = URL.createObjectURL(blob);
802
+ const a = document.createElement("a");
803
+ a.href = objUrl;
804
+ a.download = name;
805
+ document.body.appendChild(a);
806
+ a.click();
807
+ a.remove();
808
+ URL.revokeObjectURL(objUrl);
809
+ } catch {
810
+ openInTab();
811
+ }
812
+ }
777
813
  var PRESS_KIT_QUERY = `
778
814
  query PublicPressKit($productId: String!, $limit: Int, $offset: Int) {
779
815
  publicPressKitAssets(productId: $productId, limit: $limit, offset: $offset) {
@@ -839,38 +875,9 @@ var CATEGORY_LABELS = {
839
875
  DOCUMENT: "Documents",
840
876
  PRESS_RELEASE: "Press Releases"
841
877
  };
842
- function formatBytes(bytes) {
843
- if (bytes == null) return "";
844
- if (bytes < 1024) return `${bytes} B`;
845
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
846
- return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
847
- }
848
878
  function isImageAsset(a) {
849
879
  return (a.mimeType || "").startsWith("image/");
850
880
  }
851
- async function downloadAsset(e, asset) {
852
- e.preventDefault();
853
- const openInTab = () => window.open(asset.fileUrl, "_blank", "noopener,noreferrer");
854
- const name = asset.fileName || asset.fileUrl.split("/").pop()?.split("?")[0] || asset.title || "download";
855
- try {
856
- const res = await fetch(asset.fileUrl, { mode: "cors" });
857
- if (!res.ok) {
858
- openInTab();
859
- return;
860
- }
861
- const blob = await res.blob();
862
- const objUrl = URL.createObjectURL(blob);
863
- const a = document.createElement("a");
864
- a.href = objUrl;
865
- a.download = name;
866
- document.body.appendChild(a);
867
- a.click();
868
- a.remove();
869
- URL.revokeObjectURL(objUrl);
870
- } catch {
871
- openInTab();
872
- }
873
- }
874
881
  function PressKitLightbox({
875
882
  asset,
876
883
  onClose
@@ -957,7 +964,7 @@ function PressKitLightbox({
957
964
  rel: "noopener noreferrer",
958
965
  download: true,
959
966
  onClick: (e) => {
960
- void downloadAsset(e, asset);
967
+ void downloadFile(e, asset);
961
968
  },
962
969
  className: "inline-flex items-center gap-1.5 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90",
963
970
  children: [
@@ -1073,7 +1080,7 @@ function AssetCard({
1073
1080
  rel: "noopener noreferrer",
1074
1081
  download: true,
1075
1082
  onClick: (e) => {
1076
- void downloadAsset(e, asset);
1083
+ void downloadFile(e, asset);
1077
1084
  },
1078
1085
  className: "inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline",
1079
1086
  children: [
@@ -1203,9 +1210,10 @@ function PressKitPage(props) {
1203
1210
  setLoading(true);
1204
1211
  try {
1205
1212
  const PAGE_SIZE = 100;
1213
+ const MAX_PAGES = 10;
1206
1214
  const all = [];
1207
1215
  let offset = 0;
1208
- for (; ; ) {
1216
+ for (let pageNum = 0; pageNum < MAX_PAGES; pageNum++) {
1209
1217
  const result = await client.query(PRESS_KIT_QUERY, {
1210
1218
  productId: resolvedProductId,
1211
1219
  limit: PAGE_SIZE,
@@ -1406,10 +1414,170 @@ function PressKitPage(props) {
1406
1414
  /* @__PURE__ */ jsxRuntime.jsx(PressKitLightbox, { asset: preview, onClose: () => setPreview(null) })
1407
1415
  ] });
1408
1416
  }
1417
+ var CONTRACTS_QUERY = `
1418
+ query PublicContracts($productId: String!, $limit: Int, $offset: Int) {
1419
+ publicPressKitAssets(productId: $productId, category: CONTRACT, limit: $limit, offset: $offset) {
1420
+ items {
1421
+ id
1422
+ title
1423
+ slug
1424
+ description
1425
+ fileUrl
1426
+ fileName
1427
+ fileSize
1428
+ mimeType
1429
+ version
1430
+ tags
1431
+ sortOrder
1432
+ updatedAt
1433
+ }
1434
+ hasMore
1435
+ }
1436
+ }
1437
+ `;
1438
+ function ContractsPage(props) {
1439
+ const {
1440
+ productName,
1441
+ heroTitle = "Contracts & Legal Agreements",
1442
+ heroSubtitle = "Download our standard legal agreements and policies.",
1443
+ className = "",
1444
+ seoTitle,
1445
+ seoDescription,
1446
+ seoKeywords
1447
+ } = props;
1448
+ const client = useWebSDK();
1449
+ const config = useWebSDKConfig();
1450
+ const { product } = useProduct();
1451
+ const resolvedProductId = product?.id || config.productId;
1452
+ const displayName = productName ?? product?.name ?? config.productId;
1453
+ const [contracts, setContracts] = react.useState([]);
1454
+ const [loading, setLoading] = react.useState(true);
1455
+ const [error, setError] = react.useState(null);
1456
+ const fetchContracts = react.useCallback(async () => {
1457
+ if (!resolvedProductId) {
1458
+ setLoading(false);
1459
+ return;
1460
+ }
1461
+ setLoading(true);
1462
+ try {
1463
+ const PAGE_SIZE = 100;
1464
+ const MAX_PAGES = 10;
1465
+ const all = [];
1466
+ let offset = 0;
1467
+ for (let pageNum = 0; pageNum < MAX_PAGES; pageNum++) {
1468
+ const result = await client.query(CONTRACTS_QUERY, {
1469
+ productId: resolvedProductId,
1470
+ limit: PAGE_SIZE,
1471
+ offset
1472
+ });
1473
+ if (result.errors?.length) {
1474
+ setError(result.errors[0]?.message ?? "Failed to load contracts");
1475
+ return;
1476
+ }
1477
+ const page = result.data?.publicPressKitAssets;
1478
+ const items = page?.items || [];
1479
+ all.push(...items);
1480
+ if (!page?.hasMore || items.length === 0) break;
1481
+ offset += PAGE_SIZE;
1482
+ }
1483
+ all.sort(
1484
+ (a, b) => a.sortOrder - b.sortOrder || a.title.localeCompare(b.title)
1485
+ );
1486
+ setContracts(all);
1487
+ setError(null);
1488
+ } catch {
1489
+ setError("Failed to load contracts");
1490
+ } finally {
1491
+ setLoading(false);
1492
+ }
1493
+ }, [client, resolvedProductId]);
1494
+ react.useEffect(() => {
1495
+ fetchContracts();
1496
+ }, [fetchContracts]);
1497
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen bg-background ${className}`, children: [
1498
+ /* @__PURE__ */ jsxRuntime.jsx(
1499
+ PageHead,
1500
+ {
1501
+ title: seoTitle || `Contracts \u2014 ${displayName}`,
1502
+ description: seoDescription || heroSubtitle,
1503
+ productName,
1504
+ keywords: seoKeywords
1505
+ }
1506
+ ),
1507
+ /* @__PURE__ */ jsxRuntime.jsx("section", { className: "border-b border-border bg-muted/30", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-16 text-center", children: [
1508
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl md:text-5xl font-bold text-foreground mb-4", children: heroTitle }),
1509
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg text-muted-foreground max-w-2xl mx-auto", children: heroSubtitle })
1510
+ ] }) }),
1511
+ /* @__PURE__ */ jsxRuntime.jsx("section", { className: "max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-12", children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-20", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: error }) }) : contracts.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base text-muted-foreground", children: "No contracts are available yet." }) }) : /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "divide-y divide-border rounded-xl border border-border overflow-hidden bg-card", children: contracts.map((c) => {
1512
+ const ext = fileExt(c);
1513
+ const size = formatBytes(c.fileSize);
1514
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1515
+ "li",
1516
+ {
1517
+ className: "flex items-center justify-between gap-4 p-5 hover:bg-muted/40 transition-colors",
1518
+ children: [
1519
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
1520
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
1521
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-foreground truncate", children: c.title }),
1522
+ c.version && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-primary bg-primary/10 px-2 py-0.5 rounded-full", children: c.version })
1523
+ ] }),
1524
+ c.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mt-1 line-clamp-2", children: c.description }),
1525
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex items-center gap-2 text-xs text-muted-foreground", children: [
1526
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: ext }),
1527
+ size && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1528
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
1529
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: size })
1530
+ ] })
1531
+ ] })
1532
+ ] }),
1533
+ /* @__PURE__ */ jsxRuntime.jsxs(
1534
+ "a",
1535
+ {
1536
+ href: c.fileUrl,
1537
+ target: "_blank",
1538
+ rel: "noopener noreferrer",
1539
+ download: true,
1540
+ "aria-label": `Download ${c.title}`,
1541
+ onClick: (e) => {
1542
+ void downloadFile(e, c);
1543
+ },
1544
+ className: "flex-shrink-0 inline-flex items-center gap-1.5 text-sm font-medium text-primary-foreground bg-primary hover:opacity-90 px-4 py-2 rounded-lg transition-opacity",
1545
+ children: [
1546
+ /* @__PURE__ */ jsxRuntime.jsx(
1547
+ "svg",
1548
+ {
1549
+ className: "w-4 h-4",
1550
+ fill: "none",
1551
+ viewBox: "0 0 24 24",
1552
+ stroke: "currentColor",
1553
+ "aria-hidden": "true",
1554
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1555
+ "path",
1556
+ {
1557
+ strokeLinecap: "round",
1558
+ strokeLinejoin: "round",
1559
+ strokeWidth: 2,
1560
+ d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
1561
+ }
1562
+ )
1563
+ }
1564
+ ),
1565
+ "Download"
1566
+ ]
1567
+ }
1568
+ )
1569
+ ]
1570
+ },
1571
+ c.id
1572
+ );
1573
+ }) }) })
1574
+ ] });
1575
+ }
1409
1576
 
1410
1577
  exports.BlogListPage = BlogListPage;
1411
1578
  exports.BlogPostPage = BlogPostPage;
1412
1579
  exports.ContentRenderer = ContentRenderer;
1580
+ exports.ContractsPage = ContractsPage;
1413
1581
  exports.PressKitPage = PressKitPage;
1414
1582
  exports.useContentPage = useContentPage;
1415
1583
  exports.useContentPages = useContentPages;