@burdenoff/website-sdk 0.0.0-dev → 2026.510.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/analytics/index.js +0 -1
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +0 -1
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/client/index.d.mts +2 -5
- package/dist/client/index.d.ts +2 -5
- package/dist/client/index.js +2 -11
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +2 -11
- package/dist/client/index.mjs.map +1 -1
- package/dist/components/contact.d.mts +2 -77
- package/dist/components/contact.d.ts +2 -77
- package/dist/components/contact.js +9 -112
- package/dist/components/contact.js.map +1 -1
- package/dist/components/contact.mjs +10 -112
- package/dist/components/contact.mjs.map +1 -1
- package/dist/components/newsletter.js +6 -17
- package/dist/components/newsletter.js.map +1 -1
- package/dist/components/newsletter.mjs +6 -17
- package/dist/components/newsletter.mjs.map +1 -1
- package/dist/components/pricing.d.mts +0 -38
- package/dist/components/pricing.d.ts +0 -38
- package/dist/components/pricing.js +84 -267
- package/dist/components/pricing.js.map +1 -1
- package/dist/components/pricing.mjs +84 -267
- package/dist/components/pricing.mjs.map +1 -1
- package/dist/components/waitlist.js +2 -6
- package/dist/components/waitlist.js.map +1 -1
- package/dist/components/waitlist.mjs +2 -6
- package/dist/components/waitlist.mjs.map +1 -1
- package/dist/content/index.d.mts +9 -181
- package/dist/content/index.d.ts +9 -181
- package/dist/content/index.js +16 -2177
- package/dist/content/index.js.map +1 -1
- package/dist/content/index.mjs +6 -2141
- package/dist/content/index.mjs.map +1 -1
- package/dist/index.d.mts +4 -42
- package/dist/index.d.ts +4 -42
- package/dist/index.js +373 -3919
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +378 -3905
- package/dist/index.mjs.map +1 -1
- package/dist/product/index.d.mts +0 -8
- package/dist/product/index.d.ts +0 -8
- package/dist/product/index.js +4 -24
- package/dist/product/index.js.map +1 -1
- package/dist/product/index.mjs +4 -24
- package/dist/product/index.mjs.map +1 -1
- package/package.json +3 -5
- package/dist/components/electron-download.d.mts +0 -32
- package/dist/components/electron-download.d.ts +0 -32
- package/dist/components/electron-download.js +0 -131
- package/dist/components/electron-download.js.map +0 -1
- package/dist/components/electron-download.mjs +0 -108
- package/dist/components/electron-download.mjs.map +0 -1
- package/dist/components/launch-countdown.d.mts +0 -15
- package/dist/components/launch-countdown.d.ts +0 -15
- package/dist/components/launch-countdown.js +0 -89
- package/dist/components/launch-countdown.js.map +0 -1
- package/dist/components/launch-countdown.mjs +0 -87
- package/dist/components/launch-countdown.mjs.map +0 -1
- package/dist/components/partners.d.mts +0 -88
- package/dist/components/partners.d.ts +0 -88
- package/dist/components/partners.js +0 -1169
- package/dist/components/partners.js.map +0 -1
- package/dist/components/partners.mjs +0 -1143
- package/dist/components/partners.mjs.map +0 -1
- package/dist/components/problems-solved.d.mts +0 -37
- package/dist/components/problems-solved.d.ts +0 -37
- package/dist/components/problems-solved.js +0 -157
- package/dist/components/problems-solved.js.map +0 -1
- package/dist/components/problems-solved.mjs +0 -135
- package/dist/components/problems-solved.mjs.map +0 -1
- package/dist/components/resource-links.d.mts +0 -28
- package/dist/components/resource-links.d.ts +0 -28
- package/dist/components/resource-links.js +0 -229
- package/dist/components/resource-links.js.map +0 -1
- package/dist/components/resource-links.mjs +0 -227
- package/dist/components/resource-links.mjs.map +0 -1
- package/dist/components/social-links.d.mts +0 -37
- package/dist/components/social-links.d.ts +0 -37
- package/dist/components/social-links.js +0 -268
- package/dist/components/social-links.js.map +0 -1
- package/dist/components/social-links.mjs +0 -266
- package/dist/components/social-links.mjs.map +0 -1
- package/dist/components/website-switcher.d.mts +0 -27
- package/dist/components/website-switcher.d.ts +0 -27
- package/dist/components/website-switcher.js +0 -168
- package/dist/components/website-switcher.js.map +0 -1
- package/dist/components/website-switcher.mjs +0 -146
- package/dist/components/website-switcher.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { createContext, useMemo, useContext, useState, useCallback, useLayoutEffect,
|
|
2
|
+
import { createContext, useMemo, useContext, useRef, useState, useCallback, useLayoutEffect, useEffect } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
4
|
+
import { Mail, Phone, MapPin, Clock, Send } from 'lucide-react';
|
|
5
|
+
import ReCAPTCHA2 from 'react-google-recaptcha';
|
|
6
6
|
import { toast } from 'sonner';
|
|
7
7
|
import { Helmet } from 'react-helmet-async';
|
|
8
8
|
import { Slot } from '@radix-ui/react-slot';
|
|
@@ -13,7 +13,6 @@ import * as LabelPrimitive from '@radix-ui/react-label';
|
|
|
13
13
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
14
14
|
import { useForm } from 'react-hook-form';
|
|
15
15
|
import { z } from 'zod';
|
|
16
|
-
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
|
17
16
|
|
|
18
17
|
var __defProp = Object.defineProperty;
|
|
19
18
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -168,7 +167,6 @@ function getLocalFallback() {
|
|
|
168
167
|
}
|
|
169
168
|
var PRODUCT_DOMAINS = [
|
|
170
169
|
"burdenoff.com",
|
|
171
|
-
"algoshred.com",
|
|
172
170
|
"vibecontrols.com",
|
|
173
171
|
"fluidgrids.com",
|
|
174
172
|
"botlit.ai",
|
|
@@ -213,25 +211,17 @@ function isAlphaHost(hostname) {
|
|
|
213
211
|
);
|
|
214
212
|
}
|
|
215
213
|
function resolveGatewayUrl(explicitUrl) {
|
|
216
|
-
if (explicitUrl &&
|
|
214
|
+
if (explicitUrl && !isLocalhostUrl(explicitUrl)) {
|
|
217
215
|
return explicitUrl;
|
|
218
216
|
}
|
|
219
217
|
if (typeof window === "undefined") {
|
|
220
|
-
return explicitUrl
|
|
218
|
+
return explicitUrl || getLocalFallback();
|
|
221
219
|
}
|
|
222
220
|
const hostname = window.location.hostname.toLowerCase();
|
|
223
221
|
if (isProductionHost(hostname)) return PROD_GATEWAY;
|
|
224
222
|
if (isAlphaHost(hostname)) return ALPHA_GATEWAY;
|
|
225
223
|
return getLocalFallback();
|
|
226
224
|
}
|
|
227
|
-
function isAbsoluteUrl(url) {
|
|
228
|
-
try {
|
|
229
|
-
new URL(url);
|
|
230
|
-
return true;
|
|
231
|
-
} catch {
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
225
|
function isLocalhostUrl(url) {
|
|
236
226
|
try {
|
|
237
227
|
const parsed = new URL(url);
|
|
@@ -263,125 +253,6 @@ function useWebSDKConfig() {
|
|
|
263
253
|
const client = useWebSDK();
|
|
264
254
|
return client.getConfig();
|
|
265
255
|
}
|
|
266
|
-
var PRODUCT_FIELDS_BASE = `
|
|
267
|
-
id
|
|
268
|
-
name
|
|
269
|
-
slug
|
|
270
|
-
description
|
|
271
|
-
status
|
|
272
|
-
logoUrl
|
|
273
|
-
website
|
|
274
|
-
appUrl
|
|
275
|
-
docsUrl
|
|
276
|
-
contactEmail
|
|
277
|
-
supportEmail
|
|
278
|
-
contactPhone
|
|
279
|
-
contactAddress
|
|
280
|
-
seoTitle
|
|
281
|
-
seoDescription
|
|
282
|
-
seoKeywords
|
|
283
|
-
ogImage
|
|
284
|
-
socialLinks
|
|
285
|
-
recaptchaSiteKey
|
|
286
|
-
rybbitSiteId
|
|
287
|
-
notificationEmail
|
|
288
|
-
metadata
|
|
289
|
-
`;
|
|
290
|
-
var PUBLIC_PRODUCT_QUERY = `
|
|
291
|
-
query PublicProduct($slug: String!) {
|
|
292
|
-
publicProduct(slug: $slug) {
|
|
293
|
-
${PRODUCT_FIELDS_BASE}
|
|
294
|
-
resourceLinks
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
`;
|
|
298
|
-
var PUBLIC_PRODUCT_QUERY_FALLBACK = `
|
|
299
|
-
query PublicProductFallback($slug: String!) {
|
|
300
|
-
publicProduct(slug: $slug) {
|
|
301
|
-
${PRODUCT_FIELDS_BASE}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
`;
|
|
305
|
-
var ProductContext = createContext({
|
|
306
|
-
product: null,
|
|
307
|
-
loading: true,
|
|
308
|
-
error: null,
|
|
309
|
-
hasProvider: false,
|
|
310
|
-
refetch: () => {
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
function ProductProvider({ children, fallback }) {
|
|
314
|
-
const client = useWebSDK();
|
|
315
|
-
const config = useWebSDKConfig();
|
|
316
|
-
const [product, setProduct] = useState(
|
|
317
|
-
fallback ? fallback : null
|
|
318
|
-
);
|
|
319
|
-
const [loading, setLoading] = useState(true);
|
|
320
|
-
const [error, setError] = useState(null);
|
|
321
|
-
const fetchProduct = useCallback(async () => {
|
|
322
|
-
if (!config.productSlug) {
|
|
323
|
-
setLoading(false);
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
setLoading(true);
|
|
327
|
-
setError(null);
|
|
328
|
-
try {
|
|
329
|
-
let result = await client.query(
|
|
330
|
-
PUBLIC_PRODUCT_QUERY,
|
|
331
|
-
{ slug: config.productSlug }
|
|
332
|
-
);
|
|
333
|
-
const schemaMissingResourceLinks = result.errors?.some(
|
|
334
|
-
(e) => /Cannot query field ["']?resourceLinks["']?/i.test(e?.message ?? "")
|
|
335
|
-
);
|
|
336
|
-
if (schemaMissingResourceLinks) {
|
|
337
|
-
result = await client.query(
|
|
338
|
-
PUBLIC_PRODUCT_QUERY_FALLBACK,
|
|
339
|
-
{ slug: config.productSlug }
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
if (result.errors?.length) {
|
|
343
|
-
setError(result.errors[0]?.message ?? "Unknown error");
|
|
344
|
-
} else if (result.data?.publicProduct) {
|
|
345
|
-
setProduct(result.data.publicProduct);
|
|
346
|
-
}
|
|
347
|
-
} catch (err) {
|
|
348
|
-
setError(err instanceof Error ? err.message : "Failed to fetch product");
|
|
349
|
-
} finally {
|
|
350
|
-
setLoading(false);
|
|
351
|
-
}
|
|
352
|
-
}, [client, config.productSlug]);
|
|
353
|
-
useLayoutEffect(() => {
|
|
354
|
-
fetchProduct();
|
|
355
|
-
}, [fetchProduct]);
|
|
356
|
-
const value = useMemo(
|
|
357
|
-
() => ({
|
|
358
|
-
product,
|
|
359
|
-
loading,
|
|
360
|
-
error,
|
|
361
|
-
hasProvider: true,
|
|
362
|
-
refetch: fetchProduct
|
|
363
|
-
}),
|
|
364
|
-
[product, loading, error, fetchProduct]
|
|
365
|
-
);
|
|
366
|
-
return /* @__PURE__ */ jsx(ProductContext.Provider, { value, children });
|
|
367
|
-
}
|
|
368
|
-
function useProduct() {
|
|
369
|
-
return useContext(ProductContext);
|
|
370
|
-
}
|
|
371
|
-
function useProductConfig() {
|
|
372
|
-
const { product } = useProduct();
|
|
373
|
-
const config = useWebSDKConfig();
|
|
374
|
-
return {
|
|
375
|
-
// Prefer product-level config, fall back to SDK config
|
|
376
|
-
recaptchaSiteKey: product?.recaptchaSiteKey ?? config.recaptchaSiteKey ?? null,
|
|
377
|
-
rybbitSiteId: product?.rybbitSiteId ?? config.rybbitSiteId ?? null,
|
|
378
|
-
contactEmail: product?.contactEmail ?? null,
|
|
379
|
-
supportEmail: product?.supportEmail ?? null,
|
|
380
|
-
notificationEmail: product?.notificationEmail ?? product?.contactEmail ?? null,
|
|
381
|
-
productName: product?.name ?? null,
|
|
382
|
-
logoUrl: product?.logoUrl ?? null
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
256
|
function PageHead({
|
|
386
257
|
title,
|
|
387
258
|
description,
|
|
@@ -505,28 +376,6 @@ var Label = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ j
|
|
|
505
376
|
}
|
|
506
377
|
));
|
|
507
378
|
Label.displayName = LabelPrimitive.Root.displayName;
|
|
508
|
-
var Select = React.forwardRef(({ className, children, ...props }, ref) => {
|
|
509
|
-
return /* @__PURE__ */ jsx(
|
|
510
|
-
"select",
|
|
511
|
-
{
|
|
512
|
-
className: cn(
|
|
513
|
-
"flex h-9 w-full appearance-none rounded-md border border-input bg-transparent bg-[length:1rem_1rem] bg-[right_0.75rem_center] bg-no-repeat px-3 py-1 pr-8 text-base shadow-sm transition-colors 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",
|
|
514
|
-
// Inline SVG chevron: SVG inside a `background-image: url(data:…)`
|
|
515
|
-
// does NOT inherit `currentColor` from the host element (the SVG is
|
|
516
|
-
// its own document with no parent CSS context), so the stroke is
|
|
517
|
-
// hardcoded to a muted slate-400 (#94a3b8). Matches the muted
|
|
518
|
-
// foreground token visually in both light and dark themes well
|
|
519
|
-
// enough for a passive chevron — addresses #9 review feedback.
|
|
520
|
-
`bg-[url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>")]`,
|
|
521
|
-
className
|
|
522
|
-
),
|
|
523
|
-
ref,
|
|
524
|
-
...props,
|
|
525
|
-
children
|
|
526
|
-
}
|
|
527
|
-
);
|
|
528
|
-
});
|
|
529
|
-
Select.displayName = "Select";
|
|
530
379
|
var Textarea = React.forwardRef(({ className, ...props }, ref) => {
|
|
531
380
|
return /* @__PURE__ */ jsx(
|
|
532
381
|
"textarea",
|
|
@@ -541,15 +390,6 @@ var Textarea = React.forwardRef(({ className, ...props }, ref) => {
|
|
|
541
390
|
);
|
|
542
391
|
});
|
|
543
392
|
Textarea.displayName = "Textarea";
|
|
544
|
-
var DEFAULT_CONTACT_CATEGORIES = [
|
|
545
|
-
{ value: "general", label: "General enquiry" },
|
|
546
|
-
{ value: "sales", label: "Sales" },
|
|
547
|
-
{ value: "support", label: "Support" },
|
|
548
|
-
{ value: "partnership", label: "Partnership" },
|
|
549
|
-
{ value: "press", label: "Press / media" },
|
|
550
|
-
{ value: "careers", label: "Careers" },
|
|
551
|
-
{ value: "security", label: "Security disclosure" }
|
|
552
|
-
];
|
|
553
393
|
var SUBMIT_CONTACT_INQUIRY_MUTATION = (
|
|
554
394
|
/* GraphQL */
|
|
555
395
|
`
|
|
@@ -571,12 +411,6 @@ async function submitContactForm(client, data, productId) {
|
|
|
571
411
|
subject: data.subject,
|
|
572
412
|
message: data.message,
|
|
573
413
|
productId,
|
|
574
|
-
// Send `category` only when the user actually picked one. Older
|
|
575
|
-
// backend deployments without the `category` field in the
|
|
576
|
-
// `SubmitContactInquiryInput` schema would reject any unknown
|
|
577
|
-
// field; spreading conditionally keeps the SDK forward-
|
|
578
|
-
// compatible.
|
|
579
|
-
...data.category ? { category: data.category } : {},
|
|
580
414
|
...data.recaptchaToken ? { recaptchaToken: data.recaptchaToken } : {}
|
|
581
415
|
}
|
|
582
416
|
});
|
|
@@ -615,17 +449,6 @@ function ContactPage({
|
|
|
615
449
|
responseTime = "We typically respond within 24 hours",
|
|
616
450
|
heroTitle = "Get in Touch",
|
|
617
451
|
heroDescription = "Have questions about {productName}? We're here to help. Reach out to our team and we'll get back to you as soon as possible.",
|
|
618
|
-
headingLevel = 1,
|
|
619
|
-
// Backward-compatibility: default to `[]` so existing consumers
|
|
620
|
-
// (fluidgrids/burdenoff/algoshred websites) that don't pass
|
|
621
|
-
// `categories` continue to render with NO dropdown — same behavior
|
|
622
|
-
// they had before this SDK version. To opt in, pass an explicit
|
|
623
|
-
// `categories={…}` array (or the exported `DEFAULT_CONTACT_CATEGORIES`
|
|
624
|
-
// constant for the sane Burdenoff-generic vocabulary).
|
|
625
|
-
categories = [],
|
|
626
|
-
categoryLabel = "Category",
|
|
627
|
-
categoryPlaceholder = "Select a category",
|
|
628
|
-
categoryRequired = true,
|
|
629
452
|
additionalOptions = [
|
|
630
453
|
{
|
|
631
454
|
title: "Sales Inquiries",
|
|
@@ -650,10 +473,8 @@ function ContactPage({
|
|
|
650
473
|
}) {
|
|
651
474
|
const client = useWebSDK();
|
|
652
475
|
const config = useWebSDKConfig();
|
|
653
|
-
const
|
|
654
|
-
const
|
|
655
|
-
const displayName = productName ?? product?.name ?? config.productId;
|
|
656
|
-
const effectiveRecaptchaSiteKey = recaptchaSiteKey ?? product?.recaptchaSiteKey ?? config.recaptchaSiteKey ?? "";
|
|
476
|
+
const displayName = productName ?? config.productId;
|
|
477
|
+
const effectiveRecaptchaSiteKey = recaptchaSiteKey ?? config.recaptchaSiteKey ?? "";
|
|
657
478
|
const recaptchaRef = useRef(null);
|
|
658
479
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
659
480
|
const [submitStatus, setSubmitStatus] = useState("idle");
|
|
@@ -669,19 +490,11 @@ function ContactPage({
|
|
|
669
490
|
const form = e.currentTarget;
|
|
670
491
|
try {
|
|
671
492
|
const formData = new FormData(form);
|
|
672
|
-
const showCategory = categories.length > 0;
|
|
673
|
-
const rawCategory = showCategory ? (formData.get("category") ?? "").trim() : "";
|
|
674
|
-
if (showCategory && categoryRequired && !rawCategory) {
|
|
675
|
-
toast.error("Please select a category");
|
|
676
|
-
setIsSubmitting(false);
|
|
677
|
-
return;
|
|
678
|
-
}
|
|
679
493
|
const contactData = {
|
|
680
494
|
firstName: formData.get("firstName"),
|
|
681
495
|
lastName: formData.get("lastName"),
|
|
682
496
|
email: formData.get("email"),
|
|
683
497
|
company: formData.get("company"),
|
|
684
|
-
category: rawCategory || void 0,
|
|
685
498
|
subject: formData.get("subject"),
|
|
686
499
|
message: formData.get("message"),
|
|
687
500
|
recaptchaToken
|
|
@@ -689,7 +502,7 @@ function ContactPage({
|
|
|
689
502
|
const result = await submitContactForm(
|
|
690
503
|
client,
|
|
691
504
|
contactData,
|
|
692
|
-
|
|
505
|
+
config.productId
|
|
693
506
|
);
|
|
694
507
|
if (result.success) {
|
|
695
508
|
setSubmitStatus("success");
|
|
@@ -728,16 +541,10 @@ function ContactPage({
|
|
|
728
541
|
url: seo.url
|
|
729
542
|
}
|
|
730
543
|
),
|
|
731
|
-
/* @__PURE__ */ jsx(
|
|
732
|
-
"
|
|
733
|
-
{
|
|
734
|
-
|
|
735
|
-
children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-3xl mx-auto", children: [
|
|
736
|
-
headingLevel === 2 ? /* @__PURE__ */ jsx("h2", { className: "text-2xl md:text-3xl font-bold mb-3", children: heroTitle }) : /* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6", children: heroTitle }),
|
|
737
|
-
/* @__PURE__ */ jsx("p", { className: "text-lg sm:text-xl text-muted-foreground leading-relaxed", children: replacePlaceholders(heroDescription, displayName, contactEmail) })
|
|
738
|
-
] }) })
|
|
739
|
-
}
|
|
740
|
-
),
|
|
544
|
+
/* @__PURE__ */ jsx("section", { className: "bg-gradient-to-b from-background to-muted/20 py-12 sm:py-16 md:py-20 lg:py-24", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-3xl mx-auto", children: [
|
|
545
|
+
/* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6", children: heroTitle }),
|
|
546
|
+
/* @__PURE__ */ jsx("p", { className: "text-lg sm:text-xl text-muted-foreground leading-relaxed", children: replacePlaceholders(heroDescription, displayName, contactEmail) })
|
|
547
|
+
] }) }) }),
|
|
741
548
|
/* @__PURE__ */ jsx("section", { className: "py-12 sm:py-16 md:py-20 lg:py-24", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "grid sm:grid-cols-1 lg:grid-cols-3 gap-8 sm:gap-10 lg:gap-12", children: [
|
|
742
549
|
/* @__PURE__ */ jsxs("div", { className: "lg:col-span-1 order-2 lg:order-1", children: [
|
|
743
550
|
/* @__PURE__ */ jsx("h2", { className: "text-xl sm:text-2xl font-bold mb-4 sm:mb-6", children: "Contact Information" }),
|
|
@@ -749,7 +556,7 @@ function ContactPage({
|
|
|
749
556
|
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm sm:text-base break-all", children: contactEmail })
|
|
750
557
|
] })
|
|
751
558
|
] }),
|
|
752
|
-
|
|
559
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-3 sm:space-x-4", children: [
|
|
753
560
|
/* @__PURE__ */ jsx("div", { className: "w-8 h-8 sm:w-10 sm:h-10 bg-primary/10 rounded-lg flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx(Phone, { className: "h-4 w-4 sm:h-5 sm:w-5 text-primary" }) }),
|
|
754
561
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
755
562
|
/* @__PURE__ */ jsx("h3", { className: "font-semibold mb-1 text-sm sm:text-base", children: "Phone" }),
|
|
@@ -856,33 +663,6 @@ function ContactPage({
|
|
|
856
663
|
}
|
|
857
664
|
)
|
|
858
665
|
] }),
|
|
859
|
-
categories.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
860
|
-
/* @__PURE__ */ jsxs(
|
|
861
|
-
Label,
|
|
862
|
-
{
|
|
863
|
-
htmlFor: "category",
|
|
864
|
-
className: "text-sm sm:text-base",
|
|
865
|
-
children: [
|
|
866
|
-
categoryLabel,
|
|
867
|
-
categoryRequired ? " *" : ""
|
|
868
|
-
]
|
|
869
|
-
}
|
|
870
|
-
),
|
|
871
|
-
/* @__PURE__ */ jsxs(
|
|
872
|
-
Select,
|
|
873
|
-
{
|
|
874
|
-
id: "category",
|
|
875
|
-
name: "category",
|
|
876
|
-
required: categoryRequired,
|
|
877
|
-
defaultValue: "",
|
|
878
|
-
className: "text-sm sm:text-base",
|
|
879
|
-
children: [
|
|
880
|
-
/* @__PURE__ */ jsx("option", { value: "", disabled: categoryRequired, children: categoryPlaceholder }),
|
|
881
|
-
categories.map((c) => /* @__PURE__ */ jsx("option", { value: c.value, children: c.label }, c.value))
|
|
882
|
-
]
|
|
883
|
-
}
|
|
884
|
-
)
|
|
885
|
-
] }),
|
|
886
666
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
887
667
|
/* @__PURE__ */ jsx(Label, { htmlFor: "subject", className: "text-sm sm:text-base", children: "Subject *" }),
|
|
888
668
|
/* @__PURE__ */ jsx(
|
|
@@ -912,7 +692,7 @@ function ContactPage({
|
|
|
912
692
|
] }),
|
|
913
693
|
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
914
694
|
effectiveRecaptchaSiteKey && /* @__PURE__ */ jsx("div", { className: "flex justify-center sm:justify-start", children: /* @__PURE__ */ jsx(
|
|
915
|
-
|
|
695
|
+
ReCAPTCHA2,
|
|
916
696
|
{
|
|
917
697
|
ref: recaptchaRef,
|
|
918
698
|
sitekey: effectiveRecaptchaSiteKey
|
|
@@ -953,7 +733,7 @@ function ContactPage({
|
|
|
953
733
|
)
|
|
954
734
|
] }) })
|
|
955
735
|
] }) }) }),
|
|
956
|
-
|
|
736
|
+
/* @__PURE__ */ jsx("section", { className: "py-12 sm:py-16 md:py-20 lg:py-24 bg-muted/30", children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
|
|
957
737
|
/* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-center mb-8 sm:mb-12", children: "More Ways to Connect" }),
|
|
958
738
|
/* @__PURE__ */ jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8 max-w-5xl mx-auto", children: additionalOptions.map((option, index) => /* @__PURE__ */ jsxs(
|
|
959
739
|
"div",
|
|
@@ -982,999 +762,187 @@ function ContactPage({
|
|
|
982
762
|
] }) })
|
|
983
763
|
] });
|
|
984
764
|
}
|
|
985
|
-
var
|
|
986
|
-
query
|
|
987
|
-
|
|
988
|
-
id
|
|
989
|
-
title
|
|
990
|
-
slug
|
|
991
|
-
content
|
|
992
|
-
contentFormat
|
|
993
|
-
seoTitle
|
|
994
|
-
seoDescription
|
|
995
|
-
seoKeywords
|
|
996
|
-
lastUpdated
|
|
997
|
-
version
|
|
998
|
-
excerpt
|
|
999
|
-
thumbnail
|
|
1000
|
-
author
|
|
1001
|
-
publishedAt
|
|
1002
|
-
readingTime
|
|
1003
|
-
featured
|
|
1004
|
-
category
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
`;
|
|
1008
|
-
var PUBLIC_RESOLVED_CONTENT_PAGE_QUERY = `
|
|
1009
|
-
query PublicResolvedContentPage($slug: String!, $productId: String!) {
|
|
1010
|
-
publicResolvedContentPage(slug: $slug, productId: $productId) {
|
|
765
|
+
var PUBLIC_PRODUCT_QUERY = `
|
|
766
|
+
query PublicProduct($slug: String!) {
|
|
767
|
+
publicProduct(slug: $slug) {
|
|
1011
768
|
id
|
|
1012
|
-
|
|
769
|
+
name
|
|
1013
770
|
slug
|
|
1014
|
-
|
|
1015
|
-
|
|
771
|
+
description
|
|
772
|
+
status
|
|
773
|
+
logoUrl
|
|
774
|
+
website
|
|
775
|
+
appUrl
|
|
776
|
+
docsUrl
|
|
777
|
+
contactEmail
|
|
778
|
+
supportEmail
|
|
779
|
+
contactPhone
|
|
780
|
+
contactAddress
|
|
1016
781
|
seoTitle
|
|
1017
782
|
seoDescription
|
|
1018
783
|
seoKeywords
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
readingTime
|
|
1026
|
-
featured
|
|
1027
|
-
category
|
|
784
|
+
ogImage
|
|
785
|
+
socialLinks
|
|
786
|
+
recaptchaSiteKey
|
|
787
|
+
rybbitSiteId
|
|
788
|
+
notificationEmail
|
|
789
|
+
metadata
|
|
1028
790
|
}
|
|
1029
791
|
}
|
|
1030
792
|
`;
|
|
1031
|
-
var
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
slug
|
|
1038
|
-
lastUpdated
|
|
1039
|
-
tags
|
|
1040
|
-
seoDescription
|
|
1041
|
-
excerpt
|
|
1042
|
-
thumbnail
|
|
1043
|
-
author
|
|
1044
|
-
publishedAt
|
|
1045
|
-
readingTime
|
|
1046
|
-
featured
|
|
1047
|
-
category
|
|
1048
|
-
}
|
|
1049
|
-
total
|
|
1050
|
-
hasMore
|
|
1051
|
-
}
|
|
793
|
+
var ProductContext = createContext({
|
|
794
|
+
product: null,
|
|
795
|
+
loading: true,
|
|
796
|
+
error: null,
|
|
797
|
+
hasProvider: false,
|
|
798
|
+
refetch: () => {
|
|
1052
799
|
}
|
|
1053
|
-
|
|
1054
|
-
function
|
|
800
|
+
});
|
|
801
|
+
function ProductProvider({ children, fallback }) {
|
|
1055
802
|
const client = useWebSDK();
|
|
1056
803
|
const config = useWebSDKConfig();
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1059
|
-
|
|
804
|
+
const [product, setProduct] = useState(
|
|
805
|
+
fallback ? fallback : null
|
|
806
|
+
);
|
|
1060
807
|
const [loading, setLoading] = useState(true);
|
|
1061
808
|
const [error, setError] = useState(null);
|
|
1062
|
-
const
|
|
1063
|
-
if (!
|
|
809
|
+
const fetchProduct = useCallback(async () => {
|
|
810
|
+
if (!config.productSlug) {
|
|
811
|
+
setLoading(false);
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
1064
814
|
setLoading(true);
|
|
1065
815
|
setError(null);
|
|
1066
816
|
try {
|
|
1067
|
-
const query = options?.resolve ? PUBLIC_RESOLVED_CONTENT_PAGE_QUERY : PUBLIC_CONTENT_PAGE_QUERY;
|
|
1068
|
-
const queryName = options?.resolve ? "publicResolvedContentPage" : "publicContentPage";
|
|
1069
817
|
const result = await client.query(
|
|
1070
|
-
|
|
1071
|
-
{
|
|
1072
|
-
slug,
|
|
1073
|
-
productId: resolvedProductId
|
|
1074
|
-
}
|
|
818
|
+
PUBLIC_PRODUCT_QUERY,
|
|
819
|
+
{ slug: config.productSlug }
|
|
1075
820
|
);
|
|
1076
821
|
if (result.errors?.length) {
|
|
1077
822
|
setError(result.errors[0]?.message ?? "Unknown error");
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
setData(result.data?.[queryName] ?? null);
|
|
823
|
+
} else if (result.data?.publicProduct) {
|
|
824
|
+
setProduct(result.data.publicProduct);
|
|
1081
825
|
}
|
|
1082
826
|
} catch (err) {
|
|
1083
|
-
setError(err instanceof Error ? err.message : "Failed to fetch
|
|
1084
|
-
setData(null);
|
|
827
|
+
setError(err instanceof Error ? err.message : "Failed to fetch product");
|
|
1085
828
|
} finally {
|
|
1086
829
|
setLoading(false);
|
|
1087
830
|
}
|
|
1088
|
-
}, [client,
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
}, [
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
setLoading(true);
|
|
1102
|
-
setError(null);
|
|
1103
|
-
try {
|
|
1104
|
-
const result = await client.query(PUBLIC_CONTENT_PAGES_QUERY, {
|
|
1105
|
-
productId: config.productId,
|
|
1106
|
-
limit: options?.limit ?? 50,
|
|
1107
|
-
offset: options?.offset ?? 0
|
|
1108
|
-
});
|
|
1109
|
-
if (result.errors?.length) {
|
|
1110
|
-
setError(result.errors[0]?.message ?? "Unknown error");
|
|
1111
|
-
setData(null);
|
|
1112
|
-
} else {
|
|
1113
|
-
setData(result.data?.publicContentPages ?? null);
|
|
1114
|
-
}
|
|
1115
|
-
} catch (err) {
|
|
1116
|
-
setError(
|
|
1117
|
-
err instanceof Error ? err.message : "Failed to fetch content pages"
|
|
1118
|
-
);
|
|
1119
|
-
setData(null);
|
|
1120
|
-
} finally {
|
|
1121
|
-
setLoading(false);
|
|
1122
|
-
}
|
|
1123
|
-
}, [client, config.productId, options?.limit, options?.offset]);
|
|
1124
|
-
useEffect(() => {
|
|
1125
|
-
fetchPages();
|
|
1126
|
-
}, [fetchPages]);
|
|
1127
|
-
return { data, loading, error, refetch: fetchPages };
|
|
1128
|
-
}
|
|
1129
|
-
function renderMarkdown(md) {
|
|
1130
|
-
let html = md;
|
|
1131
|
-
html = html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1132
|
-
html = html.replace(/```(\w*)\n([\s\S]*?)```/g, (_m, _lang, code) => {
|
|
1133
|
-
return `<pre><code>${code.trim()}</code></pre>`;
|
|
1134
|
-
});
|
|
1135
|
-
html = html.replace(/`([^`]+)`/g, "<code>$1</code>");
|
|
1136
|
-
html = html.replace(/^###### (.+)$/gm, "<h6>$1</h6>");
|
|
1137
|
-
html = html.replace(/^##### (.+)$/gm, "<h5>$1</h5>");
|
|
1138
|
-
html = html.replace(/^#### (.+)$/gm, "<h4>$1</h4>");
|
|
1139
|
-
html = html.replace(/^### (.+)$/gm, "<h3>$1</h3>");
|
|
1140
|
-
html = html.replace(/^## (.+)$/gm, "<h2>$1</h2>");
|
|
1141
|
-
html = html.replace(/^# (.+)$/gm, "<h1>$1</h1>");
|
|
1142
|
-
html = html.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>");
|
|
1143
|
-
html = html.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
|
|
1144
|
-
html = html.replace(/\*(.+?)\*/g, "<em>$1</em>");
|
|
1145
|
-
html = html.replace(
|
|
1146
|
-
/\[([^\]]+)\]\(([^)]+)\)/g,
|
|
1147
|
-
'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
|
|
831
|
+
}, [client, config.productSlug]);
|
|
832
|
+
useLayoutEffect(() => {
|
|
833
|
+
fetchProduct();
|
|
834
|
+
}, [fetchProduct]);
|
|
835
|
+
const value = useMemo(
|
|
836
|
+
() => ({
|
|
837
|
+
product,
|
|
838
|
+
loading,
|
|
839
|
+
error,
|
|
840
|
+
hasProvider: true,
|
|
841
|
+
refetch: fetchProduct
|
|
842
|
+
}),
|
|
843
|
+
[product, loading, error, fetchProduct]
|
|
1148
844
|
);
|
|
1149
|
-
|
|
1150
|
-
html = html.replace(/(^- .+$(\n^- .+$)*)/gm, (block) => {
|
|
1151
|
-
const items = block.split("\n").map((line) => `<li>${line.replace(/^- /, "")}</li>`).join("");
|
|
1152
|
-
return `<ul>${items}</ul>`;
|
|
1153
|
-
});
|
|
1154
|
-
html = html.replace(/(^\d+\. .+$(\n^\d+\. .+$)*)/gm, (block) => {
|
|
1155
|
-
const items = block.split("\n").map((line) => `<li>${line.replace(/^\d+\. /, "")}</li>`).join("");
|
|
1156
|
-
return `<ol>${items}</ol>`;
|
|
1157
|
-
});
|
|
1158
|
-
html = html.replace(/^---$/gm, "<hr />");
|
|
1159
|
-
html = html.split(/\n\n+/).map((block) => {
|
|
1160
|
-
const trimmed = block.trim();
|
|
1161
|
-
if (!trimmed) return "";
|
|
1162
|
-
if (/^<(h[1-6]|ul|ol|pre|blockquote|hr)/.test(trimmed)) return trimmed;
|
|
1163
|
-
return `<p>${trimmed.replace(/\n/g, "<br />")}</p>`;
|
|
1164
|
-
}).join("\n");
|
|
1165
|
-
return html;
|
|
1166
|
-
}
|
|
1167
|
-
function ContentRenderer({
|
|
1168
|
-
content,
|
|
1169
|
-
format = "markdown",
|
|
1170
|
-
className
|
|
1171
|
-
}) {
|
|
1172
|
-
if (format === "markdown") {
|
|
1173
|
-
return /* @__PURE__ */ jsx(
|
|
1174
|
-
"div",
|
|
1175
|
-
{
|
|
1176
|
-
className,
|
|
1177
|
-
dangerouslySetInnerHTML: { __html: renderMarkdown(content) }
|
|
1178
|
-
}
|
|
1179
|
-
);
|
|
1180
|
-
}
|
|
1181
|
-
if (format === "html") {
|
|
1182
|
-
return /* @__PURE__ */ jsx(
|
|
1183
|
-
"div",
|
|
1184
|
-
{
|
|
1185
|
-
className,
|
|
1186
|
-
dangerouslySetInnerHTML: { __html: content }
|
|
1187
|
-
}
|
|
1188
|
-
);
|
|
1189
|
-
}
|
|
1190
|
-
return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx("pre", { style: { whiteSpace: "pre-wrap", fontFamily: "inherit" }, children: content }) });
|
|
1191
|
-
}
|
|
1192
|
-
var PARTNER_CONTENT_QUERY = `
|
|
1193
|
-
query PartnerContent($productId: String!, $limit: Int) {
|
|
1194
|
-
publicContentPages(productId: $productId, limit: $limit, offset: 0) {
|
|
1195
|
-
items {
|
|
1196
|
-
id
|
|
1197
|
-
title
|
|
1198
|
-
slug
|
|
1199
|
-
excerpt
|
|
1200
|
-
content
|
|
1201
|
-
contentFormat
|
|
1202
|
-
thumbnail
|
|
1203
|
-
tags
|
|
1204
|
-
publishedAt
|
|
1205
|
-
lastUpdated
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
`;
|
|
1210
|
-
var PARTNER_DOCUMENTS_QUERY = `
|
|
1211
|
-
query PartnerDocuments($productId: String!, $limit: Int) {
|
|
1212
|
-
publicPressKitAssets(productId: $productId, limit: $limit, offset: 0) {
|
|
1213
|
-
items {
|
|
1214
|
-
id
|
|
1215
|
-
category
|
|
1216
|
-
title
|
|
1217
|
-
description
|
|
1218
|
-
fileUrl
|
|
1219
|
-
fileName
|
|
1220
|
-
fileSize
|
|
1221
|
-
mimeType
|
|
1222
|
-
version
|
|
1223
|
-
tags
|
|
1224
|
-
sortOrder
|
|
1225
|
-
updatedAt
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
`;
|
|
1230
|
-
function formatFileSize(bytes) {
|
|
1231
|
-
if (!bytes || bytes <= 0) return "";
|
|
1232
|
-
const units = ["B", "KB", "MB", "GB"];
|
|
1233
|
-
let i = 0;
|
|
1234
|
-
let n = bytes;
|
|
1235
|
-
while (n >= 1024 && i < units.length - 1) {
|
|
1236
|
-
n /= 1024;
|
|
1237
|
-
i++;
|
|
1238
|
-
}
|
|
1239
|
-
return `${n.toFixed(n >= 10 || i === 0 ? 0 : 1)} ${units[i]}`;
|
|
1240
|
-
}
|
|
1241
|
-
async function downloadDocument(e, doc) {
|
|
1242
|
-
e.preventDefault();
|
|
1243
|
-
const name = doc.fileName || doc.fileUrl.split("/").pop()?.split("?")[0] || doc.title || "partner-document";
|
|
1244
|
-
const openInTab = () => window.open(doc.fileUrl, "_blank", "noopener,noreferrer");
|
|
1245
|
-
try {
|
|
1246
|
-
const res = await fetch(doc.fileUrl, { mode: "cors" });
|
|
1247
|
-
if (!res.ok) {
|
|
1248
|
-
openInTab();
|
|
1249
|
-
return;
|
|
1250
|
-
}
|
|
1251
|
-
const blob = await res.blob();
|
|
1252
|
-
const objUrl = URL.createObjectURL(blob);
|
|
1253
|
-
const a = document.createElement("a");
|
|
1254
|
-
a.href = objUrl;
|
|
1255
|
-
a.download = name;
|
|
1256
|
-
document.body.appendChild(a);
|
|
1257
|
-
a.click();
|
|
1258
|
-
a.remove();
|
|
1259
|
-
URL.revokeObjectURL(objUrl);
|
|
1260
|
-
} catch {
|
|
1261
|
-
openInTab();
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
function PartnerHero({
|
|
1265
|
-
title,
|
|
1266
|
-
subtitle
|
|
1267
|
-
}) {
|
|
1268
|
-
return /* @__PURE__ */ jsx("section", { className: "bg-gradient-to-b from-background to-muted/20 py-16 md:py-24", children: /* @__PURE__ */ jsxs("div", { className: "container mx-auto px-4 max-w-4xl text-center", children: [
|
|
1269
|
-
/* @__PURE__ */ jsx("h1", { className: "text-4xl md:text-5xl font-bold tracking-tight text-foreground mb-4", children: title }),
|
|
1270
|
-
subtitle && /* @__PURE__ */ jsx("p", { className: "text-lg md:text-xl text-muted-foreground max-w-2xl mx-auto", children: subtitle })
|
|
1271
|
-
] }) });
|
|
1272
|
-
}
|
|
1273
|
-
function stripLeadingHeading(content, format) {
|
|
1274
|
-
if (format === "html") {
|
|
1275
|
-
return content.replace(/^\s*<h1\b[^>]*>[\s\S]*?<\/h1>\s*/i, "");
|
|
1276
|
-
}
|
|
1277
|
-
return content.replace(/^\s*#\s+.*(?:\r?\n)*/, "");
|
|
1278
|
-
}
|
|
1279
|
-
function PartnerContentSection({
|
|
1280
|
-
page
|
|
1281
|
-
}) {
|
|
1282
|
-
return /* @__PURE__ */ jsx("section", { className: "py-12 md:py-16", children: /* @__PURE__ */ jsx(
|
|
1283
|
-
"div",
|
|
1284
|
-
{
|
|
1285
|
-
className: [
|
|
1286
|
-
"mx-auto max-w-3xl px-4",
|
|
1287
|
-
// Headings
|
|
1288
|
-
"[&_h1]:text-3xl [&_h1]:font-bold [&_h1]:tracking-tight [&_h1]:mt-0 [&_h1]:mb-6",
|
|
1289
|
-
"[&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2]:mt-10 [&_h2]:mb-4",
|
|
1290
|
-
"[&_h3]:text-xl [&_h3]:font-semibold [&_h3]:mt-7 [&_h3]:mb-3",
|
|
1291
|
-
"[&_h4]:text-lg [&_h4]:font-semibold [&_h4]:mt-6 [&_h4]:mb-2",
|
|
1292
|
-
// Block elements
|
|
1293
|
-
"[&_p]:my-4 [&_p]:leading-relaxed [&_p]:text-base",
|
|
1294
|
-
"[&_ul]:my-4 [&_ul]:pl-6 [&_ul]:list-disc [&_ul]:space-y-1",
|
|
1295
|
-
"[&_ol]:my-4 [&_ol]:pl-6 [&_ol]:list-decimal [&_ol]:space-y-1",
|
|
1296
|
-
"[&_li]:leading-relaxed",
|
|
1297
|
-
"[&_li>p]:my-1",
|
|
1298
|
-
"[&_blockquote]:border-l-4 [&_blockquote]:border-border [&_blockquote]:pl-4 [&_blockquote]:italic [&_blockquote]:my-4 [&_blockquote]:text-muted-foreground",
|
|
1299
|
-
"[&_hr]:my-8 [&_hr]:border-border",
|
|
1300
|
-
// Inline elements
|
|
1301
|
-
"[&_strong]:font-semibold [&_strong]:text-foreground",
|
|
1302
|
-
"[&_em]:italic",
|
|
1303
|
-
"[&_a]:underline [&_a]:underline-offset-2 [&_a]:text-accent hover:[&_a]:text-accent/80 [&_a]:transition-colors",
|
|
1304
|
-
"[&_code]:rounded [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:text-sm [&_code]:font-mono",
|
|
1305
|
-
"[&_pre]:my-4 [&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:bg-muted [&_pre]:p-4 [&_pre]:text-sm",
|
|
1306
|
-
"[&_pre>code]:bg-transparent [&_pre>code]:p-0"
|
|
1307
|
-
].join(" "),
|
|
1308
|
-
children: page.content && /* @__PURE__ */ jsx(
|
|
1309
|
-
ContentRenderer,
|
|
1310
|
-
{
|
|
1311
|
-
content: stripLeadingHeading(page.content, page.contentFormat),
|
|
1312
|
-
format: (
|
|
1313
|
-
// Validate before passing; unknown formats fall through to
|
|
1314
|
-
// ContentRenderer's default behavior (markdown rendering)
|
|
1315
|
-
// rather than getting silently force-cast to an
|
|
1316
|
-
// unsupported variant.
|
|
1317
|
-
page.contentFormat === "markdown" || page.contentFormat === "html" ? page.contentFormat : void 0
|
|
1318
|
-
)
|
|
1319
|
-
}
|
|
1320
|
-
)
|
|
1321
|
-
}
|
|
1322
|
-
) });
|
|
1323
|
-
}
|
|
1324
|
-
function PartnerDocumentCard({ doc }) {
|
|
1325
|
-
const sizeLabel = formatFileSize(doc.fileSize);
|
|
1326
|
-
const ext = doc.fileName?.split(".").pop()?.toUpperCase();
|
|
1327
|
-
return /* @__PURE__ */ jsxs("article", { className: "flex flex-col gap-3 rounded-xl border border-border bg-card p-5 shadow-sm hover:shadow-md transition-shadow", children: [
|
|
1328
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
1329
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-lg bg-muted p-2.5 shrink-0", children: /* @__PURE__ */ jsx(FileText, { size: 20, className: "text-muted-foreground" }) }),
|
|
1330
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1331
|
-
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground truncate", children: doc.title }),
|
|
1332
|
-
doc.version && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground mt-0.5", children: [
|
|
1333
|
-
"Version ",
|
|
1334
|
-
doc.version
|
|
1335
|
-
] })
|
|
1336
|
-
] })
|
|
1337
|
-
] }),
|
|
1338
|
-
doc.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground line-clamp-3", children: doc.description }),
|
|
1339
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 mt-auto pt-2 border-t border-border/60", children: [
|
|
1340
|
-
/* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground flex items-center gap-2", children: [
|
|
1341
|
-
ext && /* @__PURE__ */ jsx("span", { children: ext }),
|
|
1342
|
-
sizeLabel && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1343
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1344
|
-
/* @__PURE__ */ jsx("span", { children: sizeLabel })
|
|
1345
|
-
] })
|
|
1346
|
-
] }),
|
|
1347
|
-
/* @__PURE__ */ jsxs(
|
|
1348
|
-
"a",
|
|
1349
|
-
{
|
|
1350
|
-
href: doc.fileUrl,
|
|
1351
|
-
download: doc.fileName ?? void 0,
|
|
1352
|
-
onClick: (e) => void downloadDocument(e, doc),
|
|
1353
|
-
className: "inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-3 py-1.5 text-sm font-medium text-foreground hover:bg-muted transition-colors",
|
|
1354
|
-
children: [
|
|
1355
|
-
/* @__PURE__ */ jsx(Download, { size: 14 }),
|
|
1356
|
-
"Download"
|
|
1357
|
-
]
|
|
1358
|
-
}
|
|
1359
|
-
)
|
|
1360
|
-
] })
|
|
1361
|
-
] });
|
|
845
|
+
return /* @__PURE__ */ jsx(ProductContext.Provider, { value, children });
|
|
1362
846
|
}
|
|
1363
|
-
function
|
|
1364
|
-
|
|
1365
|
-
subtitle,
|
|
1366
|
-
docs
|
|
1367
|
-
}) {
|
|
1368
|
-
return /* @__PURE__ */ jsx("section", { className: "py-12 md:py-16 bg-muted/20", children: /* @__PURE__ */ jsxs("div", { className: "container mx-auto px-4 max-w-5xl", children: [
|
|
1369
|
-
/* @__PURE__ */ jsxs("header", { className: "mb-8 md:mb-10 text-center", children: [
|
|
1370
|
-
/* @__PURE__ */ jsx("h2", { className: "text-2xl md:text-3xl font-bold text-foreground mb-2", children: title }),
|
|
1371
|
-
subtitle && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground max-w-2xl mx-auto", children: subtitle })
|
|
1372
|
-
] }),
|
|
1373
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: docs.map((doc) => /* @__PURE__ */ jsx(PartnerDocumentCard, { doc }, doc.id)) })
|
|
1374
|
-
] }) });
|
|
847
|
+
function useProduct() {
|
|
848
|
+
return useContext(ProductContext);
|
|
1375
849
|
}
|
|
1376
|
-
|
|
1377
|
-
value: "partnership",
|
|
1378
|
-
label: "Partner program"
|
|
1379
|
-
};
|
|
1380
|
-
function PartnersPage(props) {
|
|
1381
|
-
const {
|
|
1382
|
-
productName: productNameProp,
|
|
1383
|
-
heroTitle = "Partner with us",
|
|
1384
|
-
heroSubtitle,
|
|
1385
|
-
contentTag = "partner",
|
|
1386
|
-
contentSlug,
|
|
1387
|
-
documentsTag = "partner",
|
|
1388
|
-
documentsTitle = "Partner Documents",
|
|
1389
|
-
documentsSubtitle,
|
|
1390
|
-
showContactForm = true,
|
|
1391
|
-
contactCategory,
|
|
1392
|
-
formTitle = "Become a partner",
|
|
1393
|
-
formSubtitle,
|
|
1394
|
-
contactEmail,
|
|
1395
|
-
contactPhone,
|
|
1396
|
-
officeAddress,
|
|
1397
|
-
responseTime,
|
|
1398
|
-
recaptchaSiteKey,
|
|
1399
|
-
additionalOptions,
|
|
1400
|
-
seoTitle,
|
|
1401
|
-
seoDescription,
|
|
1402
|
-
seoKeywords,
|
|
1403
|
-
className
|
|
1404
|
-
} = props;
|
|
1405
|
-
const client = useWebSDK();
|
|
1406
|
-
const config = useWebSDKConfig();
|
|
850
|
+
function useProductConfig() {
|
|
1407
851
|
const { product } = useProduct();
|
|
1408
|
-
const
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
}
|
|
1420
|
-
let cancelled = false;
|
|
1421
|
-
setLoading(true);
|
|
1422
|
-
void Promise.allSettled([
|
|
1423
|
-
client.query(PARTNER_CONTENT_QUERY, { productId: resolvedProductId, limit: 50 }),
|
|
1424
|
-
client.query(
|
|
1425
|
-
PARTNER_DOCUMENTS_QUERY,
|
|
1426
|
-
{ productId: resolvedProductId, limit: 50 }
|
|
1427
|
-
)
|
|
1428
|
-
]).then(([contentResult, docsResult]) => {
|
|
1429
|
-
if (cancelled) return;
|
|
1430
|
-
if (contentResult.status === "rejected") {
|
|
1431
|
-
setContentPage(null);
|
|
1432
|
-
} else if (contentResult.status === "fulfilled") {
|
|
1433
|
-
const items = contentResult.value.data?.publicContentPages?.items ?? [];
|
|
1434
|
-
const match = contentSlug ? items.find((p) => p.slug === contentSlug) : items.find((p) => p.tags?.includes(contentTag));
|
|
1435
|
-
setContentPage(match ?? null);
|
|
1436
|
-
}
|
|
1437
|
-
if (docsResult.status === "rejected") {
|
|
1438
|
-
setDocs([]);
|
|
1439
|
-
} else if (docsResult.status === "fulfilled") {
|
|
1440
|
-
const items = docsResult.value.data?.publicPressKitAssets?.items ?? [];
|
|
1441
|
-
const filtered = items.filter(
|
|
1442
|
-
(d) => d.category === "DOCUMENT" && d.tags?.includes(documentsTag) && !!d.fileUrl
|
|
1443
|
-
).sort(
|
|
1444
|
-
(a, b) => a.sortOrder - b.sortOrder
|
|
1445
|
-
);
|
|
1446
|
-
setDocs(filtered);
|
|
1447
|
-
}
|
|
1448
|
-
setLoading(false);
|
|
1449
|
-
});
|
|
1450
|
-
return () => {
|
|
1451
|
-
cancelled = true;
|
|
1452
|
-
};
|
|
1453
|
-
}, [client, resolvedProductId, contentSlug, contentTag, documentsTag]);
|
|
1454
|
-
let partnerCategories;
|
|
1455
|
-
if (contactCategory === false) {
|
|
1456
|
-
partnerCategories = [];
|
|
1457
|
-
} else if (Array.isArray(contactCategory)) {
|
|
1458
|
-
partnerCategories = contactCategory.length > 0 ? contactCategory : [DEFAULT_PARTNER_CATEGORY];
|
|
1459
|
-
} else {
|
|
1460
|
-
partnerCategories = [contactCategory ?? DEFAULT_PARTNER_CATEGORY];
|
|
1461
|
-
}
|
|
1462
|
-
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
1463
|
-
/* @__PURE__ */ jsx(
|
|
1464
|
-
PageHead,
|
|
1465
|
-
{
|
|
1466
|
-
title: seoTitle ?? `${heroTitle} \u2014 ${resolvedProductName}`,
|
|
1467
|
-
description: seoDescription ?? heroSubtitle ?? `Join the ${resolvedProductName} partner programme.`,
|
|
1468
|
-
keywords: seoKeywords
|
|
1469
|
-
}
|
|
1470
|
-
),
|
|
1471
|
-
/* @__PURE__ */ jsx(PartnerHero, { title: heroTitle, subtitle: heroSubtitle }),
|
|
1472
|
-
!loading && contentPage && /* @__PURE__ */ jsx(PartnerContentSection, { page: contentPage }),
|
|
1473
|
-
!loading && docs.length > 0 && /* @__PURE__ */ jsx(
|
|
1474
|
-
PartnerDocumentsSection,
|
|
1475
|
-
{
|
|
1476
|
-
title: documentsTitle,
|
|
1477
|
-
subtitle: documentsSubtitle,
|
|
1478
|
-
docs
|
|
1479
|
-
}
|
|
1480
|
-
),
|
|
1481
|
-
showContactForm && /* @__PURE__ */ jsx(
|
|
1482
|
-
ContactPage,
|
|
1483
|
-
{
|
|
1484
|
-
productName: resolvedProductName,
|
|
1485
|
-
heroTitle: formTitle,
|
|
1486
|
-
headingLevel: 2,
|
|
1487
|
-
heroDescription: formSubtitle ?? `Tell us about your organisation and a partner manager from ${resolvedProductName} will be in touch.`,
|
|
1488
|
-
contactEmail,
|
|
1489
|
-
contactPhone,
|
|
1490
|
-
officeAddress,
|
|
1491
|
-
responseTime,
|
|
1492
|
-
recaptchaSiteKey,
|
|
1493
|
-
additionalOptions,
|
|
1494
|
-
categories: partnerCategories,
|
|
1495
|
-
categoryLabel: "Partnership type",
|
|
1496
|
-
categoryRequired: partnerCategories.length > 0
|
|
1497
|
-
}
|
|
1498
|
-
)
|
|
1499
|
-
] });
|
|
1500
|
-
}
|
|
1501
|
-
var ALLOWED_RESUME_TYPES = {
|
|
1502
|
-
"application/pdf": "PDF",
|
|
1503
|
-
"application/msword": "DOC",
|
|
1504
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "DOCX"
|
|
1505
|
-
};
|
|
1506
|
-
var EXT_TO_MIME = {
|
|
1507
|
-
pdf: "application/pdf",
|
|
1508
|
-
doc: "application/msword",
|
|
1509
|
-
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
1510
|
-
};
|
|
1511
|
-
var DEFAULT_MAX_RESUME_BYTES = 10 * 1024 * 1024;
|
|
1512
|
-
function resolveResumeType(file) {
|
|
1513
|
-
if (ALLOWED_RESUME_TYPES[file.type]) return file.type;
|
|
1514
|
-
const ext = file.name.split(".").pop()?.toLowerCase();
|
|
1515
|
-
return ext && EXT_TO_MIME[ext] ? EXT_TO_MIME[ext] : null;
|
|
852
|
+
const config = useWebSDKConfig();
|
|
853
|
+
return {
|
|
854
|
+
// Prefer product-level config, fall back to SDK config
|
|
855
|
+
recaptchaSiteKey: product?.recaptchaSiteKey ?? config.recaptchaSiteKey ?? null,
|
|
856
|
+
rybbitSiteId: product?.rybbitSiteId ?? config.rybbitSiteId ?? null,
|
|
857
|
+
contactEmail: product?.contactEmail ?? null,
|
|
858
|
+
supportEmail: product?.supportEmail ?? null,
|
|
859
|
+
notificationEmail: product?.notificationEmail ?? product?.contactEmail ?? null,
|
|
860
|
+
productName: product?.name ?? null,
|
|
861
|
+
logoUrl: product?.logoUrl ?? null
|
|
862
|
+
};
|
|
1516
863
|
}
|
|
1517
|
-
var
|
|
864
|
+
var newsletterSchema = z.object({
|
|
865
|
+
email: z.string().email("Please enter a valid email address")
|
|
866
|
+
});
|
|
867
|
+
var SUBSCRIBE_MUTATION = (
|
|
1518
868
|
/* GraphQL */
|
|
1519
869
|
`
|
|
1520
|
-
mutation
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
870
|
+
mutation Subscribe($input: SubscribeInput!) {
|
|
871
|
+
subscribe(input: $input) {
|
|
872
|
+
id
|
|
873
|
+
email
|
|
874
|
+
alreadySubscribed
|
|
875
|
+
status
|
|
876
|
+
subscribedAt
|
|
1524
877
|
}
|
|
1525
878
|
}
|
|
1526
879
|
`
|
|
1527
880
|
);
|
|
1528
|
-
function
|
|
1529
|
-
return new Promise((resolve, reject) => {
|
|
1530
|
-
const reader = new FileReader();
|
|
1531
|
-
reader.onload = () => {
|
|
1532
|
-
const result = typeof reader.result === "string" ? reader.result : "";
|
|
1533
|
-
const comma = result.indexOf(",");
|
|
1534
|
-
resolve(comma >= 0 ? result.slice(comma + 1) : result);
|
|
1535
|
-
};
|
|
1536
|
-
reader.onerror = () => reject(new Error("Failed to read the resume file"));
|
|
1537
|
-
reader.readAsDataURL(file);
|
|
1538
|
-
});
|
|
1539
|
-
}
|
|
1540
|
-
async function submitApplication(client, data, productId) {
|
|
881
|
+
async function subscribeNewsletter(client, email, productId, recaptchaToken) {
|
|
1541
882
|
try {
|
|
1542
|
-
const result = await client.mutate(
|
|
883
|
+
const result = await client.mutate(SUBSCRIBE_MUTATION, {
|
|
1543
884
|
input: {
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
...data.phone ? { phone: data.phone } : {},
|
|
1553
|
-
...data.linkedinUrl ? { linkedinUrl: data.linkedinUrl } : {},
|
|
1554
|
-
...data.portfolioUrl ? { portfolioUrl: data.portfolioUrl } : {},
|
|
1555
|
-
...data.coverLetter ? { coverLetter: data.coverLetter } : {},
|
|
1556
|
-
...data.recaptchaToken ? { recaptchaToken: data.recaptchaToken } : {}
|
|
885
|
+
email: email.trim().toLowerCase(),
|
|
886
|
+
platformProductId: productId,
|
|
887
|
+
metadata: {
|
|
888
|
+
source: "website",
|
|
889
|
+
referrer: typeof window !== "undefined" ? window.location.href : "",
|
|
890
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
891
|
+
...recaptchaToken ? { recaptchaToken } : {}
|
|
892
|
+
}
|
|
1557
893
|
}
|
|
1558
894
|
});
|
|
1559
895
|
if (result.errors?.length) {
|
|
896
|
+
const errorMsg = result.errors[0]?.message ?? "Subscription failed";
|
|
897
|
+
const code = result.errors[0]?.extensions?.code;
|
|
898
|
+
if (code === "DUPLICATE_SUBSCRIBER" || errorMsg.toLowerCase().includes("already subscribed")) {
|
|
899
|
+
return {
|
|
900
|
+
success: true,
|
|
901
|
+
message: "You are already part of this newsletter."
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
return { success: false, message: errorMsg };
|
|
905
|
+
}
|
|
906
|
+
if (result.data?.subscribe?.alreadySubscribed) {
|
|
1560
907
|
return {
|
|
1561
|
-
success:
|
|
1562
|
-
message:
|
|
908
|
+
success: true,
|
|
909
|
+
message: "You are already part of this newsletter."
|
|
1563
910
|
};
|
|
1564
911
|
}
|
|
1565
|
-
|
|
1566
|
-
return response?.success ? { success: true, message: response.message || "Application submitted!" } : {
|
|
1567
|
-
success: false,
|
|
1568
|
-
message: response?.message || "Failed to submit application"
|
|
1569
|
-
};
|
|
912
|
+
return { success: true };
|
|
1570
913
|
} catch (error) {
|
|
1571
|
-
console.error("
|
|
914
|
+
console.error("Newsletter subscription error:", error);
|
|
1572
915
|
return { success: false, message: "Network error. Please try again." };
|
|
1573
916
|
}
|
|
1574
917
|
}
|
|
1575
|
-
function
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
}) {
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
const { product } = useProduct();
|
|
1589
|
-
const resolvedProductId = product?.id || config.productId;
|
|
1590
|
-
const displayName = productName ?? product?.name ?? config.productId;
|
|
1591
|
-
const effectiveRecaptchaSiteKey = recaptchaSiteKey ?? product?.recaptchaSiteKey ?? config.recaptchaSiteKey ?? "";
|
|
1592
|
-
const recaptchaRef = useRef(null);
|
|
1593
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
1594
|
-
const [submitted, setSubmitted] = useState(false);
|
|
1595
|
-
const [resumeFile, setResumeFile] = useState(null);
|
|
1596
|
-
const [resumeType, setResumeType] = useState(null);
|
|
1597
|
-
const [resumeError, setResumeError] = useState(null);
|
|
1598
|
-
const maxMb = Math.floor(maxResumeBytes / (1024 * 1024));
|
|
1599
|
-
const clearResume = () => {
|
|
1600
|
-
setResumeFile(null);
|
|
1601
|
-
setResumeType(null);
|
|
1602
|
-
};
|
|
1603
|
-
const handleFileChange = (e) => {
|
|
1604
|
-
setResumeError(null);
|
|
1605
|
-
const file = e.target.files?.[0] ?? null;
|
|
1606
|
-
if (!file) {
|
|
1607
|
-
clearResume();
|
|
1608
|
-
return;
|
|
918
|
+
function useRateLimit(maxAttempts, windowMinutes) {
|
|
919
|
+
const rateLimitRef = useRef(null);
|
|
920
|
+
const [isLimited, setIsLimited] = useState(false);
|
|
921
|
+
const [resetTime, setResetTime] = useState(null);
|
|
922
|
+
useEffect(() => {
|
|
923
|
+
const state = rateLimitRef.current;
|
|
924
|
+
if (state && Date.now() > state.resetTime) {
|
|
925
|
+
rateLimitRef.current = null;
|
|
926
|
+
setIsLimited(false);
|
|
927
|
+
setResetTime(null);
|
|
928
|
+
} else if (state && state.attempts >= maxAttempts) {
|
|
929
|
+
setIsLimited(true);
|
|
930
|
+
setResetTime(new Date(state.resetTime));
|
|
1609
931
|
}
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
932
|
+
}, [maxAttempts]);
|
|
933
|
+
function recordAttempt() {
|
|
934
|
+
const now = Date.now();
|
|
935
|
+
const state = rateLimitRef.current;
|
|
936
|
+
if (state && now > state.resetTime) {
|
|
937
|
+
rateLimitRef.current = null;
|
|
1615
938
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
};
|
|
1624
|
-
const handleSubmit = async (e) => {
|
|
1625
|
-
e.preventDefault();
|
|
1626
|
-
const recaptchaToken = recaptchaRef.current?.getValue() ?? "";
|
|
1627
|
-
if (effectiveRecaptchaSiteKey && !recaptchaToken) {
|
|
1628
|
-
toast.error("Please complete the reCAPTCHA verification");
|
|
1629
|
-
return;
|
|
1630
|
-
}
|
|
1631
|
-
if (!resumeFile) {
|
|
1632
|
-
setResumeError("Please attach your resume (PDF, DOC, or DOCX).");
|
|
1633
|
-
return;
|
|
1634
|
-
}
|
|
1635
|
-
if (!resolvedProductId) {
|
|
1636
|
-
console.warn(
|
|
1637
|
-
"[CareersApplyForm] No productId resolved \u2014 submission will not be attributed to a product."
|
|
1638
|
-
);
|
|
1639
|
-
}
|
|
1640
|
-
const form = e.currentTarget;
|
|
1641
|
-
setIsSubmitting(true);
|
|
1642
|
-
try {
|
|
1643
|
-
const formData = new FormData(form);
|
|
1644
|
-
const resumeBase64 = await fileToBase64(resumeFile);
|
|
1645
|
-
const result = await submitApplication(
|
|
1646
|
-
client,
|
|
1647
|
-
{
|
|
1648
|
-
firstName: formData.get("firstName") ?? "",
|
|
1649
|
-
lastName: formData.get("lastName") ?? "",
|
|
1650
|
-
email: formData.get("email") ?? "",
|
|
1651
|
-
phone: formData.get("phone") || void 0,
|
|
1652
|
-
position: formData.get("position") ?? "",
|
|
1653
|
-
linkedinUrl: formData.get("linkedinUrl") || void 0,
|
|
1654
|
-
portfolioUrl: formData.get("portfolioUrl") || void 0,
|
|
1655
|
-
coverLetter: formData.get("coverLetter") || void 0,
|
|
1656
|
-
resumeBase64,
|
|
1657
|
-
resumeFileName: resumeFile.name,
|
|
1658
|
-
// Use the resolved type (handles browsers that report an empty
|
|
1659
|
-
// file.type for .doc/.docx).
|
|
1660
|
-
resumeContentType: resumeType ?? resumeFile.type,
|
|
1661
|
-
recaptchaToken
|
|
1662
|
-
},
|
|
1663
|
-
resolvedProductId
|
|
1664
|
-
);
|
|
1665
|
-
if (result.success) {
|
|
1666
|
-
setSubmitted(true);
|
|
1667
|
-
toast.success(result.message ?? "Application submitted!");
|
|
1668
|
-
} else {
|
|
1669
|
-
toast.error(result.message ?? "Failed to submit application");
|
|
1670
|
-
recaptchaRef.current?.reset();
|
|
1671
|
-
}
|
|
1672
|
-
} catch (err) {
|
|
1673
|
-
console.error("Careers form error:", err);
|
|
1674
|
-
toast.error("Something went wrong. Please try again.");
|
|
1675
|
-
recaptchaRef.current?.reset();
|
|
1676
|
-
} finally {
|
|
1677
|
-
setIsSubmitting(false);
|
|
1678
|
-
}
|
|
1679
|
-
};
|
|
1680
|
-
const Heading = headingLevel === 2 ? "h2" : "h1";
|
|
1681
|
-
const headingClass = headingLevel === 2 ? "text-2xl md:text-3xl font-bold mb-3" : "text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6";
|
|
1682
|
-
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
1683
|
-
seo && /* @__PURE__ */ jsx(
|
|
1684
|
-
PageHead,
|
|
1685
|
-
{
|
|
1686
|
-
title: seo.title ?? `Careers \u2014 ${displayName}`,
|
|
1687
|
-
description: seo.description ?? heroDescription,
|
|
1688
|
-
keywords: seo.keywords
|
|
1689
|
-
}
|
|
1690
|
-
),
|
|
1691
|
-
/* @__PURE__ */ jsx(
|
|
1692
|
-
"section",
|
|
1693
|
-
{
|
|
1694
|
-
className: headingLevel === 2 ? "py-12 md:py-16" : "bg-gradient-to-b from-background to-muted/20 py-12 sm:py-16 md:py-20 lg:py-24",
|
|
1695
|
-
children: /* @__PURE__ */ jsxs("div", { className: "max-w-3xl mx-auto px-4 sm:px-6 lg:px-8", children: [
|
|
1696
|
-
/* @__PURE__ */ jsxs("div", { className: "text-center mb-8 sm:mb-10", children: [
|
|
1697
|
-
/* @__PURE__ */ jsx(Heading, { className: headingClass, children: heroTitle }),
|
|
1698
|
-
/* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground leading-relaxed", children: heroDescription })
|
|
1699
|
-
] }),
|
|
1700
|
-
submitted ? /* @__PURE__ */ jsxs("div", { className: "text-center rounded-xl border border-border bg-card p-10", children: [
|
|
1701
|
-
/* @__PURE__ */ jsx(CheckCircle, { className: "mx-auto mb-4 h-12 w-12 text-accent" }),
|
|
1702
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xl font-semibold text-foreground mb-2", children: "Application received" }),
|
|
1703
|
-
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
|
|
1704
|
-
"Thanks for applying to ",
|
|
1705
|
-
displayName,
|
|
1706
|
-
". We've emailed you a confirmation and our team will be in touch."
|
|
1707
|
-
] })
|
|
1708
|
-
] }) : /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-5", children: [
|
|
1709
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-5", children: [
|
|
1710
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1711
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "firstName", children: "First name *" }),
|
|
1712
|
-
/* @__PURE__ */ jsx(
|
|
1713
|
-
Input,
|
|
1714
|
-
{
|
|
1715
|
-
id: "firstName",
|
|
1716
|
-
name: "firstName",
|
|
1717
|
-
required: true,
|
|
1718
|
-
placeholder: "Ada"
|
|
1719
|
-
}
|
|
1720
|
-
)
|
|
1721
|
-
] }),
|
|
1722
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1723
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "lastName", children: "Last name *" }),
|
|
1724
|
-
/* @__PURE__ */ jsx(
|
|
1725
|
-
Input,
|
|
1726
|
-
{
|
|
1727
|
-
id: "lastName",
|
|
1728
|
-
name: "lastName",
|
|
1729
|
-
required: true,
|
|
1730
|
-
placeholder: "Lovelace"
|
|
1731
|
-
}
|
|
1732
|
-
)
|
|
1733
|
-
] })
|
|
1734
|
-
] }),
|
|
1735
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-5", children: [
|
|
1736
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1737
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "email", children: "Email *" }),
|
|
1738
|
-
/* @__PURE__ */ jsx(
|
|
1739
|
-
Input,
|
|
1740
|
-
{
|
|
1741
|
-
id: "email",
|
|
1742
|
-
name: "email",
|
|
1743
|
-
type: "email",
|
|
1744
|
-
required: true,
|
|
1745
|
-
placeholder: "ada@example.com"
|
|
1746
|
-
}
|
|
1747
|
-
)
|
|
1748
|
-
] }),
|
|
1749
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1750
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "phone", children: "Phone" }),
|
|
1751
|
-
/* @__PURE__ */ jsx(
|
|
1752
|
-
Input,
|
|
1753
|
-
{
|
|
1754
|
-
id: "phone",
|
|
1755
|
-
name: "phone",
|
|
1756
|
-
placeholder: "+1 555 010 0100"
|
|
1757
|
-
}
|
|
1758
|
-
)
|
|
1759
|
-
] })
|
|
1760
|
-
] }),
|
|
1761
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1762
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "position", children: "Position *" }),
|
|
1763
|
-
positions.length > 0 ? /* @__PURE__ */ jsxs(
|
|
1764
|
-
"select",
|
|
1765
|
-
{
|
|
1766
|
-
id: "position",
|
|
1767
|
-
name: "position",
|
|
1768
|
-
required: true,
|
|
1769
|
-
defaultValue: "",
|
|
1770
|
-
className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring",
|
|
1771
|
-
children: [
|
|
1772
|
-
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select a role" }),
|
|
1773
|
-
positions.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: p }, p))
|
|
1774
|
-
]
|
|
1775
|
-
}
|
|
1776
|
-
) : /* @__PURE__ */ jsx(
|
|
1777
|
-
Input,
|
|
1778
|
-
{
|
|
1779
|
-
id: "position",
|
|
1780
|
-
name: "position",
|
|
1781
|
-
required: true,
|
|
1782
|
-
placeholder: "Role you're applying for"
|
|
1783
|
-
}
|
|
1784
|
-
)
|
|
1785
|
-
] }),
|
|
1786
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-5", children: [
|
|
1787
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1788
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "linkedinUrl", children: "LinkedIn" }),
|
|
1789
|
-
/* @__PURE__ */ jsx(
|
|
1790
|
-
Input,
|
|
1791
|
-
{
|
|
1792
|
-
id: "linkedinUrl",
|
|
1793
|
-
name: "linkedinUrl",
|
|
1794
|
-
type: "url",
|
|
1795
|
-
placeholder: "https://linkedin.com/in/\u2026"
|
|
1796
|
-
}
|
|
1797
|
-
)
|
|
1798
|
-
] }),
|
|
1799
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1800
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "portfolioUrl", children: "Portfolio / GitHub" }),
|
|
1801
|
-
/* @__PURE__ */ jsx(
|
|
1802
|
-
Input,
|
|
1803
|
-
{
|
|
1804
|
-
id: "portfolioUrl",
|
|
1805
|
-
name: "portfolioUrl",
|
|
1806
|
-
type: "url",
|
|
1807
|
-
placeholder: "https://\u2026"
|
|
1808
|
-
}
|
|
1809
|
-
)
|
|
1810
|
-
] })
|
|
1811
|
-
] }),
|
|
1812
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1813
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "coverLetter", children: "Cover letter" }),
|
|
1814
|
-
/* @__PURE__ */ jsx(
|
|
1815
|
-
Textarea,
|
|
1816
|
-
{
|
|
1817
|
-
id: "coverLetter",
|
|
1818
|
-
name: "coverLetter",
|
|
1819
|
-
rows: 5,
|
|
1820
|
-
placeholder: "Tell us why you'd be a great fit\u2026"
|
|
1821
|
-
}
|
|
1822
|
-
)
|
|
1823
|
-
] }),
|
|
1824
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1825
|
-
/* @__PURE__ */ jsxs(Label, { htmlFor: "resume", children: [
|
|
1826
|
-
"Resume * (PDF, DOC, or DOCX \u2014 max ",
|
|
1827
|
-
maxMb,
|
|
1828
|
-
"MB)"
|
|
1829
|
-
] }),
|
|
1830
|
-
/* @__PURE__ */ jsxs(
|
|
1831
|
-
"label",
|
|
1832
|
-
{
|
|
1833
|
-
htmlFor: "resume",
|
|
1834
|
-
className: "mt-1 flex cursor-pointer items-center gap-3 rounded-md border border-dashed border-input bg-background px-4 py-3 text-sm hover:bg-muted/40 transition-colors",
|
|
1835
|
-
children: [
|
|
1836
|
-
/* @__PURE__ */ jsx(
|
|
1837
|
-
Upload,
|
|
1838
|
-
{
|
|
1839
|
-
className: "h-5 w-5 text-muted-foreground",
|
|
1840
|
-
"aria-hidden": "true"
|
|
1841
|
-
}
|
|
1842
|
-
),
|
|
1843
|
-
/* @__PURE__ */ jsx("span", { className: "text-foreground", children: resumeFile ? resumeFile.name : "Choose a file\u2026" }),
|
|
1844
|
-
/* @__PURE__ */ jsx(
|
|
1845
|
-
"input",
|
|
1846
|
-
{
|
|
1847
|
-
id: "resume",
|
|
1848
|
-
name: "resume",
|
|
1849
|
-
type: "file",
|
|
1850
|
-
accept: ".pdf,.doc,.docx,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
1851
|
-
className: "sr-only",
|
|
1852
|
-
"aria-describedby": resumeError ? "resume-error" : void 0,
|
|
1853
|
-
"aria-invalid": resumeError ? true : void 0,
|
|
1854
|
-
onChange: handleFileChange
|
|
1855
|
-
}
|
|
1856
|
-
)
|
|
1857
|
-
]
|
|
1858
|
-
}
|
|
1859
|
-
),
|
|
1860
|
-
resumeError && /* @__PURE__ */ jsx(
|
|
1861
|
-
"p",
|
|
1862
|
-
{
|
|
1863
|
-
id: "resume-error",
|
|
1864
|
-
role: "alert",
|
|
1865
|
-
className: "mt-1 text-sm text-destructive",
|
|
1866
|
-
children: resumeError
|
|
1867
|
-
}
|
|
1868
|
-
)
|
|
1869
|
-
] }),
|
|
1870
|
-
effectiveRecaptchaSiteKey && /* @__PURE__ */ jsx(
|
|
1871
|
-
ReCAPTCHA3,
|
|
1872
|
-
{
|
|
1873
|
-
ref: recaptchaRef,
|
|
1874
|
-
sitekey: effectiveRecaptchaSiteKey
|
|
1875
|
-
}
|
|
1876
|
-
),
|
|
1877
|
-
/* @__PURE__ */ jsx(
|
|
1878
|
-
Button,
|
|
1879
|
-
{
|
|
1880
|
-
type: "submit",
|
|
1881
|
-
size: "lg",
|
|
1882
|
-
disabled: isSubmitting,
|
|
1883
|
-
className: "w-full sm:w-auto",
|
|
1884
|
-
children: isSubmitting ? "Submitting\u2026" : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1885
|
-
/* @__PURE__ */ jsx(Send, { className: "mr-2 h-4 w-4" }),
|
|
1886
|
-
" Submit application"
|
|
1887
|
-
] })
|
|
1888
|
-
}
|
|
1889
|
-
)
|
|
1890
|
-
] })
|
|
1891
|
-
] })
|
|
1892
|
-
}
|
|
1893
|
-
)
|
|
1894
|
-
] });
|
|
1895
|
-
}
|
|
1896
|
-
var newsletterSchema = z.object({
|
|
1897
|
-
email: z.string().email("Please enter a valid email address")
|
|
1898
|
-
});
|
|
1899
|
-
var SUBSCRIBE_MUTATION = (
|
|
1900
|
-
/* GraphQL */
|
|
1901
|
-
`
|
|
1902
|
-
mutation Subscribe($input: SubscribeInput!) {
|
|
1903
|
-
subscribe(input: $input) {
|
|
1904
|
-
id
|
|
1905
|
-
email
|
|
1906
|
-
alreadySubscribed
|
|
1907
|
-
status
|
|
1908
|
-
subscribedAt
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
`
|
|
1912
|
-
);
|
|
1913
|
-
async function subscribeNewsletter(client, email, productId, recaptchaToken) {
|
|
1914
|
-
try {
|
|
1915
|
-
const result = await client.mutate(SUBSCRIBE_MUTATION, {
|
|
1916
|
-
input: {
|
|
1917
|
-
email: email.trim().toLowerCase(),
|
|
1918
|
-
platformProductId: productId,
|
|
1919
|
-
metadata: {
|
|
1920
|
-
source: "website",
|
|
1921
|
-
referrer: typeof window !== "undefined" ? window.location.href : "",
|
|
1922
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1923
|
-
...recaptchaToken ? { recaptchaToken } : {}
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
});
|
|
1927
|
-
if (result.errors?.length) {
|
|
1928
|
-
const errorMsg = result.errors[0]?.message ?? "Subscription failed";
|
|
1929
|
-
const code = result.errors[0]?.extensions?.code;
|
|
1930
|
-
if (code === "DUPLICATE_SUBSCRIBER" || errorMsg.toLowerCase().includes("already subscribed")) {
|
|
1931
|
-
return {
|
|
1932
|
-
success: true,
|
|
1933
|
-
message: "You are already part of this newsletter."
|
|
1934
|
-
};
|
|
1935
|
-
}
|
|
1936
|
-
return { success: false, message: errorMsg };
|
|
1937
|
-
}
|
|
1938
|
-
if (result.data?.subscribe?.alreadySubscribed) {
|
|
1939
|
-
return {
|
|
1940
|
-
success: true,
|
|
1941
|
-
message: "You are already part of this newsletter."
|
|
1942
|
-
};
|
|
1943
|
-
}
|
|
1944
|
-
return { success: true };
|
|
1945
|
-
} catch (error) {
|
|
1946
|
-
console.error("Newsletter subscription error:", error);
|
|
1947
|
-
return { success: false, message: "Network error. Please try again." };
|
|
1948
|
-
}
|
|
1949
|
-
}
|
|
1950
|
-
function useRateLimit(maxAttempts, windowMinutes) {
|
|
1951
|
-
const rateLimitRef = useRef(null);
|
|
1952
|
-
const [isLimited, setIsLimited] = useState(false);
|
|
1953
|
-
const [resetTime, setResetTime] = useState(null);
|
|
1954
|
-
useEffect(() => {
|
|
1955
|
-
const state = rateLimitRef.current;
|
|
1956
|
-
if (state && Date.now() > state.resetTime) {
|
|
1957
|
-
rateLimitRef.current = null;
|
|
1958
|
-
setIsLimited(false);
|
|
1959
|
-
setResetTime(null);
|
|
1960
|
-
} else if (state && state.attempts >= maxAttempts) {
|
|
1961
|
-
setIsLimited(true);
|
|
1962
|
-
setResetTime(new Date(state.resetTime));
|
|
1963
|
-
}
|
|
1964
|
-
}, [maxAttempts]);
|
|
1965
|
-
function recordAttempt() {
|
|
1966
|
-
const now = Date.now();
|
|
1967
|
-
const state = rateLimitRef.current;
|
|
1968
|
-
if (state && now > state.resetTime) {
|
|
1969
|
-
rateLimitRef.current = null;
|
|
1970
|
-
}
|
|
1971
|
-
const current = rateLimitRef.current;
|
|
1972
|
-
if (!current) {
|
|
1973
|
-
rateLimitRef.current = {
|
|
1974
|
-
attempts: 1,
|
|
1975
|
-
resetTime: now + windowMinutes * 60 * 1e3
|
|
1976
|
-
};
|
|
1977
|
-
return false;
|
|
939
|
+
const current = rateLimitRef.current;
|
|
940
|
+
if (!current) {
|
|
941
|
+
rateLimitRef.current = {
|
|
942
|
+
attempts: 1,
|
|
943
|
+
resetTime: now + windowMinutes * 60 * 1e3
|
|
944
|
+
};
|
|
945
|
+
return false;
|
|
1978
946
|
}
|
|
1979
947
|
current.attempts += 1;
|
|
1980
948
|
if (current.attempts >= maxAttempts) {
|
|
@@ -2182,7 +1150,7 @@ function NewsletterPage({
|
|
|
2182
1150
|
errors.email && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: errors.email.message })
|
|
2183
1151
|
] }),
|
|
2184
1152
|
effectiveRecaptchaSiteKey && /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
2185
|
-
|
|
1153
|
+
ReCAPTCHA2,
|
|
2186
1154
|
{
|
|
2187
1155
|
ref: recaptchaRef,
|
|
2188
1156
|
sitekey: effectiveRecaptchaSiteKey
|
|
@@ -2234,7 +1202,7 @@ function NewsletterPage({
|
|
|
2234
1202
|
errors.email && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: errors.email.message })
|
|
2235
1203
|
] }),
|
|
2236
1204
|
effectiveRecaptchaSiteKey && /* @__PURE__ */ jsx("div", { className: "flex justify-center sm:justify-start", children: /* @__PURE__ */ jsx(
|
|
2237
|
-
|
|
1205
|
+
ReCAPTCHA2,
|
|
2238
1206
|
{
|
|
2239
1207
|
ref: recaptchaRef,
|
|
2240
1208
|
sitekey: effectiveRecaptchaSiteKey
|
|
@@ -2402,25 +1370,14 @@ function NewsletterForm({
|
|
|
2402
1370
|
background: rgba(0,0,0,0.3) !important;
|
|
2403
1371
|
}
|
|
2404
1372
|
` }),
|
|
2405
|
-
/* @__PURE__ */ jsx(
|
|
2406
|
-
|
|
1373
|
+
/* @__PURE__ */ jsx("div", { style: { position: "relative", zIndex: 50 }, children: /* @__PURE__ */ jsx(
|
|
1374
|
+
ReCAPTCHA2,
|
|
2407
1375
|
{
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
display: "flex",
|
|
2412
|
-
justifyContent: "flex-start"
|
|
2413
|
-
},
|
|
2414
|
-
children: /* @__PURE__ */ jsx(
|
|
2415
|
-
ReCAPTCHA3,
|
|
2416
|
-
{
|
|
2417
|
-
ref: recaptchaRef,
|
|
2418
|
-
sitekey: effectiveRecaptchaSiteKey,
|
|
2419
|
-
size: "normal"
|
|
2420
|
-
}
|
|
2421
|
-
)
|
|
1376
|
+
ref: recaptchaRef,
|
|
1377
|
+
sitekey: effectiveRecaptchaSiteKey,
|
|
1378
|
+
size: "compact"
|
|
2422
1379
|
}
|
|
2423
|
-
)
|
|
1380
|
+
) })
|
|
2424
1381
|
] }),
|
|
2425
1382
|
effectiveRecaptchaSiteKey && /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isLoading, className: "w-full", children: isLoading ? "Subscribing..." : buttonText })
|
|
2426
1383
|
]
|
|
@@ -2428,9 +1385,9 @@ function NewsletterForm({
|
|
|
2428
1385
|
)
|
|
2429
1386
|
] });
|
|
2430
1387
|
}
|
|
2431
|
-
var
|
|
2432
|
-
query
|
|
2433
|
-
|
|
1388
|
+
var GET_ALL_PLANS_QUERY = `
|
|
1389
|
+
query GetAllPlans {
|
|
1390
|
+
getAllPlans {
|
|
2434
1391
|
id
|
|
2435
1392
|
name
|
|
2436
1393
|
price
|
|
@@ -2475,15 +1432,11 @@ function formatInterval(duration, billingIntervals) {
|
|
|
2475
1432
|
const intervals = billingIntervals || defaultIntervals;
|
|
2476
1433
|
return intervals[duration] || `/${duration}`;
|
|
2477
1434
|
}
|
|
2478
|
-
function isEnterprisePlan(planName) {
|
|
2479
|
-
const name = planName.toLowerCase();
|
|
2480
|
-
return name.includes("team") || name.includes("business") || name.includes("enterprise");
|
|
2481
|
-
}
|
|
2482
1435
|
function detectPlanTier(planName) {
|
|
2483
1436
|
const name = planName.toLowerCase();
|
|
2484
|
-
if (name.includes("
|
|
1437
|
+
if (name.includes("basic") || name.includes("starter")) {
|
|
2485
1438
|
return "basic";
|
|
2486
|
-
} else if (name.includes("pro") || name.includes("professional") || name.includes("premium")
|
|
1439
|
+
} else if (name.includes("pro") || name.includes("professional") || name.includes("premium")) {
|
|
2487
1440
|
return "professional";
|
|
2488
1441
|
} else if (name.includes("enterprise") || name.includes("business")) {
|
|
2489
1442
|
return "enterprise";
|
|
@@ -2503,8 +1456,7 @@ function getMetadataForPlan(planName, planMetadata) {
|
|
|
2503
1456
|
defaultDescription: meta.defaultDescription || "Choose this plan",
|
|
2504
1457
|
popular: meta.popular ?? false,
|
|
2505
1458
|
ctaText: meta.ctaText || "Get Started",
|
|
2506
|
-
ctaType: meta.ctaType || "signup"
|
|
2507
|
-
features: meta.features
|
|
1459
|
+
ctaType: meta.ctaType || "signup"
|
|
2508
1460
|
};
|
|
2509
1461
|
}
|
|
2510
1462
|
const tier = detectPlanTier(planName);
|
|
@@ -2527,54 +1479,37 @@ function getMetadataForPlan(planName, planMetadata) {
|
|
|
2527
1479
|
ctaType: "signup"
|
|
2528
1480
|
};
|
|
2529
1481
|
}
|
|
2530
|
-
function humanizeQuotaName(name) {
|
|
2531
|
-
const parts = name.split(".");
|
|
2532
|
-
const resource = parts.length >= 3 ? parts[parts.length - 2] : parts[parts.length - 1];
|
|
2533
|
-
return resource.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
2534
|
-
}
|
|
2535
1482
|
function transformQuotaToFeature(quota) {
|
|
2536
1483
|
const { name, limits } = quota;
|
|
2537
1484
|
if (!limits || typeof limits !== "object") {
|
|
2538
|
-
return
|
|
1485
|
+
return name;
|
|
2539
1486
|
}
|
|
2540
1487
|
const limitsObj = limits;
|
|
2541
1488
|
const value = limitsObj.value;
|
|
2542
1489
|
const unit = limitsObj.unit;
|
|
2543
1490
|
const type = limitsObj.type;
|
|
2544
1491
|
const description = limitsObj.description;
|
|
2545
|
-
if (
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
return description;
|
|
2550
|
-
}
|
|
2551
|
-
if (typeof unit === "string" && unit) {
|
|
2552
|
-
if (typeof value === "number") {
|
|
2553
|
-
return `${value.toLocaleString()} ${unit}`;
|
|
2554
|
-
}
|
|
2555
|
-
return `${unit}`;
|
|
2556
|
-
}
|
|
2557
|
-
const label = humanizeQuotaName(name);
|
|
2558
|
-
if (type === "boolean") {
|
|
2559
|
-
return label;
|
|
1492
|
+
if (type === "number" && typeof value === "number") {
|
|
1493
|
+
const formattedValue = value.toLocaleString();
|
|
1494
|
+
return `${formattedValue} ${unit || ""}${description ? " - " + description : ""}`.trim();
|
|
1495
|
+
} else if (type === "boolean") {
|
|
1496
|
+
return typeof description === "string" && description || name;
|
|
2560
1497
|
}
|
|
2561
1498
|
if (typeof value === "number") {
|
|
2562
|
-
|
|
1499
|
+
const formattedValue = value.toLocaleString();
|
|
1500
|
+
return `${name}: ${formattedValue} ${unit || ""}`.trim();
|
|
2563
1501
|
}
|
|
2564
|
-
return
|
|
1502
|
+
return name;
|
|
2565
1503
|
}
|
|
2566
1504
|
function extractDisplayFeatures(features, planName, fallbackFeatures) {
|
|
2567
|
-
const tier = detectPlanTier(planName);
|
|
2568
|
-
if (tier) {
|
|
2569
|
-
const tierFeatures = getFallbackFeaturesForTier(tier, fallbackFeatures);
|
|
2570
|
-
if (tierFeatures.length > 0) {
|
|
2571
|
-
return tierFeatures;
|
|
2572
|
-
}
|
|
2573
|
-
}
|
|
2574
1505
|
const quotaFeatures = features.filter((f) => f.quota).map((f) => transformQuotaToFeature(f.quota));
|
|
2575
1506
|
if (quotaFeatures.length > 0) {
|
|
2576
1507
|
return quotaFeatures;
|
|
2577
1508
|
}
|
|
1509
|
+
const tier = detectPlanTier(planName);
|
|
1510
|
+
if (tier) {
|
|
1511
|
+
return getFallbackFeaturesForTier(tier, fallbackFeatures);
|
|
1512
|
+
}
|
|
2578
1513
|
return [];
|
|
2579
1514
|
}
|
|
2580
1515
|
function transformToDisplayCard(plan, props) {
|
|
@@ -2585,7 +1520,7 @@ function transformToDisplayCard(plan, props) {
|
|
|
2585
1520
|
props.currencies
|
|
2586
1521
|
);
|
|
2587
1522
|
const interval = formatInterval(plan.duration, props.billingIntervals);
|
|
2588
|
-
const features =
|
|
1523
|
+
const features = extractDisplayFeatures(
|
|
2589
1524
|
plan.features,
|
|
2590
1525
|
plan.name,
|
|
2591
1526
|
props.fallbackFeatures
|
|
@@ -2623,25 +1558,22 @@ function PricingSection(props) {
|
|
|
2623
1558
|
const [billingCycle, setBillingCycle] = useState(
|
|
2624
1559
|
"monthly"
|
|
2625
1560
|
);
|
|
2626
|
-
const [audience, setAudience] = useState(
|
|
2627
|
-
"individual"
|
|
2628
|
-
);
|
|
2629
1561
|
useEffect(() => {
|
|
2630
1562
|
let cancelled = false;
|
|
2631
1563
|
async function loadPlans() {
|
|
2632
1564
|
try {
|
|
2633
1565
|
setLoading(true);
|
|
2634
|
-
const response = await client.query(
|
|
2635
|
-
productId: resolvedProductId
|
|
2636
|
-
});
|
|
1566
|
+
const response = await client.query(GET_ALL_PLANS_QUERY);
|
|
2637
1567
|
if (cancelled) return;
|
|
2638
1568
|
if (response.errors && response.errors.length > 0) {
|
|
2639
1569
|
throw new Error(response.errors[0].message);
|
|
2640
1570
|
}
|
|
2641
|
-
if (!response.data?.
|
|
1571
|
+
if (!response.data?.getAllPlans) {
|
|
2642
1572
|
throw new Error("No plans data received");
|
|
2643
1573
|
}
|
|
2644
|
-
const cards = response.data.
|
|
1574
|
+
const cards = response.data.getAllPlans.filter(
|
|
1575
|
+
(plan) => plan.isActive && (!resolvedProductId || plan.productID === resolvedProductId)
|
|
1576
|
+
).map((plan) => transformToDisplayCard(plan, props)).sort((a, b) => a.priceRaw - b.priceRaw);
|
|
2645
1577
|
setAllPlans(cards);
|
|
2646
1578
|
setError(null);
|
|
2647
1579
|
} catch (err) {
|
|
@@ -2659,56 +1591,13 @@ function PricingSection(props) {
|
|
|
2659
1591
|
cancelled = true;
|
|
2660
1592
|
};
|
|
2661
1593
|
}, [client, resolvedProductId]);
|
|
2662
|
-
const
|
|
2663
|
-
const enterpriseApiPlans = allPlans.filter((p) => isEnterprisePlan(p.name));
|
|
2664
|
-
const individualPlans = individualAllPlans.filter(
|
|
1594
|
+
const plans = allPlans.filter(
|
|
2665
1595
|
(plan) => billingCycle === "monthly" ? plan.duration === "monthly" : plan.duration === "yearly"
|
|
2666
1596
|
);
|
|
2667
|
-
const enterpriseCards = enterpriseApiPlans.map((p) => {
|
|
2668
|
-
if (p.priceRaw === 0 && p.name.toLowerCase().includes("enterprise")) {
|
|
2669
|
-
return {
|
|
2670
|
-
...p,
|
|
2671
|
-
price: "Custom",
|
|
2672
|
-
interval: "",
|
|
2673
|
-
ctaText: "Contact Sales",
|
|
2674
|
-
ctaLink: props.contactUrl || "/contact"
|
|
2675
|
-
};
|
|
2676
|
-
}
|
|
2677
|
-
return p;
|
|
2678
|
-
});
|
|
2679
|
-
const hasApiEnterprisePlans = enterpriseCards.length > 0;
|
|
2680
|
-
const defaultEnterpriseCard = {
|
|
2681
|
-
name: "Enterprise",
|
|
2682
|
-
subtitle: "For organizations that need more",
|
|
2683
|
-
description: "For organizations that need more",
|
|
2684
|
-
price: "Custom",
|
|
2685
|
-
period: "",
|
|
2686
|
-
interval: "",
|
|
2687
|
-
button: "Contact Sales",
|
|
2688
|
-
buttonLink: props.contactUrl || "/contact",
|
|
2689
|
-
ctaText: "Contact Sales",
|
|
2690
|
-
ctaLink: props.contactUrl || "/contact",
|
|
2691
|
-
popular: false,
|
|
2692
|
-
features: props.fallbackFeatures?.enterprise || [
|
|
2693
|
-
"Unlimited everything",
|
|
2694
|
-
"SSO & SAML",
|
|
2695
|
-
"Audit logs",
|
|
2696
|
-
"Dedicated support",
|
|
2697
|
-
"Self-hosted option"
|
|
2698
|
-
]
|
|
2699
|
-
};
|
|
2700
|
-
const resolvedEnterprisePlans = hasApiEnterprisePlans ? enterpriseCards : props.enterprisePlans ? props.enterprisePlans : [defaultEnterpriseCard];
|
|
2701
|
-
const plans = props.showAudienceTabs && audience === "enterprise" ? [] : individualPlans;
|
|
2702
1597
|
if (loading) {
|
|
2703
1598
|
return /* @__PURE__ */ jsx("section", { id, className: `py-12 sm:py-16 md:py-20 ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "container mx-auto px-4 sm:px-6", children: [
|
|
2704
1599
|
/* @__PURE__ */ jsxs("div", { className: "text-center mb-8 sm:mb-12", children: [
|
|
2705
|
-
|
|
2706
|
-
// Visually hidden but DOM-present heading so axe's heading-order
|
|
2707
|
-
// rule still sees an h2 between the consumer's hero h1 and the
|
|
2708
|
-
// h3 plan-card titles. See `getMetadataForPlan` for why a falsy
|
|
2709
|
-
// sectionHeading is the canonical "no visible heading" signal.
|
|
2710
|
-
/* @__PURE__ */ jsx("h2", { className: "sr-only", children: "Pricing" })
|
|
2711
|
-
),
|
|
1600
|
+
/* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl md:text-4xl font-bold mb-3 sm:mb-4", children: sectionHeading }),
|
|
2712
1601
|
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm sm:text-base md:text-lg", children: "Loading pricing information..." })
|
|
2713
1602
|
] }),
|
|
2714
1603
|
/* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-3 gap-6 sm:gap-8", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs(
|
|
@@ -2729,205 +1618,90 @@ function PricingSection(props) {
|
|
|
2729
1618
|
}
|
|
2730
1619
|
if (error && plans.length === 0) {
|
|
2731
1620
|
return /* @__PURE__ */ jsx("section", { id, className: `py-12 sm:py-16 md:py-20 ${className}`, children: /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 sm:px-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
2732
|
-
|
|
1621
|
+
/* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl md:text-4xl font-bold mb-4", children: sectionHeading }),
|
|
2733
1622
|
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-8", children: error }),
|
|
2734
1623
|
/* @__PURE__ */ jsx(Button, { onClick: () => window.location.reload(), children: "Retry" })
|
|
2735
1624
|
] }) }) });
|
|
2736
1625
|
}
|
|
2737
1626
|
return /* @__PURE__ */ jsx("section", { id, className: `py-12 sm:py-16 md:py-20 ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "container mx-auto px-4 sm:px-6", children: [
|
|
2738
1627
|
/* @__PURE__ */ jsxs("div", { className: "text-center mb-8 sm:mb-12", children: [
|
|
2739
|
-
|
|
1628
|
+
/* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl md:text-4xl font-bold mb-3 sm:mb-4", children: sectionHeading }),
|
|
2740
1629
|
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm sm:text-base md:text-lg mb-6", children: sectionSubtitle }),
|
|
2741
|
-
|
|
2742
|
-
/* @__PURE__ */ jsx(
|
|
2743
|
-
"button",
|
|
2744
|
-
{
|
|
2745
|
-
type: "button",
|
|
2746
|
-
onClick: () => setAudience("individual"),
|
|
2747
|
-
className: `px-6 sm:px-8 py-2.5 rounded-lg text-sm font-semibold transition-all ${audience === "individual" ? "bg-background shadow-sm text-foreground" : "text-muted-foreground hover:text-foreground"}`,
|
|
2748
|
-
children: "Individual"
|
|
2749
|
-
}
|
|
2750
|
-
),
|
|
2751
|
-
/* @__PURE__ */ jsx(
|
|
2752
|
-
"button",
|
|
2753
|
-
{
|
|
2754
|
-
type: "button",
|
|
2755
|
-
onClick: () => setAudience("enterprise"),
|
|
2756
|
-
className: `px-6 sm:px-8 py-2.5 rounded-lg text-sm font-semibold transition-all ${audience === "enterprise" ? "bg-background shadow-sm text-foreground" : "text-muted-foreground hover:text-foreground"}`,
|
|
2757
|
-
children: "Enterprise"
|
|
2758
|
-
}
|
|
2759
|
-
)
|
|
2760
|
-
] }) }),
|
|
2761
|
-
(audience === "individual" || !props.showAudienceTabs) && /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center bg-muted/60 p-1.5 rounded-xl", children: [
|
|
1630
|
+
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-3 bg-muted p-1.5 rounded-lg", children: [
|
|
2762
1631
|
/* @__PURE__ */ jsx(
|
|
2763
1632
|
"button",
|
|
2764
1633
|
{
|
|
2765
|
-
type: "button",
|
|
2766
1634
|
onClick: () => setBillingCycle("monthly"),
|
|
2767
|
-
className: `px-
|
|
1635
|
+
className: `px-6 py-2 rounded-md text-sm font-medium transition-all ${billingCycle === "monthly" ? "bg-background shadow-sm text-foreground" : "text-muted-foreground hover:text-foreground"}`,
|
|
2768
1636
|
children: "Monthly"
|
|
2769
1637
|
}
|
|
2770
1638
|
),
|
|
2771
1639
|
/* @__PURE__ */ jsx(
|
|
2772
1640
|
"button",
|
|
2773
1641
|
{
|
|
2774
|
-
type: "button",
|
|
2775
1642
|
onClick: () => setBillingCycle("yearly"),
|
|
2776
|
-
className: `px-
|
|
1643
|
+
className: `px-6 py-2 rounded-md text-sm font-medium transition-all ${billingCycle === "yearly" ? "bg-background shadow-sm text-foreground" : "text-muted-foreground hover:text-foreground"}`,
|
|
2777
1644
|
children: "Yearly"
|
|
2778
1645
|
}
|
|
2779
1646
|
)
|
|
2780
|
-
] })
|
|
2781
|
-
] }),
|
|
2782
|
-
props.showAudienceTabs && audience === "enterprise" && /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-3xl text-center mb-8", children: [
|
|
2783
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xl sm:text-2xl font-bold text-foreground", children: props.enterpriseHeading || "Enterprise Solutions" }),
|
|
2784
|
-
/* @__PURE__ */ jsx("p", { className: "mt-3 text-muted-foreground", children: props.enterpriseSubtitle || "Built for teams, agencies, and organizations that need advanced collaboration, security, support, and scale." })
|
|
1647
|
+
] })
|
|
2785
1648
|
] }),
|
|
2786
|
-
/* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-3 gap-6 sm:gap-8 max-w-6xl mx-auto items-stretch", children:
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
{
|
|
2801
|
-
|
|
2802
|
-
children:
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
note && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm font-medium text-primary", children: note })
|
|
2814
|
-
] }),
|
|
2815
|
-
/* @__PURE__ */ jsx("ul", { className: "space-y-3 mb-8 mt-6 flex-1", children: features.map((feature) => /* @__PURE__ */ jsxs(
|
|
2816
|
-
"li",
|
|
2817
|
-
{
|
|
2818
|
-
className: "text-sm flex items-start gap-2",
|
|
2819
|
-
children: [
|
|
2820
|
-
/* @__PURE__ */ jsx("span", { className: "text-primary mt-0.5 flex-shrink-0", children: "\u2713" }),
|
|
2821
|
-
/* @__PURE__ */ jsx("span", { children: feature })
|
|
2822
|
-
]
|
|
2823
|
-
},
|
|
2824
|
-
feature
|
|
2825
|
-
)) }),
|
|
2826
|
-
btnLink.startsWith("/") ? /* @__PURE__ */ jsx(
|
|
2827
|
-
Button,
|
|
1649
|
+
/* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-3 gap-6 sm:gap-8 max-w-6xl mx-auto items-stretch", children: plans.map((plan) => /* @__PURE__ */ jsxs(
|
|
1650
|
+
"div",
|
|
1651
|
+
{
|
|
1652
|
+
className: `bg-card rounded-xl p-6 sm:p-8 transition-all duration-300 flex flex-col ${plan.popular ? "border-2 border-primary shadow-xl ring-1 ring-primary/20" : "border hover:shadow-lg hover:border-primary/50"}`,
|
|
1653
|
+
children: [
|
|
1654
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center mb-6", children: [
|
|
1655
|
+
plan.popular && /* @__PURE__ */ jsx("span", { className: "inline-block bg-primary text-primary-foreground px-4 py-1 rounded-full text-xs font-semibold mb-3", children: "Most Popular" }),
|
|
1656
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl sm:text-2xl font-bold mb-2", children: plan.name }),
|
|
1657
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: plan.description })
|
|
1658
|
+
] }),
|
|
1659
|
+
/* @__PURE__ */ jsx("div", { className: "text-center mb-8", children: /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-center gap-1", children: [
|
|
1660
|
+
/* @__PURE__ */ jsx("span", { className: "text-4xl sm:text-5xl font-bold", children: plan.price }),
|
|
1661
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-lg", children: plan.interval })
|
|
1662
|
+
] }) }),
|
|
1663
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-3 mb-8 flex-1", children: plan.features.map((feature, index) => /* @__PURE__ */ jsxs("li", { className: "text-sm flex items-start gap-2", children: [
|
|
1664
|
+
/* @__PURE__ */ jsx("span", { className: "text-primary mt-0.5 flex-shrink-0", children: "\u2713" }),
|
|
1665
|
+
/* @__PURE__ */ jsx("span", { children: feature })
|
|
1666
|
+
] }, index)) }),
|
|
1667
|
+
plan.ctaLink.startsWith("/") ? /* @__PURE__ */ jsx(
|
|
1668
|
+
Button,
|
|
1669
|
+
{
|
|
1670
|
+
className: "w-full h-11",
|
|
1671
|
+
variant: plan.popular ? "default" : "outline",
|
|
1672
|
+
size: "lg",
|
|
1673
|
+
asChild: true,
|
|
1674
|
+
children: /* @__PURE__ */ jsx(
|
|
1675
|
+
"a",
|
|
2828
1676
|
{
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
asChild: true,
|
|
2833
|
-
children: /* @__PURE__ */ jsx(
|
|
2834
|
-
"a",
|
|
2835
|
-
{
|
|
2836
|
-
href: btnLink,
|
|
2837
|
-
onClick: () => window.scrollTo({ top: 0, behavior: "smooth" }),
|
|
2838
|
-
children: btnText
|
|
2839
|
-
}
|
|
2840
|
-
)
|
|
1677
|
+
href: plan.ctaLink,
|
|
1678
|
+
onClick: () => window.scrollTo({ top: 0, behavior: "smooth" }),
|
|
1679
|
+
children: plan.ctaText
|
|
2841
1680
|
}
|
|
2842
|
-
)
|
|
2843
|
-
|
|
1681
|
+
)
|
|
1682
|
+
}
|
|
1683
|
+
) : /* @__PURE__ */ jsx(
|
|
1684
|
+
Button,
|
|
1685
|
+
{
|
|
1686
|
+
className: "w-full h-11",
|
|
1687
|
+
variant: plan.popular ? "default" : "outline",
|
|
1688
|
+
size: "lg",
|
|
1689
|
+
asChild: true,
|
|
1690
|
+
children: /* @__PURE__ */ jsx(
|
|
1691
|
+
"a",
|
|
2844
1692
|
{
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
children: /* @__PURE__ */ jsx(
|
|
2850
|
-
"a",
|
|
2851
|
-
{
|
|
2852
|
-
href: btnLink,
|
|
2853
|
-
target: "_blank",
|
|
2854
|
-
rel: "noopener noreferrer",
|
|
2855
|
-
children: btnText
|
|
2856
|
-
}
|
|
2857
|
-
)
|
|
1693
|
+
href: plan.ctaLink,
|
|
1694
|
+
target: "_blank",
|
|
1695
|
+
rel: "noopener noreferrer",
|
|
1696
|
+
children: plan.ctaText
|
|
2858
1697
|
}
|
|
2859
1698
|
)
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
)
|
|
2866
|
-
/* Individual API-fetched cards */
|
|
2867
|
-
plans.map((plan) => /* @__PURE__ */ jsxs(
|
|
2868
|
-
"div",
|
|
2869
|
-
{
|
|
2870
|
-
className: `bg-card rounded-xl p-6 sm:p-8 transition-all duration-300 flex flex-col ${plan.popular ? "border-2 border-primary shadow-xl ring-1 ring-primary/20" : "border hover:shadow-lg hover:border-primary/50"}`,
|
|
2871
|
-
children: [
|
|
2872
|
-
/* @__PURE__ */ jsxs("div", { className: "text-center mb-6", children: [
|
|
2873
|
-
plan.popular && /* @__PURE__ */ jsx("span", { className: "inline-block bg-primary text-primary-foreground px-4 py-1 rounded-full text-xs font-semibold mb-3", children: "Most Popular" }),
|
|
2874
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xl sm:text-2xl font-bold mb-2", children: plan.name }),
|
|
2875
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: plan.description })
|
|
2876
|
-
] }),
|
|
2877
|
-
/* @__PURE__ */ jsx("div", { className: "text-center mb-8", children: plan.price === "Custom" ? /* @__PURE__ */ jsx("span", { className: "text-3xl sm:text-4xl font-bold", children: "Custom" }) : /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-center gap-1", children: [
|
|
2878
|
-
/* @__PURE__ */ jsx("span", { className: "text-4xl sm:text-5xl font-bold", children: plan.price }),
|
|
2879
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-lg", children: plan.interval })
|
|
2880
|
-
] }) }),
|
|
2881
|
-
/* @__PURE__ */ jsx("ul", { className: "space-y-3 mb-8 flex-1", children: plan.features.map((feature, index) => /* @__PURE__ */ jsxs(
|
|
2882
|
-
"li",
|
|
2883
|
-
{
|
|
2884
|
-
className: "text-sm flex items-start gap-2",
|
|
2885
|
-
children: [
|
|
2886
|
-
/* @__PURE__ */ jsx("span", { className: "text-primary mt-0.5 flex-shrink-0", children: "\u2713" }),
|
|
2887
|
-
/* @__PURE__ */ jsx("span", { children: feature })
|
|
2888
|
-
]
|
|
2889
|
-
},
|
|
2890
|
-
index
|
|
2891
|
-
)) }),
|
|
2892
|
-
plan.ctaLink.startsWith("/") ? /* @__PURE__ */ jsx(
|
|
2893
|
-
Button,
|
|
2894
|
-
{
|
|
2895
|
-
className: "w-full h-11",
|
|
2896
|
-
variant: plan.popular ? "default" : "outline",
|
|
2897
|
-
size: "lg",
|
|
2898
|
-
asChild: true,
|
|
2899
|
-
children: /* @__PURE__ */ jsx(
|
|
2900
|
-
"a",
|
|
2901
|
-
{
|
|
2902
|
-
href: plan.ctaLink,
|
|
2903
|
-
onClick: () => window.scrollTo({ top: 0, behavior: "smooth" }),
|
|
2904
|
-
children: plan.ctaText
|
|
2905
|
-
}
|
|
2906
|
-
)
|
|
2907
|
-
}
|
|
2908
|
-
) : /* @__PURE__ */ jsx(
|
|
2909
|
-
Button,
|
|
2910
|
-
{
|
|
2911
|
-
className: "w-full h-11",
|
|
2912
|
-
variant: plan.popular ? "default" : "outline",
|
|
2913
|
-
size: "lg",
|
|
2914
|
-
asChild: true,
|
|
2915
|
-
children: /* @__PURE__ */ jsx(
|
|
2916
|
-
"a",
|
|
2917
|
-
{
|
|
2918
|
-
href: plan.ctaLink,
|
|
2919
|
-
target: "_blank",
|
|
2920
|
-
rel: "noopener noreferrer",
|
|
2921
|
-
children: plan.ctaText
|
|
2922
|
-
}
|
|
2923
|
-
)
|
|
2924
|
-
}
|
|
2925
|
-
)
|
|
2926
|
-
]
|
|
2927
|
-
},
|
|
2928
|
-
plan.id
|
|
2929
|
-
))
|
|
2930
|
-
) })
|
|
1699
|
+
}
|
|
1700
|
+
)
|
|
1701
|
+
]
|
|
1702
|
+
},
|
|
1703
|
+
plan.id
|
|
1704
|
+
)) })
|
|
2931
1705
|
] }) });
|
|
2932
1706
|
}
|
|
2933
1707
|
function PricingPage(props) {
|
|
@@ -3225,11 +1999,7 @@ function WaitlistPage({
|
|
|
3225
1999
|
}
|
|
3226
2000
|
setIsSubmitting(true);
|
|
3227
2001
|
try {
|
|
3228
|
-
const result = await joinWaitlist(
|
|
3229
|
-
client,
|
|
3230
|
-
data,
|
|
3231
|
-
product?.id || config.productId
|
|
3232
|
-
);
|
|
2002
|
+
const result = await joinWaitlist(client, data, config.productId);
|
|
3233
2003
|
if (result.success) {
|
|
3234
2004
|
toast.success(result.message ?? successMessage);
|
|
3235
2005
|
reset();
|
|
@@ -3378,7 +2148,7 @@ function WaitlistForm({
|
|
|
3378
2148
|
const result = await joinWaitlist(
|
|
3379
2149
|
client,
|
|
3380
2150
|
{ email, name: name || void 0 },
|
|
3381
|
-
|
|
2151
|
+
config.productId
|
|
3382
2152
|
);
|
|
3383
2153
|
if (result.success) {
|
|
3384
2154
|
toast.success(result.message ?? "You have been added to the waitlist!");
|
|
@@ -3729,2476 +2499,179 @@ function UnsubscribePage({
|
|
|
3729
2499
|
strokeLinejoin: "round",
|
|
3730
2500
|
d: "M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
|
|
3731
2501
|
}
|
|
3732
|
-
)
|
|
3733
|
-
}
|
|
3734
|
-
) }),
|
|
3735
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground mb-3", children: "Invalid Unsubscribe Link" }),
|
|
3736
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "This unsubscribe link is invalid or missing. If you want to unsubscribe, please use the link from your newsletter email." })
|
|
3737
|
-
] })
|
|
3738
|
-
] })
|
|
3739
|
-
]
|
|
3740
|
-
}
|
|
3741
|
-
);
|
|
3742
|
-
}
|
|
3743
|
-
function DiscordIcon({ className }) {
|
|
3744
|
-
return /* @__PURE__ */ jsx(
|
|
3745
|
-
"svg",
|
|
3746
|
-
{
|
|
3747
|
-
role: "img",
|
|
3748
|
-
viewBox: "0 0 24 24",
|
|
3749
|
-
fill: "currentColor",
|
|
3750
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
3751
|
-
className,
|
|
3752
|
-
"aria-hidden": "true",
|
|
3753
|
-
children: /* @__PURE__ */ jsx("path", { d: "M20.317 4.369A19.79 19.79 0 0 0 16.558 3a.075.075 0 0 0-.079.037c-.34.6-.717 1.382-.98 1.99a18.27 18.27 0 0 0-5.998 0 12.51 12.51 0 0 0-.99-1.99.077.077 0 0 0-.079-.037 19.74 19.74 0 0 0-3.76 1.369.07.07 0 0 0-.032.028C.533 8.045-.32 11.6.099 15.114a.082.082 0 0 0 .031.056 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.027 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.105 13.1 13.1 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.126-.094.252-.192.372-.291a.074.074 0 0 1 .078-.01c3.927 1.793 8.18 1.793 12.061 0a.074.074 0 0 1 .079.009c.12.099.246.198.372.292a.077.077 0 0 1-.006.127 12.3 12.3 0 0 1-1.873.892.077.077 0 0 0-.041.106c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.84 19.84 0 0 0 6.002-3.03.077.077 0 0 0 .032-.055c.5-4.063-.838-7.587-3.549-10.717a.061.061 0 0 0-.031-.028zM8.02 13.001c-1.182 0-2.157-1.085-2.157-2.419 0-1.333.956-2.418 2.157-2.418 1.21 0 2.176 1.094 2.157 2.418 0 1.334-.956 2.419-2.157 2.419zm7.974 0c-1.182 0-2.157-1.085-2.157-2.419 0-1.333.956-2.418 2.157-2.418 1.21 0 2.176 1.094 2.157 2.418 0 1.334-.946 2.419-2.157 2.419z" })
|
|
3754
|
-
}
|
|
3755
|
-
);
|
|
3756
|
-
}
|
|
3757
|
-
function PinterestIcon({ className }) {
|
|
3758
|
-
return /* @__PURE__ */ jsx(
|
|
3759
|
-
"svg",
|
|
3760
|
-
{
|
|
3761
|
-
role: "img",
|
|
3762
|
-
viewBox: "0 0 24 24",
|
|
3763
|
-
fill: "currentColor",
|
|
3764
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
3765
|
-
className,
|
|
3766
|
-
"aria-hidden": "true",
|
|
3767
|
-
children: /* @__PURE__ */ jsx("path", { d: "M12.017 0C5.396 0 .029 5.367.029 11.987c0 5.079 3.158 9.417 7.618 11.162-.105-.949-.199-2.403.041-3.439.219-.937 1.406-5.957 1.406-5.957s-.359-.72-.359-1.781c0-1.663.967-2.911 2.168-2.911 1.024 0 1.518.769 1.518 1.688 0 1.029-.653 2.567-.992 3.992-.285 1.193.6 2.165 1.775 2.165 2.128 0 3.768-2.245 3.768-5.487 0-2.861-2.063-4.869-5.008-4.869-3.41 0-5.409 2.562-5.409 5.199 0 1.033.394 2.143.889 2.741.099.12.112.225.085.345-.09.375-.293 1.199-.334 1.363-.053.225-.172.271-.401.165-1.495-.69-2.433-2.878-2.433-4.646 0-3.776 2.748-7.252 7.92-7.252 4.158 0 7.392 2.967 7.392 6.923 0 4.135-2.607 7.462-6.233 7.462-1.214 0-2.357-.629-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24 12.017 24c6.624 0 11.99-5.367 11.99-11.987C24.007 5.367 18.641 0 12.017 0z" })
|
|
3768
|
-
}
|
|
3769
|
-
);
|
|
3770
|
-
}
|
|
3771
|
-
var PLATFORMS = {
|
|
3772
|
-
twitter: { Icon: Twitter, label: "Twitter / X", aliases: ["x"] },
|
|
3773
|
-
linkedin: { Icon: Linkedin, label: "LinkedIn" },
|
|
3774
|
-
github: { Icon: Github, label: "GitHub" },
|
|
3775
|
-
facebook: { Icon: Facebook, label: "Facebook" },
|
|
3776
|
-
youtube: { Icon: Youtube, label: "YouTube" },
|
|
3777
|
-
instagram: { Icon: Instagram, label: "Instagram" },
|
|
3778
|
-
discord: { Icon: DiscordIcon, label: "Discord" },
|
|
3779
|
-
pinterest: { Icon: PinterestIcon, label: "Pinterest" }
|
|
3780
|
-
};
|
|
3781
|
-
var KEY_TO_PLATFORM = (() => {
|
|
3782
|
-
const map = {};
|
|
3783
|
-
for (const [key, def] of Object.entries(PLATFORMS)) {
|
|
3784
|
-
map[key] = key;
|
|
3785
|
-
for (const alias of def.aliases ?? []) {
|
|
3786
|
-
map[alias] = key;
|
|
3787
|
-
}
|
|
3788
|
-
}
|
|
3789
|
-
return map;
|
|
3790
|
-
})();
|
|
3791
|
-
var DEFAULT_ITEM_CLASS = "text-muted-foreground hover:text-foreground transition-colors";
|
|
3792
|
-
function isSafeUrl(value) {
|
|
3793
|
-
const trimmed = value.trim();
|
|
3794
|
-
if (/^[/?#]/.test(trimmed)) return true;
|
|
3795
|
-
return /^(https?:|mailto:|tel:)/i.test(trimmed);
|
|
3796
|
-
}
|
|
3797
|
-
function SocialLinks({
|
|
3798
|
-
links: linksProp,
|
|
3799
|
-
email: emailProp,
|
|
3800
|
-
platforms: platformAllow,
|
|
3801
|
-
showEmail,
|
|
3802
|
-
iconClassName = "h-5 w-5",
|
|
3803
|
-
itemClassName = DEFAULT_ITEM_CLASS,
|
|
3804
|
-
className = "flex space-x-4"
|
|
3805
|
-
}) {
|
|
3806
|
-
const { product } = useProduct();
|
|
3807
|
-
const links = linksProp ?? product?.socialLinks ?? {};
|
|
3808
|
-
const email = emailProp !== void 0 ? emailProp : product?.contactEmail ?? null;
|
|
3809
|
-
const resolved = /* @__PURE__ */ new Map();
|
|
3810
|
-
for (const [rawKey, url] of Object.entries(links)) {
|
|
3811
|
-
if (!url || typeof url !== "string") continue;
|
|
3812
|
-
if (!isSafeUrl(url)) continue;
|
|
3813
|
-
const platform = KEY_TO_PLATFORM[rawKey.toLowerCase()];
|
|
3814
|
-
if (!platform) continue;
|
|
3815
|
-
resolved.set(platform, url);
|
|
3816
|
-
}
|
|
3817
|
-
const orderedPlatforms = platformAllow ? platformAllow.filter((p) => resolved.has(p)) : Array.from(resolved.keys());
|
|
3818
|
-
const wantEmail = (showEmail ?? !!email) && !!email;
|
|
3819
|
-
if (orderedPlatforms.length === 0 && !wantEmail) return null;
|
|
3820
|
-
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
3821
|
-
orderedPlatforms.map((platform) => {
|
|
3822
|
-
const { Icon, label } = PLATFORMS[platform];
|
|
3823
|
-
const url = resolved.get(platform);
|
|
3824
|
-
return /* @__PURE__ */ jsx(
|
|
3825
|
-
"a",
|
|
3826
|
-
{
|
|
3827
|
-
href: url,
|
|
3828
|
-
target: "_blank",
|
|
3829
|
-
rel: "noopener noreferrer",
|
|
3830
|
-
"aria-label": label,
|
|
3831
|
-
className: itemClassName,
|
|
3832
|
-
children: /* @__PURE__ */ jsx(Icon, { className: iconClassName })
|
|
3833
|
-
},
|
|
3834
|
-
platform
|
|
3835
|
-
);
|
|
3836
|
-
}),
|
|
3837
|
-
wantEmail && /* @__PURE__ */ jsx(
|
|
3838
|
-
"a",
|
|
3839
|
-
{
|
|
3840
|
-
href: `mailto:${email}`,
|
|
3841
|
-
"aria-label": "Email",
|
|
3842
|
-
className: itemClassName,
|
|
3843
|
-
children: /* @__PURE__ */ jsx(Mail, { className: iconClassName })
|
|
3844
|
-
},
|
|
3845
|
-
"email"
|
|
3846
|
-
)
|
|
3847
|
-
] });
|
|
3848
|
-
}
|
|
3849
|
-
var DEFAULT_LABELS = {
|
|
3850
|
-
docs: "Docs",
|
|
3851
|
-
community: "Community",
|
|
3852
|
-
careers: "Careers",
|
|
3853
|
-
team: "Team",
|
|
3854
|
-
companies: "Sister Companies"
|
|
3855
|
-
};
|
|
3856
|
-
var BURDENOFF_GROUP_DEFAULTS = {
|
|
3857
|
-
docs: null,
|
|
3858
|
-
// per-product → read from `Product.docsUrl`
|
|
3859
|
-
community: null,
|
|
3860
|
-
// per-product → caller supplies via prop until CMS field exists
|
|
3861
|
-
careers: "https://burdenoff.com/careers",
|
|
3862
|
-
team: "https://burdenoff.com/team",
|
|
3863
|
-
companies: "https://burdenoff.com/companies"
|
|
3864
|
-
};
|
|
3865
|
-
var DEFAULT_ORDER = [
|
|
3866
|
-
"docs",
|
|
3867
|
-
"community",
|
|
3868
|
-
"careers",
|
|
3869
|
-
"team",
|
|
3870
|
-
"companies"
|
|
3871
|
-
];
|
|
3872
|
-
var DEFAULT_ITEM_CLASS2 = "text-sm text-muted-foreground hover:text-foreground transition-colors";
|
|
3873
|
-
function isSafeUrl2(value) {
|
|
3874
|
-
const trimmed = value.trim();
|
|
3875
|
-
if (/^[/?#]/.test(trimmed)) return true;
|
|
3876
|
-
return /^(https?:|mailto:|tel:)/i.test(trimmed);
|
|
3877
|
-
}
|
|
3878
|
-
function ResourceLinks({
|
|
3879
|
-
links: linksProp,
|
|
3880
|
-
resources = DEFAULT_ORDER,
|
|
3881
|
-
labels = {},
|
|
3882
|
-
className = "space-y-2",
|
|
3883
|
-
itemClassName = DEFAULT_ITEM_CLASS2
|
|
3884
|
-
}) {
|
|
3885
|
-
const { product } = useProduct();
|
|
3886
|
-
function resolve(resource) {
|
|
3887
|
-
if (linksProp && resource in linksProp) {
|
|
3888
|
-
const override = linksProp[resource];
|
|
3889
|
-
if (override === void 0) ; else {
|
|
3890
|
-
return override;
|
|
3891
|
-
}
|
|
3892
|
-
}
|
|
3893
|
-
const fromCms = product?.resourceLinks?.[resource];
|
|
3894
|
-
if (typeof fromCms === "string" && fromCms.length > 0) {
|
|
3895
|
-
return fromCms;
|
|
3896
|
-
}
|
|
3897
|
-
if (resource === "docs" && product?.docsUrl) {
|
|
3898
|
-
return product.docsUrl;
|
|
3899
|
-
}
|
|
3900
|
-
return BURDENOFF_GROUP_DEFAULTS[resource];
|
|
3901
|
-
}
|
|
3902
|
-
const items = resources.map((r) => ({ resource: r, url: resolve(r) })).filter(
|
|
3903
|
-
(x) => !!x.url && isSafeUrl2(x.url)
|
|
3904
|
-
);
|
|
3905
|
-
if (items.length === 0) return null;
|
|
3906
|
-
return /* @__PURE__ */ jsx("ul", { className, children: items.map(({ resource, url }) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
3907
|
-
"a",
|
|
3908
|
-
{
|
|
3909
|
-
href: url,
|
|
3910
|
-
target: "_blank",
|
|
3911
|
-
rel: "noopener noreferrer",
|
|
3912
|
-
className: itemClassName,
|
|
3913
|
-
children: labels[resource] ?? DEFAULT_LABELS[resource]
|
|
3914
|
-
}
|
|
3915
|
-
) }, resource)) });
|
|
3916
|
-
}
|
|
3917
|
-
function normalizeSearch(value) {
|
|
3918
|
-
return value.toLowerCase().trim();
|
|
3919
|
-
}
|
|
3920
|
-
function filterProducts(products, query) {
|
|
3921
|
-
const normalized = normalizeSearch(query);
|
|
3922
|
-
if (!normalized) return products;
|
|
3923
|
-
return products.filter((p) => normalizeSearch(p.name).includes(normalized));
|
|
3924
|
-
}
|
|
3925
|
-
function WebsiteSwitcher({
|
|
3926
|
-
products,
|
|
3927
|
-
triggerLabel = "Explore products",
|
|
3928
|
-
searchPlaceholder = "Find a product\u2026",
|
|
3929
|
-
emptyText = "No products match your search.",
|
|
3930
|
-
className
|
|
3931
|
-
}) {
|
|
3932
|
-
const [open, setOpen] = useState(false);
|
|
3933
|
-
const [query, setQuery] = useState("");
|
|
3934
|
-
const filtered = useMemo(
|
|
3935
|
-
() => filterProducts(products, query),
|
|
3936
|
-
[products, query]
|
|
3937
|
-
);
|
|
3938
|
-
return /* @__PURE__ */ jsxs(DropdownMenu.Root, { open, onOpenChange: setOpen, children: [
|
|
3939
|
-
/* @__PURE__ */ jsxs(
|
|
3940
|
-
DropdownMenu.Trigger,
|
|
3941
|
-
{
|
|
3942
|
-
className: cn(
|
|
3943
|
-
"inline-flex items-center gap-1.5 text-sm font-medium transition-colors",
|
|
3944
|
-
"text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring rounded-md",
|
|
3945
|
-
className
|
|
3946
|
-
),
|
|
3947
|
-
"aria-label": triggerLabel,
|
|
3948
|
-
children: [
|
|
3949
|
-
/* @__PURE__ */ jsx(Globe, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
3950
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: triggerLabel }),
|
|
3951
|
-
/* @__PURE__ */ jsx(
|
|
3952
|
-
ChevronDown,
|
|
3953
|
-
{
|
|
3954
|
-
className: cn(
|
|
3955
|
-
"h-3.5 w-3.5 transition-transform duration-200",
|
|
3956
|
-
open && "rotate-180"
|
|
3957
|
-
),
|
|
3958
|
-
"aria-hidden": "true"
|
|
3959
|
-
}
|
|
3960
|
-
)
|
|
3961
|
-
]
|
|
3962
|
-
}
|
|
3963
|
-
),
|
|
3964
|
-
/* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsxs(
|
|
3965
|
-
DropdownMenu.Content,
|
|
3966
|
-
{
|
|
3967
|
-
className: "z-50 min-w-[16rem] max-w-[20rem] rounded-lg border border-border/60 bg-popover p-2 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2",
|
|
3968
|
-
sideOffset: 8,
|
|
3969
|
-
align: "end",
|
|
3970
|
-
avoidCollisions: true,
|
|
3971
|
-
children: [
|
|
3972
|
-
/* @__PURE__ */ jsxs("div", { className: "px-2 pb-2 pt-1", children: [
|
|
3973
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Burdenoff ecosystem" }),
|
|
3974
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
3975
|
-
/* @__PURE__ */ jsx(
|
|
3976
|
-
Search,
|
|
3977
|
-
{
|
|
3978
|
-
className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground",
|
|
3979
|
-
"aria-hidden": "true"
|
|
3980
|
-
}
|
|
3981
|
-
),
|
|
3982
|
-
/* @__PURE__ */ jsx(
|
|
3983
|
-
Input,
|
|
3984
|
-
{
|
|
3985
|
-
type: "search",
|
|
3986
|
-
value: query,
|
|
3987
|
-
onChange: (e) => setQuery(e.target.value),
|
|
3988
|
-
placeholder: searchPlaceholder,
|
|
3989
|
-
className: "h-8 pl-8 text-sm",
|
|
3990
|
-
"aria-label": searchPlaceholder,
|
|
3991
|
-
onKeyDown: (e) => {
|
|
3992
|
-
if (e.key === "Escape") {
|
|
3993
|
-
setQuery("");
|
|
3994
|
-
}
|
|
3995
|
-
}
|
|
3996
|
-
}
|
|
3997
|
-
)
|
|
3998
|
-
] })
|
|
3999
|
-
] }),
|
|
4000
|
-
/* @__PURE__ */ jsx(DropdownMenu.Separator, { className: "my-1 h-px bg-border/60" }),
|
|
4001
|
-
/* @__PURE__ */ jsx("div", { className: "max-h-[min(60vh,24rem)] overflow-y-auto py-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filtered.map((product) => /* @__PURE__ */ jsx(DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
4002
|
-
"a",
|
|
4003
|
-
{
|
|
4004
|
-
href: product.websiteUrl,
|
|
4005
|
-
target: "_blank",
|
|
4006
|
-
rel: "noopener noreferrer",
|
|
4007
|
-
className: cn(
|
|
4008
|
-
"flex items-center gap-3 rounded-md px-2 py-2 text-sm outline-none",
|
|
4009
|
-
"text-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
|
|
4010
|
-
),
|
|
4011
|
-
children: [
|
|
4012
|
-
product.logoUrl ? /* @__PURE__ */ jsx(
|
|
4013
|
-
"img",
|
|
4014
|
-
{
|
|
4015
|
-
src: product.logoUrl,
|
|
4016
|
-
alt: "",
|
|
4017
|
-
"aria-hidden": "true",
|
|
4018
|
-
className: "h-5 w-5 shrink-0 rounded object-contain"
|
|
4019
|
-
}
|
|
4020
|
-
) : /* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded bg-primary/10 text-[10px] font-bold text-primary", children: product.name.charAt(0) }),
|
|
4021
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: product.name })
|
|
4022
|
-
]
|
|
4023
|
-
}
|
|
4024
|
-
) }, product.slug)) }),
|
|
4025
|
-
/* @__PURE__ */ jsx(DropdownMenu.Arrow, { className: "fill-popover" })
|
|
4026
|
-
]
|
|
4027
|
-
}
|
|
4028
|
-
) })
|
|
4029
|
-
] });
|
|
4030
|
-
}
|
|
4031
|
-
function splitRemaining(ms) {
|
|
4032
|
-
const clamped = Math.max(0, ms);
|
|
4033
|
-
const totalSeconds = Math.floor(clamped / 1e3);
|
|
4034
|
-
return {
|
|
4035
|
-
days: Math.floor(totalSeconds / 86400),
|
|
4036
|
-
hours: Math.floor(totalSeconds % 86400 / 3600),
|
|
4037
|
-
minutes: Math.floor(totalSeconds % 3600 / 60),
|
|
4038
|
-
seconds: totalSeconds % 60
|
|
4039
|
-
};
|
|
4040
|
-
}
|
|
4041
|
-
function padTwo(n) {
|
|
4042
|
-
return String(n).padStart(2, "0");
|
|
4043
|
-
}
|
|
4044
|
-
function LaunchCountdown({
|
|
4045
|
-
launchDate,
|
|
4046
|
-
launchLabel,
|
|
4047
|
-
launchedMessage = "We have launched!",
|
|
4048
|
-
className
|
|
4049
|
-
}) {
|
|
4050
|
-
const [now, setNow] = useState(() => Date.now());
|
|
4051
|
-
const remainingMs = launchDate - now;
|
|
4052
|
-
const hasLaunched = remainingMs <= 0;
|
|
4053
|
-
useEffect(() => {
|
|
4054
|
-
if (hasLaunched) return;
|
|
4055
|
-
const interval = setInterval(() => {
|
|
4056
|
-
setNow(Date.now());
|
|
4057
|
-
}, 1e3);
|
|
4058
|
-
return () => clearInterval(interval);
|
|
4059
|
-
}, [hasLaunched]);
|
|
4060
|
-
const { days, hours, minutes, seconds } = splitRemaining(remainingMs);
|
|
4061
|
-
const cells = [
|
|
4062
|
-
{ label: "Days", value: padTwo(Math.min(days, 99)) },
|
|
4063
|
-
{ label: "Hours", value: padTwo(hours) },
|
|
4064
|
-
{ label: "Minutes", value: padTwo(minutes) },
|
|
4065
|
-
{ label: "Seconds", value: padTwo(seconds) }
|
|
4066
|
-
];
|
|
4067
|
-
return /* @__PURE__ */ jsxs(
|
|
4068
|
-
"div",
|
|
4069
|
-
{
|
|
4070
|
-
className: cn("inline-flex flex-col gap-3", className),
|
|
4071
|
-
role: "timer",
|
|
4072
|
-
"aria-label": launchLabel ?? (hasLaunched ? launchedMessage : `Countdown to launch`),
|
|
4073
|
-
children: [
|
|
4074
|
-
!hasLaunched && /* @__PURE__ */ jsx("span", { className: "text-xs font-mono uppercase tracking-wider text-muted-foreground", children: "Launching in" }),
|
|
4075
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-2 sm:gap-3", children: hasLaunched ? /* @__PURE__ */ jsxs(
|
|
4076
|
-
"div",
|
|
4077
|
-
{
|
|
4078
|
-
className: cn(
|
|
4079
|
-
"flex min-w-[15rem] items-center justify-center gap-3 rounded-lg border border-primary/30 bg-primary/10 px-6 py-4",
|
|
4080
|
-
"text-center"
|
|
4081
|
-
),
|
|
4082
|
-
children: [
|
|
4083
|
-
/* @__PURE__ */ jsx(Rocket, { className: "h-5 w-5 text-primary", "aria-hidden": "true" }),
|
|
4084
|
-
/* @__PURE__ */ jsx("span", { className: "text-lg font-semibold text-foreground", children: launchedMessage })
|
|
4085
|
-
]
|
|
4086
|
-
}
|
|
4087
|
-
) : cells.map((cell) => /* @__PURE__ */ jsxs(
|
|
4088
|
-
"div",
|
|
4089
|
-
{
|
|
4090
|
-
className: cn(
|
|
4091
|
-
"flex min-w-[3.75rem] flex-col items-center rounded-lg border border-border/60 bg-card px-3 py-2 sm:min-w-[4.5rem] sm:px-4 sm:py-3"
|
|
4092
|
-
),
|
|
4093
|
-
children: [
|
|
4094
|
-
/* @__PURE__ */ jsx("span", { className: "font-mono text-2xl font-bold tabular-nums text-foreground sm:text-3xl", children: cell.value }),
|
|
4095
|
-
/* @__PURE__ */ jsx("span", { className: "mt-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground sm:text-xs", children: cell.label })
|
|
4096
|
-
]
|
|
4097
|
-
},
|
|
4098
|
-
cell.label
|
|
4099
|
-
)) }),
|
|
4100
|
-
!hasLaunched && launchLabel && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: launchLabel })
|
|
4101
|
-
]
|
|
4102
|
-
}
|
|
4103
|
-
);
|
|
4104
|
-
}
|
|
4105
|
-
function ProblemsSolvedSection({
|
|
4106
|
-
eyebrow,
|
|
4107
|
-
title,
|
|
4108
|
-
subtitle,
|
|
4109
|
-
problems,
|
|
4110
|
-
storyBasePath = "/use-cases",
|
|
4111
|
-
storyLabel = "See the story",
|
|
4112
|
-
className,
|
|
4113
|
-
children
|
|
4114
|
-
}) {
|
|
4115
|
-
return /* @__PURE__ */ jsx(
|
|
4116
|
-
"section",
|
|
4117
|
-
{
|
|
4118
|
-
className: cn(
|
|
4119
|
-
"py-16 md:py-24 px-4 sm:px-6 lg:px-8 bg-muted/30",
|
|
4120
|
-
className
|
|
4121
|
-
),
|
|
4122
|
-
children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto", children: [
|
|
4123
|
-
(eyebrow || title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "max-w-3xl mx-auto text-center mb-12 md:mb-16", children: [
|
|
4124
|
-
eyebrow && /* @__PURE__ */ jsx("p", { className: "text-xs font-mono uppercase tracking-widest text-primary mb-4", children: eyebrow }),
|
|
4125
|
-
title && /* @__PURE__ */ jsx("h2", { className: "text-3xl sm:text-4xl font-bold text-foreground mb-4", children: title }),
|
|
4126
|
-
subtitle && /* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground", children: subtitle })
|
|
4127
|
-
] }),
|
|
4128
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: problems.map((item, index) => {
|
|
4129
|
-
const Icon = item.icon;
|
|
4130
|
-
const storyHref = item.storySlug ? `${storyBasePath.replace(/\/$/, "")}/${item.storySlug}` : null;
|
|
4131
|
-
return /* @__PURE__ */ jsxs(
|
|
4132
|
-
"div",
|
|
4133
|
-
{
|
|
4134
|
-
className: cn(
|
|
4135
|
-
"group relative flex flex-col rounded-2xl border border-border/40 bg-card p-6 transition-colors",
|
|
4136
|
-
"hover:border-primary/30"
|
|
4137
|
-
),
|
|
4138
|
-
children: [
|
|
4139
|
-
/* @__PURE__ */ jsx(
|
|
4140
|
-
"div",
|
|
4141
|
-
{
|
|
4142
|
-
className: cn(
|
|
4143
|
-
"mb-5 inline-flex h-12 w-12 items-center justify-center rounded-xl",
|
|
4144
|
-
"bg-primary/10 text-primary"
|
|
4145
|
-
),
|
|
4146
|
-
children: /* @__PURE__ */ jsx(Icon, { className: "h-6 w-6", "aria-hidden": true })
|
|
4147
|
-
}
|
|
4148
|
-
),
|
|
4149
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground mb-2", children: item.problem }),
|
|
4150
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed mb-4 flex-1", children: item.solution }),
|
|
4151
|
-
storyHref && /* @__PURE__ */ jsx(
|
|
4152
|
-
Button,
|
|
4153
|
-
{
|
|
4154
|
-
variant: "ghost",
|
|
4155
|
-
className: "justify-start px-0 h-auto py-0 text-sm group/link",
|
|
4156
|
-
asChild: true,
|
|
4157
|
-
children: /* @__PURE__ */ jsxs(
|
|
4158
|
-
"a",
|
|
4159
|
-
{
|
|
4160
|
-
href: storyHref,
|
|
4161
|
-
className: "inline-flex items-center gap-1 text-primary hover:underline",
|
|
4162
|
-
children: [
|
|
4163
|
-
storyLabel,
|
|
4164
|
-
/* @__PURE__ */ jsx(
|
|
4165
|
-
ArrowRight,
|
|
4166
|
-
{
|
|
4167
|
-
className: "h-3.5 w-3.5 transition-transform group-hover/link:translate-x-0.5",
|
|
4168
|
-
"aria-hidden": "true"
|
|
4169
|
-
}
|
|
4170
|
-
)
|
|
4171
|
-
]
|
|
4172
|
-
}
|
|
4173
|
-
)
|
|
4174
|
-
}
|
|
4175
|
-
)
|
|
4176
|
-
]
|
|
4177
|
-
},
|
|
4178
|
-
`${item.problem}-${index}`
|
|
4179
|
-
);
|
|
4180
|
-
}) }),
|
|
4181
|
-
children && /* @__PURE__ */ jsx("div", { className: "mt-12", children })
|
|
4182
|
-
] })
|
|
4183
|
-
}
|
|
4184
|
-
);
|
|
4185
|
-
}
|
|
4186
|
-
function detectElectronPlatform(userAgent = typeof navigator !== "undefined" ? navigator.userAgent : "") {
|
|
4187
|
-
const ua = userAgent.toLowerCase();
|
|
4188
|
-
if (ua.includes("win")) return "win";
|
|
4189
|
-
if (ua.includes("mac")) return "mac";
|
|
4190
|
-
if (ua.includes("linux")) return "linux";
|
|
4191
|
-
return "unknown";
|
|
4192
|
-
}
|
|
4193
|
-
function buildDownloadUrl(base, artifactName, platform, platformMap) {
|
|
4194
|
-
const normalizedBase = base.replace(/\/$/, "");
|
|
4195
|
-
const platformKey = platformMap[platform] ?? platform;
|
|
4196
|
-
const fileName = artifactName.includes("{platform}") ? artifactName.replace(/\{platform\}/g, platformKey) : artifactName;
|
|
4197
|
-
return `${normalizedBase}/${fileName}`;
|
|
4198
|
-
}
|
|
4199
|
-
function ElectronDownloadLink({
|
|
4200
|
-
downloadBaseUrl,
|
|
4201
|
-
artifactName,
|
|
4202
|
-
hidden = true,
|
|
4203
|
-
label = "Download desktop app",
|
|
4204
|
-
downloadLabel = label,
|
|
4205
|
-
platformMap = {},
|
|
4206
|
-
className,
|
|
4207
|
-
variant = "default",
|
|
4208
|
-
size = "default"
|
|
4209
|
-
}) {
|
|
4210
|
-
if (hidden) return null;
|
|
4211
|
-
const platform = detectElectronPlatform();
|
|
4212
|
-
const href = buildDownloadUrl(
|
|
4213
|
-
downloadBaseUrl,
|
|
4214
|
-
artifactName,
|
|
4215
|
-
platform,
|
|
4216
|
-
platformMap
|
|
4217
|
-
);
|
|
4218
|
-
return /* @__PURE__ */ jsx(
|
|
4219
|
-
Button,
|
|
4220
|
-
{
|
|
4221
|
-
variant,
|
|
4222
|
-
size,
|
|
4223
|
-
className: cn("inline-flex items-center gap-2", className),
|
|
4224
|
-
asChild: true,
|
|
4225
|
-
children: /* @__PURE__ */ jsxs(
|
|
4226
|
-
"a",
|
|
4227
|
-
{
|
|
4228
|
-
href,
|
|
4229
|
-
download: true,
|
|
4230
|
-
"aria-label": `${downloadLabel}${platform !== "unknown" ? ` for ${platform}` : ""}`,
|
|
4231
|
-
children: [
|
|
4232
|
-
/* @__PURE__ */ jsx(Download, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
4233
|
-
label
|
|
4234
|
-
]
|
|
4235
|
-
}
|
|
4236
|
-
)
|
|
4237
|
-
}
|
|
4238
|
-
);
|
|
4239
|
-
}
|
|
4240
|
-
function RybbitAnalytics({
|
|
4241
|
-
siteId,
|
|
4242
|
-
scriptUrl = "https://analytics.burdenoff.com/api/script.js",
|
|
4243
|
-
enabled = true
|
|
4244
|
-
}) {
|
|
4245
|
-
useEffect(() => {
|
|
4246
|
-
if (!enabled || !siteId) return;
|
|
4247
|
-
const existingScript = document.querySelector(
|
|
4248
|
-
`script[data-site-id="${siteId}"]`
|
|
4249
|
-
);
|
|
4250
|
-
if (existingScript) return;
|
|
4251
|
-
const script = document.createElement("script");
|
|
4252
|
-
script.src = scriptUrl;
|
|
4253
|
-
script.defer = true;
|
|
4254
|
-
script.crossOrigin = "anonymous";
|
|
4255
|
-
script.setAttribute("data-site-id", siteId);
|
|
4256
|
-
document.head.appendChild(script);
|
|
4257
|
-
return () => {
|
|
4258
|
-
const scriptToRemove = document.querySelector(
|
|
4259
|
-
`script[data-site-id="${siteId}"]`
|
|
4260
|
-
);
|
|
4261
|
-
if (scriptToRemove) {
|
|
4262
|
-
document.head.removeChild(scriptToRemove);
|
|
4263
|
-
}
|
|
4264
|
-
};
|
|
4265
|
-
}, [siteId, scriptUrl, enabled]);
|
|
4266
|
-
return null;
|
|
4267
|
-
}
|
|
4268
|
-
var BLOG_POSTS_QUERY = `
|
|
4269
|
-
query BlogPosts($productId: String!, $limit: Int, $offset: Int) {
|
|
4270
|
-
publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
|
|
4271
|
-
items {
|
|
4272
|
-
id
|
|
4273
|
-
title
|
|
4274
|
-
slug
|
|
4275
|
-
lastUpdated
|
|
4276
|
-
tags
|
|
4277
|
-
seoDescription
|
|
4278
|
-
excerpt
|
|
4279
|
-
thumbnail
|
|
4280
|
-
author
|
|
4281
|
-
publishedAt
|
|
4282
|
-
readingTime
|
|
4283
|
-
featured
|
|
4284
|
-
category
|
|
4285
|
-
}
|
|
4286
|
-
total
|
|
4287
|
-
hasMore
|
|
4288
|
-
}
|
|
4289
|
-
}
|
|
4290
|
-
`;
|
|
4291
|
-
var BLOG_POST_QUERY = `
|
|
4292
|
-
query BlogPost($slug: String!, $productId: String) {
|
|
4293
|
-
publicContentPage(slug: $slug, productId: $productId) {
|
|
4294
|
-
id
|
|
4295
|
-
title
|
|
4296
|
-
slug
|
|
4297
|
-
content
|
|
4298
|
-
contentFormat
|
|
4299
|
-
seoTitle
|
|
4300
|
-
seoDescription
|
|
4301
|
-
seoKeywords
|
|
4302
|
-
lastUpdated
|
|
4303
|
-
tags
|
|
4304
|
-
excerpt
|
|
4305
|
-
thumbnail
|
|
4306
|
-
author
|
|
4307
|
-
publishedAt
|
|
4308
|
-
readingTime
|
|
4309
|
-
featured
|
|
4310
|
-
category
|
|
4311
|
-
}
|
|
4312
|
-
}
|
|
4313
|
-
`;
|
|
4314
|
-
function BlogCard({
|
|
4315
|
-
post,
|
|
4316
|
-
basePath = "/blog"
|
|
4317
|
-
}) {
|
|
4318
|
-
const date = post.publishedAt || post.lastUpdated;
|
|
4319
|
-
const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
|
|
4320
|
-
year: "numeric",
|
|
4321
|
-
month: "long",
|
|
4322
|
-
day: "numeric"
|
|
4323
|
-
}) : "";
|
|
4324
|
-
const [imgError, setImgError] = useState(false);
|
|
4325
|
-
return /* @__PURE__ */ jsxs(
|
|
4326
|
-
"a",
|
|
4327
|
-
{
|
|
4328
|
-
href: `${basePath}/${post.slug}`,
|
|
4329
|
-
className: "group block bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300",
|
|
4330
|
-
children: [
|
|
4331
|
-
post.thumbnail && !imgError ? /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
4332
|
-
"img",
|
|
4333
|
-
{
|
|
4334
|
-
src: post.thumbnail,
|
|
4335
|
-
alt: post.title,
|
|
4336
|
-
className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300",
|
|
4337
|
-
loading: "lazy",
|
|
4338
|
-
onError: () => setImgError(true)
|
|
4339
|
-
}
|
|
4340
|
-
) }) : /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
4341
|
-
"svg",
|
|
4342
|
-
{
|
|
4343
|
-
className: "w-12 h-12 text-muted-foreground/20",
|
|
4344
|
-
fill: "none",
|
|
4345
|
-
viewBox: "0 0 24 24",
|
|
4346
|
-
stroke: "currentColor",
|
|
4347
|
-
children: /* @__PURE__ */ jsx(
|
|
4348
|
-
"path",
|
|
4349
|
-
{
|
|
4350
|
-
strokeLinecap: "round",
|
|
4351
|
-
strokeLinejoin: "round",
|
|
4352
|
-
strokeWidth: 1.5,
|
|
4353
|
-
d: "M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
|
4354
|
-
}
|
|
4355
|
-
)
|
|
4356
|
-
}
|
|
4357
|
-
) }),
|
|
4358
|
-
/* @__PURE__ */ jsxs("div", { className: "p-5 sm:p-6", children: [
|
|
4359
|
-
post.category && /* @__PURE__ */ jsx("span", { className: "inline-block text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-3", children: post.category }),
|
|
4360
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground mb-2 group-hover:text-primary transition-colors line-clamp-2", children: post.title }),
|
|
4361
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4 line-clamp-3", children: post.excerpt || post.seoDescription || "" }),
|
|
4362
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
4363
|
-
post.author && /* @__PURE__ */ jsx("span", { className: "font-medium", children: post.author }),
|
|
4364
|
-
post.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
4365
|
-
formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
|
|
4366
|
-
post.readingTime && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4367
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
4368
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
4369
|
-
post.readingTime,
|
|
4370
|
-
" min read"
|
|
4371
|
-
] })
|
|
4372
|
-
] })
|
|
4373
|
-
] })
|
|
4374
|
-
] })
|
|
4375
|
-
]
|
|
4376
|
-
}
|
|
4377
|
-
);
|
|
4378
|
-
}
|
|
4379
|
-
function BlogListPage(props) {
|
|
4380
|
-
const {
|
|
4381
|
-
productName,
|
|
4382
|
-
heroTitle = "Blog",
|
|
4383
|
-
heroSubtitle = "Latest updates, engineering insights, and product news",
|
|
4384
|
-
blogPostBasePath = "/blog",
|
|
4385
|
-
className = "",
|
|
4386
|
-
seoTitle,
|
|
4387
|
-
seoDescription,
|
|
4388
|
-
seoKeywords
|
|
4389
|
-
} = props;
|
|
4390
|
-
const client = useWebSDK();
|
|
4391
|
-
const config = useWebSDKConfig();
|
|
4392
|
-
const { product } = useProduct();
|
|
4393
|
-
const resolvedProductId = product?.id || config.productId;
|
|
4394
|
-
const [posts, setPosts] = useState([]);
|
|
4395
|
-
const [total, setTotal] = useState(0);
|
|
4396
|
-
const [loading, setLoading] = useState(true);
|
|
4397
|
-
const [error, setError] = useState(null);
|
|
4398
|
-
const [offset, setOffset] = useState(0);
|
|
4399
|
-
const limit = 12;
|
|
4400
|
-
const fetchPosts = useCallback(async () => {
|
|
4401
|
-
if (!resolvedProductId) return;
|
|
4402
|
-
setLoading(true);
|
|
4403
|
-
try {
|
|
4404
|
-
const result = await client.query(BLOG_POSTS_QUERY, {
|
|
4405
|
-
productId: resolvedProductId,
|
|
4406
|
-
limit,
|
|
4407
|
-
offset
|
|
4408
|
-
});
|
|
4409
|
-
if (result.errors?.length) {
|
|
4410
|
-
setError(result.errors[0]?.message ?? "Failed to load posts");
|
|
4411
|
-
return;
|
|
4412
|
-
}
|
|
4413
|
-
const blogPosts = (result.data?.publicContentPages?.items || []).filter(
|
|
4414
|
-
(p) => p.tags?.includes("blog")
|
|
4415
|
-
);
|
|
4416
|
-
setPosts(blogPosts);
|
|
4417
|
-
setTotal(result.data?.publicContentPages?.total || 0);
|
|
4418
|
-
setError(null);
|
|
4419
|
-
} catch {
|
|
4420
|
-
setError("Failed to load blog posts");
|
|
4421
|
-
} finally {
|
|
4422
|
-
setLoading(false);
|
|
4423
|
-
}
|
|
4424
|
-
}, [client, resolvedProductId, offset]);
|
|
4425
|
-
useEffect(() => {
|
|
4426
|
-
fetchPosts();
|
|
4427
|
-
}, [fetchPosts]);
|
|
4428
|
-
const featuredPosts = posts.filter((p) => p.featured);
|
|
4429
|
-
const regularPosts = posts.filter((p) => !p.featured);
|
|
4430
|
-
return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
|
|
4431
|
-
seoTitle && /* @__PURE__ */ jsx(
|
|
4432
|
-
PageHead,
|
|
4433
|
-
{
|
|
4434
|
-
title: seoTitle,
|
|
4435
|
-
description: seoDescription || heroSubtitle,
|
|
4436
|
-
productName,
|
|
4437
|
-
keywords: seoKeywords
|
|
4438
|
-
}
|
|
4439
|
-
),
|
|
4440
|
-
/* @__PURE__ */ jsx("section", { className: "py-16 sm:py-20 md:py-24", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-3xl mx-auto", children: [
|
|
4441
|
-
/* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground", children: heroTitle }),
|
|
4442
|
-
/* @__PURE__ */ jsx("p", { className: "mt-4 text-lg text-muted-foreground", children: heroSubtitle })
|
|
4443
|
-
] }) }) }),
|
|
4444
|
-
/* @__PURE__ */ jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: loading ? /* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs(
|
|
4445
|
-
"div",
|
|
4446
|
-
{
|
|
4447
|
-
className: "bg-card border rounded-xl overflow-hidden animate-pulse",
|
|
4448
|
-
children: [
|
|
4449
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted" }),
|
|
4450
|
-
/* @__PURE__ */ jsxs("div", { className: "p-6 space-y-3", children: [
|
|
4451
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
|
|
4452
|
-
/* @__PURE__ */ jsx("div", { className: "h-6 bg-muted rounded w-3/4" }),
|
|
4453
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded" }),
|
|
4454
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
|
|
4455
|
-
] })
|
|
4456
|
-
]
|
|
4457
|
-
},
|
|
4458
|
-
i
|
|
4459
|
-
)) }) : error ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: error }) }) : posts.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No blog posts yet. Check back soon!" }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4460
|
-
featuredPosts.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 gap-6 sm:gap-8 mb-8", children: featuredPosts.map((post) => /* @__PURE__ */ jsx(
|
|
4461
|
-
BlogCard,
|
|
4462
|
-
{
|
|
4463
|
-
post,
|
|
4464
|
-
basePath: blogPostBasePath
|
|
4465
|
-
},
|
|
4466
|
-
post.id
|
|
4467
|
-
)) }),
|
|
4468
|
-
/* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8", children: regularPosts.map((post) => /* @__PURE__ */ jsx(
|
|
4469
|
-
BlogCard,
|
|
4470
|
-
{
|
|
4471
|
-
post,
|
|
4472
|
-
basePath: blogPostBasePath
|
|
4473
|
-
},
|
|
4474
|
-
post.id
|
|
4475
|
-
)) }),
|
|
4476
|
-
total > limit && /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4 mt-12", children: [
|
|
4477
|
-
/* @__PURE__ */ jsx(
|
|
4478
|
-
"button",
|
|
4479
|
-
{
|
|
4480
|
-
onClick: () => setOffset(Math.max(0, offset - limit)),
|
|
4481
|
-
disabled: offset === 0,
|
|
4482
|
-
className: "px-5 py-2.5 text-sm font-medium border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
|
|
4483
|
-
children: "Previous"
|
|
4484
|
-
}
|
|
4485
|
-
),
|
|
4486
|
-
/* @__PURE__ */ jsx(
|
|
4487
|
-
"button",
|
|
4488
|
-
{
|
|
4489
|
-
onClick: () => setOffset(offset + limit),
|
|
4490
|
-
disabled: offset + limit >= total,
|
|
4491
|
-
className: "px-5 py-2.5 text-sm font-medium border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
|
|
4492
|
-
children: "Next"
|
|
4493
|
-
}
|
|
4494
|
-
)
|
|
4495
|
-
] })
|
|
4496
|
-
] }) }) })
|
|
4497
|
-
] });
|
|
4498
|
-
}
|
|
4499
|
-
function BlogPostPage(props) {
|
|
4500
|
-
const {
|
|
4501
|
-
productName,
|
|
4502
|
-
blogListUrl = "/blog",
|
|
4503
|
-
backLabel = "Back to Blog",
|
|
4504
|
-
className = ""
|
|
4505
|
-
} = props;
|
|
4506
|
-
const client = useWebSDK();
|
|
4507
|
-
const config = useWebSDKConfig();
|
|
4508
|
-
const { product } = useProduct();
|
|
4509
|
-
const resolvedProductId = product?.id || config.productId;
|
|
4510
|
-
const [post, setPost] = useState(null);
|
|
4511
|
-
const [loading, setLoading] = useState(true);
|
|
4512
|
-
const [error, setError] = useState(null);
|
|
4513
|
-
const slug = typeof window !== "undefined" ? window.location.pathname.split("/").pop() || "" : "";
|
|
4514
|
-
useEffect(() => {
|
|
4515
|
-
if (!slug || !resolvedProductId) return;
|
|
4516
|
-
async function fetchPost() {
|
|
4517
|
-
setLoading(true);
|
|
4518
|
-
try {
|
|
4519
|
-
const result = await client.query(BLOG_POST_QUERY, {
|
|
4520
|
-
slug,
|
|
4521
|
-
productId: resolvedProductId
|
|
4522
|
-
});
|
|
4523
|
-
if (result.errors?.length) {
|
|
4524
|
-
setError(result.errors[0]?.message ?? "Failed to load post");
|
|
4525
|
-
return;
|
|
4526
|
-
}
|
|
4527
|
-
setPost(result.data?.publicContentPage ?? null);
|
|
4528
|
-
setError(null);
|
|
4529
|
-
} catch {
|
|
4530
|
-
setError("Failed to load blog post");
|
|
4531
|
-
} finally {
|
|
4532
|
-
setLoading(false);
|
|
4533
|
-
}
|
|
4534
|
-
}
|
|
4535
|
-
fetchPost();
|
|
4536
|
-
}, [client, slug, resolvedProductId]);
|
|
4537
|
-
if (loading) {
|
|
4538
|
-
return /* @__PURE__ */ jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-6", children: [
|
|
4539
|
-
/* @__PURE__ */ jsx("div", { className: "h-8 bg-muted rounded w-2/3" }),
|
|
4540
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/3" }),
|
|
4541
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted rounded-xl" }),
|
|
4542
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded" }, i)) })
|
|
4543
|
-
] }) }) });
|
|
4544
|
-
}
|
|
4545
|
-
if (error || !post) {
|
|
4546
|
-
return /* @__PURE__ */ jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24 text-center", children: [
|
|
4547
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold mb-4", children: "Post not found" }),
|
|
4548
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-6", children: error || "This blog post doesn't exist or has been removed." }),
|
|
4549
|
-
/* @__PURE__ */ jsxs(
|
|
4550
|
-
"a",
|
|
4551
|
-
{
|
|
4552
|
-
href: blogListUrl,
|
|
4553
|
-
className: "text-primary hover:underline font-medium",
|
|
4554
|
-
children: [
|
|
4555
|
-
"\u2190 ",
|
|
4556
|
-
backLabel
|
|
4557
|
-
]
|
|
4558
|
-
}
|
|
4559
|
-
)
|
|
4560
|
-
] }) });
|
|
4561
|
-
}
|
|
4562
|
-
const date = post.publishedAt || post.lastUpdated;
|
|
4563
|
-
const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
|
|
4564
|
-
year: "numeric",
|
|
4565
|
-
month: "long",
|
|
4566
|
-
day: "numeric"
|
|
4567
|
-
}) : "";
|
|
4568
|
-
return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
|
|
4569
|
-
/* @__PURE__ */ jsx(
|
|
4570
|
-
PageHead,
|
|
4571
|
-
{
|
|
4572
|
-
title: post.seoTitle || post.title,
|
|
4573
|
-
description: post.seoDescription || post.excerpt || "",
|
|
4574
|
-
productName,
|
|
4575
|
-
keywords: post.seoKeywords || ""
|
|
4576
|
-
}
|
|
4577
|
-
),
|
|
4578
|
-
/* @__PURE__ */ jsxs("article", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20", children: [
|
|
4579
|
-
/* @__PURE__ */ jsxs(
|
|
4580
|
-
"a",
|
|
4581
|
-
{
|
|
4582
|
-
href: blogListUrl,
|
|
4583
|
-
className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-8 transition-colors",
|
|
4584
|
-
children: [
|
|
4585
|
-
"\u2190 ",
|
|
4586
|
-
backLabel
|
|
4587
|
-
]
|
|
4588
|
-
}
|
|
4589
|
-
),
|
|
4590
|
-
post.category && /* @__PURE__ */ 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 }),
|
|
4591
|
-
/* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground mb-4", children: post.title }),
|
|
4592
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm text-muted-foreground mb-8", children: [
|
|
4593
|
-
post.author && /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: post.author }),
|
|
4594
|
-
post.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
4595
|
-
formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
|
|
4596
|
-
post.readingTime && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4597
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
4598
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
4599
|
-
post.readingTime,
|
|
4600
|
-
" min read"
|
|
4601
|
-
] })
|
|
4602
|
-
] })
|
|
4603
|
-
] }),
|
|
4604
|
-
post.thumbnail && /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] rounded-xl overflow-hidden mb-10", children: /* @__PURE__ */ jsx(
|
|
4605
|
-
"img",
|
|
4606
|
-
{
|
|
4607
|
-
src: post.thumbnail,
|
|
4608
|
-
alt: post.title,
|
|
4609
|
-
className: "w-full h-full object-cover"
|
|
4610
|
-
}
|
|
4611
|
-
) }),
|
|
4612
|
-
/* @__PURE__ */ jsx("div", { className: "prose prose-gray dark:prose-invert max-w-none", children: /* @__PURE__ */ jsx(ContentRenderer, { content: post.content, format: post.contentFormat }) })
|
|
4613
|
-
] })
|
|
4614
|
-
] });
|
|
4615
|
-
}
|
|
4616
|
-
var CASE_STUDY_TAG = "case-study";
|
|
4617
|
-
var CASE_STUDIES_QUERY = `
|
|
4618
|
-
query CaseStudies($productId: String!, $limit: Int, $offset: Int) {
|
|
4619
|
-
publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
|
|
4620
|
-
items {
|
|
4621
|
-
id
|
|
4622
|
-
title
|
|
4623
|
-
slug
|
|
4624
|
-
lastUpdated
|
|
4625
|
-
tags
|
|
4626
|
-
seoDescription
|
|
4627
|
-
excerpt
|
|
4628
|
-
thumbnail
|
|
4629
|
-
author
|
|
4630
|
-
publishedAt
|
|
4631
|
-
readingTime
|
|
4632
|
-
featured
|
|
4633
|
-
category
|
|
4634
|
-
}
|
|
4635
|
-
total
|
|
4636
|
-
hasMore
|
|
4637
|
-
}
|
|
4638
|
-
}
|
|
4639
|
-
`;
|
|
4640
|
-
var CASE_STUDY_QUERY = `
|
|
4641
|
-
query CaseStudy($slug: String!, $productId: String) {
|
|
4642
|
-
publicContentPage(slug: $slug, productId: $productId) {
|
|
4643
|
-
id
|
|
4644
|
-
title
|
|
4645
|
-
slug
|
|
4646
|
-
content
|
|
4647
|
-
contentFormat
|
|
4648
|
-
seoTitle
|
|
4649
|
-
seoDescription
|
|
4650
|
-
seoKeywords
|
|
4651
|
-
lastUpdated
|
|
4652
|
-
tags
|
|
4653
|
-
excerpt
|
|
4654
|
-
thumbnail
|
|
4655
|
-
author
|
|
4656
|
-
publishedAt
|
|
4657
|
-
readingTime
|
|
4658
|
-
featured
|
|
4659
|
-
category
|
|
4660
|
-
}
|
|
4661
|
-
}
|
|
4662
|
-
`;
|
|
4663
|
-
function CaseStudyCard({
|
|
4664
|
-
post,
|
|
4665
|
-
basePath = "/case-studies"
|
|
4666
|
-
}) {
|
|
4667
|
-
const date = post.publishedAt || post.lastUpdated;
|
|
4668
|
-
const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
|
|
4669
|
-
year: "numeric",
|
|
4670
|
-
month: "long",
|
|
4671
|
-
day: "numeric"
|
|
4672
|
-
}) : "";
|
|
4673
|
-
const [imgError, setImgError] = useState(false);
|
|
4674
|
-
return /* @__PURE__ */ jsxs(
|
|
4675
|
-
"a",
|
|
4676
|
-
{
|
|
4677
|
-
href: `${basePath}/${post.slug}`,
|
|
4678
|
-
className: "group block bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300",
|
|
4679
|
-
children: [
|
|
4680
|
-
post.thumbnail && !imgError ? /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
4681
|
-
"img",
|
|
4682
|
-
{
|
|
4683
|
-
src: post.thumbnail,
|
|
4684
|
-
alt: post.title,
|
|
4685
|
-
className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300",
|
|
4686
|
-
loading: "lazy",
|
|
4687
|
-
onError: () => setImgError(true)
|
|
4688
|
-
}
|
|
4689
|
-
) }) : /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
4690
|
-
"svg",
|
|
4691
|
-
{
|
|
4692
|
-
className: "w-12 h-12 text-muted-foreground/20",
|
|
4693
|
-
fill: "none",
|
|
4694
|
-
viewBox: "0 0 24 24",
|
|
4695
|
-
stroke: "currentColor",
|
|
4696
|
-
children: /* @__PURE__ */ jsx(
|
|
4697
|
-
"path",
|
|
4698
|
-
{
|
|
4699
|
-
strokeLinecap: "round",
|
|
4700
|
-
strokeLinejoin: "round",
|
|
4701
|
-
strokeWidth: 1.5,
|
|
4702
|
-
d: "M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
|
4703
|
-
}
|
|
4704
|
-
)
|
|
4705
|
-
}
|
|
4706
|
-
) }),
|
|
4707
|
-
/* @__PURE__ */ jsxs("div", { className: "p-5 sm:p-6", children: [
|
|
4708
|
-
post.category && /* @__PURE__ */ jsx("span", { className: "inline-block text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-3", children: post.category }),
|
|
4709
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground mb-2 group-hover:text-primary transition-colors line-clamp-2", children: post.title }),
|
|
4710
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4 line-clamp-3", children: post.excerpt || post.seoDescription || "" }),
|
|
4711
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
4712
|
-
post.author && /* @__PURE__ */ jsx("span", { className: "font-medium", children: post.author }),
|
|
4713
|
-
post.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
4714
|
-
formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
|
|
4715
|
-
post.readingTime && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4716
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
4717
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
4718
|
-
post.readingTime,
|
|
4719
|
-
" min read"
|
|
4720
|
-
] })
|
|
4721
|
-
] })
|
|
4722
|
-
] })
|
|
4723
|
-
] })
|
|
4724
|
-
]
|
|
4725
|
-
}
|
|
4726
|
-
);
|
|
4727
|
-
}
|
|
4728
|
-
function CaseStudiesListPage(props) {
|
|
4729
|
-
const {
|
|
4730
|
-
productName,
|
|
4731
|
-
heroTitle = "Case Studies",
|
|
4732
|
-
heroSubtitle = "Real-world stories of teams building with our platform",
|
|
4733
|
-
caseStudyBasePath = "/case-studies",
|
|
4734
|
-
className = "",
|
|
4735
|
-
seoTitle,
|
|
4736
|
-
seoDescription,
|
|
4737
|
-
seoKeywords
|
|
4738
|
-
} = props;
|
|
4739
|
-
const client = useWebSDK();
|
|
4740
|
-
const config = useWebSDKConfig();
|
|
4741
|
-
const { product } = useProduct();
|
|
4742
|
-
const resolvedProductId = product?.id || config.productId;
|
|
4743
|
-
const [posts, setPosts] = useState([]);
|
|
4744
|
-
const [total, setTotal] = useState(0);
|
|
4745
|
-
const [loading, setLoading] = useState(true);
|
|
4746
|
-
const [error, setError] = useState(null);
|
|
4747
|
-
const [offset, setOffset] = useState(0);
|
|
4748
|
-
const limit = 12;
|
|
4749
|
-
const fetchPosts = useCallback(async () => {
|
|
4750
|
-
if (!resolvedProductId) return;
|
|
4751
|
-
setLoading(true);
|
|
4752
|
-
try {
|
|
4753
|
-
const result = await client.query(CASE_STUDIES_QUERY, {
|
|
4754
|
-
productId: resolvedProductId,
|
|
4755
|
-
limit,
|
|
4756
|
-
offset
|
|
4757
|
-
});
|
|
4758
|
-
if (result.errors?.length) {
|
|
4759
|
-
setError(result.errors[0]?.message ?? "Failed to load case studies");
|
|
4760
|
-
return;
|
|
4761
|
-
}
|
|
4762
|
-
const caseStudies = (result.data?.publicContentPages?.items || []).filter(
|
|
4763
|
-
(p) => p.tags?.includes(CASE_STUDY_TAG)
|
|
4764
|
-
);
|
|
4765
|
-
setPosts(caseStudies);
|
|
4766
|
-
setTotal(result.data?.publicContentPages?.total || 0);
|
|
4767
|
-
setError(null);
|
|
4768
|
-
} catch {
|
|
4769
|
-
setError("Failed to load case studies");
|
|
4770
|
-
} finally {
|
|
4771
|
-
setLoading(false);
|
|
4772
|
-
}
|
|
4773
|
-
}, [client, resolvedProductId, offset]);
|
|
4774
|
-
useEffect(() => {
|
|
4775
|
-
fetchPosts();
|
|
4776
|
-
}, [fetchPosts]);
|
|
4777
|
-
const featuredPosts = posts.filter((p) => p.featured);
|
|
4778
|
-
const regularPosts = posts.filter((p) => !p.featured);
|
|
4779
|
-
return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
|
|
4780
|
-
seoTitle && /* @__PURE__ */ jsx(
|
|
4781
|
-
PageHead,
|
|
4782
|
-
{
|
|
4783
|
-
title: seoTitle,
|
|
4784
|
-
description: seoDescription || heroSubtitle,
|
|
4785
|
-
productName,
|
|
4786
|
-
keywords: seoKeywords
|
|
4787
|
-
}
|
|
4788
|
-
),
|
|
4789
|
-
/* @__PURE__ */ jsx("section", { className: "py-16 sm:py-20 md:py-24", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-3xl mx-auto", children: [
|
|
4790
|
-
/* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground", children: heroTitle }),
|
|
4791
|
-
/* @__PURE__ */ jsx("p", { className: "mt-4 text-lg text-muted-foreground", children: heroSubtitle })
|
|
4792
|
-
] }) }) }),
|
|
4793
|
-
/* @__PURE__ */ jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: loading ? /* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs(
|
|
4794
|
-
"div",
|
|
4795
|
-
{
|
|
4796
|
-
className: "bg-card border rounded-xl overflow-hidden animate-pulse",
|
|
4797
|
-
children: [
|
|
4798
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted" }),
|
|
4799
|
-
/* @__PURE__ */ jsxs("div", { className: "p-6 space-y-3", children: [
|
|
4800
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
|
|
4801
|
-
/* @__PURE__ */ jsx("div", { className: "h-6 bg-muted rounded w-3/4" }),
|
|
4802
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded" }),
|
|
4803
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
|
|
4804
|
-
] })
|
|
4805
|
-
]
|
|
4806
|
-
},
|
|
4807
|
-
i
|
|
4808
|
-
)) }) : error ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: error }) }) : posts.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No case studies yet. Check back soon!" }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4809
|
-
featuredPosts.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 gap-6 sm:gap-8 mb-8", children: featuredPosts.map((post) => /* @__PURE__ */ jsx(
|
|
4810
|
-
CaseStudyCard,
|
|
4811
|
-
{
|
|
4812
|
-
post,
|
|
4813
|
-
basePath: caseStudyBasePath
|
|
4814
|
-
},
|
|
4815
|
-
post.id
|
|
4816
|
-
)) }),
|
|
4817
|
-
/* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8", children: regularPosts.map((post) => /* @__PURE__ */ jsx(
|
|
4818
|
-
CaseStudyCard,
|
|
4819
|
-
{
|
|
4820
|
-
post,
|
|
4821
|
-
basePath: caseStudyBasePath
|
|
4822
|
-
},
|
|
4823
|
-
post.id
|
|
4824
|
-
)) }),
|
|
4825
|
-
total > limit && /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4 mt-12", children: [
|
|
4826
|
-
/* @__PURE__ */ jsx(
|
|
4827
|
-
"button",
|
|
4828
|
-
{
|
|
4829
|
-
onClick: () => setOffset(Math.max(0, offset - limit)),
|
|
4830
|
-
disabled: offset === 0,
|
|
4831
|
-
className: "px-5 py-2.5 text-sm font-medium border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
|
|
4832
|
-
children: "Previous"
|
|
4833
|
-
}
|
|
4834
|
-
),
|
|
4835
|
-
/* @__PURE__ */ jsx(
|
|
4836
|
-
"button",
|
|
4837
|
-
{
|
|
4838
|
-
onClick: () => setOffset(offset + limit),
|
|
4839
|
-
disabled: offset + limit >= total,
|
|
4840
|
-
className: "px-5 py-2.5 text-sm font-medium border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
|
|
4841
|
-
children: "Next"
|
|
4842
|
-
}
|
|
4843
|
-
)
|
|
4844
|
-
] })
|
|
4845
|
-
] }) }) })
|
|
4846
|
-
] });
|
|
4847
|
-
}
|
|
4848
|
-
function CaseStudyPage(props) {
|
|
4849
|
-
const {
|
|
4850
|
-
productName,
|
|
4851
|
-
caseStudiesListUrl = "/case-studies",
|
|
4852
|
-
backLabel = "Back to Case Studies",
|
|
4853
|
-
className = ""
|
|
4854
|
-
} = props;
|
|
4855
|
-
const client = useWebSDK();
|
|
4856
|
-
const config = useWebSDKConfig();
|
|
4857
|
-
const { product } = useProduct();
|
|
4858
|
-
const resolvedProductId = product?.id || config.productId;
|
|
4859
|
-
const [post, setPost] = useState(null);
|
|
4860
|
-
const [loading, setLoading] = useState(true);
|
|
4861
|
-
const [error, setError] = useState(null);
|
|
4862
|
-
const slug = typeof window !== "undefined" ? window.location.pathname.split("/").pop() || "" : "";
|
|
4863
|
-
useEffect(() => {
|
|
4864
|
-
if (!slug || !resolvedProductId) return;
|
|
4865
|
-
async function fetchPost() {
|
|
4866
|
-
setLoading(true);
|
|
4867
|
-
try {
|
|
4868
|
-
const result = await client.query(CASE_STUDY_QUERY, {
|
|
4869
|
-
slug,
|
|
4870
|
-
productId: resolvedProductId
|
|
4871
|
-
});
|
|
4872
|
-
if (result.errors?.length) {
|
|
4873
|
-
setError(result.errors[0]?.message ?? "Failed to load case study");
|
|
4874
|
-
return;
|
|
4875
|
-
}
|
|
4876
|
-
setPost(result.data?.publicContentPage ?? null);
|
|
4877
|
-
setError(null);
|
|
4878
|
-
} catch {
|
|
4879
|
-
setError("Failed to load case study");
|
|
4880
|
-
} finally {
|
|
4881
|
-
setLoading(false);
|
|
4882
|
-
}
|
|
4883
|
-
}
|
|
4884
|
-
fetchPost();
|
|
4885
|
-
}, [client, slug, resolvedProductId]);
|
|
4886
|
-
if (loading) {
|
|
4887
|
-
return /* @__PURE__ */ jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-6", children: [
|
|
4888
|
-
/* @__PURE__ */ jsx("div", { className: "h-8 bg-muted rounded w-2/3" }),
|
|
4889
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/3" }),
|
|
4890
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted rounded-xl" }),
|
|
4891
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded" }, i)) })
|
|
4892
|
-
] }) }) });
|
|
4893
|
-
}
|
|
4894
|
-
if (error || !post) {
|
|
4895
|
-
return /* @__PURE__ */ jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24 text-center", children: [
|
|
4896
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold mb-4", children: "Case study not found" }),
|
|
4897
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-6", children: error || "This case study doesn't exist or has been removed." }),
|
|
4898
|
-
/* @__PURE__ */ jsxs(
|
|
4899
|
-
"a",
|
|
4900
|
-
{
|
|
4901
|
-
href: caseStudiesListUrl,
|
|
4902
|
-
className: "text-primary hover:underline font-medium",
|
|
4903
|
-
children: [
|
|
4904
|
-
"\u2190 ",
|
|
4905
|
-
backLabel
|
|
4906
|
-
]
|
|
4907
|
-
}
|
|
4908
|
-
)
|
|
4909
|
-
] }) });
|
|
4910
|
-
}
|
|
4911
|
-
const date = post.publishedAt || post.lastUpdated;
|
|
4912
|
-
const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
|
|
4913
|
-
year: "numeric",
|
|
4914
|
-
month: "long",
|
|
4915
|
-
day: "numeric"
|
|
4916
|
-
}) : "";
|
|
4917
|
-
return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
|
|
4918
|
-
/* @__PURE__ */ jsx(
|
|
4919
|
-
PageHead,
|
|
4920
|
-
{
|
|
4921
|
-
title: post.seoTitle || post.title,
|
|
4922
|
-
description: post.seoDescription || post.excerpt || "",
|
|
4923
|
-
productName,
|
|
4924
|
-
keywords: post.seoKeywords || ""
|
|
4925
|
-
}
|
|
4926
|
-
),
|
|
4927
|
-
/* @__PURE__ */ jsxs("article", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20", children: [
|
|
4928
|
-
/* @__PURE__ */ jsxs(
|
|
4929
|
-
"a",
|
|
4930
|
-
{
|
|
4931
|
-
href: caseStudiesListUrl,
|
|
4932
|
-
className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-8 transition-colors",
|
|
4933
|
-
children: [
|
|
4934
|
-
"\u2190 ",
|
|
4935
|
-
backLabel
|
|
4936
|
-
]
|
|
4937
|
-
}
|
|
4938
|
-
),
|
|
4939
|
-
post.category && /* @__PURE__ */ 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 }),
|
|
4940
|
-
/* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground mb-4", children: post.title }),
|
|
4941
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm text-muted-foreground mb-8", children: [
|
|
4942
|
-
post.author && /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: post.author }),
|
|
4943
|
-
post.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
4944
|
-
formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
|
|
4945
|
-
post.readingTime && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4946
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
4947
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
4948
|
-
post.readingTime,
|
|
4949
|
-
" min read"
|
|
4950
|
-
] })
|
|
4951
|
-
] })
|
|
4952
|
-
] }),
|
|
4953
|
-
post.thumbnail && /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] rounded-xl overflow-hidden mb-10", children: /* @__PURE__ */ jsx(
|
|
4954
|
-
"img",
|
|
4955
|
-
{
|
|
4956
|
-
src: post.thumbnail,
|
|
4957
|
-
alt: post.title,
|
|
4958
|
-
className: "w-full h-full object-cover"
|
|
4959
|
-
}
|
|
4960
|
-
) }),
|
|
4961
|
-
/* @__PURE__ */ jsx("div", { className: "prose prose-gray dark:prose-invert max-w-none", children: /* @__PURE__ */ jsx(ContentRenderer, { content: post.content, format: post.contentFormat }) })
|
|
4962
|
-
] })
|
|
4963
|
-
] });
|
|
4964
|
-
}
|
|
4965
|
-
var CHANGELOG_TAG = "changelog";
|
|
4966
|
-
var CHANGELOG_LIST_QUERY = `
|
|
4967
|
-
query ChangelogList($productId: String!, $limit: Int, $offset: Int) {
|
|
4968
|
-
publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
|
|
4969
|
-
items {
|
|
4970
|
-
id
|
|
4971
|
-
title
|
|
4972
|
-
slug
|
|
4973
|
-
lastUpdated
|
|
4974
|
-
tags
|
|
4975
|
-
excerpt
|
|
4976
|
-
seoDescription
|
|
4977
|
-
thumbnail
|
|
4978
|
-
author
|
|
4979
|
-
publishedAt
|
|
4980
|
-
readingTime
|
|
4981
|
-
featured
|
|
4982
|
-
category
|
|
4983
|
-
}
|
|
4984
|
-
total
|
|
4985
|
-
hasMore
|
|
4986
|
-
}
|
|
4987
|
-
}
|
|
4988
|
-
`;
|
|
4989
|
-
var CHANGELOG_ENTRY_QUERY = `
|
|
4990
|
-
query ChangelogEntry($slug: String!, $productId: String) {
|
|
4991
|
-
publicContentPage(slug: $slug, productId: $productId) {
|
|
4992
|
-
content
|
|
4993
|
-
contentFormat
|
|
4994
|
-
}
|
|
4995
|
-
}
|
|
4996
|
-
`;
|
|
4997
|
-
function formatDate(value) {
|
|
4998
|
-
if (!value) return "";
|
|
4999
|
-
return new Date(value).toLocaleDateString("en-US", {
|
|
5000
|
-
year: "numeric",
|
|
5001
|
-
month: "long",
|
|
5002
|
-
day: "numeric"
|
|
5003
|
-
});
|
|
5004
|
-
}
|
|
5005
|
-
function sortByDateDesc(a, b) {
|
|
5006
|
-
const da = new Date(a.publishedAt || a.lastUpdated || 0).getTime();
|
|
5007
|
-
const db = new Date(b.publishedAt || b.lastUpdated || 0).getTime();
|
|
5008
|
-
return db - da;
|
|
5009
|
-
}
|
|
5010
|
-
function normalize(value) {
|
|
5011
|
-
return value.toLowerCase().trim();
|
|
5012
|
-
}
|
|
5013
|
-
function paginate(items, page, pageSize) {
|
|
5014
|
-
const start = (page - 1) * pageSize;
|
|
5015
|
-
return items.slice(start, start + pageSize);
|
|
5016
|
-
}
|
|
5017
|
-
function parseEntryDate(date) {
|
|
5018
|
-
return new Date(date).getTime();
|
|
5019
|
-
}
|
|
5020
|
-
function useCmsChangelog() {
|
|
5021
|
-
const client = useWebSDK();
|
|
5022
|
-
const config = useWebSDKConfig();
|
|
5023
|
-
const { product } = useProduct();
|
|
5024
|
-
const resolvedProductId = product?.id || config.productId;
|
|
5025
|
-
const [entries, setEntries] = useState([]);
|
|
5026
|
-
const [loading, setLoading] = useState(true);
|
|
5027
|
-
const [error, setError] = useState(null);
|
|
5028
|
-
const fetchEntries = useCallback(async () => {
|
|
5029
|
-
if (!resolvedProductId) {
|
|
5030
|
-
setLoading(false);
|
|
5031
|
-
return;
|
|
5032
|
-
}
|
|
5033
|
-
setLoading(true);
|
|
5034
|
-
try {
|
|
5035
|
-
const listResult = await client.query(CHANGELOG_LIST_QUERY, {
|
|
5036
|
-
productId: resolvedProductId,
|
|
5037
|
-
limit: 50,
|
|
5038
|
-
offset: 0
|
|
5039
|
-
});
|
|
5040
|
-
if (listResult.errors?.length) {
|
|
5041
|
-
setError(listResult.errors[0]?.message ?? "Failed to load changelog");
|
|
5042
|
-
return;
|
|
5043
|
-
}
|
|
5044
|
-
const changelogItems = (listResult.data?.publicContentPages?.items || []).filter((p) => p.tags?.includes(CHANGELOG_TAG)).sort(sortByDateDesc);
|
|
5045
|
-
const resolved = await Promise.all(
|
|
5046
|
-
changelogItems.map(async (item) => {
|
|
5047
|
-
try {
|
|
5048
|
-
const detail = await client.query(CHANGELOG_ENTRY_QUERY, {
|
|
5049
|
-
slug: item.slug,
|
|
5050
|
-
productId: resolvedProductId
|
|
5051
|
-
});
|
|
5052
|
-
const page = detail.data?.publicContentPage;
|
|
5053
|
-
return {
|
|
5054
|
-
...item,
|
|
5055
|
-
content: page?.content,
|
|
5056
|
-
contentFormat: page?.contentFormat
|
|
5057
|
-
};
|
|
5058
|
-
} catch {
|
|
5059
|
-
return { ...item };
|
|
5060
|
-
}
|
|
5061
|
-
})
|
|
5062
|
-
);
|
|
5063
|
-
setEntries(resolved);
|
|
5064
|
-
setError(null);
|
|
5065
|
-
} catch {
|
|
5066
|
-
setError("Failed to load changelog");
|
|
5067
|
-
} finally {
|
|
5068
|
-
setLoading(false);
|
|
5069
|
-
}
|
|
5070
|
-
}, [client, resolvedProductId]);
|
|
5071
|
-
useEffect(() => {
|
|
5072
|
-
fetchEntries();
|
|
5073
|
-
}, [fetchEntries]);
|
|
5074
|
-
return { entries, loading, error };
|
|
5075
|
-
}
|
|
5076
|
-
function CmsTimeline(props) {
|
|
5077
|
-
const { entries, loading, error } = props;
|
|
5078
|
-
if (loading) {
|
|
5079
|
-
return /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto space-y-12", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsx(
|
|
5080
|
-
"div",
|
|
5081
|
-
{
|
|
5082
|
-
className: "rounded-2xl border border-border/40 bg-card overflow-hidden animate-pulse",
|
|
5083
|
-
children: /* @__PURE__ */ jsxs("div", { className: "p-6 sm:p-8 space-y-4", children: [
|
|
5084
|
-
/* @__PURE__ */ jsx("div", { className: "h-3 bg-muted rounded w-1/3" }),
|
|
5085
|
-
/* @__PURE__ */ jsx("div", { className: "h-6 bg-muted rounded w-2/3" }),
|
|
5086
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded" }),
|
|
5087
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-5/6" })
|
|
5088
|
-
] })
|
|
5089
|
-
},
|
|
5090
|
-
i
|
|
5091
|
-
)) });
|
|
5092
|
-
}
|
|
5093
|
-
if (error) {
|
|
5094
|
-
return /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: error }) });
|
|
5095
|
-
}
|
|
5096
|
-
if (entries.length === 0) {
|
|
5097
|
-
return /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No changelog entries yet. Check back soon!" }) });
|
|
5098
|
-
}
|
|
5099
|
-
return /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto space-y-12", children: entries.map((entry) => /* @__PURE__ */ jsxs(
|
|
5100
|
-
"article",
|
|
5101
|
-
{
|
|
5102
|
-
id: entry.slug,
|
|
5103
|
-
className: "rounded-2xl border border-border/40 bg-card overflow-hidden scroll-mt-24",
|
|
5104
|
-
children: [
|
|
5105
|
-
entry.thumbnail && /* @__PURE__ */ jsx(
|
|
5106
|
-
"img",
|
|
5107
|
-
{
|
|
5108
|
-
src: entry.thumbnail,
|
|
5109
|
-
alt: "",
|
|
5110
|
-
width: 1024,
|
|
5111
|
-
height: 576,
|
|
5112
|
-
loading: "lazy",
|
|
5113
|
-
decoding: "async",
|
|
5114
|
-
className: "w-full aspect-video object-cover border-b border-border/40"
|
|
5115
|
-
}
|
|
5116
|
-
),
|
|
5117
|
-
/* @__PURE__ */ jsxs("div", { className: "p-6 sm:p-8", children: [
|
|
5118
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground mb-2", children: [
|
|
5119
|
-
entry.publishedAt && /* @__PURE__ */ jsx("time", { dateTime: entry.publishedAt, children: formatDate(entry.publishedAt || entry.lastUpdated) }),
|
|
5120
|
-
entry.author && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5121
|
-
" \xB7 ",
|
|
5122
|
-
entry.author
|
|
5123
|
-
] })
|
|
5124
|
-
] }),
|
|
5125
|
-
/* @__PURE__ */ jsx("h2", { className: "text-xl sm:text-2xl font-bold text-foreground mb-4", children: entry.title }),
|
|
5126
|
-
entry.content ? /* @__PURE__ */ jsx("div", { className: "prose prose-sm prose-gray dark:prose-invert max-w-none", children: /* @__PURE__ */ jsx(
|
|
5127
|
-
ContentRenderer,
|
|
5128
|
-
{
|
|
5129
|
-
content: entry.content,
|
|
5130
|
-
format: entry.contentFormat
|
|
5131
|
-
}
|
|
5132
|
-
) }) : entry.excerpt && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: entry.excerpt })
|
|
5133
|
-
] })
|
|
5134
|
-
]
|
|
5135
|
-
},
|
|
5136
|
-
entry.id
|
|
5137
|
-
)) });
|
|
5138
|
-
}
|
|
5139
|
-
function EntryContent({ content }) {
|
|
5140
|
-
if (typeof content === "string") {
|
|
5141
|
-
return /* @__PURE__ */ jsx("div", { className: "prose prose-sm prose-gray dark:prose-invert max-w-none", children: /* @__PURE__ */ jsx(ContentRenderer, { content, format: "markdown" }) });
|
|
5142
|
-
}
|
|
5143
|
-
return /* @__PURE__ */ jsx("div", { className: "prose prose-sm max-w-none", children: content });
|
|
5144
|
-
}
|
|
5145
|
-
function EntriesTimeline(props) {
|
|
5146
|
-
const { entries, pageSize, productName } = props;
|
|
5147
|
-
const [query, setQuery] = useState("");
|
|
5148
|
-
const [selectedCategory, setSelectedCategory] = useState(null);
|
|
5149
|
-
const [page, setPage] = useState(1);
|
|
5150
|
-
const categories = useMemo(
|
|
5151
|
-
() => Array.from(new Set(entries.map((e) => e.category))).sort(),
|
|
5152
|
-
[entries]
|
|
5153
|
-
);
|
|
5154
|
-
const filtered = useMemo(() => {
|
|
5155
|
-
const normalized = normalize(query);
|
|
5156
|
-
return entries.filter((entry) => {
|
|
5157
|
-
if (selectedCategory && entry.category !== selectedCategory) {
|
|
5158
|
-
return false;
|
|
5159
|
-
}
|
|
5160
|
-
if (!normalized) return true;
|
|
5161
|
-
const haystack = [
|
|
5162
|
-
entry.title,
|
|
5163
|
-
entry.version,
|
|
5164
|
-
entry.category,
|
|
5165
|
-
...entry.tags ?? [],
|
|
5166
|
-
typeof entry.content === "string" ? entry.content : ""
|
|
5167
|
-
].join(" ").toLowerCase();
|
|
5168
|
-
return haystack.includes(normalized);
|
|
5169
|
-
}).sort((a, b) => parseEntryDate(b.date) - parseEntryDate(a.date));
|
|
5170
|
-
}, [entries, query, selectedCategory]);
|
|
5171
|
-
const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
|
|
5172
|
-
const safePage = Math.min(page, totalPages);
|
|
5173
|
-
const pageItems = paginate(filtered, safePage, pageSize);
|
|
5174
|
-
useEffect(() => {
|
|
5175
|
-
setPage(1);
|
|
5176
|
-
}, [query, selectedCategory]);
|
|
5177
|
-
if (entries.length === 0) {
|
|
5178
|
-
return /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No changelog entries yet. Check back soon!" }) });
|
|
5179
|
-
}
|
|
5180
|
-
return /* @__PURE__ */ jsxs("div", { className: "max-w-3xl mx-auto", children: [
|
|
5181
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-8 space-y-4", children: [
|
|
5182
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
5183
|
-
/* @__PURE__ */ jsx(
|
|
5184
|
-
Search,
|
|
5185
|
-
{
|
|
5186
|
-
className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground",
|
|
5187
|
-
"aria-hidden": "true"
|
|
5188
|
-
}
|
|
5189
|
-
),
|
|
5190
|
-
/* @__PURE__ */ jsx(
|
|
5191
|
-
Input,
|
|
5192
|
-
{
|
|
5193
|
-
type: "search",
|
|
5194
|
-
placeholder: "Search releases, features, fixes\u2026",
|
|
5195
|
-
value: query,
|
|
5196
|
-
onChange: (e) => setQuery(e.target.value),
|
|
5197
|
-
className: "pl-9",
|
|
5198
|
-
"aria-label": "Search changelog"
|
|
5199
|
-
}
|
|
5200
|
-
)
|
|
5201
|
-
] }),
|
|
5202
|
-
categories.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
5203
|
-
/* @__PURE__ */ jsx(
|
|
5204
|
-
"button",
|
|
5205
|
-
{
|
|
5206
|
-
type: "button",
|
|
5207
|
-
onClick: () => setSelectedCategory(null),
|
|
5208
|
-
className: cn(
|
|
5209
|
-
"px-3 py-1 rounded-full text-xs font-medium border transition-colors",
|
|
5210
|
-
selectedCategory === null ? "bg-primary text-primary-foreground border-primary" : "bg-background text-muted-foreground border-border/60 hover:border-primary/40"
|
|
5211
|
-
),
|
|
5212
|
-
children: "All"
|
|
5213
|
-
}
|
|
5214
|
-
),
|
|
5215
|
-
categories.map((category) => /* @__PURE__ */ jsx(
|
|
5216
|
-
"button",
|
|
5217
|
-
{
|
|
5218
|
-
type: "button",
|
|
5219
|
-
onClick: () => setSelectedCategory(category),
|
|
5220
|
-
className: cn(
|
|
5221
|
-
"px-3 py-1 rounded-full text-xs font-medium border transition-colors",
|
|
5222
|
-
selectedCategory === category ? "bg-primary text-primary-foreground border-primary" : "bg-background text-muted-foreground border-border/60 hover:border-primary/40"
|
|
5223
|
-
),
|
|
5224
|
-
children: category
|
|
5225
|
-
},
|
|
5226
|
-
category
|
|
5227
|
-
))
|
|
5228
|
-
] })
|
|
5229
|
-
] }),
|
|
5230
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
5231
|
-
/* @__PURE__ */ jsx(
|
|
5232
|
-
"div",
|
|
5233
|
-
{
|
|
5234
|
-
className: "absolute left-[1.125rem] top-3 bottom-3 w-px bg-border/60 hidden sm:block",
|
|
5235
|
-
"aria-hidden": "true"
|
|
5236
|
-
}
|
|
5237
|
-
),
|
|
5238
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-8", children: pageItems.map((entry) => /* @__PURE__ */ jsxs(
|
|
5239
|
-
"article",
|
|
5240
|
-
{
|
|
5241
|
-
className: "relative sm:pl-12",
|
|
5242
|
-
children: [
|
|
5243
|
-
/* @__PURE__ */ jsx(
|
|
5244
|
-
"div",
|
|
5245
|
-
{
|
|
5246
|
-
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",
|
|
5247
|
-
"aria-hidden": "true",
|
|
5248
|
-
children: /* @__PURE__ */ jsx("span", { className: "h-2 w-2 rounded-full bg-primary-foreground" })
|
|
5249
|
-
}
|
|
5250
|
-
),
|
|
5251
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-2xl border border-border/40 bg-card overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "p-6 sm:p-8", children: [
|
|
5252
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 mb-3", children: [
|
|
5253
|
-
/* @__PURE__ */ 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 }),
|
|
5254
|
-
/* @__PURE__ */ 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: [
|
|
5255
|
-
"v",
|
|
5256
|
-
entry.version
|
|
5257
|
-
] }),
|
|
5258
|
-
/* @__PURE__ */ jsx(
|
|
5259
|
-
"time",
|
|
5260
|
-
{
|
|
5261
|
-
className: "text-xs text-muted-foreground",
|
|
5262
|
-
dateTime: entry.date,
|
|
5263
|
-
children: formatDate(entry.date)
|
|
5264
|
-
}
|
|
5265
|
-
)
|
|
5266
|
-
] }),
|
|
5267
|
-
entry.tags && entry.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5 mb-3", children: entry.tags.map((tag) => /* @__PURE__ */ jsx(
|
|
5268
|
-
"span",
|
|
5269
|
-
{
|
|
5270
|
-
className: "text-[10px] uppercase tracking-wide text-muted-foreground bg-background border border-border/40 px-1.5 py-0.5 rounded",
|
|
5271
|
-
children: tag
|
|
5272
|
-
},
|
|
5273
|
-
tag
|
|
5274
|
-
)) }),
|
|
5275
|
-
/* @__PURE__ */ jsx("h2", { className: "text-xl sm:text-2xl font-bold text-foreground mb-4", children: entry.title }),
|
|
5276
|
-
/* @__PURE__ */ jsx(EntryContent, { content: entry.content })
|
|
5277
|
-
] }) })
|
|
5278
|
-
]
|
|
5279
|
-
},
|
|
5280
|
-
`${entry.version}-${entry.date}`
|
|
5281
|
-
)) })
|
|
5282
|
-
] }),
|
|
5283
|
-
pageItems.length === 0 && /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No entries match your filters." }) }),
|
|
5284
|
-
totalPages > 1 && /* @__PURE__ */ jsxs("div", { className: "mt-10 flex items-center justify-between", children: [
|
|
5285
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
5286
|
-
"Page ",
|
|
5287
|
-
safePage,
|
|
5288
|
-
" of ",
|
|
5289
|
-
totalPages,
|
|
5290
|
-
" \xB7 ",
|
|
5291
|
-
filtered.length,
|
|
5292
|
-
" entries"
|
|
5293
|
-
] }),
|
|
5294
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
5295
|
-
/* @__PURE__ */ jsx(
|
|
5296
|
-
Button,
|
|
5297
|
-
{
|
|
5298
|
-
variant: "outline",
|
|
5299
|
-
size: "sm",
|
|
5300
|
-
onClick: () => setPage((p) => Math.max(1, p - 1)),
|
|
5301
|
-
disabled: safePage <= 1,
|
|
5302
|
-
"aria-label": "Previous page",
|
|
5303
|
-
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
|
|
5304
|
-
}
|
|
5305
|
-
),
|
|
5306
|
-
/* @__PURE__ */ jsx(
|
|
5307
|
-
Button,
|
|
5308
|
-
{
|
|
5309
|
-
variant: "outline",
|
|
5310
|
-
size: "sm",
|
|
5311
|
-
onClick: () => setPage((p) => Math.min(totalPages, p + 1)),
|
|
5312
|
-
disabled: safePage >= totalPages,
|
|
5313
|
-
"aria-label": "Next page",
|
|
5314
|
-
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
|
|
5315
|
-
}
|
|
5316
|
-
)
|
|
5317
|
-
] })
|
|
5318
|
-
] }),
|
|
5319
|
-
productName && pageItems.length > 0 && /* @__PURE__ */ jsx("script", { type: "application/ld+json", children: JSON.stringify({
|
|
5320
|
-
"@context": "https://schema.org",
|
|
5321
|
-
"@type": "ItemList",
|
|
5322
|
-
name: `${productName} Changelog`,
|
|
5323
|
-
itemListElement: pageItems.map((entry, index) => ({
|
|
5324
|
-
"@type": "ListItem",
|
|
5325
|
-
position: (safePage - 1) * pageSize + index + 1,
|
|
5326
|
-
name: entry.title,
|
|
5327
|
-
description: typeof entry.content === "string" ? entry.content.slice(0, 200) : void 0,
|
|
5328
|
-
datePublished: entry.date
|
|
5329
|
-
}))
|
|
5330
|
-
}) })
|
|
5331
|
-
] });
|
|
5332
|
-
}
|
|
5333
|
-
function ChangelogPage(props) {
|
|
5334
|
-
const {
|
|
5335
|
-
productName,
|
|
5336
|
-
heroEyebrow = "What's new",
|
|
5337
|
-
heroTitle = "Changelog",
|
|
5338
|
-
heroSubtitle = "Platform updates, improvements, and announcements \u2014 newest first.",
|
|
5339
|
-
ctaTitle,
|
|
5340
|
-
ctaSubtitle,
|
|
5341
|
-
ctaHref,
|
|
5342
|
-
ctaLabel,
|
|
5343
|
-
className = "",
|
|
5344
|
-
seoTitle,
|
|
5345
|
-
seoDescription,
|
|
5346
|
-
seoKeywords,
|
|
5347
|
-
entries,
|
|
5348
|
-
pageSize = 10
|
|
5349
|
-
} = props;
|
|
5350
|
-
const { product } = useProduct();
|
|
5351
|
-
const resolvedProductName = productName || product?.name;
|
|
5352
|
-
const cms = useCmsChangelog();
|
|
5353
|
-
const showCta = Boolean(ctaHref && ctaLabel);
|
|
5354
|
-
const isPropDriven = entries != null;
|
|
5355
|
-
return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
|
|
5356
|
-
/* @__PURE__ */ jsx(
|
|
5357
|
-
PageHead,
|
|
5358
|
-
{
|
|
5359
|
-
title: seoTitle || heroTitle,
|
|
5360
|
-
description: seoDescription || heroSubtitle,
|
|
5361
|
-
productName: resolvedProductName,
|
|
5362
|
-
keywords: seoKeywords
|
|
5363
|
-
}
|
|
5364
|
-
),
|
|
5365
|
-
/* @__PURE__ */ jsx("section", { className: "py-16 md:py-20 px-4 sm:px-6 lg:px-8 text-center", children: /* @__PURE__ */ jsxs("div", { className: "max-w-3xl mx-auto", children: [
|
|
5366
|
-
/* @__PURE__ */ 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: [
|
|
5367
|
-
/* @__PURE__ */ jsx(History, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
5368
|
-
heroEyebrow
|
|
5369
|
-
] }),
|
|
5370
|
-
/* @__PURE__ */ jsx("h1", { className: "text-4xl sm:text-5xl font-bold text-foreground mb-4", children: heroTitle }),
|
|
5371
|
-
/* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground", children: heroSubtitle })
|
|
5372
|
-
] }) }),
|
|
5373
|
-
/* @__PURE__ */ jsx("section", { className: "px-4 sm:px-6 lg:px-8 pb-20", children: isPropDriven ? /* @__PURE__ */ jsx(
|
|
5374
|
-
EntriesTimeline,
|
|
5375
|
-
{
|
|
5376
|
-
entries,
|
|
5377
|
-
pageSize,
|
|
5378
|
-
productName: resolvedProductName
|
|
5379
|
-
}
|
|
5380
|
-
) : /* @__PURE__ */ jsx(
|
|
5381
|
-
CmsTimeline,
|
|
5382
|
-
{
|
|
5383
|
-
entries: cms.entries,
|
|
5384
|
-
loading: cms.loading,
|
|
5385
|
-
error: cms.error
|
|
5386
|
-
}
|
|
5387
|
-
) }),
|
|
5388
|
-
showCta && /* @__PURE__ */ jsx("section", { className: "py-14 px-4 sm:px-6 lg:px-8 bg-primary/5 border-t border-border/40", children: /* @__PURE__ */ jsxs("div", { className: "max-w-2xl mx-auto text-center", children: [
|
|
5389
|
-
ctaTitle && /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold text-foreground mb-3", children: ctaTitle }),
|
|
5390
|
-
ctaSubtitle && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-7", children: ctaSubtitle }),
|
|
5391
|
-
/* @__PURE__ */ jsx(
|
|
5392
|
-
"a",
|
|
5393
|
-
{
|
|
5394
|
-
href: ctaHref,
|
|
5395
|
-
className: "inline-flex items-center justify-center rounded-lg bg-primary px-6 py-3 text-sm font-medium text-primary-foreground hover:opacity-90 transition-opacity",
|
|
5396
|
-
children: ctaLabel
|
|
5397
|
-
}
|
|
5398
|
-
)
|
|
5399
|
-
] }) })
|
|
5400
|
-
] });
|
|
5401
|
-
}
|
|
5402
|
-
|
|
5403
|
-
// src/content/utils.ts
|
|
5404
|
-
function formatBytes(bytes) {
|
|
5405
|
-
if (bytes == null) return "";
|
|
5406
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
5407
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
|
|
5408
|
-
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
5409
|
-
}
|
|
5410
|
-
function fileExt(file) {
|
|
5411
|
-
const name = file.fileName || file.fileUrl.split("/").pop()?.split("?")[0] || "";
|
|
5412
|
-
const ext = name.split(".").pop();
|
|
5413
|
-
return ext && ext !== name ? ext.toUpperCase() : "FILE";
|
|
5414
|
-
}
|
|
5415
|
-
async function downloadFile(e, file) {
|
|
5416
|
-
e.preventDefault();
|
|
5417
|
-
const openInTab = () => window.open(file.fileUrl, "_blank", "noopener,noreferrer");
|
|
5418
|
-
const name = file.fileName || file.fileUrl.split("/").pop()?.split("?")[0] || file.title || "download";
|
|
5419
|
-
try {
|
|
5420
|
-
const res = await fetch(file.fileUrl, { mode: "cors" });
|
|
5421
|
-
if (!res.ok) {
|
|
5422
|
-
openInTab();
|
|
5423
|
-
return;
|
|
5424
|
-
}
|
|
5425
|
-
const blob = await res.blob();
|
|
5426
|
-
const objUrl = URL.createObjectURL(blob);
|
|
5427
|
-
const a = document.createElement("a");
|
|
5428
|
-
a.href = objUrl;
|
|
5429
|
-
a.download = name;
|
|
5430
|
-
document.body.appendChild(a);
|
|
5431
|
-
a.click();
|
|
5432
|
-
a.remove();
|
|
5433
|
-
URL.revokeObjectURL(objUrl);
|
|
5434
|
-
} catch {
|
|
5435
|
-
openInTab();
|
|
5436
|
-
}
|
|
5437
|
-
}
|
|
5438
|
-
var PRESS_KIT_QUERY = `
|
|
5439
|
-
query PublicPressKit($productId: String!, $limit: Int, $offset: Int) {
|
|
5440
|
-
publicPressKitAssets(productId: $productId, limit: $limit, offset: $offset) {
|
|
5441
|
-
items {
|
|
5442
|
-
id
|
|
5443
|
-
category
|
|
5444
|
-
title
|
|
5445
|
-
slug
|
|
5446
|
-
description
|
|
5447
|
-
fileUrl
|
|
5448
|
-
fileName
|
|
5449
|
-
fileSize
|
|
5450
|
-
mimeType
|
|
5451
|
-
thumbnailUrl
|
|
5452
|
-
version
|
|
5453
|
-
tags
|
|
5454
|
-
sortOrder
|
|
5455
|
-
updatedAt
|
|
5456
|
-
}
|
|
5457
|
-
total
|
|
5458
|
-
hasMore
|
|
5459
|
-
}
|
|
5460
|
-
}
|
|
5461
|
-
`;
|
|
5462
|
-
var PRESS_RELEASES_QUERY = `
|
|
5463
|
-
query PublicPressReleases($productId: String!, $limit: Int, $offset: Int) {
|
|
5464
|
-
publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
|
|
5465
|
-
items {
|
|
5466
|
-
id
|
|
5467
|
-
title
|
|
5468
|
-
slug
|
|
5469
|
-
lastUpdated
|
|
5470
|
-
tags
|
|
5471
|
-
seoDescription
|
|
5472
|
-
excerpt
|
|
5473
|
-
thumbnail
|
|
5474
|
-
author
|
|
5475
|
-
publishedAt
|
|
5476
|
-
readingTime
|
|
5477
|
-
featured
|
|
5478
|
-
category
|
|
5479
|
-
}
|
|
5480
|
-
total
|
|
5481
|
-
hasMore
|
|
5482
|
-
}
|
|
5483
|
-
}
|
|
5484
|
-
`;
|
|
5485
|
-
var CATEGORY_ORDER = [
|
|
5486
|
-
"LOGO",
|
|
5487
|
-
"BANNER",
|
|
5488
|
-
"SCREENSHOT",
|
|
5489
|
-
"BRAND_GUIDE",
|
|
5490
|
-
"BROCHURE",
|
|
5491
|
-
"DOCUMENT",
|
|
5492
|
-
"PRESS_RELEASE"
|
|
5493
|
-
];
|
|
5494
|
-
var CATEGORY_LABELS = {
|
|
5495
|
-
LOGO: "Logos",
|
|
5496
|
-
BANNER: "Banners",
|
|
5497
|
-
SCREENSHOT: "Screenshots",
|
|
5498
|
-
BRAND_GUIDE: "Brand Guides",
|
|
5499
|
-
BROCHURE: "Brochures",
|
|
5500
|
-
DOCUMENT: "Documents",
|
|
5501
|
-
PRESS_RELEASE: "Press Releases"
|
|
5502
|
-
};
|
|
5503
|
-
function isImageAsset(a) {
|
|
5504
|
-
return (a.mimeType || "").startsWith("image/");
|
|
5505
|
-
}
|
|
5506
|
-
function PressKitLightbox({
|
|
5507
|
-
asset,
|
|
5508
|
-
onClose
|
|
5509
|
-
}) {
|
|
5510
|
-
useEffect(() => {
|
|
5511
|
-
if (!asset) return;
|
|
5512
|
-
const onKey = (e) => {
|
|
5513
|
-
if (e.key === "Escape") onClose();
|
|
5514
|
-
};
|
|
5515
|
-
document.addEventListener("keydown", onKey);
|
|
5516
|
-
const prevOverflow = document.body.style.overflow;
|
|
5517
|
-
document.body.style.overflow = "hidden";
|
|
5518
|
-
return () => {
|
|
5519
|
-
document.removeEventListener("keydown", onKey);
|
|
5520
|
-
document.body.style.overflow = prevOverflow;
|
|
5521
|
-
};
|
|
5522
|
-
}, [asset, onClose]);
|
|
5523
|
-
if (!asset) return null;
|
|
5524
|
-
const ext = (asset.mimeType || "file").split("/").pop()?.toUpperCase() || "FILE";
|
|
5525
|
-
const size = formatBytes(asset.fileSize);
|
|
5526
|
-
return /* @__PURE__ */ jsx(
|
|
5527
|
-
"div",
|
|
5528
|
-
{
|
|
5529
|
-
role: "dialog",
|
|
5530
|
-
"aria-modal": "true",
|
|
5531
|
-
"aria-label": `${asset.title} preview`,
|
|
5532
|
-
onClick: onClose,
|
|
5533
|
-
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-4 sm:p-8",
|
|
5534
|
-
children: /* @__PURE__ */ jsxs(
|
|
5535
|
-
"div",
|
|
5536
|
-
{
|
|
5537
|
-
onClick: (e) => e.stopPropagation(),
|
|
5538
|
-
className: "relative flex max-h-full w-full max-w-4xl flex-col overflow-hidden rounded-xl border bg-card shadow-2xl",
|
|
5539
|
-
children: [
|
|
5540
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 border-b p-4", children: [
|
|
5541
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
5542
|
-
/* @__PURE__ */ jsx("h3", { className: "truncate text-sm font-semibold text-foreground", children: asset.title }),
|
|
5543
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
5544
|
-
ext,
|
|
5545
|
-
size ? ` \xB7 ${size}` : ""
|
|
5546
|
-
] })
|
|
5547
|
-
] }),
|
|
5548
|
-
/* @__PURE__ */ jsx(
|
|
5549
|
-
"button",
|
|
5550
|
-
{
|
|
5551
|
-
type: "button",
|
|
5552
|
-
onClick: onClose,
|
|
5553
|
-
"aria-label": "Close preview",
|
|
5554
|
-
className: "shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
5555
|
-
children: /* @__PURE__ */ jsx(
|
|
5556
|
-
"svg",
|
|
5557
|
-
{
|
|
5558
|
-
className: "h-5 w-5",
|
|
5559
|
-
fill: "none",
|
|
5560
|
-
viewBox: "0 0 24 24",
|
|
5561
|
-
stroke: "currentColor",
|
|
5562
|
-
strokeWidth: 2,
|
|
5563
|
-
children: /* @__PURE__ */ jsx(
|
|
5564
|
-
"path",
|
|
5565
|
-
{
|
|
5566
|
-
strokeLinecap: "round",
|
|
5567
|
-
strokeLinejoin: "round",
|
|
5568
|
-
d: "M6 18L18 6M6 6l12 12"
|
|
5569
|
-
}
|
|
5570
|
-
)
|
|
5571
|
-
}
|
|
5572
|
-
)
|
|
5573
|
-
}
|
|
5574
|
-
)
|
|
5575
|
-
] }),
|
|
5576
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center overflow-auto bg-muted/20 p-4", children: /* @__PURE__ */ jsx(
|
|
5577
|
-
"img",
|
|
5578
|
-
{
|
|
5579
|
-
src: asset.fileUrl,
|
|
5580
|
-
alt: asset.title,
|
|
5581
|
-
className: "max-h-[70vh] w-auto max-w-full object-contain"
|
|
5582
|
-
}
|
|
5583
|
-
) }),
|
|
5584
|
-
/* @__PURE__ */ jsx("div", { className: "flex justify-end border-t p-4", children: /* @__PURE__ */ jsxs(
|
|
5585
|
-
"a",
|
|
5586
|
-
{
|
|
5587
|
-
href: asset.fileUrl,
|
|
5588
|
-
target: "_blank",
|
|
5589
|
-
rel: "noopener noreferrer",
|
|
5590
|
-
download: true,
|
|
5591
|
-
onClick: (e) => {
|
|
5592
|
-
void downloadFile(e, asset);
|
|
5593
|
-
},
|
|
5594
|
-
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",
|
|
5595
|
-
children: [
|
|
5596
|
-
/* @__PURE__ */ jsx(
|
|
5597
|
-
"svg",
|
|
5598
|
-
{
|
|
5599
|
-
className: "h-4 w-4",
|
|
5600
|
-
fill: "none",
|
|
5601
|
-
viewBox: "0 0 24 24",
|
|
5602
|
-
stroke: "currentColor",
|
|
5603
|
-
strokeWidth: 2,
|
|
5604
|
-
children: /* @__PURE__ */ jsx(
|
|
5605
|
-
"path",
|
|
5606
|
-
{
|
|
5607
|
-
strokeLinecap: "round",
|
|
5608
|
-
strokeLinejoin: "round",
|
|
5609
|
-
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
5610
|
-
}
|
|
5611
|
-
)
|
|
5612
|
-
}
|
|
5613
|
-
),
|
|
5614
|
-
"Download"
|
|
5615
|
-
]
|
|
5616
|
-
}
|
|
5617
|
-
) })
|
|
5618
|
-
]
|
|
5619
|
-
}
|
|
5620
|
-
)
|
|
5621
|
-
}
|
|
5622
|
-
);
|
|
5623
|
-
}
|
|
5624
|
-
function AssetCard({
|
|
5625
|
-
asset,
|
|
5626
|
-
onPreview
|
|
5627
|
-
}) {
|
|
5628
|
-
const date = asset.updatedAt ? new Date(asset.updatedAt).toLocaleDateString("en-US", {
|
|
5629
|
-
year: "numeric",
|
|
5630
|
-
month: "short",
|
|
5631
|
-
day: "numeric"
|
|
5632
|
-
}) : "";
|
|
5633
|
-
const ext = (asset.mimeType || "file").split("/").pop()?.toUpperCase() || "FILE";
|
|
5634
|
-
const size = formatBytes(asset.fileSize);
|
|
5635
|
-
const [imgError, setImgError] = useState(false);
|
|
5636
|
-
const thumb = asset.thumbnailUrl && !imgError ? /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] overflow-hidden bg-muted/30", children: /* @__PURE__ */ jsx(
|
|
5637
|
-
"img",
|
|
5638
|
-
{
|
|
5639
|
-
src: asset.thumbnailUrl,
|
|
5640
|
-
alt: asset.title,
|
|
5641
|
-
className: "w-full h-full object-contain group-hover:scale-105 transition-transform duration-300",
|
|
5642
|
-
loading: "lazy",
|
|
5643
|
-
onError: () => setImgError(true)
|
|
5644
|
-
}
|
|
5645
|
-
) }) : /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
5646
|
-
"svg",
|
|
5647
|
-
{
|
|
5648
|
-
className: "w-12 h-12 text-muted-foreground/20",
|
|
5649
|
-
fill: "none",
|
|
5650
|
-
viewBox: "0 0 24 24",
|
|
5651
|
-
stroke: "currentColor",
|
|
5652
|
-
children: /* @__PURE__ */ jsx(
|
|
5653
|
-
"path",
|
|
5654
|
-
{
|
|
5655
|
-
strokeLinecap: "round",
|
|
5656
|
-
strokeLinejoin: "round",
|
|
5657
|
-
strokeWidth: 1.5,
|
|
5658
|
-
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"
|
|
5659
|
-
}
|
|
5660
|
-
)
|
|
5661
|
-
}
|
|
5662
|
-
) });
|
|
5663
|
-
return /* @__PURE__ */ 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: [
|
|
5664
|
-
onPreview && isImageAsset(asset) ? /* @__PURE__ */ jsx(
|
|
5665
|
-
"button",
|
|
5666
|
-
{
|
|
5667
|
-
type: "button",
|
|
5668
|
-
onClick: () => onPreview(asset),
|
|
5669
|
-
"aria-label": `Preview ${asset.title}`,
|
|
5670
|
-
className: "block w-full text-left cursor-zoom-in",
|
|
5671
|
-
children: thumb
|
|
5672
|
-
}
|
|
5673
|
-
) : /* @__PURE__ */ jsx(
|
|
5674
|
-
"a",
|
|
5675
|
-
{
|
|
5676
|
-
href: asset.fileUrl,
|
|
5677
|
-
target: "_blank",
|
|
5678
|
-
rel: "noopener noreferrer",
|
|
5679
|
-
"aria-label": `Open ${asset.title}`,
|
|
5680
|
-
className: "block",
|
|
5681
|
-
children: thumb
|
|
5682
|
-
}
|
|
5683
|
-
),
|
|
5684
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col flex-1 p-5", children: [
|
|
5685
|
-
/* @__PURE__ */ 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 }),
|
|
5686
|
-
/* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-foreground mb-1 line-clamp-2", children: asset.title }),
|
|
5687
|
-
asset.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-3 line-clamp-2", children: asset.description }),
|
|
5688
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between pt-3", children: [
|
|
5689
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
5690
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: ext }),
|
|
5691
|
-
size && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5692
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
5693
|
-
/* @__PURE__ */ jsx("span", { children: size })
|
|
5694
|
-
] }),
|
|
5695
|
-
date && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5696
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
5697
|
-
/* @__PURE__ */ jsx("span", { children: date })
|
|
5698
|
-
] })
|
|
5699
|
-
] }),
|
|
5700
|
-
/* @__PURE__ */ jsxs(
|
|
5701
|
-
"a",
|
|
5702
|
-
{
|
|
5703
|
-
href: asset.fileUrl,
|
|
5704
|
-
target: "_blank",
|
|
5705
|
-
rel: "noopener noreferrer",
|
|
5706
|
-
download: true,
|
|
5707
|
-
onClick: (e) => {
|
|
5708
|
-
void downloadFile(e, asset);
|
|
5709
|
-
},
|
|
5710
|
-
className: "inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline",
|
|
5711
|
-
children: [
|
|
5712
|
-
/* @__PURE__ */ jsx(
|
|
5713
|
-
"svg",
|
|
5714
|
-
{
|
|
5715
|
-
className: "w-4 h-4",
|
|
5716
|
-
fill: "none",
|
|
5717
|
-
viewBox: "0 0 24 24",
|
|
5718
|
-
stroke: "currentColor",
|
|
5719
|
-
strokeWidth: 2,
|
|
5720
|
-
children: /* @__PURE__ */ jsx(
|
|
5721
|
-
"path",
|
|
5722
|
-
{
|
|
5723
|
-
strokeLinecap: "round",
|
|
5724
|
-
strokeLinejoin: "round",
|
|
5725
|
-
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
5726
|
-
}
|
|
5727
|
-
)
|
|
5728
|
-
}
|
|
5729
|
-
),
|
|
5730
|
-
"Download"
|
|
5731
|
-
]
|
|
5732
|
-
}
|
|
5733
|
-
)
|
|
5734
|
-
] })
|
|
5735
|
-
] })
|
|
5736
|
-
] });
|
|
5737
|
-
}
|
|
5738
|
-
function PressReleaseCard({
|
|
5739
|
-
release,
|
|
5740
|
-
basePath
|
|
5741
|
-
}) {
|
|
5742
|
-
const date = release.publishedAt || release.lastUpdated;
|
|
5743
|
-
const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
|
|
5744
|
-
year: "numeric",
|
|
5745
|
-
month: "long",
|
|
5746
|
-
day: "numeric"
|
|
5747
|
-
}) : "";
|
|
5748
|
-
const [imgError, setImgError] = useState(false);
|
|
5749
|
-
return /* @__PURE__ */ jsxs(
|
|
5750
|
-
"a",
|
|
5751
|
-
{
|
|
5752
|
-
href: `${basePath}/${release.slug}`,
|
|
5753
|
-
className: "group flex flex-col bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300",
|
|
5754
|
-
children: [
|
|
5755
|
-
release.thumbnail && !imgError ? /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] overflow-hidden bg-muted/30", children: /* @__PURE__ */ jsx(
|
|
5756
|
-
"img",
|
|
5757
|
-
{
|
|
5758
|
-
src: release.thumbnail,
|
|
5759
|
-
alt: release.title,
|
|
5760
|
-
className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300",
|
|
5761
|
-
loading: "lazy",
|
|
5762
|
-
onError: () => setImgError(true)
|
|
5763
|
-
}
|
|
5764
|
-
) }) : /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
5765
|
-
"svg",
|
|
5766
|
-
{
|
|
5767
|
-
className: "w-12 h-12 text-muted-foreground/20",
|
|
5768
|
-
fill: "none",
|
|
5769
|
-
viewBox: "0 0 24 24",
|
|
5770
|
-
stroke: "currentColor",
|
|
5771
|
-
children: /* @__PURE__ */ jsx(
|
|
5772
|
-
"path",
|
|
5773
|
-
{
|
|
5774
|
-
strokeLinecap: "round",
|
|
5775
|
-
strokeLinejoin: "round",
|
|
5776
|
-
strokeWidth: 1.5,
|
|
5777
|
-
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"
|
|
5778
|
-
}
|
|
5779
|
-
)
|
|
5780
|
-
}
|
|
5781
|
-
) }),
|
|
5782
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col flex-1 p-5 sm:p-6", children: [
|
|
5783
|
-
release.category && /* @__PURE__ */ 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 }),
|
|
5784
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground mb-2 group-hover:text-primary transition-colors line-clamp-2", children: release.title }),
|
|
5785
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4 line-clamp-3", children: release.excerpt || release.seoDescription || "" }),
|
|
5786
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
5787
|
-
release.author && /* @__PURE__ */ jsx("span", { className: "font-medium", children: release.author }),
|
|
5788
|
-
release.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
5789
|
-
formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
|
|
5790
|
-
release.readingTime ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5791
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
5792
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
5793
|
-
release.readingTime,
|
|
5794
|
-
" min read"
|
|
5795
|
-
] })
|
|
5796
|
-
] }) : null
|
|
2502
|
+
)
|
|
2503
|
+
}
|
|
2504
|
+
) }),
|
|
2505
|
+
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground mb-3", children: "Invalid Unsubscribe Link" }),
|
|
2506
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "This unsubscribe link is invalid or missing. If you want to unsubscribe, please use the link from your newsletter email." })
|
|
5797
2507
|
] })
|
|
5798
2508
|
] })
|
|
5799
2509
|
]
|
|
5800
2510
|
}
|
|
5801
2511
|
);
|
|
5802
2512
|
}
|
|
5803
|
-
function
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
mediaContactEmail,
|
|
5809
|
-
brandKitUrl,
|
|
5810
|
-
className = "",
|
|
5811
|
-
seoTitle,
|
|
5812
|
-
seoDescription,
|
|
5813
|
-
seoKeywords,
|
|
5814
|
-
showPressReleases = true,
|
|
5815
|
-
pressReleaseBasePath = "/press",
|
|
5816
|
-
pressReleasesTitle = "Press Releases"
|
|
5817
|
-
} = props;
|
|
5818
|
-
const client = useWebSDK();
|
|
5819
|
-
const config = useWebSDKConfig();
|
|
5820
|
-
const { product } = useProduct();
|
|
5821
|
-
const resolvedProductId = product?.id || config.productId;
|
|
5822
|
-
const contactEmail = mediaContactEmail || product?.contactEmail || void 0;
|
|
5823
|
-
const [assets, setAssets] = useState([]);
|
|
5824
|
-
const [loading, setLoading] = useState(true);
|
|
5825
|
-
const [error, setError] = useState(null);
|
|
5826
|
-
const [activeCategory, setActiveCategory] = useState("ALL");
|
|
5827
|
-
const [releases, setReleases] = useState([]);
|
|
5828
|
-
const [releasesLoading, setReleasesLoading] = useState(true);
|
|
5829
|
-
const [preview, setPreview] = useState(null);
|
|
5830
|
-
const fetchAssets = useCallback(async () => {
|
|
5831
|
-
if (!resolvedProductId) {
|
|
5832
|
-
setLoading(false);
|
|
5833
|
-
return;
|
|
5834
|
-
}
|
|
5835
|
-
setLoading(true);
|
|
5836
|
-
try {
|
|
5837
|
-
const PAGE_SIZE = 100;
|
|
5838
|
-
const MAX_PAGES = 10;
|
|
5839
|
-
const all = [];
|
|
5840
|
-
let offset = 0;
|
|
5841
|
-
for (let pageNum = 0; pageNum < MAX_PAGES; pageNum++) {
|
|
5842
|
-
const result = await client.query(PRESS_KIT_QUERY, {
|
|
5843
|
-
productId: resolvedProductId,
|
|
5844
|
-
limit: PAGE_SIZE,
|
|
5845
|
-
offset
|
|
5846
|
-
});
|
|
5847
|
-
if (result.errors?.length) {
|
|
5848
|
-
setError(result.errors[0]?.message ?? "Failed to load press kit");
|
|
5849
|
-
return;
|
|
5850
|
-
}
|
|
5851
|
-
const page = result.data?.publicPressKitAssets;
|
|
5852
|
-
const items = page?.items || [];
|
|
5853
|
-
all.push(...items);
|
|
5854
|
-
if (!page?.hasMore || items.length === 0) break;
|
|
5855
|
-
offset += PAGE_SIZE;
|
|
5856
|
-
}
|
|
5857
|
-
setAssets(all);
|
|
5858
|
-
setError(null);
|
|
5859
|
-
} catch {
|
|
5860
|
-
setError("Failed to load press kit");
|
|
5861
|
-
} finally {
|
|
5862
|
-
setLoading(false);
|
|
5863
|
-
}
|
|
5864
|
-
}, [client, resolvedProductId]);
|
|
5865
|
-
useEffect(() => {
|
|
5866
|
-
fetchAssets();
|
|
5867
|
-
}, [fetchAssets]);
|
|
5868
|
-
const fetchReleases = useCallback(async () => {
|
|
5869
|
-
if (!resolvedProductId || !showPressReleases) {
|
|
5870
|
-
setReleasesLoading(false);
|
|
5871
|
-
return;
|
|
5872
|
-
}
|
|
5873
|
-
setReleasesLoading(true);
|
|
5874
|
-
try {
|
|
5875
|
-
const PAGE_SIZE = 100;
|
|
5876
|
-
const MAX_PAGES = 10;
|
|
5877
|
-
const all = [];
|
|
5878
|
-
let offset = 0;
|
|
5879
|
-
for (let pageNum = 0; pageNum < MAX_PAGES; pageNum++) {
|
|
5880
|
-
const result = await client.query(PRESS_RELEASES_QUERY, {
|
|
5881
|
-
productId: resolvedProductId,
|
|
5882
|
-
limit: PAGE_SIZE,
|
|
5883
|
-
offset
|
|
5884
|
-
});
|
|
5885
|
-
if (result.errors?.length) {
|
|
5886
|
-
setReleases([]);
|
|
5887
|
-
return;
|
|
5888
|
-
}
|
|
5889
|
-
const page = result.data?.publicContentPages;
|
|
5890
|
-
const items = page?.items || [];
|
|
5891
|
-
all.push(...items);
|
|
5892
|
-
if (!page?.hasMore || items.length === 0) break;
|
|
5893
|
-
offset += PAGE_SIZE;
|
|
5894
|
-
}
|
|
5895
|
-
const pressOnly = all.filter((p) => p.tags?.includes("press")).sort((a, b) => {
|
|
5896
|
-
const da = new Date(a.publishedAt || a.lastUpdated || 0).getTime();
|
|
5897
|
-
const db = new Date(b.publishedAt || b.lastUpdated || 0).getTime();
|
|
5898
|
-
return db - da;
|
|
5899
|
-
});
|
|
5900
|
-
setReleases(pressOnly);
|
|
5901
|
-
} catch {
|
|
5902
|
-
setReleases([]);
|
|
5903
|
-
} finally {
|
|
5904
|
-
setReleasesLoading(false);
|
|
5905
|
-
}
|
|
5906
|
-
}, [client, resolvedProductId, showPressReleases]);
|
|
2513
|
+
function RybbitAnalytics({
|
|
2514
|
+
siteId,
|
|
2515
|
+
scriptUrl = "https://analytics.burdenoff.com/api/script.js",
|
|
2516
|
+
enabled = true
|
|
2517
|
+
}) {
|
|
5907
2518
|
useEffect(() => {
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
productName,
|
|
5925
|
-
keywords: seoKeywords
|
|
2519
|
+
if (!enabled || !siteId) return;
|
|
2520
|
+
const existingScript = document.querySelector(
|
|
2521
|
+
`script[data-site-id="${siteId}"]`
|
|
2522
|
+
);
|
|
2523
|
+
if (existingScript) return;
|
|
2524
|
+
const script = document.createElement("script");
|
|
2525
|
+
script.src = scriptUrl;
|
|
2526
|
+
script.defer = true;
|
|
2527
|
+
script.setAttribute("data-site-id", siteId);
|
|
2528
|
+
document.head.appendChild(script);
|
|
2529
|
+
return () => {
|
|
2530
|
+
const scriptToRemove = document.querySelector(
|
|
2531
|
+
`script[data-site-id="${siteId}"]`
|
|
2532
|
+
);
|
|
2533
|
+
if (scriptToRemove) {
|
|
2534
|
+
document.head.removeChild(scriptToRemove);
|
|
5926
2535
|
}
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
/* @__PURE__ */ jsx("p", { className: "mt-4 text-lg text-muted-foreground", children: heroSubtitle }),
|
|
5931
|
-
(brandKitUrl || contactEmail) && /* @__PURE__ */ jsxs("div", { className: "mt-8 flex flex-wrap items-center justify-center gap-4", children: [
|
|
5932
|
-
brandKitUrl && /* @__PURE__ */ jsx(
|
|
5933
|
-
"a",
|
|
5934
|
-
{
|
|
5935
|
-
href: brandKitUrl,
|
|
5936
|
-
target: "_blank",
|
|
5937
|
-
rel: "noopener noreferrer",
|
|
5938
|
-
className: "inline-flex items-center gap-2 px-6 py-3 rounded-lg bg-primary text-primary-foreground font-medium hover:opacity-90 transition-opacity",
|
|
5939
|
-
children: "Download brand kit"
|
|
5940
|
-
}
|
|
5941
|
-
),
|
|
5942
|
-
contactEmail && /* @__PURE__ */ jsx(
|
|
5943
|
-
"a",
|
|
5944
|
-
{
|
|
5945
|
-
href: `mailto:${contactEmail}`,
|
|
5946
|
-
className: "inline-flex items-center gap-2 px-6 py-3 rounded-lg border font-medium text-foreground hover:bg-muted transition-colors",
|
|
5947
|
-
children: "Media inquiries"
|
|
5948
|
-
}
|
|
5949
|
-
)
|
|
5950
|
-
] })
|
|
5951
|
-
] }) }) }),
|
|
5952
|
-
showPressReleases && (releasesLoading || releases.length > 0) && /* @__PURE__ */ jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
|
|
5953
|
-
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground mb-6", children: pressReleasesTitle }),
|
|
5954
|
-
/* @__PURE__ */ jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: releasesLoading ? [1, 2, 3].map((i) => /* @__PURE__ */ jsxs(
|
|
5955
|
-
"div",
|
|
5956
|
-
{
|
|
5957
|
-
className: "bg-card border rounded-xl overflow-hidden animate-pulse",
|
|
5958
|
-
children: [
|
|
5959
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted" }),
|
|
5960
|
-
/* @__PURE__ */ jsxs("div", { className: "p-5 space-y-3", children: [
|
|
5961
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
|
|
5962
|
-
/* @__PURE__ */ jsx("div", { className: "h-5 bg-muted rounded w-3/4" }),
|
|
5963
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
|
|
5964
|
-
] })
|
|
5965
|
-
]
|
|
5966
|
-
},
|
|
5967
|
-
i
|
|
5968
|
-
)) : releases.map((r) => /* @__PURE__ */ jsx(
|
|
5969
|
-
PressReleaseCard,
|
|
5970
|
-
{
|
|
5971
|
-
release: r,
|
|
5972
|
-
basePath: pressReleaseBasePath
|
|
5973
|
-
},
|
|
5974
|
-
r.id
|
|
5975
|
-
)) })
|
|
5976
|
-
] }) }),
|
|
5977
|
-
/* @__PURE__ */ jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: loading ? /* @__PURE__ */ jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: [1, 2, 3, 4, 5, 6].map((i) => /* @__PURE__ */ jsxs(
|
|
5978
|
-
"div",
|
|
5979
|
-
{
|
|
5980
|
-
className: "bg-card border rounded-xl overflow-hidden animate-pulse",
|
|
5981
|
-
children: [
|
|
5982
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted" }),
|
|
5983
|
-
/* @__PURE__ */ jsxs("div", { className: "p-5 space-y-3", children: [
|
|
5984
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
|
|
5985
|
-
/* @__PURE__ */ jsx("div", { className: "h-5 bg-muted rounded w-3/4" }),
|
|
5986
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
|
|
5987
|
-
] })
|
|
5988
|
-
]
|
|
5989
|
-
},
|
|
5990
|
-
i
|
|
5991
|
-
)) }) : error ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: error }) }) : assets.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
|
|
5992
|
-
"Press materials are coming soon. For media inquiries",
|
|
5993
|
-
contactEmail ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5994
|
-
", contact ",
|
|
5995
|
-
/* @__PURE__ */ jsx(
|
|
5996
|
-
"a",
|
|
5997
|
-
{
|
|
5998
|
-
href: `mailto:${contactEmail}`,
|
|
5999
|
-
className: "text-primary hover:underline",
|
|
6000
|
-
children: contactEmail
|
|
6001
|
-
}
|
|
6002
|
-
)
|
|
6003
|
-
] }) : " please reach out to our team",
|
|
6004
|
-
"."
|
|
6005
|
-
] }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6006
|
-
presentCategories.length > 1 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2 mb-10 justify-center", children: ["ALL", ...presentCategories].map((c) => {
|
|
6007
|
-
const active = activeCategory === c;
|
|
6008
|
-
return /* @__PURE__ */ jsx(
|
|
6009
|
-
"button",
|
|
6010
|
-
{
|
|
6011
|
-
type: "button",
|
|
6012
|
-
onClick: () => setActiveCategory(c),
|
|
6013
|
-
className: `px-4 py-2 rounded-full text-sm font-medium transition-colors ${active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"}`,
|
|
6014
|
-
children: c === "ALL" ? "All" : CATEGORY_LABELS[c] ?? c
|
|
6015
|
-
},
|
|
6016
|
-
c
|
|
6017
|
-
);
|
|
6018
|
-
}) }),
|
|
6019
|
-
grouped.map((group) => /* @__PURE__ */ jsxs("div", { className: "mb-12", children: [
|
|
6020
|
-
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground mb-5", children: CATEGORY_LABELS[group.cat] ?? group.cat }),
|
|
6021
|
-
/* @__PURE__ */ jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: group.items.map((a) => /* @__PURE__ */ jsx(AssetCard, { asset: a, onPreview: setPreview }, a.id)) })
|
|
6022
|
-
] }, group.cat)),
|
|
6023
|
-
contactEmail && /* @__PURE__ */ jsxs("div", { className: "mt-8 border-t pt-10 text-center", children: [
|
|
6024
|
-
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground mb-2", children: "Media Contact" }),
|
|
6025
|
-
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
|
|
6026
|
-
"For interviews, partnerships, and press inquiries:",
|
|
6027
|
-
" ",
|
|
6028
|
-
/* @__PURE__ */ jsx(
|
|
6029
|
-
"a",
|
|
6030
|
-
{
|
|
6031
|
-
href: `mailto:${contactEmail}`,
|
|
6032
|
-
className: "text-primary hover:underline",
|
|
6033
|
-
children: contactEmail
|
|
6034
|
-
}
|
|
6035
|
-
)
|
|
6036
|
-
] })
|
|
6037
|
-
] })
|
|
6038
|
-
] }) }) }),
|
|
6039
|
-
/* @__PURE__ */ jsx(PressKitLightbox, { asset: preview, onClose: () => setPreview(null) })
|
|
6040
|
-
] });
|
|
2536
|
+
};
|
|
2537
|
+
}, [siteId, scriptUrl, enabled]);
|
|
2538
|
+
return null;
|
|
6041
2539
|
}
|
|
6042
|
-
var
|
|
6043
|
-
query
|
|
6044
|
-
|
|
2540
|
+
var PUBLIC_CONTENT_PAGE_QUERY = `
|
|
2541
|
+
query PublicContentPage($slug: String!, $productId: String) {
|
|
2542
|
+
publicContentPage(slug: $slug, productId: $productId) {
|
|
2543
|
+
id
|
|
2544
|
+
title
|
|
2545
|
+
slug
|
|
2546
|
+
content
|
|
2547
|
+
contentFormat
|
|
2548
|
+
seoTitle
|
|
2549
|
+
seoDescription
|
|
2550
|
+
seoKeywords
|
|
2551
|
+
lastUpdated
|
|
2552
|
+
version
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
`;
|
|
2556
|
+
var PUBLIC_RESOLVED_CONTENT_PAGE_QUERY = `
|
|
2557
|
+
query PublicResolvedContentPage($slug: String!, $productId: String!) {
|
|
2558
|
+
publicResolvedContentPage(slug: $slug, productId: $productId) {
|
|
2559
|
+
id
|
|
2560
|
+
title
|
|
2561
|
+
slug
|
|
2562
|
+
content
|
|
2563
|
+
contentFormat
|
|
2564
|
+
seoTitle
|
|
2565
|
+
seoDescription
|
|
2566
|
+
seoKeywords
|
|
2567
|
+
lastUpdated
|
|
2568
|
+
version
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
`;
|
|
2572
|
+
var PUBLIC_CONTENT_PAGES_QUERY = `
|
|
2573
|
+
query PublicContentPages($productId: String!, $limit: Int, $offset: Int) {
|
|
2574
|
+
publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
|
|
6045
2575
|
items {
|
|
6046
2576
|
id
|
|
6047
2577
|
title
|
|
6048
2578
|
slug
|
|
6049
|
-
|
|
6050
|
-
fileUrl
|
|
6051
|
-
fileName
|
|
6052
|
-
fileSize
|
|
6053
|
-
mimeType
|
|
6054
|
-
version
|
|
6055
|
-
tags
|
|
6056
|
-
sortOrder
|
|
6057
|
-
updatedAt
|
|
2579
|
+
lastUpdated
|
|
6058
2580
|
}
|
|
2581
|
+
total
|
|
6059
2582
|
hasMore
|
|
6060
2583
|
}
|
|
6061
2584
|
}
|
|
6062
2585
|
`;
|
|
6063
|
-
function
|
|
6064
|
-
const {
|
|
6065
|
-
productName,
|
|
6066
|
-
heroTitle = "Contracts & Legal Agreements",
|
|
6067
|
-
heroSubtitle = "Download our standard legal agreements and policies.",
|
|
6068
|
-
className = "",
|
|
6069
|
-
seoTitle,
|
|
6070
|
-
seoDescription,
|
|
6071
|
-
seoKeywords
|
|
6072
|
-
} = props;
|
|
2586
|
+
function useContentPage(slug, options) {
|
|
6073
2587
|
const client = useWebSDK();
|
|
6074
2588
|
const config = useWebSDKConfig();
|
|
6075
|
-
const
|
|
6076
|
-
const resolvedProductId = product?.id || config.productId;
|
|
6077
|
-
const displayName = productName ?? product?.name ?? config.productId;
|
|
6078
|
-
const [contracts, setContracts] = useState([]);
|
|
2589
|
+
const [data, setData] = useState(null);
|
|
6079
2590
|
const [loading, setLoading] = useState(true);
|
|
6080
2591
|
const [error, setError] = useState(null);
|
|
6081
|
-
const
|
|
6082
|
-
|
|
2592
|
+
const fetchPage = useCallback(async () => {
|
|
2593
|
+
setLoading(true);
|
|
2594
|
+
setError(null);
|
|
2595
|
+
try {
|
|
2596
|
+
const query = options?.resolve ? PUBLIC_RESOLVED_CONTENT_PAGE_QUERY : PUBLIC_CONTENT_PAGE_QUERY;
|
|
2597
|
+
const queryName = options?.resolve ? "publicResolvedContentPage" : "publicContentPage";
|
|
2598
|
+
const result = await client.query(
|
|
2599
|
+
query,
|
|
2600
|
+
{
|
|
2601
|
+
slug,
|
|
2602
|
+
productId: config.productId
|
|
2603
|
+
}
|
|
2604
|
+
);
|
|
2605
|
+
if (result.errors?.length) {
|
|
2606
|
+
setError(result.errors[0]?.message ?? "Unknown error");
|
|
2607
|
+
setData(null);
|
|
2608
|
+
} else {
|
|
2609
|
+
setData(result.data?.[queryName] ?? null);
|
|
2610
|
+
}
|
|
2611
|
+
} catch (err) {
|
|
2612
|
+
setError(err instanceof Error ? err.message : "Failed to fetch content");
|
|
2613
|
+
setData(null);
|
|
2614
|
+
} finally {
|
|
6083
2615
|
setLoading(false);
|
|
6084
|
-
return;
|
|
6085
2616
|
}
|
|
2617
|
+
}, [client, config.productId, slug, options?.resolve]);
|
|
2618
|
+
useEffect(() => {
|
|
2619
|
+
fetchPage();
|
|
2620
|
+
}, [fetchPage]);
|
|
2621
|
+
return { data, loading, error, refetch: fetchPage };
|
|
2622
|
+
}
|
|
2623
|
+
function useContentPages(options) {
|
|
2624
|
+
const client = useWebSDK();
|
|
2625
|
+
const config = useWebSDKConfig();
|
|
2626
|
+
const [data, setData] = useState(null);
|
|
2627
|
+
const [loading, setLoading] = useState(true);
|
|
2628
|
+
const [error, setError] = useState(null);
|
|
2629
|
+
const fetchPages = useCallback(async () => {
|
|
6086
2630
|
setLoading(true);
|
|
2631
|
+
setError(null);
|
|
6087
2632
|
try {
|
|
6088
|
-
const
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
if (result.errors?.length) {
|
|
6099
|
-
setError(result.errors[0]?.message ?? "Failed to load contracts");
|
|
6100
|
-
return;
|
|
6101
|
-
}
|
|
6102
|
-
const page = result.data?.publicPressKitAssets;
|
|
6103
|
-
const items = page?.items || [];
|
|
6104
|
-
all.push(...items);
|
|
6105
|
-
if (!page?.hasMore || items.length === 0) break;
|
|
6106
|
-
offset += PAGE_SIZE;
|
|
2633
|
+
const result = await client.query(PUBLIC_CONTENT_PAGES_QUERY, {
|
|
2634
|
+
productId: config.productId,
|
|
2635
|
+
limit: options?.limit ?? 50,
|
|
2636
|
+
offset: options?.offset ?? 0
|
|
2637
|
+
});
|
|
2638
|
+
if (result.errors?.length) {
|
|
2639
|
+
setError(result.errors[0]?.message ?? "Unknown error");
|
|
2640
|
+
setData(null);
|
|
2641
|
+
} else {
|
|
2642
|
+
setData(result.data?.publicContentPages ?? null);
|
|
6107
2643
|
}
|
|
6108
|
-
|
|
6109
|
-
|
|
2644
|
+
} catch (err) {
|
|
2645
|
+
setError(
|
|
2646
|
+
err instanceof Error ? err.message : "Failed to fetch content pages"
|
|
6110
2647
|
);
|
|
6111
|
-
|
|
6112
|
-
setError(null);
|
|
6113
|
-
} catch {
|
|
6114
|
-
setError("Failed to load contracts");
|
|
2648
|
+
setData(null);
|
|
6115
2649
|
} finally {
|
|
6116
2650
|
setLoading(false);
|
|
6117
2651
|
}
|
|
6118
|
-
}, [client,
|
|
2652
|
+
}, [client, config.productId, options?.limit, options?.offset]);
|
|
6119
2653
|
useEffect(() => {
|
|
6120
|
-
|
|
6121
|
-
}, [
|
|
6122
|
-
return
|
|
6123
|
-
|
|
6124
|
-
|
|
2654
|
+
fetchPages();
|
|
2655
|
+
}, [fetchPages]);
|
|
2656
|
+
return { data, loading, error, refetch: fetchPages };
|
|
2657
|
+
}
|
|
2658
|
+
function ContentRenderer({
|
|
2659
|
+
content,
|
|
2660
|
+
format = "markdown",
|
|
2661
|
+
className
|
|
2662
|
+
}) {
|
|
2663
|
+
if (format === "html" || format === "markdown") {
|
|
2664
|
+
return /* @__PURE__ */ jsx(
|
|
2665
|
+
"div",
|
|
6125
2666
|
{
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
productName,
|
|
6129
|
-
keywords: seoKeywords
|
|
2667
|
+
className,
|
|
2668
|
+
dangerouslySetInnerHTML: { __html: content }
|
|
6130
2669
|
}
|
|
6131
|
-
)
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
/* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground max-w-2xl mx-auto", children: heroSubtitle })
|
|
6135
|
-
] }) }),
|
|
6136
|
-
/* @__PURE__ */ jsx("section", { className: "max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-12", children: loading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-20", children: /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : error ? /* @__PURE__ */ jsx("div", { className: "text-center py-16", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: error }) }) : contracts.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-16", children: /* @__PURE__ */ jsx("p", { className: "text-base text-muted-foreground", children: "No contracts are available yet." }) }) : /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border rounded-xl border border-border overflow-hidden bg-card", children: contracts.map((c) => {
|
|
6137
|
-
const ext = fileExt(c);
|
|
6138
|
-
const size = formatBytes(c.fileSize);
|
|
6139
|
-
return /* @__PURE__ */ jsxs(
|
|
6140
|
-
"li",
|
|
6141
|
-
{
|
|
6142
|
-
className: "flex items-center justify-between gap-4 p-5 hover:bg-muted/40 transition-colors",
|
|
6143
|
-
children: [
|
|
6144
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
6145
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
6146
|
-
/* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-foreground truncate", children: c.title }),
|
|
6147
|
-
c.version && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-primary bg-primary/10 px-2 py-0.5 rounded-full", children: c.version })
|
|
6148
|
-
] }),
|
|
6149
|
-
c.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1 line-clamp-2", children: c.description }),
|
|
6150
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
6151
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: ext }),
|
|
6152
|
-
size && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6153
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
6154
|
-
/* @__PURE__ */ jsx("span", { children: size })
|
|
6155
|
-
] })
|
|
6156
|
-
] })
|
|
6157
|
-
] }),
|
|
6158
|
-
/* @__PURE__ */ jsxs(
|
|
6159
|
-
"a",
|
|
6160
|
-
{
|
|
6161
|
-
href: c.fileUrl,
|
|
6162
|
-
target: "_blank",
|
|
6163
|
-
rel: "noopener noreferrer",
|
|
6164
|
-
download: true,
|
|
6165
|
-
"aria-label": `Download ${c.title}`,
|
|
6166
|
-
onClick: (e) => {
|
|
6167
|
-
void downloadFile(e, c);
|
|
6168
|
-
},
|
|
6169
|
-
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",
|
|
6170
|
-
children: [
|
|
6171
|
-
/* @__PURE__ */ jsx(
|
|
6172
|
-
"svg",
|
|
6173
|
-
{
|
|
6174
|
-
className: "w-4 h-4",
|
|
6175
|
-
fill: "none",
|
|
6176
|
-
viewBox: "0 0 24 24",
|
|
6177
|
-
stroke: "currentColor",
|
|
6178
|
-
"aria-hidden": "true",
|
|
6179
|
-
children: /* @__PURE__ */ jsx(
|
|
6180
|
-
"path",
|
|
6181
|
-
{
|
|
6182
|
-
strokeLinecap: "round",
|
|
6183
|
-
strokeLinejoin: "round",
|
|
6184
|
-
strokeWidth: 2,
|
|
6185
|
-
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
6186
|
-
}
|
|
6187
|
-
)
|
|
6188
|
-
}
|
|
6189
|
-
),
|
|
6190
|
-
"Download"
|
|
6191
|
-
]
|
|
6192
|
-
}
|
|
6193
|
-
)
|
|
6194
|
-
]
|
|
6195
|
-
},
|
|
6196
|
-
c.id
|
|
6197
|
-
);
|
|
6198
|
-
}) }) })
|
|
6199
|
-
] });
|
|
2670
|
+
);
|
|
2671
|
+
}
|
|
2672
|
+
return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx("pre", { style: { whiteSpace: "pre-wrap", fontFamily: "inherit" }, children: content }) });
|
|
6200
2673
|
}
|
|
6201
2674
|
|
|
6202
|
-
export {
|
|
2675
|
+
export { Button, ContactPage, ContentRenderer, Input, Label, NewsletterForm, NewsletterPage, PageHead, PricingPage, PricingSection, ProductProvider, RybbitAnalytics, Textarea, UnsubscribePage, WaitlistForm, WaitlistPage, WebSDKClient, WebSDKProvider, buttonVariants, cn, useContentPage, useContentPages, useProduct, useProductConfig, useWebSDK, useWebSDKConfig };
|
|
6203
2676
|
//# sourceMappingURL=index.mjs.map
|
|
6204
2677
|
//# sourceMappingURL=index.mjs.map
|