@burdenoff/website-sdk 2026.716.3 → 2026.719.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3943,6 +3943,10 @@ function ResourceLinks({
3943
3943
  function normalizeSearch(value) {
3944
3944
  return value.toLowerCase().trim();
3945
3945
  }
3946
+ function resolveWebsiteProductLogo(product) {
3947
+ if (product.logoUrl) return product.logoUrl;
3948
+ return `${product.websiteUrl.replace(/\/+$/, "")}/logo-icon.png`;
3949
+ }
3946
3950
  function filterProducts(products, query) {
3947
3951
  const normalized = normalizeSearch(query);
3948
3952
  if (!normalized) return products;
@@ -3957,6 +3961,9 @@ function WebsiteSwitcher({
3957
3961
  }) {
3958
3962
  const [open, setOpen] = React.useState(false);
3959
3963
  const [query, setQuery] = React.useState("");
3964
+ const [failedLogos, setFailedLogos] = React.useState(
3965
+ () => /* @__PURE__ */ new Set()
3966
+ );
3960
3967
  const filtered = React.useMemo(
3961
3968
  () => filterProducts(products, query),
3962
3969
  [products, query]
@@ -4035,15 +4042,21 @@ function WebsiteSwitcher({
4035
4042
  "text-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
4036
4043
  ),
4037
4044
  children: [
4038
- product.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx(
4045
+ failedLogos.has(product.slug) ? /* @__PURE__ */ jsxRuntime.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) }) : /* @__PURE__ */ jsxRuntime.jsx(
4039
4046
  "img",
4040
4047
  {
4041
- src: product.logoUrl,
4048
+ src: resolveWebsiteProductLogo(product),
4042
4049
  alt: "",
4043
4050
  "aria-hidden": "true",
4044
- className: "h-5 w-5 shrink-0 rounded object-contain"
4051
+ loading: "lazy",
4052
+ className: "h-5 w-5 shrink-0 rounded object-contain",
4053
+ onError: () => setFailedLogos((prev) => {
4054
+ const next = new Set(prev);
4055
+ next.add(product.slug);
4056
+ return next;
4057
+ })
4045
4058
  }
4046
- ) : /* @__PURE__ */ jsxRuntime.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) }),
4059
+ ),
4047
4060
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: product.name })
4048
4061
  ]
4049
4062
  }
@@ -6266,7 +6279,11 @@ function TypeBadge({ type }) {
6266
6279
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block text-xs px-2 py-0.5 rounded-full bg-primary/10 text-primary font-medium", children: labels[type] ?? type });
6267
6280
  }
6268
6281
  function ProductCard({ product, onClick, href }) {
6269
- const priceLabel = formatPrice2(product.price, product.currency, product.pricingModel);
6282
+ const priceLabel = formatPrice2(
6283
+ product.price,
6284
+ product.currency,
6285
+ product.pricingModel
6286
+ );
6270
6287
  const inner = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group bg-card border border-border rounded-xl p-4 flex flex-col gap-3 transition-all duration-200 hover:shadow-md hover:border-primary/30 cursor-pointer h-full", children: [
6271
6288
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
6272
6289
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 rounded-lg bg-muted flex-shrink-0 overflow-hidden", children: product.icon ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -6277,11 +6294,48 @@ function ProductCard({ product, onClick, href }) {
6277
6294
  "aria-hidden": "true",
6278
6295
  className: "w-full h-full object-cover"
6279
6296
  }
6280
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center bg-gradient-to-br from-primary/15 to-primary/5", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 32 32", className: "w-8 h-8", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
6281
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "16,4 28,10 16,16 4,10", className: "fill-primary/30", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.35" }),
6282
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "4,10 16,16 16,28 4,22", className: "fill-primary/15", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.35" }),
6283
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "28,10 16,16 16,28 28,22", className: "fill-primary/20", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.35" })
6284
- ] }) }) }),
6297
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center bg-gradient-to-br from-primary/15 to-primary/5", children: /* @__PURE__ */ jsxRuntime.jsxs(
6298
+ "svg",
6299
+ {
6300
+ viewBox: "0 0 32 32",
6301
+ className: "w-8 h-8",
6302
+ fill: "none",
6303
+ xmlns: "http://www.w3.org/2000/svg",
6304
+ "aria-hidden": "true",
6305
+ children: [
6306
+ /* @__PURE__ */ jsxRuntime.jsx(
6307
+ "polygon",
6308
+ {
6309
+ points: "16,4 28,10 16,16 4,10",
6310
+ className: "fill-primary/30",
6311
+ stroke: "currentColor",
6312
+ strokeWidth: "0.6",
6313
+ strokeOpacity: "0.35"
6314
+ }
6315
+ ),
6316
+ /* @__PURE__ */ jsxRuntime.jsx(
6317
+ "polygon",
6318
+ {
6319
+ points: "4,10 16,16 16,28 4,22",
6320
+ className: "fill-primary/15",
6321
+ stroke: "currentColor",
6322
+ strokeWidth: "0.6",
6323
+ strokeOpacity: "0.35"
6324
+ }
6325
+ ),
6326
+ /* @__PURE__ */ jsxRuntime.jsx(
6327
+ "polygon",
6328
+ {
6329
+ points: "28,10 16,16 16,28 28,22",
6330
+ className: "fill-primary/20",
6331
+ stroke: "currentColor",
6332
+ strokeWidth: "0.6",
6333
+ strokeOpacity: "0.35"
6334
+ }
6335
+ )
6336
+ ]
6337
+ }
6338
+ ) }) }),
6285
6339
  /* @__PURE__ */ jsxRuntime.jsx(TypeBadge, { type: product.type })
6286
6340
  ] }),
