@burdenoff/website-sdk 2026.518.3 → 2026.520.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/dist/content/index.d.mts +16 -0
- package/dist/content/index.d.ts +16 -0
- package/dist/content/index.js +380 -33
- package/dist/content/index.js.map +1 -1
- package/dist/content/index.mjs +380 -33
- package/dist/content/index.mjs.map +1 -1
- package/dist/index.js +380 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +380 -33
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/content/index.d.mts
CHANGED
|
@@ -106,6 +106,9 @@ interface BlogListPageProps {
|
|
|
106
106
|
interface BlogPostPageProps {
|
|
107
107
|
productName?: string;
|
|
108
108
|
blogListUrl?: string;
|
|
109
|
+
/** Back-link label. Default: "Back to Blog". Use e.g. "Back to Press"
|
|
110
|
+
* when reusing this renderer for a press release at /press/:slug. */
|
|
111
|
+
backLabel?: string;
|
|
109
112
|
className?: string;
|
|
110
113
|
}
|
|
111
114
|
declare function BlogListPage(props: BlogListPageProps): react_jsx_runtime.JSX.Element;
|
|
@@ -140,6 +143,19 @@ interface PressKitPageProps {
|
|
|
140
143
|
seoTitle?: string;
|
|
141
144
|
seoDescription?: string;
|
|
142
145
|
seoKeywords?: string;
|
|
146
|
+
/**
|
|
147
|
+
* Show a "Press Releases" section (published content pages tagged
|
|
148
|
+
* "press") above the downloadable assets. Self-hides when there are
|
|
149
|
+
* none. Default: true.
|
|
150
|
+
*/
|
|
151
|
+
showPressReleases?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Base path for press-release detail links — `${basePath}/${slug}`.
|
|
154
|
+
* Default: "/press".
|
|
155
|
+
*/
|
|
156
|
+
pressReleaseBasePath?: string;
|
|
157
|
+
/** Heading for the press-releases section. Default: "Press Releases". */
|
|
158
|
+
pressReleasesTitle?: string;
|
|
143
159
|
}
|
|
144
160
|
declare function PressKitPage(props: PressKitPageProps): react_jsx_runtime.JSX.Element;
|
|
145
161
|
|
package/dist/content/index.d.ts
CHANGED
|
@@ -106,6 +106,9 @@ interface BlogListPageProps {
|
|
|
106
106
|
interface BlogPostPageProps {
|
|
107
107
|
productName?: string;
|
|
108
108
|
blogListUrl?: string;
|
|
109
|
+
/** Back-link label. Default: "Back to Blog". Use e.g. "Back to Press"
|
|
110
|
+
* when reusing this renderer for a press release at /press/:slug. */
|
|
111
|
+
backLabel?: string;
|
|
109
112
|
className?: string;
|
|
110
113
|
}
|
|
111
114
|
declare function BlogListPage(props: BlogListPageProps): react_jsx_runtime.JSX.Element;
|
|
@@ -140,6 +143,19 @@ interface PressKitPageProps {
|
|
|
140
143
|
seoTitle?: string;
|
|
141
144
|
seoDescription?: string;
|
|
142
145
|
seoKeywords?: string;
|
|
146
|
+
/**
|
|
147
|
+
* Show a "Press Releases" section (published content pages tagged
|
|
148
|
+
* "press") above the downloadable assets. Self-hides when there are
|
|
149
|
+
* none. Default: true.
|
|
150
|
+
*/
|
|
151
|
+
showPressReleases?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Base path for press-release detail links — `${basePath}/${slug}`.
|
|
154
|
+
* Default: "/press".
|
|
155
|
+
*/
|
|
156
|
+
pressReleaseBasePath?: string;
|
|
157
|
+
/** Heading for the press-releases section. Default: "Press Releases". */
|
|
158
|
+
pressReleasesTitle?: string;
|
|
143
159
|
}
|
|
144
160
|
declare function PressKitPage(props: PressKitPageProps): react_jsx_runtime.JSX.Element;
|
|
145
161
|
|
package/dist/content/index.js
CHANGED
|
@@ -482,19 +482,21 @@ function BlogCard({
|
|
|
482
482
|
month: "long",
|
|
483
483
|
day: "numeric"
|
|
484
484
|
}) : "";
|
|
485
|
+
const [imgError, setImgError] = react.useState(false);
|
|
485
486
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
486
487
|
"a",
|
|
487
488
|
{
|
|
488
489
|
href: `${basePath}/${post.slug}`,
|
|
489
490
|
className: "group block bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300",
|
|
490
491
|
children: [
|
|
491
|
-
post.thumbnail ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
492
|
+
post.thumbnail && !imgError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
492
493
|
"img",
|
|
493
494
|
{
|
|
494
495
|
src: post.thumbnail,
|
|
495
496
|
alt: post.title,
|
|
496
497
|
className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300",
|
|
497
|
-
loading: "lazy"
|
|
498
|
+
loading: "lazy",
|
|
499
|
+
onError: () => setImgError(true)
|
|
498
500
|
}
|
|
499
501
|
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
500
502
|
"svg",
|
|
@@ -656,7 +658,12 @@ function BlogListPage(props) {
|
|
|
656
658
|
] });
|
|
657
659
|
}
|
|
658
660
|
function BlogPostPage(props) {
|
|
659
|
-
const {
|
|
661
|
+
const {
|
|
662
|
+
productName,
|
|
663
|
+
blogListUrl = "/blog",
|
|
664
|
+
backLabel = "Back to Blog",
|
|
665
|
+
className = ""
|
|
666
|
+
} = props;
|
|
660
667
|
const client = useWebSDK();
|
|
661
668
|
const config = useWebSDKConfig();
|
|
662
669
|
const { product } = useProduct();
|
|
@@ -700,12 +707,15 @@ function BlogPostPage(props) {
|
|
|
700
707
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24 text-center", children: [
|
|
701
708
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold mb-4", children: "Post not found" }),
|
|
702
709
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mb-6", children: error || "This blog post doesn't exist or has been removed." }),
|
|
703
|
-
/* @__PURE__ */ jsxRuntime.
|
|
710
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
704
711
|
"a",
|
|
705
712
|
{
|
|
706
713
|
href: blogListUrl,
|
|
707
714
|
className: "text-primary hover:underline font-medium",
|
|
708
|
-
children:
|
|
715
|
+
children: [
|
|
716
|
+
"\u2190 ",
|
|
717
|
+
backLabel
|
|
718
|
+
]
|
|
709
719
|
}
|
|
710
720
|
)
|
|
711
721
|
] }) });
|
|
@@ -727,12 +737,15 @@ function BlogPostPage(props) {
|
|
|
727
737
|
}
|
|
728
738
|
),
|
|
729
739
|
/* @__PURE__ */ jsxRuntime.jsxs("article", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20", children: [
|
|
730
|
-
/* @__PURE__ */ jsxRuntime.
|
|
740
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
731
741
|
"a",
|
|
732
742
|
{
|
|
733
743
|
href: blogListUrl,
|
|
734
744
|
className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-8 transition-colors",
|
|
735
|
-
children:
|
|
745
|
+
children: [
|
|
746
|
+
"\u2190 ",
|
|
747
|
+
backLabel
|
|
748
|
+
]
|
|
736
749
|
}
|
|
737
750
|
),
|
|
738
751
|
post.category && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-4", children: post.category }),
|
|
@@ -785,6 +798,29 @@ var PRESS_KIT_QUERY = `
|
|
|
785
798
|
}
|
|
786
799
|
}
|
|
787
800
|
`;
|
|
801
|
+
var PRESS_RELEASES_QUERY = `
|
|
802
|
+
query PublicPressReleases($productId: String!, $limit: Int, $offset: Int) {
|
|
803
|
+
publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
|
|
804
|
+
items {
|
|
805
|
+
id
|
|
806
|
+
title
|
|
807
|
+
slug
|
|
808
|
+
lastUpdated
|
|
809
|
+
tags
|
|
810
|
+
seoDescription
|
|
811
|
+
excerpt
|
|
812
|
+
thumbnail
|
|
813
|
+
author
|
|
814
|
+
publishedAt
|
|
815
|
+
readingTime
|
|
816
|
+
featured
|
|
817
|
+
category
|
|
818
|
+
}
|
|
819
|
+
total
|
|
820
|
+
hasMore
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
`;
|
|
788
824
|
var CATEGORY_ORDER = [
|
|
789
825
|
"LOGO",
|
|
790
826
|
"BANNER",
|
|
@@ -809,7 +845,154 @@ function formatBytes(bytes) {
|
|
|
809
845
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
|
|
810
846
|
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
811
847
|
}
|
|
812
|
-
function
|
|
848
|
+
function isImageAsset(a) {
|
|
849
|
+
return (a.mimeType || "").startsWith("image/");
|
|
850
|
+
}
|
|
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
|
+
function PressKitLightbox({
|
|
875
|
+
asset,
|
|
876
|
+
onClose
|
|
877
|
+
}) {
|
|
878
|
+
react.useEffect(() => {
|
|
879
|
+
if (!asset) return;
|
|
880
|
+
const onKey = (e) => {
|
|
881
|
+
if (e.key === "Escape") onClose();
|
|
882
|
+
};
|
|
883
|
+
document.addEventListener("keydown", onKey);
|
|
884
|
+
const prevOverflow = document.body.style.overflow;
|
|
885
|
+
document.body.style.overflow = "hidden";
|
|
886
|
+
return () => {
|
|
887
|
+
document.removeEventListener("keydown", onKey);
|
|
888
|
+
document.body.style.overflow = prevOverflow;
|
|
889
|
+
};
|
|
890
|
+
}, [asset, onClose]);
|
|
891
|
+
if (!asset) return null;
|
|
892
|
+
const ext = (asset.mimeType || "file").split("/").pop()?.toUpperCase() || "FILE";
|
|
893
|
+
const size = formatBytes(asset.fileSize);
|
|
894
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
895
|
+
"div",
|
|
896
|
+
{
|
|
897
|
+
role: "dialog",
|
|
898
|
+
"aria-modal": "true",
|
|
899
|
+
"aria-label": `${asset.title} preview`,
|
|
900
|
+
onClick: onClose,
|
|
901
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-4 sm:p-8",
|
|
902
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
903
|
+
"div",
|
|
904
|
+
{
|
|
905
|
+
onClick: (e) => e.stopPropagation(),
|
|
906
|
+
className: "relative flex max-h-full w-full max-w-4xl flex-col overflow-hidden rounded-xl border bg-card shadow-2xl",
|
|
907
|
+
children: [
|
|
908
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b p-4", children: [
|
|
909
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
910
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "truncate text-sm font-semibold text-foreground", children: asset.title }),
|
|
911
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
912
|
+
ext,
|
|
913
|
+
size ? ` \xB7 ${size}` : ""
|
|
914
|
+
] })
|
|
915
|
+
] }),
|
|
916
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
917
|
+
"button",
|
|
918
|
+
{
|
|
919
|
+
type: "button",
|
|
920
|
+
onClick: onClose,
|
|
921
|
+
"aria-label": "Close preview",
|
|
922
|
+
className: "shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
923
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
924
|
+
"svg",
|
|
925
|
+
{
|
|
926
|
+
className: "h-5 w-5",
|
|
927
|
+
fill: "none",
|
|
928
|
+
viewBox: "0 0 24 24",
|
|
929
|
+
stroke: "currentColor",
|
|
930
|
+
strokeWidth: 2,
|
|
931
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
932
|
+
"path",
|
|
933
|
+
{
|
|
934
|
+
strokeLinecap: "round",
|
|
935
|
+
strokeLinejoin: "round",
|
|
936
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
937
|
+
}
|
|
938
|
+
)
|
|
939
|
+
}
|
|
940
|
+
)
|
|
941
|
+
}
|
|
942
|
+
)
|
|
943
|
+
] }),
|
|
944
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center justify-center overflow-auto bg-muted/20 p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
945
|
+
"img",
|
|
946
|
+
{
|
|
947
|
+
src: asset.fileUrl,
|
|
948
|
+
alt: asset.title,
|
|
949
|
+
className: "max-h-[70vh] w-auto max-w-full object-contain"
|
|
950
|
+
}
|
|
951
|
+
) }),
|
|
952
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end border-t p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
953
|
+
"a",
|
|
954
|
+
{
|
|
955
|
+
href: asset.fileUrl,
|
|
956
|
+
target: "_blank",
|
|
957
|
+
rel: "noopener noreferrer",
|
|
958
|
+
download: true,
|
|
959
|
+
onClick: (e) => {
|
|
960
|
+
void downloadAsset(e, asset);
|
|
961
|
+
},
|
|
962
|
+
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
|
+
children: [
|
|
964
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
965
|
+
"svg",
|
|
966
|
+
{
|
|
967
|
+
className: "h-4 w-4",
|
|
968
|
+
fill: "none",
|
|
969
|
+
viewBox: "0 0 24 24",
|
|
970
|
+
stroke: "currentColor",
|
|
971
|
+
strokeWidth: 2,
|
|
972
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
973
|
+
"path",
|
|
974
|
+
{
|
|
975
|
+
strokeLinecap: "round",
|
|
976
|
+
strokeLinejoin: "round",
|
|
977
|
+
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
978
|
+
}
|
|
979
|
+
)
|
|
980
|
+
}
|
|
981
|
+
),
|
|
982
|
+
"Download"
|
|
983
|
+
]
|
|
984
|
+
}
|
|
985
|
+
) })
|
|
986
|
+
]
|
|
987
|
+
}
|
|
988
|
+
)
|
|
989
|
+
}
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
function AssetCard({
|
|
993
|
+
asset,
|
|
994
|
+
onPreview
|
|
995
|
+
}) {
|
|
813
996
|
const date = asset.updatedAt ? new Date(asset.updatedAt).toLocaleDateString("en-US", {
|
|
814
997
|
year: "numeric",
|
|
815
998
|
month: "short",
|
|
@@ -817,33 +1000,55 @@ function AssetCard({ asset }) {
|
|
|
817
1000
|
}) : "";
|
|
818
1001
|
const ext = (asset.mimeType || "file").split("/").pop()?.toUpperCase() || "FILE";
|
|
819
1002
|
const size = formatBytes(asset.fileSize);
|
|
1003
|
+
const [imgError, setImgError] = react.useState(false);
|
|
1004
|
+
const thumb = asset.thumbnailUrl && !imgError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] overflow-hidden bg-muted/30", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1005
|
+
"img",
|
|
1006
|
+
{
|
|
1007
|
+
src: asset.thumbnailUrl,
|
|
1008
|
+
alt: asset.title,
|
|
1009
|
+
className: "w-full h-full object-contain group-hover:scale-105 transition-transform duration-300",
|
|
1010
|
+
loading: "lazy",
|
|
1011
|
+
onError: () => setImgError(true)
|
|
1012
|
+
}
|
|
1013
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1014
|
+
"svg",
|
|
1015
|
+
{
|
|
1016
|
+
className: "w-12 h-12 text-muted-foreground/20",
|
|
1017
|
+
fill: "none",
|
|
1018
|
+
viewBox: "0 0 24 24",
|
|
1019
|
+
stroke: "currentColor",
|
|
1020
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1021
|
+
"path",
|
|
1022
|
+
{
|
|
1023
|
+
strokeLinecap: "round",
|
|
1024
|
+
strokeLinejoin: "round",
|
|
1025
|
+
strokeWidth: 1.5,
|
|
1026
|
+
d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"
|
|
1027
|
+
}
|
|
1028
|
+
)
|
|
1029
|
+
}
|
|
1030
|
+
) });
|
|
820
1031
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group flex flex-col bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300", children: [
|
|
821
|
-
|
|
822
|
-
"
|
|
1032
|
+
onPreview && isImageAsset(asset) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1033
|
+
"button",
|
|
823
1034
|
{
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1035
|
+
type: "button",
|
|
1036
|
+
onClick: () => onPreview(asset),
|
|
1037
|
+
"aria-label": `Preview ${asset.title}`,
|
|
1038
|
+
className: "block w-full text-left cursor-zoom-in",
|
|
1039
|
+
children: thumb
|
|
828
1040
|
}
|
|
829
|
-
)
|
|
830
|
-
"
|
|
1041
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1042
|
+
"a",
|
|
831
1043
|
{
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
{
|
|
839
|
-
strokeLinecap: "round",
|
|
840
|
-
strokeLinejoin: "round",
|
|
841
|
-
strokeWidth: 1.5,
|
|
842
|
-
d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"
|
|
843
|
-
}
|
|
844
|
-
)
|
|
1044
|
+
href: asset.fileUrl,
|
|
1045
|
+
target: "_blank",
|
|
1046
|
+
rel: "noopener noreferrer",
|
|
1047
|
+
"aria-label": `Open ${asset.title}`,
|
|
1048
|
+
className: "block",
|
|
1049
|
+
children: thumb
|
|
845
1050
|
}
|
|
846
|
-
)
|
|
1051
|
+
),
|
|
847
1052
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col flex-1 p-5", children: [
|
|
848
1053
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block self-start text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-3", children: CATEGORY_LABELS[asset.category] ?? asset.category }),
|
|
849
1054
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-foreground mb-1 line-clamp-2", children: asset.title }),
|
|
@@ -867,6 +1072,9 @@ function AssetCard({ asset }) {
|
|
|
867
1072
|
target: "_blank",
|
|
868
1073
|
rel: "noopener noreferrer",
|
|
869
1074
|
download: true,
|
|
1075
|
+
onClick: (e) => {
|
|
1076
|
+
void downloadAsset(e, asset);
|
|
1077
|
+
},
|
|
870
1078
|
className: "inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline",
|
|
871
1079
|
children: [
|
|
872
1080
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -895,6 +1103,71 @@ function AssetCard({ asset }) {
|
|
|
895
1103
|
] })
|
|
896
1104
|
] });
|
|
897
1105
|
}
|
|
1106
|
+
function PressReleaseCard({
|
|
1107
|
+
release,
|
|
1108
|
+
basePath
|
|
1109
|
+
}) {
|
|
1110
|
+
const date = release.publishedAt || release.lastUpdated;
|
|
1111
|
+
const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
|
|
1112
|
+
year: "numeric",
|
|
1113
|
+
month: "long",
|
|
1114
|
+
day: "numeric"
|
|
1115
|
+
}) : "";
|
|
1116
|
+
const [imgError, setImgError] = react.useState(false);
|
|
1117
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1118
|
+
"a",
|
|
1119
|
+
{
|
|
1120
|
+
href: `${basePath}/${release.slug}`,
|
|
1121
|
+
className: "group flex flex-col bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300",
|
|
1122
|
+
children: [
|
|
1123
|
+
release.thumbnail && !imgError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] overflow-hidden bg-muted/30", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1124
|
+
"img",
|
|
1125
|
+
{
|
|
1126
|
+
src: release.thumbnail,
|
|
1127
|
+
alt: release.title,
|
|
1128
|
+
className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300",
|
|
1129
|
+
loading: "lazy",
|
|
1130
|
+
onError: () => setImgError(true)
|
|
1131
|
+
}
|
|
1132
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1133
|
+
"svg",
|
|
1134
|
+
{
|
|
1135
|
+
className: "w-12 h-12 text-muted-foreground/20",
|
|
1136
|
+
fill: "none",
|
|
1137
|
+
viewBox: "0 0 24 24",
|
|
1138
|
+
stroke: "currentColor",
|
|
1139
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1140
|
+
"path",
|
|
1141
|
+
{
|
|
1142
|
+
strokeLinecap: "round",
|
|
1143
|
+
strokeLinejoin: "round",
|
|
1144
|
+
strokeWidth: 1.5,
|
|
1145
|
+
d: "M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m-1 13a2 2 0 01-2-2V7m3 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"
|
|
1146
|
+
}
|
|
1147
|
+
)
|
|
1148
|
+
}
|
|
1149
|
+
) }),
|
|
1150
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col flex-1 p-5 sm:p-6", children: [
|
|
1151
|
+
release.category && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block self-start text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-3", children: release.category }),
|
|
1152
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-foreground mb-2 group-hover:text-primary transition-colors line-clamp-2", children: release.title }),
|
|
1153
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-4 line-clamp-3", children: release.excerpt || release.seoDescription || "" }),
|
|
1154
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
1155
|
+
release.author && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: release.author }),
|
|
1156
|
+
release.author && formattedDate && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
1157
|
+
formattedDate && /* @__PURE__ */ jsxRuntime.jsx("span", { children: formattedDate }),
|
|
1158
|
+
release.readingTime ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1159
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
1160
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1161
|
+
release.readingTime,
|
|
1162
|
+
" min read"
|
|
1163
|
+
] })
|
|
1164
|
+
] }) : null
|
|
1165
|
+
] })
|
|
1166
|
+
] })
|
|
1167
|
+
]
|
|
1168
|
+
}
|
|
1169
|
+
);
|
|
1170
|
+
}
|
|
898
1171
|
function PressKitPage(props) {
|
|
899
1172
|
const {
|
|
900
1173
|
productName,
|
|
@@ -905,7 +1178,10 @@ function PressKitPage(props) {
|
|
|
905
1178
|
className = "",
|
|
906
1179
|
seoTitle,
|
|
907
1180
|
seoDescription,
|
|
908
|
-
seoKeywords
|
|
1181
|
+
seoKeywords,
|
|
1182
|
+
showPressReleases = true,
|
|
1183
|
+
pressReleaseBasePath = "/press",
|
|
1184
|
+
pressReleasesTitle = "Press Releases"
|
|
909
1185
|
} = props;
|
|
910
1186
|
const client = useWebSDK();
|
|
911
1187
|
const config = useWebSDKConfig();
|
|
@@ -916,6 +1192,9 @@ function PressKitPage(props) {
|
|
|
916
1192
|
const [loading, setLoading] = react.useState(true);
|
|
917
1193
|
const [error, setError] = react.useState(null);
|
|
918
1194
|
const [activeCategory, setActiveCategory] = react.useState("ALL");
|
|
1195
|
+
const [releases, setReleases] = react.useState([]);
|
|
1196
|
+
const [releasesLoading, setReleasesLoading] = react.useState(true);
|
|
1197
|
+
const [preview, setPreview] = react.useState(null);
|
|
919
1198
|
const fetchAssets = react.useCallback(async () => {
|
|
920
1199
|
if (!resolvedProductId) {
|
|
921
1200
|
setLoading(false);
|
|
@@ -953,6 +1232,48 @@ function PressKitPage(props) {
|
|
|
953
1232
|
react.useEffect(() => {
|
|
954
1233
|
fetchAssets();
|
|
955
1234
|
}, [fetchAssets]);
|
|
1235
|
+
const fetchReleases = react.useCallback(async () => {
|
|
1236
|
+
if (!resolvedProductId || !showPressReleases) {
|
|
1237
|
+
setReleasesLoading(false);
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
setReleasesLoading(true);
|
|
1241
|
+
try {
|
|
1242
|
+
const PAGE_SIZE = 100;
|
|
1243
|
+
const MAX_PAGES = 10;
|
|
1244
|
+
const all = [];
|
|
1245
|
+
let offset = 0;
|
|
1246
|
+
for (let pageNum = 0; pageNum < MAX_PAGES; pageNum++) {
|
|
1247
|
+
const result = await client.query(PRESS_RELEASES_QUERY, {
|
|
1248
|
+
productId: resolvedProductId,
|
|
1249
|
+
limit: PAGE_SIZE,
|
|
1250
|
+
offset
|
|
1251
|
+
});
|
|
1252
|
+
if (result.errors?.length) {
|
|
1253
|
+
setReleases([]);
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
const page = result.data?.publicContentPages;
|
|
1257
|
+
const items = page?.items || [];
|
|
1258
|
+
all.push(...items);
|
|
1259
|
+
if (!page?.hasMore || items.length === 0) break;
|
|
1260
|
+
offset += PAGE_SIZE;
|
|
1261
|
+
}
|
|
1262
|
+
const pressOnly = all.filter((p) => p.tags?.includes("press")).sort((a, b) => {
|
|
1263
|
+
const da = new Date(a.publishedAt || a.lastUpdated || 0).getTime();
|
|
1264
|
+
const db = new Date(b.publishedAt || b.lastUpdated || 0).getTime();
|
|
1265
|
+
return db - da;
|
|
1266
|
+
});
|
|
1267
|
+
setReleases(pressOnly);
|
|
1268
|
+
} catch {
|
|
1269
|
+
setReleases([]);
|
|
1270
|
+
} finally {
|
|
1271
|
+
setReleasesLoading(false);
|
|
1272
|
+
}
|
|
1273
|
+
}, [client, resolvedProductId, showPressReleases]);
|
|
1274
|
+
react.useEffect(() => {
|
|
1275
|
+
fetchReleases();
|
|
1276
|
+
}, [fetchReleases]);
|
|
956
1277
|
const presentCategories = CATEGORY_ORDER.filter(
|
|
957
1278
|
(c) => assets.some((a) => a.category === c)
|
|
958
1279
|
);
|
|
@@ -995,6 +1316,31 @@ function PressKitPage(props) {
|
|
|
995
1316
|
)
|
|
996
1317
|
] })
|
|
997
1318
|
] }) }) }),
|
|
1319
|
+
showPressReleases && (releasesLoading || releases.length > 0) && /* @__PURE__ */ jsxRuntime.jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
|
|
1320
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-foreground mb-6", children: pressReleasesTitle }),
|
|
1321
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: releasesLoading ? [1, 2, 3].map((i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1322
|
+
"div",
|
|
1323
|
+
{
|
|
1324
|
+
className: "bg-card border rounded-xl overflow-hidden animate-pulse",
|
|
1325
|
+
children: [
|
|
1326
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] bg-muted" }),
|
|
1327
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-5 space-y-3", children: [
|
|
1328
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
|
|
1329
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-5 bg-muted rounded w-3/4" }),
|
|
1330
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
|
|
1331
|
+
] })
|
|
1332
|
+
]
|
|
1333
|
+
},
|
|
1334
|
+
i
|
|
1335
|
+
)) : releases.map((r) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1336
|
+
PressReleaseCard,
|
|
1337
|
+
{
|
|
1338
|
+
release: r,
|
|
1339
|
+
basePath: pressReleaseBasePath
|
|
1340
|
+
},
|
|
1341
|
+
r.id
|
|
1342
|
+
)) })
|
|
1343
|
+
] }) }),
|
|
998
1344
|
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: [1, 2, 3, 4, 5, 6].map((i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
999
1345
|
"div",
|
|
1000
1346
|
{
|
|
@@ -1039,7 +1385,7 @@ function PressKitPage(props) {
|
|
|
1039
1385
|
}) }),
|
|
1040
1386
|
grouped.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-12", children: [
|
|
1041
1387
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-foreground mb-5", children: CATEGORY_LABELS[group.cat] ?? group.cat }),
|
|
1042
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: group.items.map((a) => /* @__PURE__ */ jsxRuntime.jsx(AssetCard, { asset: a }, a.id)) })
|
|
1388
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: group.items.map((a) => /* @__PURE__ */ jsxRuntime.jsx(AssetCard, { asset: a, onPreview: setPreview }, a.id)) })
|
|
1043
1389
|
] }, group.cat)),
|
|
1044
1390
|
contactEmail && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-8 border-t pt-10 text-center", children: [
|
|
1045
1391
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-foreground mb-2", children: "Media Contact" }),
|
|
@@ -1056,7 +1402,8 @@ function PressKitPage(props) {
|
|
|
1056
1402
|
)
|
|
1057
1403
|
] })
|
|
1058
1404
|
] })
|
|
1059
|
-
] }) }) })
|
|
1405
|
+
] }) }) }),
|
|
1406
|
+
/* @__PURE__ */ jsxRuntime.jsx(PressKitLightbox, { asset: preview, onClose: () => setPreview(null) })
|
|
1060
1407
|
] });
|
|
1061
1408
|
}
|
|
1062
1409
|
|