6287
6341
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
@@ -6390,7 +6444,11 @@ function FeaturedHeroCard({
6390
6444
  product,
6391
6445
  onNavigate
6392
6446
  }) {
6393
- const priceLabel = formatPrice2(product.price, product.currency, product.pricingModel);
6447
+ const priceLabel = formatPrice2(
6448
+ product.price,
6449
+ product.currency,
6450
+ product.pricingModel
6451
+ );
6394
6452
  return /* @__PURE__ */ jsxRuntime.jsxs(
6395
6453
  "button",
6396
6454
  {
@@ -6399,28 +6457,155 @@ function FeaturedHeroCard({
6399
6457
  className: "group w-full text-left h-full rounded-2xl border border-border bg-card overflow-hidden hover:border-primary/40 transition-all duration-300 hover:shadow-xl hover:shadow-primary/10 flex flex-col",
6400
6458
  children: [
6401
6459
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-44 sm:h-52 bg-gradient-to-br from-primary/20 via-primary/8 to-background overflow-hidden flex-shrink-0", children: [
6402
- product.bannerUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: product.bannerUrl, alt: "", "aria-hidden": "true", className: "w-full h-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6403
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "absolute inset-0 w-full h-full opacity-[0.07]", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
6404
- /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("pattern", { id: "fg-hero-grid", width: "36", height: "36", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 36 0 L 0 0 0 36", fill: "none", stroke: "currentColor", strokeWidth: "1" }) }) }),
6405
- /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: "url(#fg-hero-grid)" })
6406
- ] }),
6407
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 64 64", className: "w-20 h-20 opacity-25", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
6408
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "32,8 56,20 32,32 8,20", className: "fill-primary/40", stroke: "currentColor", strokeWidth: "1", strokeOpacity: "0.5" }),
6409
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "8,20 32,32 32,56 8,44", className: "fill-primary/20", stroke: "currentColor", strokeWidth: "1", strokeOpacity: "0.5" }),
6410
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "56,20 32,32 32,56 56,44", className: "fill-primary/30", stroke: "currentColor", strokeWidth: "1", strokeOpacity: "0.5" })
6411
- ] }) })
6460
+ product.bannerUrl ? /* @__PURE__ */ jsxRuntime.jsx(
6461
+ "img",
6462
+ {
6463
+ src: product.bannerUrl,
6464
+ alt: "",
6465
+ "aria-hidden": "true",
6466
+ className: "w-full h-full object-cover"
6467
+ }
6468
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6469
+ /* @__PURE__ */ jsxRuntime.jsxs(
6470
+ "svg",
6471
+ {
6472
+ className: "absolute inset-0 w-full h-full opacity-[0.07]",
6473
+ xmlns: "http://www.w3.org/2000/svg",
6474
+ "aria-hidden": "true",
6475
+ children: [
6476
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx(
6477
+ "pattern",
6478
+ {
6479
+ id: "fg-hero-grid",
6480
+ width: "36",
6481
+ height: "36",
6482
+ patternUnits: "userSpaceOnUse",
6483
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6484
+ "path",
6485
+ {
6486
+ d: "M 36 0 L 0 0 0 36",
6487
+ fill: "none",
6488
+ stroke: "currentColor",
6489
+ strokeWidth: "1"
6490
+ }
6491
+ )
6492
+ }
6493
+ ) }),
6494
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: "url(#fg-hero-grid)" })
6495
+ ]
6496
+ }
6497
+ ),
6498
+ /* @__PURE__ */ jsxRuntime.jsx(
6499
+ "div",
6500
+ {
6501
+ className: "absolute inset-0 flex items-center justify-center",
6502
+ "aria-hidden": "true",
6503
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
6504
+ "svg",
6505
+ {
6506
+ viewBox: "0 0 64 64",
6507
+ className: "w-20 h-20 opacity-25",
6508
+ fill: "none",
6509
+ xmlns: "http://www.w3.org/2000/svg",
6510
+ children: [
6511
+ /* @__PURE__ */ jsxRuntime.jsx(
6512
+ "polygon",
6513
+ {
6514
+ points: "32,8 56,20 32,32 8,20",
6515
+ className: "fill-primary/40",
6516
+ stroke: "currentColor",
6517
+ strokeWidth: "1",
6518
+ strokeOpacity: "0.5"
6519
+ }
6520
+ ),
6521
+ /* @__PURE__ */ jsxRuntime.jsx(
6522
+ "polygon",
6523
+ {
6524
+ points: "8,20 32,32 32,56 8,44",
6525
+ className: "fill-primary/20",
6526
+ stroke: "currentColor",
6527
+ strokeWidth: "1",
6528
+ strokeOpacity: "0.5"
6529
+ }
6530
+ ),
6531
+ /* @__PURE__ */ jsxRuntime.jsx(
6532
+ "polygon",
6533
+ {
6534
+ points: "56,20 32,32 32,56 56,44",
6535
+ className: "fill-primary/30",
6536
+ stroke: "currentColor",
6537
+ strokeWidth: "1",
6538
+ strokeOpacity: "0.5"
6539
+ }
6540
+ )
6541
+ ]
6542
+ }
6543
+ )
6544
+ }
6545
+ )
6412
6546
  ] }),
6413
6547
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-3 left-3 text-xs font-semibold px-2.5 py-1 rounded-full bg-primary text-primary-foreground shadow-sm", children: "Featured" }),
6414
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-4 left-4 w-14 h-14 rounded-xl shadow-lg overflow-hidden border-2 border-background", children: product.icon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: product.icon, alt: "", "aria-hidden": "true", className: "w-full h-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-gradient-to-br from-primary/25 to-primary/10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 32 32", className: "w-8 h-8", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
6415
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "16,4 28,10 16,16 4,10", className: "fill-primary/40", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.4" }),
6416
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "4,10 16,16 16,28 4,22", className: "fill-primary/20", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.4" }),
6417
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "28,10 16,16 16,28 28,22", className: "fill-primary/30", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.4" })
6418
- ] }) }) })
6548
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-4 left-4 w-14 h-14 rounded-xl shadow-lg overflow-hidden border-2 border-background", children: product.icon ? /* @__PURE__ */ jsxRuntime.jsx(
6549
+ "img",
6550
+ {
6551
+ src: product.icon,
6552
+ alt: "",
6553
+ "aria-hidden": "true",
6554
+ className: "w-full h-full object-cover"
6555
+ }
6556
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-gradient-to-br from-primary/25 to-primary/10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs(
6557
+ "svg",
6558
+ {
6559
+ viewBox: "0 0 32 32",
6560
+ className: "w-8 h-8",
6561
+ fill: "none",
6562
+ xmlns: "http://www.w3.org/2000/svg",
6563
+ "aria-hidden": "true",
6564
+ children: [
6565
+ /* @__PURE__ */ jsxRuntime.jsx(
6566
+ "polygon",
6567
+ {
6568
+ points: "16,4 28,10 16,16 4,10",
6569
+ className: "fill-primary/40",
6570
+ stroke: "currentColor",
6571
+ strokeWidth: "0.6",
6572
+ strokeOpacity: "0.4"
6573
+ }
6574
+ ),
6575
+ /* @__PURE__ */ jsxRuntime.jsx(
6576
+ "polygon",
6577
+ {
6578
+ points: "4,10 16,16 16,28 4,22",
6579
+ className: "fill-primary/20",
6580
+ stroke: "currentColor",
6581
+ strokeWidth: "0.6",
6582
+ strokeOpacity: "0.4"
6583
+ }
6584
+ ),
6585
+ /* @__PURE__ */ jsxRuntime.jsx(
6586
+ "polygon",
6587
+ {
6588
+ points: "28,10 16,16 16,28 28,22",
6589
+ className: "fill-primary/30",
6590
+ stroke: "currentColor",
6591
+ strokeWidth: "0.6",
6592
+ strokeOpacity: "0.4"
6593
+ }
6594
+ )
6595
+ ]
6596
+ }
6597
+ ) }) })
6419
6598
  ] }),
6420
6599
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-5 flex flex-col flex-1", children: [
6421
6600
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3 mb-2", children: [
6422
6601
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold text-foreground group-hover:text-primary transition-colors line-clamp-1", children: product.name }),
6423
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-sm font-bold flex-shrink-0 ${priceLabel === "Free" ? "text-emerald-500" : "text-foreground"}`, children: priceLabel })
6602
+ /* @__PURE__ */ jsxRuntime.jsx(
6603
+ "span",
6604
+ {
6605
+ className: `text-sm font-bold flex-shrink-0 ${priceLabel === "Free" ? "text-emerald-500" : "text-foreground"}`,
6606
+ children: priceLabel
6607
+ }
6608
+ )
6424
6609
  ] }),
6425
6610
  product.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground line-clamp-2 leading-relaxed flex-1", children: product.description }),
6426
6611
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex items-center gap-2", children: [
@@ -6441,7 +6626,10 @@ function ScrollRow({
6441
6626
  }) {
6442
6627
  const ref = React.useRef(null);
6443
6628
  function scroll(dir) {
6444
- ref.current?.scrollBy({ left: dir === "r" ? 272 : -272, behavior: "smooth" });
6629
+ ref.current?.scrollBy({
6630
+ left: dir === "r" ? 272 : -272,
6631
+ behavior: "smooth"
6632
+ });
6445
6633
  }
6446
6634
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group/row", children: [
6447
6635
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6451,7 +6639,19 @@ function ScrollRow({
6451
6639
  onClick: () => scroll("l"),
6452
6640
  "aria-label": "Scroll left",
6453
6641
  className: "absolute left-0 top-1/2 -translate-y-1/2 -translate-x-4 z-10 w-8 h-8 rounded-full bg-background border border-border shadow-md items-center justify-center text-muted-foreground hover:text-primary hover:border-primary/40 transition-all hidden sm:flex opacity-0 group-hover/row:opacity-100",
6454
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 16 16", className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L6 8l4 5" }) })
6642
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6643
+ "svg",
6644
+ {
6645
+ viewBox: "0 0 16 16",
6646
+ className: "w-4 h-4",
6647
+ fill: "none",
6648
+ stroke: "currentColor",
6649
+ strokeWidth: "1.5",
6650
+ strokeLinecap: "round",
6651
+ strokeLinejoin: "round",
6652
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L6 8l4 5" })
6653
+ }
6654
+ )
6455
6655
  }
6456
6656
  ),
6457
6657
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6460,7 +6660,13 @@ function ScrollRow({
6460
6660
  ref,
6461
6661
  className: "flex gap-3 overflow-x-auto pb-1 snap-x snap-mandatory",
6462
6662
  style: { scrollbarWidth: "none", msOverflowStyle: "none" },
6463
- children: products.map((product) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-56 snap-start", children: /* @__PURE__ */ jsxRuntime.jsx(ProductCard, { product, onClick: () => onProductClick(product) }) }, product.id))
6663
+ children: products.map((product) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-56 snap-start", children: /* @__PURE__ */ jsxRuntime.jsx(
6664
+ ProductCard,
6665
+ {
6666
+ product,
6667
+ onClick: () => onProductClick(product)
6668
+ }
6669
+ ) }, product.id))
6464
6670
  }
6465
6671
  ),
6466
6672
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6470,7 +6676,19 @@ function ScrollRow({
6470
6676
  onClick: () => scroll("r"),
6471
6677
  "aria-label": "Scroll right",
6472
6678
  className: "absolute right-0 top-1/2 -translate-y-1/2 translate-x-4 z-10 w-8 h-8 rounded-full bg-background border border-border shadow-md items-center justify-center text-muted-foreground hover:text-primary hover:border-primary/40 transition-all hidden sm:flex opacity-0 group-hover/row:opacity-100",
6473
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 16 16", className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 3l4 5-4 5" }) })
6679
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6680
+ "svg",
6681
+ {
6682
+ viewBox: "0 0 16 16",
6683
+ className: "w-4 h-4",
6684
+ fill: "none",
6685
+ stroke: "currentColor",
6686
+ strokeWidth: "1.5",
6687
+ strokeLinecap: "round",
6688
+ strokeLinejoin: "round",
6689
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 3l4 5-4 5" })
6690
+ }
6691
+ )
6474
6692
  }
6475
6693
  )
6476
6694
  ] });
@@ -6573,10 +6791,8 @@ function StoreHomePage({
6573
6791
  const [grouped, setGrouped] = React.useState(null);
6574
6792
  const [loading, setLoading] = React.useState(true);
6575
6793
  const [error, setError] = React.useState(null);
6576
- const [retryKey, setRetryKey] = React.useState(0);
6577
6794
  React.useEffect(() => {
6578
6795
  let cancelled = false;
6579
- let autoRetryTimer = null;
6580
6796
  async function load() {
6581
6797
  setLoading(true);
6582
6798
  try {
@@ -6590,15 +6806,7 @@ function StoreHomePage({
6590
6806
  setGrouped(res.data.homeGroupedProducts);
6591
6807
  setError(null);
6592
6808
  } catch {
6593
- if (!cancelled) {
6594
- if (retryKey < 1) {
6595
- autoRetryTimer = setTimeout(() => {
6596
- if (!cancelled) setRetryKey(1);
6597
- }, 2e3);
6598
- } else {
6599
- setError("Failed to load store. Please try again.");
6600
- }
6601
- }
6809
+ if (!cancelled) setError("Failed to load store. Please try again.");
6602
6810
  } finally {
6603
6811
  if (!cancelled) setLoading(false);
6604
6812
  }
@@ -6606,9 +6814,8 @@ function StoreHomePage({
6606
6814
  load();
6607
6815
  return () => {
6608
6816
  cancelled = true;
6609
- if (autoRetryTimer) clearTimeout(autoRetryTimer);
6610
6817
  };
6611
- }, [client, compatibleWith, retryKey]);
6818
+ }, [client, compatibleWith]);
6612
6819
  function navigate(path) {
6613
6820
  if (onNavigate) {
6614
6821
  onNavigate(path);
@@ -6636,16 +6843,65 @@ function StoreHomePage({
6636
6843
  }
6637
6844
  ),
6638
6845
  /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "relative overflow-hidden pt-14 pb-12 sm:pt-20 sm:pb-16", children: [
6639
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-gradient-to-b from-background via-primary/[0.06] to-background pointer-events-none", "aria-hidden": "true" }),
6640
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "absolute inset-0 w-full h-full opacity-[0.035] pointer-events-none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
6641
- /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("pattern", { id: "store-home-grid", width: "40", height: "40", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 40 0 L 0 0 0 40", fill: "none", stroke: "currentColor", strokeWidth: "1" }) }) }),
6642
- /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: "url(#store-home-grid)" })
6643
- ] }),
6644
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-16 left-1/3 w-80 h-80 rounded-full bg-primary/10 blur-3xl pointer-events-none", "aria-hidden": "true" }),
6645
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-8 right-1/4 w-56 h-56 rounded-full bg-primary/8 blur-2xl pointer-events-none", "aria-hidden": "true" }),
6846
+ /* @__PURE__ */ jsxRuntime.jsx(
6847
+ "div",
6848
+ {
6849
+ className: "absolute inset-0 bg-gradient-to-b from-background via-primary/[0.06] to-background pointer-events-none",
6850
+ "aria-hidden": "true"
6851
+ }
6852
+ ),
6853
+ /* @__PURE__ */ jsxRuntime.jsxs(
6854
+ "svg",
6855
+ {
6856
+ className: "absolute inset-0 w-full h-full opacity-[0.035] pointer-events-none",
6857
+ xmlns: "http://www.w3.org/2000/svg",
6858
+ "aria-hidden": "true",
6859
+ children: [
6860
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx(
6861
+ "pattern",
6862
+ {
6863
+ id: "store-home-grid",
6864
+ width: "40",
6865
+ height: "40",
6866
+ patternUnits: "userSpaceOnUse",
6867
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6868
+ "path",
6869
+ {
6870
+ d: "M 40 0 L 0 0 0 40",
6871
+ fill: "none",
6872
+ stroke: "currentColor",
6873
+ strokeWidth: "1"
6874
+ }
6875
+ )
6876
+ }
6877
+ ) }),
6878
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: "url(#store-home-grid)" })
6879
+ ]
6880
+ }
6881
+ ),
6882
+ /* @__PURE__ */ jsxRuntime.jsx(
6883
+ "div",
6884
+ {
6885
+ className: "absolute -top-16 left-1/3 w-80 h-80 rounded-full bg-primary/10 blur-3xl pointer-events-none",
6886
+ "aria-hidden": "true"
6887
+ }
6888
+ ),
6889
+ /* @__PURE__ */ jsxRuntime.jsx(
6890
+ "div",
6891
+ {
6892
+ className: "absolute top-8 right-1/4 w-56 h-56 rounded-full bg-primary/8 blur-2xl pointer-events-none",
6893
+ "aria-hidden": "true"
6894
+ }
6895
+ ),
6646
6896
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center", children: [
6647
6897
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-2 px-3 py-1 rounded-full border border-primary/30 bg-primary/10 text-xs font-semibold text-primary mb-5", children: [
6648
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0", "aria-hidden": "true" }),
6898
+ /* @__PURE__ */ jsxRuntime.jsx(
6899
+ "span",
6900
+ {
6901
+ className: "w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0",
6902
+ "aria-hidden": "true"
6903
+ }
6904
+ ),
6649
6905
  "Community Marketplace"
6650
6906
  ] }),
6651
6907
  /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl sm:text-5xl md:text-6xl font-extrabold tracking-tight text-foreground mb-4 leading-[1.08]", children: resolvedTitle }),
@@ -6657,7 +6913,9 @@ function StoreHomePage({
6657
6913
  onSubmit: (e) => {
6658
6914
  e.preventDefault();
6659
6915
  const q = new FormData(e.currentTarget).get("q");
6660
- navigate(q.trim() ? `${browsePath}?q=${encodeURIComponent(q.trim())}` : browsePath);
6916
+ navigate(
6917
+ q.trim() ? `${browsePath}?q=${encodeURIComponent(q.trim())}` : browsePath
6918
+ );
6661
6919
  },
6662
6920
  children: [
6663
6921
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6699,9 +6957,23 @@ function StoreHomePage({
6699
6957
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [...Array(4)].map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(GridCardSkeleton, {}, i)) })
6700
6958
  ] }) : error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-16 text-center", children: [
6701
6959
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mb-4", children: error }),
6702
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => setRetryKey((k) => k + 1), className: "text-sm text-primary hover:underline", children: "Retry" })
6960
+ /* @__PURE__ */ jsxRuntime.jsx(
6961
+ "button",
6962
+ {
6963
+ type: "button",
6964
+ onClick: () => window.location.reload(),
6965
+ className: "text-sm text-primary hover:underline",
6966
+ children: "Retry"
6967
+ }
6968
+ )
6703
6969
  ] }) : featuredItems.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-[1fr_2fr] gap-4 items-start", children: [
6704
- /* @__PURE__ */ jsxRuntime.jsx(FeaturedHeroCard, { product: featuredItems[0], onNavigate: navigate }),
6970
+ /* @__PURE__ */ jsxRuntime.jsx(
6971
+ FeaturedHeroCard,
6972
+ {
6973
+ product: featuredItems[0],
6974
+ onNavigate: navigate
6975
+ }
6976
+ ),
6705
6977
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: featuredItems.slice(1, 5).map((product) => /* @__PURE__ */ jsxRuntime.jsx(
6706
6978
  ProductCard,
6707
6979
  {
@@ -6722,7 +6994,13 @@ function StoreHomePage({
6722
6994
  onNavigate: navigate
6723
6995
  }
6724
6996
  ),
6725
- loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3 overflow-hidden", children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(ScrollCardSkeleton, {}, i)) }) : /* @__PURE__ */ jsxRuntime.jsx(ScrollRow, { products: popularItems, onProductClick: handleProductClick })
6997
+ loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3 overflow-hidden", children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(ScrollCardSkeleton, {}, i)) }) : /* @__PURE__ */ jsxRuntime.jsx(
6998
+ ScrollRow,
6999
+ {
7000
+ products: popularItems,
7001
+ onProductClick: handleProductClick
7002
+ }
7003
+ )
6726
7004
  ] }),
6727
7005
  (loading || freeItems.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
6728
7006
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6745,16 +7023,35 @@ function StoreHomePage({
6745
7023
  ] })
6746
7024
  ] }),
6747
7025
  /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "relative overflow-hidden border-t border-border", children: [
6748
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-primary/8 via-background to-primary/5 pointer-events-none", "aria-hidden": "true" }),
6749
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-80 h-40 rounded-full bg-primary/12 blur-3xl pointer-events-none", "aria-hidden": "true" }),
7026
+ /* @__PURE__ */ jsxRuntime.jsx(
7027
+ "div",
7028
+ {
7029
+ className: "absolute inset-0 bg-gradient-to-br from-primary/8 via-background to-primary/5 pointer-events-none",
7030
+ "aria-hidden": "true"
7031
+ }
7032
+ ),
7033
+ /* @__PURE__ */ jsxRuntime.jsx(
7034
+ "div",
7035
+ {
7036
+ className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-80 h-40 rounded-full bg-primary/12 blur-3xl pointer-events-none",
7037
+ "aria-hidden": "true"
7038
+ }
7039
+ ),
6750
7040
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-2xl mx-auto px-4 py-16 text-center", children: [
6751
7041
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-2 px-3 py-1 rounded-full border border-primary/30 bg-primary/10 text-xs font-semibold text-primary mb-5", children: [
6752
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0", "aria-hidden": "true" }),
7042
+ /* @__PURE__ */ jsxRuntime.jsx(
7043
+ "span",
7044
+ {
7045
+ className: "w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0",
7046
+ "aria-hidden": "true"
7047
+ }
7048
+ ),
6753
7049
  "Become a publisher"
6754
7050
  ] }),
6755
7051
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground mb-3", children: "Built something useful?" }),
6756
7052
  /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-muted-foreground mb-8 max-w-lg mx-auto leading-relaxed", children: [
6757
- "Share your workflows, nodes, and integrations with ",
7053
+ "Share your workflows, nodes, and integrations with",
7054
+ " ",
6758
7055
  productName ?? "the",
6759
7056
  " community. Earn from your work or contribute for free."
6760
7057
  ] }),
@@ -6810,7 +7107,14 @@ var PRICING_OPTIONS = [
6810
7107
  ];
6811
7108
  function parseUrlParams() {
6812
7109
  if (typeof window === "undefined")
6813
- return { q: "", type: "", pricingModel: "", category: "", sortBy: "RELEVANCE", featured: false };
7110
+ return {
7111
+ q: "",
7112
+ type: "",
7113
+ pricingModel: "",
7114
+ category: "",
7115
+ sortBy: "RELEVANCE",
7116
+ featured: false
7117
+ };
6814
7118
  const p = new URLSearchParams(window.location.search);
6815
7119
  return {
6816
7120
  q: p.get("q") ?? "",
@@ -6862,7 +7166,9 @@ function StoreBrowsePage({
6862
7166
  const [featured, setFeatured] = React.useState(initial.featured);
6863
7167
  const [offset, setOffset] = React.useState(0);
6864
7168
  const [result, setResult] = React.useState(null);
6865
- const [allProducts, setAllProducts] = React.useState([]);
7169
+ const [allProducts, setAllProducts] = React.useState(
7170
+ []
7171
+ );
6866
7172
  const [categories, setCategories] = React.useState([]);
6867
7173
  const [loading, setLoading] = React.useState(true);
6868
7174
  const [loadingMore, setLoadingMore] = React.useState(false);
@@ -6906,7 +7212,16 @@ function StoreBrowsePage({
6906
7212
  return () => {
6907
7213
  cancelled = true;
6908
7214
  };
6909
- }, [client, search, type, pricingModel, category, sortBy, compatibleWith, featured]);
7215
+ }, [
7216
+ client,
7217
+ search,
7218
+ type,
7219
+ pricingModel,
7220
+ category,
7221
+ sortBy,
7222
+ compatibleWith,
7223
+ featured
7224
+ ]);
6910
7225
  function loadMore() {
6911
7226
  const nextOffset = offset + PAGE_SIZE;
6912
7227
  setLoadingMore(true);
@@ -7082,7 +7397,8 @@ function StoreBrowsePage({
7082
7397
  onClick: () => setFiltersOpen(!filtersOpen),
7083
7398
  className: "lg:hidden h-10 px-4 rounded-lg border border-border bg-background text-sm text-foreground hover:bg-muted/50 transition-colors",
7084
7399
  children: [
7085
- "Filters ",
7400
+ "Filters",
7401
+ " ",
7086
7402
  hasActiveFilters && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary", children: "\u2022" })
7087
7403
  ]
7088
7404
  }
@@ -7096,14 +7412,32 @@ function StoreBrowsePage({
7096
7412
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-4 flex-wrap", children: [
7097
7413
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: loading ? "Loading\u2026" : `${result?.totalCount ?? 0} results` }),
7098
7414
  hasActiveFilters && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1.5", children: [
7099
- search && /* @__PURE__ */ jsxRuntime.jsx(Chip, { label: `"${search}"`, onRemove: () => {
7100
- setSearch("");
7101
- setInputValue("");
7102
- } }),
7415
+ search && /* @__PURE__ */ jsxRuntime.jsx(
7416
+ Chip,
7417
+ {
7418
+ label: `"${search}"`,
7419
+ onRemove: () => {
7420
+ setSearch("");
7421
+ setInputValue("");
7422
+ }
7423
+ }
7424
+ ),
7103
7425
  type && /* @__PURE__ */ jsxRuntime.jsx(Chip, { label: type, onRemove: () => setType("") }),
7104
- pricingModel && /* @__PURE__ */ jsxRuntime.jsx(Chip, { label: pricingModel, onRemove: () => setPricingModel("") }),
7426
+ pricingModel && /* @__PURE__ */ jsxRuntime.jsx(
7427
+ Chip,
7428
+ {
7429
+ label: pricingModel,
7430
+ onRemove: () => setPricingModel("")
7431
+ }
7432
+ ),
7105
7433
  category && /* @__PURE__ */ jsxRuntime.jsx(Chip, { label: category, onRemove: () => setCategory("") }),
7106
- featured && /* @__PURE__ */ jsxRuntime.jsx(Chip, { label: "Featured", onRemove: () => setFeatured(false) })
7434
+ featured && /* @__PURE__ */ jsxRuntime.jsx(
7435
+ Chip,
7436
+ {
7437
+ label: "Featured",
7438
+ onRemove: () => setFeatured(false)
7439
+ }
7440
+ )
7107
7441
  ] })
7108
7442
  ] }),
7109
7443
  loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-4", children: [...Array(12)].map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -7155,9 +7489,97 @@ function StoreBrowsePage({
7155
7489
  function Chip({ label, onRemove }) {
7156
7490
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-xs bg-primary/10 text-primary rounded-full px-2.5 py-0.5 font-medium", children: [
7157
7491
  label,
7158
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onRemove, "aria-label": `Remove ${label}`, className: "hover:opacity-70", children: "\xD7" })
7492
+ /* @__PURE__ */ jsxRuntime.jsx(
7493
+ "button",
7494
+ {
7495
+ type: "button",
7496
+ onClick: onRemove,
7497
+ "aria-label": `Remove ${label}`,
7498
+ className: "hover:opacity-70",
7499
+ children: "\xD7"
7500
+ }
7501
+ )
7159
7502
  ] });
7160
7503
  }
7504
+ function detectTheme() {
7505
+ if (typeof document === "undefined") return "light";
7506
+ const root = document.documentElement;
7507
+ return root.classList.contains("dark") || root.getAttribute("data-theme") === "dark" ? "dark" : "light";
7508
+ }
7509
+ function WorkflowEmbed({
7510
+ appUrl,
7511
+ productId,
7512
+ theme,
7513
+ clickToInteract = true,
7514
+ hideCta = false,
7515
+ className,
7516
+ onError
7517
+ }) {
7518
+ const iframeRef = React.useRef(null);
7519
+ const [status, setStatus] = React.useState("loading");
7520
+ const [interactive, setInteractive] = React.useState(!clickToInteract);
7521
+ const resolvedTheme = React.useMemo(() => theme ?? detectTheme(), [theme]);
7522
+ const src = React.useMemo(() => {
7523
+ const base = appUrl.replace(/\/+$/, "");
7524
+ const params = new URLSearchParams({
7525
+ productId,
7526
+ theme: resolvedTheme
7527
+ });
7528
+ if (hideCta) params.set("cta", "false");
7529
+ return `${base}/embed/workflow?${params.toString()}`;
7530
+ }, [appUrl, productId, resolvedTheme, hideCta]);
7531
+ React.useEffect(() => {
7532
+ const handler = (event) => {
7533
+ if (event.source !== iframeRef.current?.contentWindow) return;
7534
+ const data = event.data;
7535
+ if (data?.type === "fluidgrids:embed:loaded") setStatus("loaded");
7536
+ if (data?.type === "fluidgrids:embed:error") {
7537
+ setStatus("error");
7538
+ onError?.(data.message ?? "Failed to load workflow preview");
7539
+ }
7540
+ };
7541
+ window.addEventListener("message", handler);
7542
+ return () => window.removeEventListener("message", handler);
7543
+ }, [onError]);
7544
+ if (status === "error") return null;
7545
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7546
+ "div",
7547
+ {
7548
+ className: `relative w-full overflow-hidden rounded-xl border border-border bg-muted ${className ?? ""}`,
7549
+ style: { aspectRatio: "16 / 9" },
7550
+ children: [
7551
+ status === "loading" && /* @__PURE__ */ jsxRuntime.jsx(
7552
+ "div",
7553
+ {
7554
+ className: "absolute inset-0 animate-pulse bg-muted",
7555
+ "aria-hidden": "true"
7556
+ }
7557
+ ),
7558
+ /* @__PURE__ */ jsxRuntime.jsx(
7559
+ "iframe",
7560
+ {
7561
+ ref: iframeRef,
7562
+ src,
7563
+ title: "Workflow preview",
7564
+ loading: "lazy",
7565
+ className: "h-full w-full border-0",
7566
+ style: interactive ? void 0 : { pointerEvents: "none" }
7567
+ }
7568
+ ),
7569
+ clickToInteract && !interactive && status === "loaded" && /* @__PURE__ */ jsxRuntime.jsx(
7570
+ "button",
7571
+ {
7572
+ type: "button",
7573
+ onClick: () => setInteractive(true),
7574
+ className: "absolute inset-0 flex items-end justify-center bg-transparent pb-4",
7575
+ "aria-label": "Click to explore the workflow",
7576
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full border border-border bg-background/90 px-4 py-1.5 text-xs font-medium text-foreground shadow-sm backdrop-blur transition-colors hover:bg-background", children: "Click to explore" })
7577
+ }
7578
+ )
7579
+ ]
7580
+ }
7581
+ );
7582
+ }
7161
7583
  var ANIM_STYLES = `
7162
7584
  @keyframes sdFadeUp {
7163
7585
  from { opacity: 0; transform: translateY(16px); }
@@ -7190,50 +7612,11 @@ var ANIM_STYLES = `
7190
7612
  .sd-d5 { animation-delay: 320ms; }
7191
7613
  .sd-d6 { animation-delay: 400ms; }
7192
7614
  `;
7193
- function mdInline(text) {
7194
- const parts = text.split(/(\*\*[^*]+\*\*)/g);
7195
- if (parts.length === 1) return text;
7196
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: parts.map(
7197
- (part, i) => part.startsWith("**") && part.endsWith("**") ? /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-semibold text-foreground", children: part.slice(2, -2) }, i) : part || null
7198
- ) });
7199
- }
7200
- function MdAbout({ content }) {
7201
- let key = 0;
7202
- const nodes = [];
7203
- let listItems = [];
7204
- const flushList = () => {
7205
- if (!listItems.length) return;
7206
- nodes.push(
7207
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "list-disc list-inside space-y-0.5 my-2", children: listItems.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "text-sm leading-relaxed", children: mdInline(item) }, i)) }, key++)
7208
- );
7209
- listItems = [];
7210
- };
7211
- for (const line of content.split("\n")) {
7212
- if (!line.trim()) {
7213
- flushList();
7214
- continue;
7215
- }
7216
- const hm = line.match(/^(#{1,3})\s+(.*)/);
7217
- if (hm) {
7218
- flushList();
7219
- nodes.push(
7220
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold text-foreground mt-4 first:mt-0 text-sm", children: mdInline(hm[2]) }, key++)
7221
- );
7222
- continue;
7223
- }
7224
- if (/^[-*]\s/.test(line)) {
7225
- listItems.push(line.replace(/^[-*]\s+/, ""));
7226
- continue;
7227
- }
7228
- flushList();
7229
- nodes.push(
7230
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-relaxed mb-1", children: mdInline(line) }, key++)
7231
- );
7232
- }
7233
- flushList();
7234
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: nodes });
7235
- }
7236
- function RatingBar({ label, count, total }) {
7615
+ function RatingBar({
7616
+ label,
7617
+ count,
7618
+ total
7619
+ }) {
7237
7620
  const pct = total > 0 ? Math.round(count / total * 100) : 0;
7238
7621
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
7239
7622
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-12 text-right shrink-0", children: label }),
@@ -7249,12 +7632,63 @@ function RatingBar({ label, count, total }) {
7249
7632
  }
7250
7633
  function IconBlock({ src }) {
7251
7634
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-shrink-0", children: [
7252
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sd-gp absolute -inset-1.5 rounded-2xl bg-primary/30 blur-md pointer-events-none", "aria-hidden": "true" }),
7253
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sd-si relative w-20 h-20 rounded-2xl overflow-hidden shadow-lg ring-1 ring-border", children: src ? /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: "", "aria-hidden": true, className: "w-full h-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-gradient-to-br from-primary/25 to-primary/8 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 40 40", className: "w-10 h-10", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
7254
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "20,4 34,11 20,18 6,11", className: "fill-primary/40", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.4" }),
7255
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "6,11 20,18 20,34 6,27", className: "fill-primary/20", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.4" }),
7256
- /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "34,11 20,18 20,34 34,27", className: "fill-primary/30", stroke: "currentColor", strokeWidth: "0.6", strokeOpacity: "0.4" })
7257
- ] }) }) })
7635
+ /* @__PURE__ */ jsxRuntime.jsx(
7636
+ "div",
7637
+ {
7638
+ className: "sd-gp absolute -inset-1.5 rounded-2xl bg-primary/30 blur-md pointer-events-none",
7639
+ "aria-hidden": "true"
7640
+ }
7641
+ ),
7642
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sd-si relative w-20 h-20 rounded-2xl overflow-hidden shadow-lg ring-1 ring-border", children: src ? /* @__PURE__ */ jsxRuntime.jsx(
7643
+ "img",
7644
+ {
7645
+ src,
7646
+ alt: "",
7647
+ "aria-hidden": true,
7648
+ className: "w-full h-full object-cover"
7649
+ }
7650
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-gradient-to-br from-primary/25 to-primary/8 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs(
7651
+ "svg",
7652
+ {
7653
+ viewBox: "0 0 40 40",
7654
+ className: "w-10 h-10",
7655
+ fill: "none",
7656
+ xmlns: "http://www.w3.org/2000/svg",
7657
+ "aria-hidden": "true",
7658
+ children: [
7659
+ /* @__PURE__ */ jsxRuntime.jsx(
7660
+ "polygon",
7661
+ {
7662
+ points: "20,4 34,11 20,18 6,11",
7663
+ className: "fill-primary/40",
7664
+ stroke: "currentColor",
7665
+ strokeWidth: "0.6",
7666
+ strokeOpacity: "0.4"
7667
+ }
7668
+ ),
7669
+ /* @__PURE__ */ jsxRuntime.jsx(
7670
+ "polygon",
7671
+ {
7672
+ points: "6,11 20,18 20,34 6,27",
7673
+ className: "fill-primary/20",
7674
+ stroke: "currentColor",
7675
+ strokeWidth: "0.6",
7676
+ strokeOpacity: "0.4"
7677
+ }
7678
+ ),
7679
+ /* @__PURE__ */ jsxRuntime.jsx(
7680
+ "polygon",
7681
+ {
7682
+ points: "34,11 20,18 20,34 34,27",
7683
+ className: "fill-primary/30",
7684
+ stroke: "currentColor",
7685
+ strokeWidth: "0.6",
7686
+ strokeOpacity: "0.4"
7687
+ }
7688
+ )
7689
+ ]
7690
+ }
7691
+ ) }) })
7258
7692
  ] });
7259
7693
  }
7260
7694
  function StoreProductDetailPage({
@@ -7270,6 +7704,7 @@ function StoreProductDetailPage({
7270
7704
  const [error, setError] = React.useState(null);
7271
7705
  const [activeScreenshot, setActiveScreenshot] = React.useState(0);
7272
7706
  const [screenshotKey, setScreenshotKey] = React.useState(0);
7707
+ const [embedFailed, setEmbedFailed] = React.useState(false);
7273
7708
  React.useEffect(() => {
7274
7709
  if (!slug && !id) {
7275
7710
  setError("Product not found.");
@@ -7323,11 +7758,30 @@ function StoreProductDetailPage({
7323
7758
  if (error || !details) {
7324
7759
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 text-center", children: [
7325
7760
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mb-4", children: error ?? "Product not found." }),
7326
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => navigate("/store"), className: "text-sm text-primary hover:underline", children: "Back to Store" })
7761
+ /* @__PURE__ */ jsxRuntime.jsx(
7762
+ "button",
7763
+ {
7764
+ type: "button",
7765
+ onClick: () => navigate("/store"),
7766
+ className: "text-sm text-primary hover:underline",
7767
+ children: "Back to Store"
7768
+ }
7769
+ )
7327
7770
  ] });
7328
7771
  }
7329
- const { product, publisher, reviews, reviewsCount, relatedProducts, ratingDistribution } = details;
7330
- const priceLabel = formatPrice2(product.price, product.currency, product.pricingModel);
7772
+ const {
7773
+ product,
7774
+ publisher,
7775
+ reviews,
7776
+ reviewsCount,
7777
+ relatedProducts,
7778
+ ratingDistribution
7779
+ } = details;
7780
+ const priceLabel = formatPrice2(
7781
+ product.price,
7782
+ product.currency,
7783
+ product.pricingModel
7784
+ );
7331
7785
  const screenshots = product.screenshots ?? [];
7332
7786
  const totalRatings = ratingDistribution ? ratingDistribution.fiveStars + ratingDistribution.fourStars + ratingDistribution.threeStars + ratingDistribution.twoStars + ratingDistribution.oneStar : 0;
7333
7787
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
@@ -7341,15 +7795,60 @@ function StoreProductDetailPage({
7341
7795
  }
7342
7796
  ),
7343
7797
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative overflow-hidden", children: [
7344
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-gradient-to-b from-primary/[0.07] via-background to-background pointer-events-none", "aria-hidden": "true" }),
7345
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "absolute inset-0 w-full h-full opacity-[0.04] pointer-events-none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
7346
- /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("pattern", { id: "sd-grid", width: "40", height: "40", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 40 0 L 0 0 0 40", fill: "none", stroke: "currentColor", strokeWidth: "1" }) }) }),
7347
- /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: "url(#sd-grid)" })
7348
- ] }),
7349
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-12 -left-12 w-72 h-72 rounded-full bg-primary/10 blur-3xl pointer-events-none", "aria-hidden": "true" }),
7798
+ /* @__PURE__ */ jsxRuntime.jsx(
7799
+ "div",
7800
+ {
7801
+ className: "absolute inset-0 bg-gradient-to-b from-primary/[0.07] via-background to-background pointer-events-none",
7802
+ "aria-hidden": "true"
7803
+ }
7804
+ ),
7805
+ /* @__PURE__ */ jsxRuntime.jsxs(
7806
+ "svg",
7807
+ {
7808
+ className: "absolute inset-0 w-full h-full opacity-[0.04] pointer-events-none",
7809
+ xmlns: "http://www.w3.org/2000/svg",
7810
+ "aria-hidden": "true",
7811
+ children: [
7812
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx(
7813
+ "pattern",
7814
+ {
7815
+ id: "sd-grid",
7816
+ width: "40",
7817
+ height: "40",
7818
+ patternUnits: "userSpaceOnUse",
7819
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7820
+ "path",
7821
+ {
7822
+ d: "M 40 0 L 0 0 0 40",
7823
+ fill: "none",
7824
+ stroke: "currentColor",
7825
+ strokeWidth: "1"
7826
+ }
7827
+ )
7828
+ }
7829
+ ) }),
7830
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: "url(#sd-grid)" })
7831
+ ]
7832
+ }
7833
+ ),
7834
+ /* @__PURE__ */ jsxRuntime.jsx(
7835
+ "div",
7836
+ {
7837
+ className: "absolute -top-12 -left-12 w-72 h-72 rounded-full bg-primary/10 blur-3xl pointer-events-none",
7838
+ "aria-hidden": "true"
7839
+ }
7840
+ ),
7350
7841
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pt-6 pb-8", children: [
7351
7842
  /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "sd-fi text-sm text-muted-foreground mb-6 flex items-center gap-1.5 flex-wrap", children: [
7352
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => navigate("/store"), className: "hover:text-primary transition-colors", children: "Store" }),
7843
+ /* @__PURE__ */ jsxRuntime.jsx(
7844
+ "button",
7845
+ {
7846
+ type: "button",
7847
+ onClick: () => navigate("/store"),
7848
+ className: "hover:text-primary transition-colors",
7849
+ children: "Store"
7850
+ }
7851
+ ),
7353
7852
  /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u203A" }),
7354
7853
  product.category && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7355
7854
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -7415,6 +7914,14 @@ function StoreProductDetailPage({
7415
7914
  }
7416
7915
  )
7417
7916
  ] }),
7917
+ product.type === "WORKFLOW" && !embedFailed && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sd-fu sd-d3 mb-8", children: /* @__PURE__ */ jsxRuntime.jsx(
7918
+ WorkflowEmbed,
7919
+ {
7920
+ appUrl: appLoginUrl,
7921
+ productId: product.id,
7922
+ onError: () => setEmbedFailed(true)
7923
+ }
7924
+ ) }),
7418
7925
  screenshots.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sd-fu sd-d3 mb-8", children: [
7419
7926
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl overflow-hidden bg-muted aspect-video mb-3 shadow-md", children: /* @__PURE__ */ jsxRuntime.jsx(
7420
7927
  "img",
@@ -7431,19 +7938,33 @@ function StoreProductDetailPage({
7431
7938
  type: "button",
7432
7939
  onClick: () => switchScreenshot(i),
7433
7940
  className: `w-20 h-14 rounded-lg overflow-hidden flex-shrink-0 border-2 transition-all duration-200 ${i === activeScreenshot ? "border-primary shadow-sm shadow-primary/20" : "border-transparent opacity-50 hover:opacity-80"}`,
7434
- children: /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: `Thumbnail ${i + 1}`, className: "w-full h-full object-cover" })
7941
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7942
+ "img",
7943
+ {
7944
+ src,
7945
+ alt: `Thumbnail ${i + 1}`,
7946
+ className: "w-full h-full object-cover"
7947
+ }
7948
+ )
7435
7949
  },
7436
7950
  i
7437
7951
  )) })
7438
7952
  ] }),
7439
7953
  product.longDescription && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sd-fu sd-d4 mb-8", children: [
7440
7954
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-bold text-foreground mb-3", children: "About" }),
7441
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(MdAbout, { content: product.longDescription }) })
7955
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose prose-sm max-w-none text-muted-foreground leading-relaxed whitespace-pre-line", children: product.longDescription })
7442
7956
  ] }),
7443
7957
  publisher && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sd-fu sd-d5 mb-8 p-4 rounded-xl border border-border bg-card hover:border-primary/30 transition-colors duration-300", children: [
7444
7958
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm font-semibold text-foreground mb-3", children: "Publisher" }),
7445
7959
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
7446
- publisher.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: publisher.logoUrl, alt: publisher.name, className: "w-10 h-10 rounded-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary text-sm font-bold", children: publisher.name.charAt(0).toUpperCase() }),
7960
+ publisher.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7961
+ "img",
7962
+ {
7963
+ src: publisher.logoUrl,
7964
+ alt: publisher.name,
7965
+ className: "w-10 h-10 rounded-full object-cover"
7966
+ }
7967
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary text-sm font-bold", children: publisher.name.charAt(0).toUpperCase() }),
7447
7968
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
7448
7969
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
7449
7970
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground text-sm", children: publisher.name }),
@@ -7469,11 +7990,46 @@ function StoreProductDetailPage({
7469
7990
  ] })
7470
7991
  ] }),
7471
7992
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-1.5 pt-1", children: [
7472
- /* @__PURE__ */ jsxRuntime.jsx(RatingBar, { label: "5 \u2605", count: ratingDistribution.fiveStars, total: totalRatings }),
7473
- /* @__PURE__ */ jsxRuntime.jsx(RatingBar, { label: "4 \u2605", count: ratingDistribution.fourStars, total: totalRatings }),
7474
- /* @__PURE__ */ jsxRuntime.jsx(RatingBar, { label: "3 \u2605", count: ratingDistribution.threeStars, total: totalRatings }),
7475
- /* @__PURE__ */ jsxRuntime.jsx(RatingBar, { label: "2 \u2605", count: ratingDistribution.twoStars, total: totalRatings }),
7476
- /* @__PURE__ */ jsxRuntime.jsx(RatingBar, { label: "1 \u2605", count: ratingDistribution.oneStar, total: totalRatings })
7993
+ /* @__PURE__ */ jsxRuntime.jsx(
7994
+ RatingBar,
7995
+ {
7996
+ label: "5 \u2605",
7997
+ count: ratingDistribution.fiveStars,
7998
+ total: totalRatings
7999
+ }
8000
+ ),
8001
+ /* @__PURE__ */ jsxRuntime.jsx(
8002
+ RatingBar,
8003
+ {
8004
+ label: "4 \u2605",
8005
+ count: ratingDistribution.fourStars,
8006
+ total: totalRatings
8007
+ }
8008
+ ),
8009
+ /* @__PURE__ */ jsxRuntime.jsx(
8010
+ RatingBar,
8011
+ {
8012
+ label: "3 \u2605",
8013
+ count: ratingDistribution.threeStars,
8014
+ total: totalRatings
8015
+ }
8016
+ ),
8017
+ /* @__PURE__ */ jsxRuntime.jsx(
8018
+ RatingBar,
8019
+ {
8020
+ label: "2 \u2605",
8021
+ count: ratingDistribution.twoStars,
8022
+ total: totalRatings
8023
+ }
8024
+ ),
8025
+ /* @__PURE__ */ jsxRuntime.jsx(
8026
+ RatingBar,
8027
+ {
8028
+ label: "1 \u2605",
8029
+ count: ratingDistribution.oneStar,
8030
+ total: totalRatings
8031
+ }
8032
+ )
7477
8033
  ] })
7478
8034
  ] }),
7479
8035
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: reviews.slice(0, 5).map((review, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
@@ -7488,11 +8044,14 @@ function StoreProductDetailPage({
7488
8044
  ] }),
7489
8045
  review.title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold text-sm text-foreground mb-1", children: review.title }),
7490
8046
  review.comment && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: review.comment }),
7491
- review.createdAt && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-2", children: new Date(review.createdAt).toLocaleDateString("en-US", {
7492
- year: "numeric",
7493
- month: "short",
7494
- day: "numeric"
7495
- }) })
8047
+ review.createdAt && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-2", children: new Date(review.createdAt).toLocaleDateString(
8048
+ "en-US",
8049
+ {
8050
+ year: "numeric",
8051
+ month: "short",
8052
+ day: "numeric"
8053
+ }
8054
+ ) })
7496
8055
  ]
7497
8056
  },
7498
8057
  review.id
@@ -7512,7 +8071,13 @@ function StoreProductDetailPage({
7512
8071
  ] }),
7513
8072
  /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "lg:sticky lg:top-24 self-start", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sd-fu sd-d4 bg-card border border-border rounded-xl p-5 space-y-4 hover:border-primary/30 transition-colors duration-300 hover:shadow-lg hover:shadow-primary/5", children: [
7514
8073
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
7515
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `text-3xl font-extrabold ${priceLabel === "Free" ? "text-emerald-500" : "text-foreground"}`, children: priceLabel }),
8074
+ /* @__PURE__ */ jsxRuntime.jsx(
8075
+ "div",
8076
+ {
8077
+ className: `text-3xl font-extrabold ${priceLabel === "Free" ? "text-emerald-500" : "text-foreground"}`,
8078
+ children: priceLabel
8079
+ }
8080
+ ),
7516
8081
  product.pricingModel === "SUBSCRIPTION" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: "per month" })
7517
8082
  ] }),
7518
8083
  /* @__PURE__ */ jsxRuntime.jsx(