@snowcone-app/ui 0.4.0 → 0.4.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/index.js CHANGED
@@ -10100,12 +10100,18 @@ var HeroProductImage = memo3(function HeroProductImage2({
10100
10100
  const [showNew, setShowNew] = useState31(false);
10101
10101
  const [renderedUrl, setRenderedUrl] = useState31(displayUrl);
10102
10102
  const [firstImageLoaded, setFirstImageLoaded] = useState31(false);
10103
+ const [loaderMounted, setLoaderMounted] = useState31(true);
10104
+ const [imgFailed, setImgFailed] = useState31(false);
10105
+ const [retryNonce, setRetryNonce] = useState31(0);
10106
+ const retriedUrlRef = useRef23(null);
10103
10107
  const prevDisplayUrlRef = useRef23(displayUrl);
10104
10108
  const signHintShownRef = useRef23(false);
10105
10109
  useEffect32(() => {
10106
10110
  if (!displayUrl || displayUrl === prevDisplayUrlRef.current) return;
10107
10111
  const oldUrl = prevDisplayUrlRef.current;
10108
10112
  prevDisplayUrlRef.current = displayUrl;
10113
+ setImgFailed(false);
10114
+ retriedUrlRef.current = null;
10109
10115
  if (!oldUrl) {
10110
10116
  setRenderedUrl(displayUrl);
10111
10117
  return;
@@ -10131,6 +10137,7 @@ var HeroProductImage = memo3(function HeroProductImage2({
10131
10137
  setPrevUrl(null);
10132
10138
  setShowNew(false);
10133
10139
  }, []);
10140
+ const handleLoaderExited = useCallback18(() => setLoaderMounted(false), []);
10134
10141
  if (!hasArtwork) {
10135
10142
  return /* @__PURE__ */ jsx60(
10136
10143
  "div",
@@ -10179,19 +10186,19 @@ var HeroProductImage = memo3(function HeroProductImage2({
10179
10186
  style,
10180
10187
  "data-hero-image": "true",
10181
10188
  children: [
10182
- !firstImageLoaded && /* @__PURE__ */ jsx60("div", { className: "absolute inset-0 bg-muted-foreground/20 animate-pulse" }),
10183
- renderedUrl && /* @__PURE__ */ jsx60(
10189
+ renderedUrl && !imgFailed && /* @__PURE__ */ jsx60(
10184
10190
  "img",
10185
10191
  {
10186
10192
  alt: `Product mockup${placement ? ` - ${placement}` : ""}`,
10187
10193
  crossOrigin: "anonymous",
10188
10194
  className: "absolute inset-0 w-full h-full object-cover",
10189
10195
  draggable,
10190
- src: renderedUrl,
10196
+ src: retriedUrlRef.current === renderedUrl ? `${renderedUrl}${renderedUrl.includes("?") ? "&" : "?"}_cb=${retryNonce}` : renderedUrl,
10191
10197
  loading: "eager",
10192
10198
  fetchPriority: "high",
10193
10199
  onClick,
10194
10200
  onLoad: () => {
10201
+ setImgFailed(false);
10195
10202
  setFirstImageLoaded(true);
10196
10203
  if (!onLoadCalledRef.current && onLoad) {
10197
10204
  onLoadCalledRef.current = true;
@@ -10200,6 +10207,12 @@ var HeroProductImage = memo3(function HeroProductImage2({
10200
10207
  onUrlGeneratedRef.current?.(renderedUrl);
10201
10208
  },
10202
10209
  onError: () => {
10210
+ if (renderedUrl && retriedUrlRef.current !== renderedUrl) {
10211
+ retriedUrlRef.current = renderedUrl;
10212
+ setRetryNonce((n) => n + 1);
10213
+ return;
10214
+ }
10215
+ setImgFailed(true);
10203
10216
  setFirstImageLoaded(true);
10204
10217
  onError?.();
10205
10218
  if (process.env.NODE_ENV !== "production" && !signHintShownRef.current && renderedUrl && /\/[A-Za-z0-9]+\?/.test(renderedUrl) && !/[?&]signature=/.test(renderedUrl)) {
@@ -10212,6 +10225,7 @@ var HeroProductImage = memo3(function HeroProductImage2({
10212
10225
  }
10213
10226
  }
10214
10227
  ),
10228
+ imgFailed && !prevUrl && /* @__PURE__ */ jsx60("div", { className: "absolute inset-0 flex items-center justify-center bg-muted", children: /* @__PURE__ */ jsx60("p", { className: "text-muted-foreground text-xs", children: "Preview unavailable" }) }),
10215
10229
  realtimeContext?.renderError && /* @__PURE__ */ jsx60(
10216
10230
  "div",
10217
10231
  {
@@ -10235,12 +10249,45 @@ var HeroProductImage = memo3(function HeroProductImage2({
10235
10249
  },
10236
10250
  onTransitionEnd: handleCrossfadeEnd
10237
10251
  }
10252
+ ),
10253
+ loaderMounted && /* @__PURE__ */ jsx60(
10254
+ LoadingOverlayPrismCandyInline,
10255
+ {
10256
+ visible: !firstImageLoaded,
10257
+ variant: "light",
10258
+ onExited: handleLoaderExited
10259
+ }
10238
10260
  )
10239
10261
  ]
10240
10262
  }
10241
10263
  );
10242
10264
  });
10243
10265
 
10266
+ // src/composed/SafeImg.tsx
10267
+ import React44, { useEffect as useEffect33, useState as useState32 } from "react";
10268
+ import { Fragment as Fragment12, jsx as jsx61 } from "react/jsx-runtime";
10269
+ var SafeImg = React44.forwardRef(
10270
+ function SafeImg2({ fallback = null, onError, src, ...rest }, ref) {
10271
+ const [failed, setFailed] = useState32(false);
10272
+ useEffect33(() => {
10273
+ setFailed(false);
10274
+ }, [src]);
10275
+ if (failed) return /* @__PURE__ */ jsx61(Fragment12, { children: fallback });
10276
+ return /* @__PURE__ */ jsx61(
10277
+ "img",
10278
+ {
10279
+ ...rest,
10280
+ ref,
10281
+ src,
10282
+ onError: (e) => {
10283
+ setFailed(true);
10284
+ onError?.(e);
10285
+ }
10286
+ }
10287
+ );
10288
+ }
10289
+ );
10290
+
10244
10291
  // src/index.ts
10245
10292
  import {
10246
10293
  describeProductArtAlignment as describeProductArtAlignment2,
@@ -10253,7 +10300,7 @@ import { InstantSearch, Configure, useSearchBox } from "react-instantsearch";
10253
10300
  // src/composed/search/meilisearchAdapter.ts
10254
10301
  import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";
10255
10302
  var MEILISEARCH_HOST = readEnv("NEXT_PUBLIC_MEILISEARCH_HOST") || "https://ms-e5d999b2eaca-15654.sfo.meilisearch.io";
10256
- var MEILISEARCH_API_KEY = readEnv("NEXT_PUBLIC_MEILISEARCH_API_KEY") || "eee819b849798ad9091228c486ec05d0931e5292";
10303
+ var MEILISEARCH_API_KEY = readEnv("NEXT_PUBLIC_MEILISEARCH_API_KEY") || "4a11f6599e39af365f6289dab46b77a30ef78ba1ac078f7d74e152c099b3b63c";
10257
10304
  var { searchClient } = instantMeiliSearch(
10258
10305
  MEILISEARCH_HOST,
10259
10306
  MEILISEARCH_API_KEY,
@@ -10264,11 +10311,11 @@ var { searchClient } = instantMeiliSearch(
10264
10311
  );
10265
10312
 
10266
10313
  // src/composed/search/SearchProvider.tsx
10267
- import { useEffect as useEffect33 } from "react";
10268
- import { jsx as jsx61, jsxs as jsxs40 } from "react/jsx-runtime";
10314
+ import { useEffect as useEffect34 } from "react";
10315
+ import { jsx as jsx62, jsxs as jsxs40 } from "react/jsx-runtime";
10269
10316
  function InitialSearchTrigger() {
10270
10317
  const { refine } = useSearchBox();
10271
- useEffect33(() => {
10318
+ useEffect34(() => {
10272
10319
  refine("");
10273
10320
  }, [refine]);
10274
10321
  return null;
@@ -10320,7 +10367,7 @@ function SearchProvider({
10320
10367
  }
10321
10368
  },
10322
10369
  children: [
10323
- /* @__PURE__ */ jsx61(
10370
+ /* @__PURE__ */ jsx62(
10324
10371
  Configure,
10325
10372
  {
10326
10373
  hitsPerPage,
@@ -10329,7 +10376,7 @@ function SearchProvider({
10329
10376
  attributesToRetrieve
10330
10377
  }
10331
10378
  ),
10332
- /* @__PURE__ */ jsx61(InitialSearchTrigger, {}),
10379
+ /* @__PURE__ */ jsx62(InitialSearchTrigger, {}),
10333
10380
  children
10334
10381
  ]
10335
10382
  }
@@ -10339,17 +10386,17 @@ function SearchProvider({
10339
10386
  // src/composed/search/SearchBox.tsx
10340
10387
  import { useSearchBox as useSearchBox2 } from "react-instantsearch";
10341
10388
  import { Search, X } from "lucide-react";
10342
- import { useEffect as useEffect34, useRef as useRef24, useState as useState32 } from "react";
10343
- import { jsx as jsx62, jsxs as jsxs41 } from "react/jsx-runtime";
10389
+ import { useEffect as useEffect35, useRef as useRef24, useState as useState33 } from "react";
10390
+ import { jsx as jsx63, jsxs as jsxs41 } from "react/jsx-runtime";
10344
10391
  function SearchBox() {
10345
10392
  const { query, refine, clear } = useSearchBox2();
10346
10393
  const searchParams = useUiSearchParams();
10347
10394
  const router = useUiRouter();
10348
10395
  const inputRef = useRef24(null);
10349
- const [showShimmer, setShowShimmer] = useState32(false);
10396
+ const [showShimmer, setShowShimmer] = useState33(false);
10350
10397
  const inputId = "search-products-input";
10351
10398
  const descriptionId = "search-description";
10352
- useEffect34(() => {
10399
+ useEffect35(() => {
10353
10400
  const handleSpotlight = () => {
10354
10401
  inputRef.current?.focus();
10355
10402
  inputRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
@@ -10359,7 +10406,7 @@ function SearchBox() {
10359
10406
  window.addEventListener("search-spotlight", handleSpotlight);
10360
10407
  return () => window.removeEventListener("search-spotlight", handleSpotlight);
10361
10408
  }, []);
10362
- useEffect34(() => {
10409
+ useEffect35(() => {
10363
10410
  const shouldFocus = searchParams.get("focus") === "search";
10364
10411
  if (shouldFocus && inputRef.current) {
10365
10412
  const timer = setTimeout(() => {
@@ -10374,8 +10421,8 @@ function SearchBox() {
10374
10421
  return () => clearTimeout(timer);
10375
10422
  }
10376
10423
  }, [searchParams, router]);
10377
- return /* @__PURE__ */ jsx62("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ jsxs41("div", { className: "relative", children: [
10378
- /* @__PURE__ */ jsx62(
10424
+ return /* @__PURE__ */ jsx63("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ jsxs41("div", { className: "relative", children: [
10425
+ /* @__PURE__ */ jsx63(
10379
10426
  Input,
10380
10427
  {
10381
10428
  ref: inputRef,
@@ -10384,15 +10431,15 @@ function SearchBox() {
10384
10431
  value: query,
10385
10432
  onChange: (e) => refine(e.target.value),
10386
10433
  placeholder: "Search products...",
10387
- startContent: /* @__PURE__ */ jsx62(Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10388
- endContent: query ? /* @__PURE__ */ jsx62(
10434
+ startContent: /* @__PURE__ */ jsx63(Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10435
+ endContent: query ? /* @__PURE__ */ jsx63(
10389
10436
  "button",
10390
10437
  {
10391
10438
  type: "button",
10392
10439
  onClick: clear,
10393
10440
  className: "hover:text-foreground transition-colors",
10394
10441
  "aria-label": "Clear search",
10395
- children: /* @__PURE__ */ jsx62(X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10442
+ children: /* @__PURE__ */ jsx63(X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10396
10443
  }
10397
10444
  ) : void 0,
10398
10445
  "aria-label": "Search products",
@@ -10402,11 +10449,11 @@ function SearchBox() {
10402
10449
  className: "[&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden"
10403
10450
  }
10404
10451
  ),
10405
- showShimmer && /* @__PURE__ */ jsx62(
10452
+ showShimmer && /* @__PURE__ */ jsx63(
10406
10453
  "div",
10407
10454
  {
10408
10455
  className: "absolute inset-0 pointer-events-none rounded-input z-20 overflow-hidden",
10409
- children: /* @__PURE__ */ jsx62(
10456
+ children: /* @__PURE__ */ jsx63(
10410
10457
  "div",
10411
10458
  {
10412
10459
  className: "absolute inset-0",
@@ -10419,13 +10466,13 @@ function SearchBox() {
10419
10466
  )
10420
10467
  }
10421
10468
  ),
10422
- /* @__PURE__ */ jsx62("style", { dangerouslySetInnerHTML: { __html: `
10469
+ /* @__PURE__ */ jsx63("style", { dangerouslySetInnerHTML: { __html: `
10423
10470
  @keyframes searchShimmer {
10424
10471
  0% { transform: translateX(-100%); }
10425
10472
  100% { transform: translateX(100%); }
10426
10473
  }
10427
10474
  ` } }),
10428
- /* @__PURE__ */ jsx62("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10475
+ /* @__PURE__ */ jsx63("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10429
10476
  ] }) });
10430
10477
  }
10431
10478
 
@@ -10433,7 +10480,7 @@ function SearchBox() {
10433
10480
  import { Hits, useStats, useInstantSearch } from "react-instantsearch";
10434
10481
 
10435
10482
  // src/composed/search/ProductHit.tsx
10436
- import { jsx as jsx63 } from "react/jsx-runtime";
10483
+ import { jsx as jsx64 } from "react/jsx-runtime";
10437
10484
  function ProductHitComponent({
10438
10485
  hit: product,
10439
10486
  variant = "overlay"
@@ -10450,12 +10497,12 @@ function ProductHitComponent({
10450
10497
  }
10451
10498
  return "";
10452
10499
  };
10453
- return /* @__PURE__ */ jsx63(
10500
+ return /* @__PURE__ */ jsx64(
10454
10501
  Product,
10455
10502
  {
10456
10503
  productId,
10457
10504
  productData: product,
10458
- children: /* @__PURE__ */ jsx63(
10505
+ children: /* @__PURE__ */ jsx64(
10459
10506
  ProductCard,
10460
10507
  {
10461
10508
  variant,
@@ -10476,10 +10523,10 @@ function ProductHitComponent({
10476
10523
  }
10477
10524
 
10478
10525
  // src/composed/search/ProductGrid.tsx
10479
- import { useState as useState33, useEffect as useEffect35, useCallback as useCallback19 } from "react";
10480
- import { jsx as jsx64, jsxs as jsxs42 } from "react/jsx-runtime";
10526
+ import { useState as useState34, useEffect as useEffect36, useCallback as useCallback19 } from "react";
10527
+ import { jsx as jsx65, jsxs as jsxs42 } from "react/jsx-runtime";
10481
10528
  function ProductGridSkeletonItem() {
10482
- return /* @__PURE__ */ jsx64("div", { className: "aspect-square bg-muted animate-pulse" });
10529
+ return /* @__PURE__ */ jsx65("div", { className: "aspect-square bg-muted animate-pulse" });
10483
10530
  }
10484
10531
  function ProductGrid({
10485
10532
  className = "",
@@ -10489,16 +10536,16 @@ function ProductGrid({
10489
10536
  }) {
10490
10537
  const { nbHits } = useStats();
10491
10538
  const { status, results } = useInstantSearch();
10492
- const [announcement, setAnnouncement] = useState33("");
10539
+ const [announcement, setAnnouncement] = useState34("");
10493
10540
  const hitsCount = results?.hits?.length ?? 0;
10494
10541
  const showSkeleton = hitsCount === 0 && status !== "error";
10495
- useEffect35(() => {
10542
+ useEffect36(() => {
10496
10543
  const timer = setTimeout(() => {
10497
10544
  setAnnouncement(`${nbHits} ${nbHits === 1 ? "product" : "products"} found`);
10498
10545
  }, 1e3);
10499
10546
  return () => clearTimeout(timer);
10500
10547
  }, [nbHits]);
10501
- const HitComponent = useCallback19(({ hit }) => /* @__PURE__ */ jsx64(
10548
+ const HitComponent = useCallback19(({ hit }) => /* @__PURE__ */ jsx65(
10502
10549
  ProductHitComponent,
10503
10550
  {
10504
10551
  hit,
@@ -10506,9 +10553,9 @@ function ProductGrid({
10506
10553
  }
10507
10554
  ), [variant]);
10508
10555
  return /* @__PURE__ */ jsxs42("div", { className, children: [
10509
- /* @__PURE__ */ jsx64("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10510
- showSkeleton && /* @__PURE__ */ jsx64("div", { className: `grid ${gridClassName}`, children: Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ jsx64(ProductGridSkeletonItem, {}, i)) }),
10511
- /* @__PURE__ */ jsx64("div", { className: showSkeleton ? "hidden" : "", children: /* @__PURE__ */ jsx64(
10556
+ /* @__PURE__ */ jsx65("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10557
+ showSkeleton && /* @__PURE__ */ jsx65("div", { className: `grid ${gridClassName}`, children: Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ jsx65(ProductGridSkeletonItem, {}, i)) }),
10558
+ /* @__PURE__ */ jsx65("div", { className: showSkeleton ? "hidden" : "", children: /* @__PURE__ */ jsx65(
10512
10559
  Hits,
10513
10560
  {
10514
10561
  hitComponent: HitComponent,
@@ -10523,11 +10570,11 @@ function ProductGrid({
10523
10570
  }
10524
10571
 
10525
10572
  // src/composed/search/Filters.tsx
10526
- import { useState as useState35 } from "react";
10573
+ import { useState as useState36 } from "react";
10527
10574
 
10528
10575
  // src/composed/search/FiltersButton.tsx
10529
10576
  import { SlidersHorizontal as LucideSlidersHorizontal } from "lucide-react";
10530
- import { jsx as jsx65, jsxs as jsxs43 } from "react/jsx-runtime";
10577
+ import { jsx as jsx66, jsxs as jsxs43 } from "react/jsx-runtime";
10531
10578
  var SlidersHorizontalIcon = LucideSlidersHorizontal;
10532
10579
  function FiltersButton({
10533
10580
  onClick,
@@ -10542,8 +10589,8 @@ function FiltersButton({
10542
10589
  className,
10543
10590
  "aria-label": "Open filters",
10544
10591
  children: [
10545
- /* @__PURE__ */ jsx65(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10546
- /* @__PURE__ */ jsx65("span", { children })
10592
+ /* @__PURE__ */ jsx66(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10593
+ /* @__PURE__ */ jsx66("span", { children })
10547
10594
  ]
10548
10595
  }
10549
10596
  );
@@ -10552,15 +10599,15 @@ function FiltersButton({
10552
10599
  // src/composed/search/FiltersDrawer.tsx
10553
10600
  import { useRefinementList, useRange, useStats as useStats2 } from "react-instantsearch";
10554
10601
  import { X as LucideX2, SlidersHorizontal as LucideSlidersHorizontal2 } from "lucide-react";
10555
- import { useState as useState34, useEffect as useEffect36 } from "react";
10602
+ import { useState as useState35, useEffect as useEffect37 } from "react";
10556
10603
  import * as Slider2 from "@radix-ui/react-slider";
10557
- import { Fragment as Fragment12, jsx as jsx66, jsxs as jsxs44 } from "react/jsx-runtime";
10604
+ import { Fragment as Fragment13, jsx as jsx67, jsxs as jsxs44 } from "react/jsx-runtime";
10558
10605
  var XIcon2 = LucideX2;
10559
10606
  function FiltersDrawer({ isOpen, onClose }) {
10560
- const [showCounts, setShowCounts] = useState34(false);
10607
+ const [showCounts, setShowCounts] = useState35(false);
10561
10608
  const { nbHits } = useStats2();
10562
10609
  const containerRef = useFocusTrap(isOpen, onClose);
10563
- useEffect36(() => {
10610
+ useEffect37(() => {
10564
10611
  if (isOpen) {
10565
10612
  document.body.style.overflow = "hidden";
10566
10613
  } else {
@@ -10570,7 +10617,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10570
10617
  document.body.style.overflow = "";
10571
10618
  };
10572
10619
  }, [isOpen]);
10573
- useEffect36(() => {
10620
+ useEffect37(() => {
10574
10621
  const handleEscape = (e) => {
10575
10622
  if (e.key === "Escape" && isOpen) {
10576
10623
  onClose();
@@ -10579,8 +10626,8 @@ function FiltersDrawer({ isOpen, onClose }) {
10579
10626
  document.addEventListener("keydown", handleEscape);
10580
10627
  return () => document.removeEventListener("keydown", handleEscape);
10581
10628
  }, [isOpen, onClose]);
10582
- return /* @__PURE__ */ jsxs44(Fragment12, { children: [
10583
- /* @__PURE__ */ jsx66(
10629
+ return /* @__PURE__ */ jsxs44(Fragment13, { children: [
10630
+ /* @__PURE__ */ jsx67(
10584
10631
  "div",
10585
10632
  {
10586
10633
  className: `fixed inset-0 bg-black/50 z-40 transition-opacity ${isOpen ? "opacity-100" : "opacity-0 pointer-events-none"}`,
@@ -10598,25 +10645,25 @@ function FiltersDrawer({ isOpen, onClose }) {
10598
10645
  "aria-labelledby": "filters-drawer-title",
10599
10646
  children: [
10600
10647
  /* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-between px-4 py-4", children: [
10601
- /* @__PURE__ */ jsx66("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10602
- /* @__PURE__ */ jsx66(
10648
+ /* @__PURE__ */ jsx67("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10649
+ /* @__PURE__ */ jsx67(
10603
10650
  "button",
10604
10651
  {
10605
10652
  onClick: onClose,
10606
10653
  className: "p-2 hover:bg-foreground/5 rounded-full transition-colors",
10607
10654
  "aria-label": "Close filters",
10608
- children: /* @__PURE__ */ jsx66(XIcon2, { className: "w-5 h-5" })
10655
+ children: /* @__PURE__ */ jsx67(XIcon2, { className: "w-5 h-5" })
10609
10656
  }
10610
10657
  )
10611
10658
  ] }),
10612
- /* @__PURE__ */ jsx66("div", { className: "px-4 pb-4", children: /* @__PURE__ */ jsxs44("p", { className: "text-sm font-caption text-foreground/60", role: "status", "aria-live": "polite", children: [
10659
+ /* @__PURE__ */ jsx67("div", { className: "px-4 pb-4", children: /* @__PURE__ */ jsxs44("p", { className: "text-sm font-caption text-foreground/60", role: "status", "aria-live": "polite", children: [
10613
10660
  nbHits.toLocaleString(),
10614
10661
  " ",
10615
10662
  nbHits === 1 ? "result" : "results"
10616
10663
  ] }) }),
10617
- /* @__PURE__ */ jsx66("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: /* @__PURE__ */ jsxs44("div", { className: "flex flex-col gap-8", children: [
10618
- /* @__PURE__ */ jsx66(TagsSection, { showCounts, setShowCounts }),
10619
- /* @__PURE__ */ jsx66(PriceSection, {})
10664
+ /* @__PURE__ */ jsx67("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: /* @__PURE__ */ jsxs44("div", { className: "flex flex-col gap-8", children: [
10665
+ /* @__PURE__ */ jsx67(TagsSection, { showCounts, setShowCounts }),
10666
+ /* @__PURE__ */ jsx67(PriceSection, {})
10620
10667
  ] }) })
10621
10668
  ]
10622
10669
  }
@@ -10632,7 +10679,7 @@ function TagsSection({
10632
10679
  sortBy: ["count:desc", "name:asc"],
10633
10680
  limit: 100
10634
10681
  });
10635
- const [isExpanded, setIsExpanded] = useState34(true);
10682
+ const [isExpanded, setIsExpanded] = useState35(true);
10636
10683
  return /* @__PURE__ */ jsxs44("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
10637
10684
  /* @__PURE__ */ jsxs44(
10638
10685
  "button",
@@ -10642,8 +10689,8 @@ function TagsSection({
10642
10689
  "aria-expanded": isExpanded,
10643
10690
  "aria-controls": "tags-content",
10644
10691
  children: [
10645
- /* @__PURE__ */ jsx66("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
10646
- /* @__PURE__ */ jsx66(
10692
+ /* @__PURE__ */ jsx67("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
10693
+ /* @__PURE__ */ jsx67(
10647
10694
  "svg",
10648
10695
  {
10649
10696
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -10652,14 +10699,14 @@ function TagsSection({
10652
10699
  stroke: "currentColor",
10653
10700
  strokeWidth: 2.5,
10654
10701
  "aria-hidden": "true",
10655
- children: /* @__PURE__ */ jsx66("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
10702
+ children: /* @__PURE__ */ jsx67("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
10656
10703
  }
10657
10704
  )
10658
10705
  ]
10659
10706
  }
10660
10707
  ),
10661
10708
  isExpanded && /* @__PURE__ */ jsxs44("div", { className: "space-y-4", id: "tags-content", children: [
10662
- /* @__PURE__ */ jsx66("div", { className: "flex flex-wrap gap-2", role: "group", "aria-label": "Product tags filter", children: items.map((item) => /* @__PURE__ */ jsxs44(
10709
+ /* @__PURE__ */ jsx67("div", { className: "flex flex-wrap gap-2", role: "group", "aria-label": "Product tags filter", children: items.map((item) => /* @__PURE__ */ jsxs44(
10663
10710
  "button",
10664
10711
  {
10665
10712
  onClick: () => refine(item.value),
@@ -10670,15 +10717,15 @@ function TagsSection({
10670
10717
  "aria-label": `${item.isRefined ? "Remove" : "Apply"} ${item.label} filter${showCounts ? ` (${item.count} products)` : ""}`,
10671
10718
  "aria-pressed": item.isRefined,
10672
10719
  children: [
10673
- /* @__PURE__ */ jsx66("span", { "aria-hidden": "true", children: item.label }),
10674
- showCounts && /* @__PURE__ */ jsx66("span", { className: `text-xs font-caption ${item.isRefined ? "opacity-80" : "opacity-60"}`, "aria-hidden": "true", children: item.count })
10720
+ /* @__PURE__ */ jsx67("span", { "aria-hidden": "true", children: item.label }),
10721
+ showCounts && /* @__PURE__ */ jsx67("span", { className: `text-xs font-caption ${item.isRefined ? "opacity-80" : "opacity-60"}`, "aria-hidden": "true", children: item.count })
10675
10722
  ]
10676
10723
  },
10677
10724
  item.value
10678
10725
  )) }),
10679
10726
  /* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-between pt-2", children: [
10680
- /* @__PURE__ */ jsx66("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
10681
- /* @__PURE__ */ jsx66(
10727
+ /* @__PURE__ */ jsx67("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
10728
+ /* @__PURE__ */ jsx67(
10682
10729
  "button",
10683
10730
  {
10684
10731
  onClick: () => setShowCounts(!showCounts),
@@ -10686,7 +10733,7 @@ function TagsSection({
10686
10733
  role: "switch",
10687
10734
  "aria-checked": showCounts,
10688
10735
  "aria-labelledby": "show-counts-label",
10689
- children: /* @__PURE__ */ jsx66(
10736
+ children: /* @__PURE__ */ jsx67(
10690
10737
  "span",
10691
10738
  {
10692
10739
  className: `inline-block h-4 w-4 transform rounded-full bg-background shadow-sm transition-transform ${showCounts ? "translate-x-6" : "translate-x-1"}`,
@@ -10703,11 +10750,11 @@ function PriceSection() {
10703
10750
  const { range, refine, start, canRefine } = useRange({ attribute: "price" });
10704
10751
  const rangeMin = typeof range.min === "number" && isFinite(range.min) ? range.min : 0;
10705
10752
  const rangeMax = typeof range.max === "number" && isFinite(range.max) ? range.max : 15e3;
10706
- const [localRange, setLocalRange] = useState34([
10753
+ const [localRange, setLocalRange] = useState35([
10707
10754
  typeof start?.[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
10708
10755
  typeof start?.[1] === "number" && isFinite(start[1]) ? start[1] : rangeMax
10709
10756
  ]);
10710
- useEffect36(() => {
10757
+ useEffect37(() => {
10711
10758
  if (start && Array.isArray(start)) {
10712
10759
  setLocalRange([
10713
10760
  typeof start[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
@@ -10717,7 +10764,7 @@ function PriceSection() {
10717
10764
  setLocalRange([rangeMin, rangeMax]);
10718
10765
  }
10719
10766
  }, [start, rangeMin, rangeMax]);
10720
- const [isExpanded, setIsExpanded] = useState34(true);
10767
+ const [isExpanded, setIsExpanded] = useState35(true);
10721
10768
  if (!canRefine) {
10722
10769
  return null;
10723
10770
  }
@@ -10741,8 +10788,8 @@ function PriceSection() {
10741
10788
  "aria-expanded": isExpanded,
10742
10789
  "aria-controls": "price-content",
10743
10790
  children: [
10744
- /* @__PURE__ */ jsx66("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
10745
- /* @__PURE__ */ jsx66(
10791
+ /* @__PURE__ */ jsx67("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
10792
+ /* @__PURE__ */ jsx67(
10746
10793
  "svg",
10747
10794
  {
10748
10795
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -10751,7 +10798,7 @@ function PriceSection() {
10751
10798
  stroke: "currentColor",
10752
10799
  strokeWidth: 2.5,
10753
10800
  "aria-hidden": "true",
10754
- children: /* @__PURE__ */ jsx66("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
10801
+ children: /* @__PURE__ */ jsx67("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
10755
10802
  }
10756
10803
  )
10757
10804
  ]
@@ -10759,14 +10806,14 @@ function PriceSection() {
10759
10806
  ),
10760
10807
  isExpanded && /* @__PURE__ */ jsxs44("div", { className: "space-y-6", id: "price-content", children: [
10761
10808
  /* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-between text-sm font-display", children: [
10762
- /* @__PURE__ */ jsx66("span", { children: formatPrice2(localRange[0]) }),
10763
- /* @__PURE__ */ jsx66("span", { className: "text-foreground/70", children: formatPrice2(localRange[1]) })
10809
+ /* @__PURE__ */ jsx67("span", { children: formatPrice2(localRange[0]) }),
10810
+ /* @__PURE__ */ jsx67("span", { className: "text-foreground/70", children: formatPrice2(localRange[1]) })
10764
10811
  ] }),
10765
- /* @__PURE__ */ jsx66("div", { className: "relative h-24 flex items-end justify-between gap-0.5 px-1", "aria-hidden": "true", role: "presentation", children: [60, 40, 80, 50, 60, 30, 20, 15, 10, 5, 30, 20, 15, 10, 5, 3, 3, 60, 40].map((height, i) => {
10812
+ /* @__PURE__ */ jsx67("div", { className: "relative h-24 flex items-end justify-between gap-0.5 px-1", "aria-hidden": "true", role: "presentation", children: [60, 40, 80, 50, 60, 30, 20, 15, 10, 5, 30, 20, 15, 10, 5, 3, 3, 60, 40].map((height, i) => {
10766
10813
  const totalBars = 19;
10767
10814
  const barPrice = rangeMin + (rangeMax - rangeMin) / totalBars * i;
10768
10815
  const isInRange = barPrice >= localRange[0] && barPrice <= localRange[1];
10769
- return /* @__PURE__ */ jsx66(
10816
+ return /* @__PURE__ */ jsx67(
10770
10817
  "div",
10771
10818
  {
10772
10819
  className: `flex-1 rounded-t-sm transition-opacity ${isInRange ? "bg-foreground" : "bg-foreground/20"}`,
@@ -10775,7 +10822,7 @@ function PriceSection() {
10775
10822
  i
10776
10823
  );
10777
10824
  }) }),
10778
- /* @__PURE__ */ jsx66("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ jsxs44(
10825
+ /* @__PURE__ */ jsx67("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ jsxs44(
10779
10826
  Slider2.Root,
10780
10827
  {
10781
10828
  className: "relative flex w-full touch-none select-none items-center",
@@ -10793,8 +10840,8 @@ function PriceSection() {
10793
10840
  step: 1,
10794
10841
  minStepsBetweenThumbs: 1,
10795
10842
  children: [
10796
- /* @__PURE__ */ jsx66(Slider2.Track, { className: "relative h-3 w-full grow overflow-hidden rounded-full bg-foreground/20", children: /* @__PURE__ */ jsx66(Slider2.Range, { className: "absolute h-full bg-foreground" }) }),
10797
- /* @__PURE__ */ jsx66(
10843
+ /* @__PURE__ */ jsx67(Slider2.Track, { className: "relative h-3 w-full grow overflow-hidden rounded-full bg-foreground/20", children: /* @__PURE__ */ jsx67(Slider2.Range, { className: "absolute h-full bg-foreground" }) }),
10844
+ /* @__PURE__ */ jsx67(
10798
10845
  Slider2.Thumb,
10799
10846
  {
10800
10847
  className: "block h-6 w-6 rounded-full bg-background shadow transition-all focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50 cursor-grab active:cursor-grabbing hover:scale-105 border-2 border-primary",
@@ -10808,7 +10855,7 @@ function PriceSection() {
10808
10855
  "aria-valuetext": formatPrice2(localRange[0])
10809
10856
  }
10810
10857
  ),
10811
- /* @__PURE__ */ jsx66(
10858
+ /* @__PURE__ */ jsx67(
10812
10859
  Slider2.Thumb,
10813
10860
  {
10814
10861
  className: "block h-6 w-6 rounded-full bg-background shadow transition-all focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50 cursor-grab active:cursor-grabbing hover:scale-105 border-2 border-primary",
@@ -10827,8 +10874,8 @@ function PriceSection() {
10827
10874
  ) }),
10828
10875
  /* @__PURE__ */ jsxs44("div", { className: "grid grid-cols-2 gap-3", children: [
10829
10876
  /* @__PURE__ */ jsxs44("div", { children: [
10830
- /* @__PURE__ */ jsx66("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
10831
- /* @__PURE__ */ jsx66(
10877
+ /* @__PURE__ */ jsx67("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
10878
+ /* @__PURE__ */ jsx67(
10832
10879
  "input",
10833
10880
  {
10834
10881
  id: "price-min",
@@ -10847,8 +10894,8 @@ function PriceSection() {
10847
10894
  )
10848
10895
  ] }),
10849
10896
  /* @__PURE__ */ jsxs44("div", { children: [
10850
- /* @__PURE__ */ jsx66("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
10851
- /* @__PURE__ */ jsx66(
10897
+ /* @__PURE__ */ jsx67("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
10898
+ /* @__PURE__ */ jsx67(
10852
10899
  "input",
10853
10900
  {
10854
10901
  id: "price-max",
@@ -10872,11 +10919,11 @@ function PriceSection() {
10872
10919
  }
10873
10920
 
10874
10921
  // src/composed/search/Filters.tsx
10875
- import { Fragment as Fragment13, jsx as jsx67, jsxs as jsxs45 } from "react/jsx-runtime";
10922
+ import { Fragment as Fragment14, jsx as jsx68, jsxs as jsxs45 } from "react/jsx-runtime";
10876
10923
  function Filters({ buttonClassName, buttonText }) {
10877
- const [isOpen, setIsOpen] = useState35(false);
10878
- return /* @__PURE__ */ jsxs45(Fragment13, { children: [
10879
- /* @__PURE__ */ jsx67(
10924
+ const [isOpen, setIsOpen] = useState36(false);
10925
+ return /* @__PURE__ */ jsxs45(Fragment14, { children: [
10926
+ /* @__PURE__ */ jsx68(
10880
10927
  FiltersButton,
10881
10928
  {
10882
10929
  onClick: () => setIsOpen(true),
@@ -10884,14 +10931,14 @@ function Filters({ buttonClassName, buttonText }) {
10884
10931
  children: buttonText
10885
10932
  }
10886
10933
  ),
10887
- /* @__PURE__ */ jsx67(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
10934
+ /* @__PURE__ */ jsx68(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
10888
10935
  ] });
10889
10936
  }
10890
10937
 
10891
10938
  // src/composed/search/CurrentRefinements.tsx
10892
10939
  import { useCurrentRefinements } from "react-instantsearch";
10893
10940
  import { X as LucideX3 } from "lucide-react";
10894
- import { jsx as jsx68, jsxs as jsxs46 } from "react/jsx-runtime";
10941
+ import { jsx as jsx69, jsxs as jsxs46 } from "react/jsx-runtime";
10895
10942
  var XIcon3 = LucideX3;
10896
10943
  function CurrentRefinements() {
10897
10944
  const { items, refine } = useCurrentRefinements();
@@ -10937,15 +10984,15 @@ function CurrentRefinements() {
10937
10984
  if (allRefinements.length === 0) {
10938
10985
  return null;
10939
10986
  }
10940
- return /* @__PURE__ */ jsx68("div", { className: "flex flex-wrap items-center gap-2 mb-4 -mt-1", role: "group", "aria-label": "Active filters", children: allRefinements.map((refinement, index) => /* @__PURE__ */ jsxs46(
10987
+ return /* @__PURE__ */ jsx69("div", { className: "flex flex-wrap items-center gap-2 mb-4 -mt-1", role: "group", "aria-label": "Active filters", children: allRefinements.map((refinement, index) => /* @__PURE__ */ jsxs46(
10941
10988
  "button",
10942
10989
  {
10943
10990
  className: "bg-primary text-on-primary hover:bg-primary/90 inline-flex h-7 items-center gap-1.5 rounded-full px-3 text-sm transition-colors",
10944
10991
  onClick: () => refinement.refine(),
10945
10992
  "aria-label": `Remove filter: ${refinement.displayLabel}`,
10946
10993
  children: [
10947
- /* @__PURE__ */ jsx68("span", { className: "truncate", children: refinement.displayLabel }),
10948
- /* @__PURE__ */ jsx68(XIcon3, { className: "w-3 h-3" })
10994
+ /* @__PURE__ */ jsx69("span", { className: "truncate", children: refinement.displayLabel }),
10995
+ /* @__PURE__ */ jsx69(XIcon3, { className: "w-3 h-3" })
10949
10996
  ]
10950
10997
  },
10951
10998
  `${refinement.attribute}-${refinement.value}-${index}`
@@ -10969,12 +11016,12 @@ var FACET_SECTIONS = [
10969
11016
  ];
10970
11017
 
10971
11018
  // src/composed/zoom/ResponsiveZoom.tsx
10972
- import { useState as useState38, useEffect as useEffect38 } from "react";
11019
+ import { useState as useState39, useEffect as useEffect39 } from "react";
10973
11020
 
10974
11021
  // src/composed/zoom/ZoomOverlay.tsx
10975
- import { useState as useState36, useCallback as useCallback20 } from "react";
11022
+ import { useState as useState37, useCallback as useCallback20 } from "react";
10976
11023
  import { Plus as LucidePlus2, Minus as LucideMinus2 } from "lucide-react";
10977
- import { Fragment as Fragment14, jsx as jsx69, jsxs as jsxs47 } from "react/jsx-runtime";
11024
+ import { Fragment as Fragment15, jsx as jsx70, jsxs as jsxs47 } from "react/jsx-runtime";
10978
11025
  var PlusIcon2 = LucidePlus2;
10979
11026
  var MinusIcon2 = LucideMinus2;
10980
11027
  function ZoomOverlay({
@@ -10986,12 +11033,12 @@ function ZoomOverlay({
10986
11033
  className,
10987
11034
  style
10988
11035
  }) {
10989
- const [zoomedImageIndex, setZoomedImageIndex] = useState36(null);
10990
- const [zoomOrigin, setZoomOrigin] = useState36({ x: 50, y: 50 });
10991
- const [hoveredImageIndex, setHoveredImageIndex] = useState36(null);
10992
- const [cursorPos, setCursorPos] = useState36({ x: 0, y: 0 });
10993
- const [announcement, setAnnouncement] = useState36("");
10994
- const [isZooming, setIsZooming] = useState36(false);
11036
+ const [zoomedImageIndex, setZoomedImageIndex] = useState37(null);
11037
+ const [zoomOrigin, setZoomOrigin] = useState37({ x: 50, y: 50 });
11038
+ const [hoveredImageIndex, setHoveredImageIndex] = useState37(null);
11039
+ const [cursorPos, setCursorPos] = useState37({ x: 0, y: 0 });
11040
+ const [announcement, setAnnouncement] = useState37("");
11041
+ const [isZooming, setIsZooming] = useState37(false);
10995
11042
  const handleZoomClick = useCallback20(
10996
11043
  (e) => {
10997
11044
  e.stopPropagation();
@@ -11033,9 +11080,9 @@ function ZoomOverlay({
11033
11080
  const isZoomed = zoomedImageIndex === imageIndex;
11034
11081
  const isHovered = hoveredImageIndex === imageIndex;
11035
11082
  const cursorStyle = isLargeTouchDevice ? "pointer" : isTouchDevice ? "default" : "none";
11036
- return /* @__PURE__ */ jsxs47(Fragment14, { children: [
11037
- /* @__PURE__ */ jsx69("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11038
- /* @__PURE__ */ jsx69(
11083
+ return /* @__PURE__ */ jsxs47(Fragment15, { children: [
11084
+ /* @__PURE__ */ jsx70("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11085
+ /* @__PURE__ */ jsx70(
11039
11086
  "div",
11040
11087
  {
11041
11088
  className,
@@ -11043,7 +11090,7 @@ function ZoomOverlay({
11043
11090
  ...style,
11044
11091
  position: "relative"
11045
11092
  },
11046
- children: /* @__PURE__ */ jsx69(
11093
+ children: /* @__PURE__ */ jsx70(
11047
11094
  "div",
11048
11095
  {
11049
11096
  style: {
@@ -11066,7 +11113,7 @@ function ZoomOverlay({
11066
11113
  handleZoomClick(e);
11067
11114
  }
11068
11115
  },
11069
- children: /* @__PURE__ */ jsx69(
11116
+ children: /* @__PURE__ */ jsx70(
11070
11117
  "div",
11071
11118
  {
11072
11119
  style: {
@@ -11082,7 +11129,7 @@ function ZoomOverlay({
11082
11129
  )
11083
11130
  }
11084
11131
  ),
11085
- isHovered && !isTouchDevice && /* @__PURE__ */ jsx69(
11132
+ isHovered && !isTouchDevice && /* @__PURE__ */ jsx70(
11086
11133
  "div",
11087
11134
  {
11088
11135
  className: "fixed pointer-events-none z-50 hidden md:block",
@@ -11092,7 +11139,7 @@ function ZoomOverlay({
11092
11139
  transform: "translate(-50%, -50%)"
11093
11140
  },
11094
11141
  "aria-hidden": "true",
11095
- children: /* @__PURE__ */ jsx69("div", { className: "bg-white dark:bg-gray-800 rounded-full p-2 shadow-sm dark:shadow-gray-950/50", children: isZoomed ? /* @__PURE__ */ jsx69(
11142
+ children: /* @__PURE__ */ jsx70("div", { className: "bg-white dark:bg-gray-800 rounded-full p-2 shadow-sm dark:shadow-gray-950/50", children: isZoomed ? /* @__PURE__ */ jsx70(
11096
11143
  MinusIcon2,
11097
11144
  {
11098
11145
  size: 20,
@@ -11100,7 +11147,7 @@ function ZoomOverlay({
11100
11147
  strokeWidth: 1.5,
11101
11148
  "aria-hidden": "true"
11102
11149
  }
11103
- ) : /* @__PURE__ */ jsx69(
11150
+ ) : /* @__PURE__ */ jsx70(
11104
11151
  PlusIcon2,
11105
11152
  {
11106
11153
  size: 20,
@@ -11116,9 +11163,9 @@ function ZoomOverlay({
11116
11163
 
11117
11164
  // src/composed/zoom/EnhancedImageViewer.tsx
11118
11165
  import {
11119
- useState as useState37,
11166
+ useState as useState38,
11120
11167
  useRef as useRef25,
11121
- useEffect as useEffect37,
11168
+ useEffect as useEffect38,
11122
11169
  useLayoutEffect as useLayoutEffect6,
11123
11170
  useCallback as useCallback21
11124
11171
  } from "react";
@@ -11128,7 +11175,7 @@ import {
11128
11175
  TransformComponent as OriginalTransformComponent
11129
11176
  } from "react-zoom-pan-pinch";
11130
11177
  import { X as X2 } from "lucide-react";
11131
- import { Fragment as Fragment15, jsx as jsx70, jsxs as jsxs48 } from "react/jsx-runtime";
11178
+ import { Fragment as Fragment16, jsx as jsx71, jsxs as jsxs48 } from "react/jsx-runtime";
11132
11179
  var TransformWrapper = OriginalTransformWrapper;
11133
11180
  var TransformComponent = OriginalTransformComponent;
11134
11181
  var EnhancedImageViewer = ({
@@ -11139,11 +11186,11 @@ var EnhancedImageViewer = ({
11139
11186
  onIndexChange,
11140
11187
  currentIndex: propCurrentIndex
11141
11188
  }) => {
11142
- const [isMounted, setIsMounted] = useState37(false);
11143
- const [isClient, setIsClient] = useState37(false);
11144
- const [scale, setScale] = useState37({ initial: 1, min: 1, max: 8 });
11145
- const [cropDimensions, setCropDimensions] = useState37({ width: 0, height: 0 });
11146
- const [currentZoomScale, setCurrentZoomScale] = useState37(1);
11189
+ const [isMounted, setIsMounted] = useState38(false);
11190
+ const [isClient, setIsClient] = useState38(false);
11191
+ const [scale, setScale] = useState38({ initial: 1, min: 1, max: 8 });
11192
+ const [cropDimensions, setCropDimensions] = useState38({ width: 0, height: 0 });
11193
+ const [currentZoomScale, setCurrentZoomScale] = useState38(1);
11147
11194
  const imgRef = useRef25(null);
11148
11195
  const touchStartRef = useRef25(
11149
11196
  null
@@ -11173,17 +11220,17 @@ var EnhancedImageViewer = ({
11173
11220
  document.body.style.overflow = "";
11174
11221
  };
11175
11222
  }, [calculateScale]);
11176
- useEffect37(() => {
11223
+ useEffect38(() => {
11177
11224
  calculateScale();
11178
11225
  }, [calculateScale]);
11179
- useEffect37(() => {
11226
+ useEffect38(() => {
11180
11227
  const handleResize = () => {
11181
11228
  calculateScale();
11182
11229
  };
11183
11230
  window.addEventListener("resize", handleResize);
11184
11231
  return () => window.removeEventListener("resize", handleResize);
11185
11232
  }, [calculateScale]);
11186
- useEffect37(() => {
11233
+ useEffect38(() => {
11187
11234
  const handleKeyDown = (e) => {
11188
11235
  if (e.key === "Escape") {
11189
11236
  onClose();
@@ -11268,12 +11315,12 @@ var EnhancedImageViewer = ({
11268
11315
  );
11269
11316
  if (!isMounted || !isClient) {
11270
11317
  return createPortal3(
11271
- /* @__PURE__ */ jsx70(
11318
+ /* @__PURE__ */ jsx71(
11272
11319
  "div",
11273
11320
  {
11274
11321
  className: "fixed inset-0 bg-black flex items-center justify-center",
11275
11322
  style: { zIndex: 999999 },
11276
- children: /* @__PURE__ */ jsx70(
11323
+ children: /* @__PURE__ */ jsx71(
11277
11324
  "div",
11278
11325
  {
11279
11326
  style: {
@@ -11298,7 +11345,7 @@ var EnhancedImageViewer = ({
11298
11345
  "aria-modal": "true",
11299
11346
  "aria-label": "Image viewer",
11300
11347
  children: [
11301
- /* @__PURE__ */ jsx70(
11348
+ /* @__PURE__ */ jsx71(
11302
11349
  "button",
11303
11350
  {
11304
11351
  onClick: (e) => {
@@ -11324,10 +11371,10 @@ var EnhancedImageViewer = ({
11324
11371
  touchAction: "manipulation",
11325
11372
  marginBottom: "env(safe-area-inset-bottom, 0px)"
11326
11373
  },
11327
- children: /* @__PURE__ */ jsx70(X2, { className: "w-7 h-7", strokeWidth: 2.5 })
11374
+ children: /* @__PURE__ */ jsx71(X2, { className: "w-7 h-7", strokeWidth: 2.5 })
11328
11375
  }
11329
11376
  ),
11330
- /* @__PURE__ */ jsx70(
11377
+ /* @__PURE__ */ jsx71(
11331
11378
  TransformWrapper,
11332
11379
  {
11333
11380
  initialScale: scale.initial,
@@ -11374,14 +11421,14 @@ var EnhancedImageViewer = ({
11374
11421
  onTouchStart: handleTouchStart,
11375
11422
  onTouchEnd: handleTouchEnd,
11376
11423
  children: [
11377
- /* @__PURE__ */ jsx70(
11424
+ /* @__PURE__ */ jsx71(
11378
11425
  TransformComponent,
11379
11426
  {
11380
11427
  wrapperStyle: {
11381
11428
  width: "100%",
11382
11429
  height: "100%"
11383
11430
  },
11384
- children: /* @__PURE__ */ jsx70(
11431
+ children: /* @__PURE__ */ jsx71(
11385
11432
  "div",
11386
11433
  {
11387
11434
  style: {
@@ -11392,8 +11439,8 @@ var EnhancedImageViewer = ({
11392
11439
  alignItems: "center",
11393
11440
  justifyContent: "center"
11394
11441
  },
11395
- children: /* @__PURE__ */ jsx70(
11396
- "img",
11442
+ children: /* @__PURE__ */ jsx71(
11443
+ SafeImg,
11397
11444
  {
11398
11445
  ref: imgRef,
11399
11446
  src: imageUrl,
@@ -11414,7 +11461,7 @@ var EnhancedImageViewer = ({
11414
11461
  }
11415
11462
  ),
11416
11463
  /* @__PURE__ */ jsxs48("div", { className: "fixed bottom-5 left-0 right-0 z-50", children: [
11417
- /* @__PURE__ */ jsx70("div", { className: "flex justify-center gap-2", children: (() => {
11464
+ /* @__PURE__ */ jsx71("div", { className: "flex justify-center gap-2", children: (() => {
11418
11465
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11419
11466
  if (currentIndex === -1) {
11420
11467
  currentIndex = images.findIndex(
@@ -11447,8 +11494,8 @@ var EnhancedImageViewer = ({
11447
11494
  };
11448
11495
  const nextIndex = findNextAvailableIndex(currentIndex, 1);
11449
11496
  const prevIndex = findNextAvailableIndex(currentIndex, -1);
11450
- return /* @__PURE__ */ jsxs48(Fragment15, { children: [
11451
- /* @__PURE__ */ jsx70(
11497
+ return /* @__PURE__ */ jsxs48(Fragment16, { children: [
11498
+ /* @__PURE__ */ jsx71(
11452
11499
  "button",
11453
11500
  {
11454
11501
  onClick: () => {
@@ -11461,7 +11508,7 @@ var EnhancedImageViewer = ({
11461
11508
  className: `w-10 h-10 rounded-full shadow-lg flex items-center justify-center transition-all duration-200 ${prevIndex === -1 ? "bg-white/40 text-black opacity-50 cursor-not-allowed" : "bg-white/90 hover:bg-white text-black"}`,
11462
11509
  style: { touchAction: "manipulation" },
11463
11510
  "aria-label": "Previous image",
11464
- children: /* @__PURE__ */ jsx70(
11511
+ children: /* @__PURE__ */ jsx71(
11465
11512
  "svg",
11466
11513
  {
11467
11514
  className: "w-4 h-4",
@@ -11469,7 +11516,7 @@ var EnhancedImageViewer = ({
11469
11516
  stroke: "currentColor",
11470
11517
  viewBox: "0 0 24 24",
11471
11518
  "aria-hidden": "true",
11472
- children: /* @__PURE__ */ jsx70(
11519
+ children: /* @__PURE__ */ jsx71(
11473
11520
  "path",
11474
11521
  {
11475
11522
  strokeLinecap: "round",
@@ -11482,7 +11529,7 @@ var EnhancedImageViewer = ({
11482
11529
  )
11483
11530
  }
11484
11531
  ),
11485
- /* @__PURE__ */ jsx70(
11532
+ /* @__PURE__ */ jsx71(
11486
11533
  "button",
11487
11534
  {
11488
11535
  onClick: () => {
@@ -11495,7 +11542,7 @@ var EnhancedImageViewer = ({
11495
11542
  className: `w-10 h-10 rounded-full shadow-lg flex items-center justify-center transition-all duration-200 ${nextIndex === -1 ? "bg-white/40 text-black opacity-50 cursor-not-allowed" : "bg-white/90 hover:bg-white text-black"}`,
11496
11543
  style: { touchAction: "manipulation" },
11497
11544
  "aria-label": "Next image",
11498
- children: /* @__PURE__ */ jsx70(
11545
+ children: /* @__PURE__ */ jsx71(
11499
11546
  "svg",
11500
11547
  {
11501
11548
  className: "w-4 h-4",
@@ -11503,7 +11550,7 @@ var EnhancedImageViewer = ({
11503
11550
  stroke: "currentColor",
11504
11551
  viewBox: "0 0 24 24",
11505
11552
  "aria-hidden": "true",
11506
- children: /* @__PURE__ */ jsx70(
11553
+ children: /* @__PURE__ */ jsx71(
11507
11554
  "path",
11508
11555
  {
11509
11556
  strokeLinecap: "round",
@@ -11518,7 +11565,7 @@ var EnhancedImageViewer = ({
11518
11565
  )
11519
11566
  ] });
11520
11567
  })() }),
11521
- /* @__PURE__ */ jsx70("div", { style: { position: "fixed", bottom: 20, left: 24, zIndex: 10, marginBottom: "env(safe-area-inset-bottom, 0px)" }, className: "h-10 px-3 rounded-full bg-white/90 text-black text-sm font-medium flex items-center justify-center shadow-lg", children: (() => {
11568
+ /* @__PURE__ */ jsx71("div", { style: { position: "fixed", bottom: 20, left: 24, zIndex: 10, marginBottom: "env(safe-area-inset-bottom, 0px)" }, className: "h-10 px-3 rounded-full bg-white/90 text-black text-sm font-medium flex items-center justify-center shadow-lg", children: (() => {
11522
11569
  const total = Math.max(images.length, 1);
11523
11570
  const current = propCurrentIndex !== void 0 ? Math.min(propCurrentIndex + 1, total) : 1;
11524
11571
  return `${current} / ${total}`;
@@ -11530,7 +11577,7 @@ var EnhancedImageViewer = ({
11530
11577
  },
11531
11578
  `${scale.initial}-${scale.min}-${scale.max}`
11532
11579
  ),
11533
- /* @__PURE__ */ jsx70(
11580
+ /* @__PURE__ */ jsx71(
11534
11581
  "div",
11535
11582
  {
11536
11583
  className: "absolute inset-0 bg-black",
@@ -11549,7 +11596,7 @@ var EnhancedImageViewer = ({
11549
11596
  };
11550
11597
 
11551
11598
  // src/composed/zoom/ResponsiveZoom.tsx
11552
- import { Fragment as Fragment16, jsx as jsx71, jsxs as jsxs49 } from "react/jsx-runtime";
11599
+ import { Fragment as Fragment17, jsx as jsx72, jsxs as jsxs49 } from "react/jsx-runtime";
11553
11600
  function ResponsiveZoom({
11554
11601
  imageIndex,
11555
11602
  children,
@@ -11559,11 +11606,11 @@ function ResponsiveZoom({
11559
11606
  imageUrl,
11560
11607
  alt = "Product image"
11561
11608
  }) {
11562
- const [isTouchDevice, setIsTouchDevice] = useState38(false);
11563
- const [showEnhancedViewer, setShowEnhancedViewer] = useState38(false);
11564
- const [viewerIndex, setViewerIndex] = useState38(0);
11565
- const [currentImageUrl, setCurrentImageUrl] = useState38(imageUrl || "");
11566
- useEffect38(() => {
11609
+ const [isTouchDevice, setIsTouchDevice] = useState39(false);
11610
+ const [showEnhancedViewer, setShowEnhancedViewer] = useState39(false);
11611
+ const [viewerIndex, setViewerIndex] = useState39(0);
11612
+ const [currentImageUrl, setCurrentImageUrl] = useState39(imageUrl || "");
11613
+ useEffect39(() => {
11567
11614
  const checkDeviceType = () => {
11568
11615
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
11569
11616
  setIsTouchDevice(hasTouch);
@@ -11590,8 +11637,8 @@ function ResponsiveZoom({
11590
11637
  }
11591
11638
  }
11592
11639
  };
11593
- return /* @__PURE__ */ jsxs49(Fragment16, { children: [
11594
- isTouchDevice ? /* @__PURE__ */ jsx71(
11640
+ return /* @__PURE__ */ jsxs49(Fragment17, { children: [
11641
+ isTouchDevice ? /* @__PURE__ */ jsx72(
11595
11642
  "div",
11596
11643
  {
11597
11644
  className,
@@ -11608,7 +11655,7 @@ function ResponsiveZoom({
11608
11655
  },
11609
11656
  children
11610
11657
  }
11611
- ) : /* @__PURE__ */ jsx71(
11658
+ ) : /* @__PURE__ */ jsx72(
11612
11659
  ZoomOverlay,
11613
11660
  {
11614
11661
  imageIndex,
@@ -11619,7 +11666,7 @@ function ResponsiveZoom({
11619
11666
  children
11620
11667
  }
11621
11668
  ),
11622
- showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ jsx71(
11669
+ showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ jsx72(
11623
11670
  EnhancedImageViewer,
11624
11671
  {
11625
11672
  imageUrl: currentImageUrl,
@@ -11643,14 +11690,37 @@ function ResponsiveZoom({
11643
11690
 
11644
11691
  // src/composed/carousels/MobileProductCarousel.tsx
11645
11692
  import {
11646
- useState as useState39,
11693
+ useState as useState40,
11647
11694
  useRef as useRef26,
11648
- useEffect as useEffect39,
11695
+ useEffect as useEffect40,
11649
11696
  useCallback as useCallback22,
11650
11697
  useMemo as useMemo15,
11651
11698
  memo as memo4
11652
11699
  } from "react";
11653
- import { jsx as jsx72, jsxs as jsxs50 } from "react/jsx-runtime";
11700
+ import { jsx as jsx73, jsxs as jsxs50 } from "react/jsx-runtime";
11701
+ function StaticCarouselImage({
11702
+ src,
11703
+ alt,
11704
+ className
11705
+ }) {
11706
+ const [failed, setFailed] = useState40(false);
11707
+ if (failed || !src) {
11708
+ return /* @__PURE__ */ jsx73("div", { className: `bg-muted ${className ?? ""}`, role: "img", "aria-label": alt });
11709
+ }
11710
+ return /* @__PURE__ */ jsx73(
11711
+ "img",
11712
+ {
11713
+ src,
11714
+ alt,
11715
+ crossOrigin: "anonymous",
11716
+ className,
11717
+ loading: "lazy",
11718
+ decoding: "async",
11719
+ draggable: false,
11720
+ onError: () => setFailed(true)
11721
+ }
11722
+ );
11723
+ }
11654
11724
  var MobileProductCarousel = memo4(function MobileProductCarousel2({
11655
11725
  images,
11656
11726
  currentIndex = 0,
@@ -11666,23 +11736,23 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11666
11736
  mockupWidth,
11667
11737
  onMockupUrlGenerated
11668
11738
  }) {
11669
- const [activeIndex, setActiveIndex] = useState39(currentIndex);
11670
- const [touchStart, setTouchStart] = useState39(
11739
+ const [activeIndex, setActiveIndex] = useState40(currentIndex);
11740
+ const [touchStart, setTouchStart] = useState40(
11671
11741
  null
11672
11742
  );
11673
- const [touchEnd, setTouchEnd] = useState39(
11743
+ const [touchEnd, setTouchEnd] = useState40(
11674
11744
  null
11675
11745
  );
11676
- const [showImageViewer, setShowImageViewer] = useState39(false);
11677
- const [viewerKey, setViewerKey] = useState39(0);
11678
- const [isDragging, setIsDragging] = useState39(false);
11679
- const [dragOffset, setDragOffset] = useState39(0);
11680
- const [isTransitioning, setIsTransitioning] = useState39(false);
11681
- const [isHorizontalSwipe, setIsHorizontalSwipe] = useState39(
11746
+ const [showImageViewer, setShowImageViewer] = useState40(false);
11747
+ const [viewerKey, setViewerKey] = useState40(0);
11748
+ const [isDragging, setIsDragging] = useState40(false);
11749
+ const [dragOffset, setDragOffset] = useState40(0);
11750
+ const [isTransitioning, setIsTransitioning] = useState40(false);
11751
+ const [isHorizontalSwipe, setIsHorizontalSwipe] = useState40(
11682
11752
  null
11683
11753
  );
11684
- const [isPeeking, setIsPeeking] = useState39(false);
11685
- const [isPeekReturning, setIsPeekReturning] = useState39(false);
11754
+ const [isPeeking, setIsPeeking] = useState40(false);
11755
+ const [isPeekReturning, setIsPeekReturning] = useState40(false);
11686
11756
  const carouselRef = useRef26(null);
11687
11757
  const indicatorRef = useRef26(null);
11688
11758
  const touchStartRef = useRef26(
@@ -11693,7 +11763,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11693
11763
  const hasSwipedThisSessionRef = useRef26(false);
11694
11764
  const generatedUrlsRef = useRef26(/* @__PURE__ */ new Map());
11695
11765
  const prevArtworkSrcRef = useRef26(currentArtwork?.src);
11696
- useEffect39(() => {
11766
+ useEffect40(() => {
11697
11767
  if (currentArtwork?.src !== prevArtworkSrcRef.current) {
11698
11768
  generatedUrlsRef.current.clear();
11699
11769
  prevArtworkSrcRef.current = currentArtwork?.src;
@@ -11709,8 +11779,8 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11709
11779
  const shouldHideDots = stickyHeroContext?.shouldHideDots ?? false;
11710
11780
  const priorityContext = useMockupPriorityOptional();
11711
11781
  const realtimeContext = useRealtimeOptional();
11712
- const [urlUpdateCounter, setUrlUpdateCounter] = useState39(0);
11713
- useEffect39(() => {
11782
+ const [urlUpdateCounter, setUrlUpdateCounter] = useState40(0);
11783
+ useEffect40(() => {
11714
11784
  if (!realtimeContext?.subscribeMockupResults) return;
11715
11785
  const unsubscribe = realtimeContext.subscribeMockupResults(() => {
11716
11786
  setUrlUpdateCounter((c) => c + 1);
@@ -11738,10 +11808,10 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11738
11808
  });
11739
11809
  }, [images, realtimeMockupUrls]);
11740
11810
  const minSwipeDistance = 50;
11741
- useEffect39(() => {
11811
+ useEffect40(() => {
11742
11812
  setActiveIndex(currentIndex);
11743
11813
  }, [currentIndex]);
11744
- useEffect39(() => {
11814
+ useEffect40(() => {
11745
11815
  if (!priorityContext) return;
11746
11816
  const realMockups = images.map((img, idx) => ({ img, originalIdx: idx })).filter(({ img }) => img.isRealMockup && img.mockupId);
11747
11817
  const mockupIdsList = realMockups.map(({ img }) => img.mockupId);
@@ -11769,7 +11839,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11769
11839
  priorityContext.clearMobileCarouselMode?.();
11770
11840
  };
11771
11841
  }, [priorityContext, activeIndex, images]);
11772
- useEffect39(() => {
11842
+ useEffect40(() => {
11773
11843
  const indicator = indicatorRef.current;
11774
11844
  if (!indicator) return;
11775
11845
  let ticking = false;
@@ -11834,7 +11904,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11834
11904
  } catch {
11835
11905
  }
11836
11906
  }, []);
11837
- useEffect39(() => {
11907
+ useEffect40(() => {
11838
11908
  if (!enablePeekAnimation || images.length <= 1) return;
11839
11909
  const tracking = getSwipeTracking();
11840
11910
  const newViewCount = tracking.viewsWithoutSwipe + 1;
@@ -11938,7 +12008,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11938
12008
  },
11939
12009
  [activeIndex, images.length, onIndexChange, recordSwipe]
11940
12010
  );
11941
- useEffect39(() => {
12011
+ useEffect40(() => {
11942
12012
  const container = carouselRef.current;
11943
12013
  if (!container) return;
11944
12014
  const handleTouchStart = (e) => {
@@ -12031,7 +12101,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12031
12101
  null
12032
12102
  );
12033
12103
  const isMouseDraggingRef = useRef26(false);
12034
- useEffect39(() => {
12104
+ useEffect40(() => {
12035
12105
  const container = carouselRef.current;
12036
12106
  if (!container) return;
12037
12107
  const handleMouseDown = (e) => {
@@ -12125,16 +12195,16 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12125
12195
  },
12126
12196
  [onIndexChange]
12127
12197
  );
12128
- useEffect39(() => {
12198
+ useEffect40(() => {
12129
12199
  if (stickyHeroContext?.setCarouselIndicator && images.length > 1) {
12130
- const indicator = /* @__PURE__ */ jsx72(
12200
+ const indicator = /* @__PURE__ */ jsx73(
12131
12201
  "div",
12132
12202
  {
12133
12203
  className: "w-full",
12134
12204
  role: "group",
12135
12205
  "aria-label": "Product image navigation",
12136
12206
  children: /* @__PURE__ */ jsxs50("div", { className: "relative h-1", children: [
12137
- /* @__PURE__ */ jsx72("div", { className: "flex h-full", children: images.map((_, index) => /* @__PURE__ */ jsx72(
12207
+ /* @__PURE__ */ jsx73("div", { className: "flex h-full", children: images.map((_, index) => /* @__PURE__ */ jsx73(
12138
12208
  "button",
12139
12209
  {
12140
12210
  onClick: () => goToSlide(index),
@@ -12144,7 +12214,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12144
12214
  },
12145
12215
  index
12146
12216
  )) }),
12147
- /* @__PURE__ */ jsx72(
12217
+ /* @__PURE__ */ jsx73(
12148
12218
  "div",
12149
12219
  {
12150
12220
  className: "absolute top-0 h-full bg-primary transition-all duration-300 ease-out",
@@ -12167,10 +12237,10 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12167
12237
  };
12168
12238
  }, [activeIndex, images.length, goToSlide, stickyHeroContext]);
12169
12239
  if (!images || images.length === 0) {
12170
- return /* @__PURE__ */ jsx72("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12240
+ return /* @__PURE__ */ jsx73("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12171
12241
  }
12172
12242
  return /* @__PURE__ */ jsxs50("div", { className: `relative w-full h-full ${className}`, children: [
12173
- /* @__PURE__ */ jsx72(
12243
+ /* @__PURE__ */ jsx73(
12174
12244
  "div",
12175
12245
  {
12176
12246
  ref: carouselRef,
@@ -12188,7 +12258,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12188
12258
  role: "region",
12189
12259
  "aria-roledescription": "carousel",
12190
12260
  "aria-label": "Product images",
12191
- children: /* @__PURE__ */ jsx72(
12261
+ children: /* @__PURE__ */ jsx73(
12192
12262
  "div",
12193
12263
  {
12194
12264
  className: `flex h-full ${isPeekReturning ? "transition-transform duration-300 ease-[cubic-bezier(0,0,0.2,1)]" : isPeeking ? "transition-transform duration-500 ease-[cubic-bezier(0.4,0,0.2,1)]" : isTransitioning || !isDragging ? "transition-transform duration-300 ease-[cubic-bezier(0.25,0.46,0.45,0.94)]" : ""}`,
@@ -12198,11 +12268,15 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12198
12268
  children: images.map((image, index) => {
12199
12269
  const DECODE_WINDOW = 1;
12200
12270
  const isWithinDecodeWindow = Math.abs(index - activeIndex) <= DECODE_WINDOW;
12201
- return /* @__PURE__ */ jsx72(
12271
+ return /* @__PURE__ */ jsx73(
12202
12272
  "div",
12203
12273
  {
12204
12274
  className: "w-full h-full flex-shrink-0 relative select-none",
12205
- children: !isWithinDecodeWindow ? /* @__PURE__ */ jsx72("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? /* @__PURE__ */ jsx72("div", { className: "w-full h-full bg-muted-foreground/20 animate-pulse" }) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ jsx72(
12275
+ children: !isWithinDecodeWindow ? /* @__PURE__ */ jsx73("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? (
12276
+ // Rainbow prism loader (same as the /create route) instead of
12277
+ // a flat pulse; fills this relative slide via inset:0.
12278
+ /* @__PURE__ */ jsx73(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" })
12279
+ ) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ jsx73(
12206
12280
  HeroProductImage,
12207
12281
  {
12208
12282
  productId,
@@ -12214,16 +12288,12 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12214
12288
  onUrlGenerated: image.mockupId ? (url) => handleUrlGenerated(image.mockupId, url) : void 0,
12215
12289
  className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12216
12290
  }
12217
- ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ jsx72("div", { className: "w-full h-full bg-muted animate-pulse" }) : /* @__PURE__ */ jsx72(
12218
- "img",
12291
+ ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ jsx73(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" }) : /* @__PURE__ */ jsx73(
12292
+ StaticCarouselImage,
12219
12293
  {
12220
12294
  src: image.src,
12221
- alt: image.label,
12222
- crossOrigin: "anonymous",
12223
- className: "w-full h-full object-cover cursor-pointer pointer-events-none",
12224
- loading: "lazy",
12225
- decoding: "async",
12226
- draggable: false
12295
+ alt: image.label ?? "",
12296
+ className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12227
12297
  }
12228
12298
  )
12229
12299
  },
@@ -12234,7 +12304,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12234
12304
  )
12235
12305
  }
12236
12306
  ),
12237
- showIndicators && images.length > 1 && /* @__PURE__ */ jsx72(
12307
+ showIndicators && images.length > 1 && /* @__PURE__ */ jsx73(
12238
12308
  "div",
12239
12309
  {
12240
12310
  ref: indicatorRef,
@@ -12243,7 +12313,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12243
12313
  role: "group",
12244
12314
  "aria-label": "Product image navigation",
12245
12315
  children: /* @__PURE__ */ jsxs50("div", { className: "relative h-1", children: [
12246
- /* @__PURE__ */ jsx72("div", { className: "flex h-full absolute inset-0", children: images.map((_, index) => /* @__PURE__ */ jsx72(
12316
+ /* @__PURE__ */ jsx73("div", { className: "flex h-full absolute inset-0", children: images.map((_, index) => /* @__PURE__ */ jsx73(
12247
12317
  "button",
12248
12318
  {
12249
12319
  onClick: () => goToSlide(index),
@@ -12253,7 +12323,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12253
12323
  },
12254
12324
  index
12255
12325
  )) }),
12256
- /* @__PURE__ */ jsx72(
12326
+ /* @__PURE__ */ jsx73(
12257
12327
  "div",
12258
12328
  {
12259
12329
  className: `absolute top-0 h-full bg-foreground ${isPeekReturning ? "transition-all duration-300 ease-[cubic-bezier(0,0,0.2,1)]" : isPeeking ? "transition-all duration-500 ease-[cubic-bezier(0.4,0,0.2,1)]" : isDragging ? "" : "transition-all duration-300 ease-out"}`,
@@ -12288,7 +12358,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12288
12358
  naturalHeight: img.naturalHeight
12289
12359
  } : null;
12290
12360
  }).filter((img) => img !== null);
12291
- return /* @__PURE__ */ jsx72(
12361
+ return /* @__PURE__ */ jsx73(
12292
12362
  EnhancedImageViewer,
12293
12363
  {
12294
12364
  imageUrl,
@@ -12327,8 +12397,8 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12327
12397
  });
12328
12398
 
12329
12399
  // src/composed/carousels/HeroCarousel.tsx
12330
- import { useState as useState40, useRef as useRef27, useCallback as useCallback23, useEffect as useEffect40 } from "react";
12331
- import { jsx as jsx73, jsxs as jsxs51 } from "react/jsx-runtime";
12400
+ import { useState as useState41, useRef as useRef27, useCallback as useCallback23, useEffect as useEffect41 } from "react";
12401
+ import { jsx as jsx74, jsxs as jsxs51 } from "react/jsx-runtime";
12332
12402
  function HeroCarousel({
12333
12403
  images,
12334
12404
  currentIndex = 0,
@@ -12338,13 +12408,13 @@ function HeroCarousel({
12338
12408
  productId,
12339
12409
  onImageTap
12340
12410
  }) {
12341
- const [activeIndex, setActiveIndex] = useState40(currentIndex);
12411
+ const [activeIndex, setActiveIndex] = useState41(currentIndex);
12342
12412
  const containerRef = useRef27(null);
12343
12413
  const touchStartRef = useRef27(
12344
12414
  null
12345
12415
  );
12346
12416
  const isSwipingRef = useRef27(false);
12347
- useEffect40(() => {
12417
+ useEffect41(() => {
12348
12418
  setActiveIndex(currentIndex);
12349
12419
  }, [currentIndex]);
12350
12420
  const goToSlide = useCallback23(
@@ -12355,7 +12425,7 @@ function HeroCarousel({
12355
12425
  },
12356
12426
  [images.length, onIndexChange]
12357
12427
  );
12358
- useEffect40(() => {
12428
+ useEffect41(() => {
12359
12429
  const container = containerRef.current;
12360
12430
  if (!container) return;
12361
12431
  const handleTouchStart = (e) => {
@@ -12407,7 +12477,7 @@ function HeroCarousel({
12407
12477
  };
12408
12478
  }, [activeIndex, images.length, goToSlide, onImageTap]);
12409
12479
  if (!images || images.length === 0) {
12410
- return /* @__PURE__ */ jsx73("div", { className: "w-full h-full bg-muted" });
12480
+ return /* @__PURE__ */ jsx74("div", { className: "w-full h-full bg-muted" });
12411
12481
  }
12412
12482
  return /* @__PURE__ */ jsxs51(
12413
12483
  "div",
@@ -12420,7 +12490,7 @@ function HeroCarousel({
12420
12490
  overflow: "hidden"
12421
12491
  },
12422
12492
  children: [
12423
- /* @__PURE__ */ jsx73(
12493
+ /* @__PURE__ */ jsx74(
12424
12494
  "div",
12425
12495
  {
12426
12496
  className: "flex h-full transition-transform duration-300 ease-out",
@@ -12431,14 +12501,14 @@ function HeroCarousel({
12431
12501
  backfaceVisibility: "hidden",
12432
12502
  WebkitBackfaceVisibility: "hidden"
12433
12503
  },
12434
- children: images.map((image, index) => /* @__PURE__ */ jsx73(
12504
+ children: images.map((image, index) => /* @__PURE__ */ jsx74(
12435
12505
  "div",
12436
12506
  {
12437
12507
  className: "w-full h-full flex-shrink-0",
12438
12508
  style: {
12439
12509
  contain: "layout paint"
12440
12510
  },
12441
- children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ jsx73(
12511
+ children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ jsx74(
12442
12512
  HeroProductImage,
12443
12513
  {
12444
12514
  productId,
@@ -12447,7 +12517,7 @@ function HeroCarousel({
12447
12517
  mockupId: image.mockupId,
12448
12518
  className: "w-full h-full object-cover"
12449
12519
  }
12450
- ) : /* @__PURE__ */ jsx73(
12520
+ ) : /* @__PURE__ */ jsx74(
12451
12521
  "img",
12452
12522
  {
12453
12523
  src: image.src,
@@ -12464,12 +12534,12 @@ function HeroCarousel({
12464
12534
  ))
12465
12535
  }
12466
12536
  ),
12467
- images.length > 1 && /* @__PURE__ */ jsx73(
12537
+ images.length > 1 && /* @__PURE__ */ jsx74(
12468
12538
  "div",
12469
12539
  {
12470
12540
  className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 z-10",
12471
12541
  style: { contain: "layout style" },
12472
- children: images.map((_, index) => /* @__PURE__ */ jsx73(
12542
+ children: images.map((_, index) => /* @__PURE__ */ jsx74(
12473
12543
  "button",
12474
12544
  {
12475
12545
  onClick: () => goToSlide(index),
@@ -12486,8 +12556,8 @@ function HeroCarousel({
12486
12556
  }
12487
12557
 
12488
12558
  // src/composed/grids/MasonryGrid.tsx
12489
- import { useState as useState41, useEffect as useEffect41, useMemo as useMemo16 } from "react";
12490
- import { Fragment as Fragment17, jsx as jsx74 } from "react/jsx-runtime";
12559
+ import { useState as useState42, useEffect as useEffect42, useMemo as useMemo16 } from "react";
12560
+ import { Fragment as Fragment18, jsx as jsx75 } from "react/jsx-runtime";
12491
12561
  var BREAKPOINTS = {
12492
12562
  sm: 640,
12493
12563
  md: 768,
@@ -12539,13 +12609,13 @@ function MasonryGrid({
12539
12609
  className = "",
12540
12610
  emptyContent
12541
12611
  }) {
12542
- const [columnCount, setColumnCount] = useState41(
12612
+ const [columnCount, setColumnCount] = useState42(
12543
12613
  () => typeof columns === "number" ? columns : getColumnCount(
12544
12614
  typeof window !== "undefined" ? window.innerWidth : 1024,
12545
12615
  columns
12546
12616
  )
12547
12617
  );
12548
- useEffect41(() => {
12618
+ useEffect42(() => {
12549
12619
  const updateColumnCount = () => {
12550
12620
  setColumnCount(getColumnCount(window.innerWidth, columns));
12551
12621
  };
@@ -12559,24 +12629,24 @@ function MasonryGrid({
12559
12629
  );
12560
12630
  if (items.length === 0) {
12561
12631
  if (emptyContent) {
12562
- return /* @__PURE__ */ jsx74(Fragment17, { children: emptyContent });
12632
+ return /* @__PURE__ */ jsx75(Fragment18, { children: emptyContent });
12563
12633
  }
12564
12634
  return null;
12565
12635
  }
12566
- return /* @__PURE__ */ jsx74(
12636
+ return /* @__PURE__ */ jsx75(
12567
12637
  "div",
12568
12638
  {
12569
12639
  className: `flex ${className}`,
12570
12640
  style: { gap: `${gap}px` },
12571
12641
  role: "list",
12572
- children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ jsx74(
12642
+ children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ jsx75(
12573
12643
  "div",
12574
12644
  {
12575
12645
  className: "flex-1 flex flex-col",
12576
12646
  style: { gap: `${gap}px` },
12577
12647
  children: columnItems.map((item, itemIndex) => {
12578
12648
  const originalIndex = itemIndex * columnCount + columnIndex;
12579
- return /* @__PURE__ */ jsx74("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12649
+ return /* @__PURE__ */ jsx75("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12580
12650
  })
12581
12651
  },
12582
12652
  columnIndex
@@ -12586,7 +12656,7 @@ function MasonryGrid({
12586
12656
  }
12587
12657
 
12588
12658
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12589
- import { useEffect as useEffect43, useRef as useRef28 } from "react";
12659
+ import { useEffect as useEffect44, useRef as useRef28 } from "react";
12590
12660
 
12591
12661
  // src/layouts/hero-zoom/types.ts
12592
12662
  var DEFAULT_HERO_ZOOM_CONFIG = {
@@ -12598,15 +12668,15 @@ var DEFAULT_HERO_ZOOM_CONFIG = {
12598
12668
  };
12599
12669
 
12600
12670
  // src/layouts/hero-zoom/useHeroZoomScales.ts
12601
- import { useEffect as useEffect42, useState as useState42, useCallback as useCallback24 } from "react";
12671
+ import { useEffect as useEffect43, useState as useState43, useCallback as useCallback24 } from "react";
12602
12672
  function useHeroZoomScales(config = {}) {
12603
12673
  const { initialScale, accountForRetina, maxRetinaMultiplier } = {
12604
12674
  ...DEFAULT_HERO_ZOOM_CONFIG,
12605
12675
  ...config
12606
12676
  };
12607
- const [isHydrated, setIsHydrated] = useState42(false);
12677
+ const [isHydrated, setIsHydrated] = useState43(false);
12608
12678
  const ssrMultiplier = accountForRetina ? maxRetinaMultiplier : 2;
12609
- const [scales, setScales] = useState42(() => ({
12679
+ const [scales, setScales] = useState43(() => ({
12610
12680
  visual: initialScale,
12611
12681
  render: initialScale * ssrMultiplier
12612
12682
  }));
@@ -12625,7 +12695,7 @@ function useHeroZoomScales(config = {}) {
12625
12695
  renderScale = Math.max(1, Math.min(8, renderScale));
12626
12696
  return { visual: visualScale, render: renderScale };
12627
12697
  }, [initialScale, accountForRetina, maxRetinaMultiplier]);
12628
- useEffect42(() => {
12698
+ useEffect43(() => {
12629
12699
  const supportsScrollTimeline = CSS.supports(
12630
12700
  "animation-timeline",
12631
12701
  "scroll()"
@@ -12675,7 +12745,7 @@ function useHeroZoomScales(config = {}) {
12675
12745
  }
12676
12746
 
12677
12747
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12678
- import { jsx as jsx75, jsxs as jsxs52 } from "react/jsx-runtime";
12748
+ import { jsx as jsx76, jsxs as jsxs52 } from "react/jsx-runtime";
12679
12749
  function HeroZoomLayout({
12680
12750
  config = {},
12681
12751
  header,
@@ -12692,7 +12762,7 @@ function HeroZoomLayout({
12692
12762
  const { visual, render, isHydrated } = useHeroZoomScales(mergedConfig);
12693
12763
  const imageContainerRef = useRef28(null);
12694
12764
  const headerRef = useRef28(null);
12695
- useEffect43(() => {
12765
+ useEffect44(() => {
12696
12766
  if (typeof window === "undefined") return;
12697
12767
  const originalRestoration = "scrollRestoration" in history ? history.scrollRestoration : "auto";
12698
12768
  if ("scrollRestoration" in history) {
@@ -12705,7 +12775,7 @@ function HeroZoomLayout({
12705
12775
  }
12706
12776
  };
12707
12777
  }, []);
12708
- useEffect43(() => {
12778
+ useEffect44(() => {
12709
12779
  const supportsScrollTimeline = CSS.supports(
12710
12780
  "animation-timeline",
12711
12781
  "scroll()"
@@ -12848,8 +12918,8 @@ function HeroZoomLayout({
12848
12918
  "--hero-zoom-final-transform": 1 / activeRender
12849
12919
  },
12850
12920
  children: [
12851
- /* @__PURE__ */ jsx75("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
12852
- /* @__PURE__ */ jsx75(
12921
+ /* @__PURE__ */ jsx76("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
12922
+ /* @__PURE__ */ jsx76(
12853
12923
  "div",
12854
12924
  {
12855
12925
  style: {
@@ -12857,7 +12927,7 @@ function HeroZoomLayout({
12857
12927
  }
12858
12928
  }
12859
12929
  ),
12860
- header && /* @__PURE__ */ jsx75(
12930
+ header && /* @__PURE__ */ jsx76(
12861
12931
  "div",
12862
12932
  {
12863
12933
  ref: headerRef,
@@ -12870,7 +12940,7 @@ function HeroZoomLayout({
12870
12940
  children: header
12871
12941
  }
12872
12942
  ),
12873
- /* @__PURE__ */ jsx75(
12943
+ /* @__PURE__ */ jsx76(
12874
12944
  "div",
12875
12945
  {
12876
12946
  ref: imageContainerRef,
@@ -12890,15 +12960,15 @@ function HeroZoomLayout({
12890
12960
  children: hero
12891
12961
  }
12892
12962
  ),
12893
- /* @__PURE__ */ jsx75("div", { className: "relative z-10", children })
12963
+ /* @__PURE__ */ jsx76("div", { className: "relative z-10", children })
12894
12964
  ]
12895
12965
  }
12896
12966
  );
12897
12967
  }
12898
12968
 
12899
12969
  // src/layouts/hero-zoom/HeroShrinkLayout.tsx
12900
- import { useEffect as useEffect44, useRef as useRef29, useState as useState43 } from "react";
12901
- import { jsx as jsx76, jsxs as jsxs53 } from "react/jsx-runtime";
12970
+ import { useEffect as useEffect45, useRef as useRef29, useState as useState44 } from "react";
12971
+ import { jsx as jsx77, jsxs as jsxs53 } from "react/jsx-runtime";
12902
12972
  var DEFAULT_CONFIG = {
12903
12973
  aspectRatio: 16 / 9,
12904
12974
  initialHeightPercent: 70,
@@ -12920,11 +12990,11 @@ function HeroShrinkLayout({
12920
12990
  const { aspectRatio, initialHeightPercent, minHeightPercent, headerHeight } = mergedConfig;
12921
12991
  const heroRef = useRef29(null);
12922
12992
  const headerRef = useRef29(null);
12923
- const [isClient, setIsClient] = useState43(false);
12924
- useEffect44(() => {
12993
+ const [isClient, setIsClient] = useState44(false);
12994
+ useEffect45(() => {
12925
12995
  setIsClient(true);
12926
12996
  }, []);
12927
- useEffect44(() => {
12997
+ useEffect45(() => {
12928
12998
  if (!isClient) return;
12929
12999
  const supportsScrollTimeline = CSS.supports("animation-timeline", "scroll()");
12930
13000
  if (supportsScrollTimeline) return;
@@ -13017,9 +13087,9 @@ function HeroShrinkLayout({
13017
13087
  className: `relative min-h-screen ${className}`,
13018
13088
  style: { ...style, ...cssVars },
13019
13089
  children: [
13020
- /* @__PURE__ */ jsx76("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13021
- /* @__PURE__ */ jsx76("div", { style: { height: spacerHeight } }),
13022
- header && /* @__PURE__ */ jsx76(
13090
+ /* @__PURE__ */ jsx77("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13091
+ /* @__PURE__ */ jsx77("div", { style: { height: spacerHeight } }),
13092
+ header && /* @__PURE__ */ jsx77(
13023
13093
  "div",
13024
13094
  {
13025
13095
  ref: headerRef,
@@ -13028,7 +13098,7 @@ function HeroShrinkLayout({
13028
13098
  children: header
13029
13099
  }
13030
13100
  ),
13031
- /* @__PURE__ */ jsx76(
13101
+ /* @__PURE__ */ jsx77(
13032
13102
  "div",
13033
13103
  {
13034
13104
  ref: heroRef,
@@ -13036,15 +13106,15 @@ function HeroShrinkLayout({
13036
13106
  children: hero
13037
13107
  }
13038
13108
  ),
13039
- /* @__PURE__ */ jsx76("div", { className: "relative z-10 bg-background", children })
13109
+ /* @__PURE__ */ jsx77("div", { className: "relative z-10 bg-background", children })
13040
13110
  ]
13041
13111
  }
13042
13112
  );
13043
13113
  }
13044
13114
 
13045
13115
  // src/layouts/pdp/ImageEdgeBlur.tsx
13046
- import React50 from "react";
13047
- import { jsx as jsx77 } from "react/jsx-runtime";
13116
+ import React51 from "react";
13117
+ import { jsx as jsx78 } from "react/jsx-runtime";
13048
13118
  var BLUR_CONFIG = {
13049
13119
  blur: 24,
13050
13120
  crossfade: 68
@@ -13068,7 +13138,7 @@ var BLUR_LAYERS = [
13068
13138
  { blur: Math.round(BLUR_CONFIG.blur * 0.5), zone: 0.6 },
13069
13139
  { blur: BLUR_CONFIG.blur, zone: 1 }
13070
13140
  ];
13071
- var ImageEdgeBlur = React50.memo(
13141
+ var ImageEdgeBlur = React51.memo(
13072
13142
  function ImageEdgeBlur2({
13073
13143
  imageSrc,
13074
13144
  imageCapInfo,
@@ -13099,7 +13169,7 @@ var ImageEdgeBlur = React50.memo(
13099
13169
  viewportWidth / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO,
13100
13170
  maxWidthPx / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO
13101
13171
  );
13102
- return /* @__PURE__ */ jsx77(
13172
+ return /* @__PURE__ */ jsx78(
13103
13173
  "div",
13104
13174
  {
13105
13175
  className: `absolute inset-0 pointer-events-none overflow-hidden ${className}`,
@@ -13107,7 +13177,7 @@ var ImageEdgeBlur = React50.memo(
13107
13177
  children: BLUR_LAYERS.map((layer, index) => {
13108
13178
  const layerMask = index === BLUR_LAYERS.length - 1 ? void 0 : `linear-gradient(to right, black 0%, black ${layer.zone * 100}%, transparent ${layer.zone * 100 + 10}%)`;
13109
13179
  const blurScale = 1 + layer.blur * 3 / containerHeightPx;
13110
- return /* @__PURE__ */ jsx77(
13180
+ return /* @__PURE__ */ jsx78(
13111
13181
  "img",
13112
13182
  {
13113
13183
  src: imageSrc,
@@ -13154,7 +13224,7 @@ var ImageEdgeBlur = React50.memo(
13154
13224
  );
13155
13225
 
13156
13226
  // src/layouts/pdp/PDPLayout.tsx
13157
- import { jsx as jsx78, jsxs as jsxs54 } from "react/jsx-runtime";
13227
+ import { jsx as jsx79, jsxs as jsxs54 } from "react/jsx-runtime";
13158
13228
  function PDPLayout({
13159
13229
  renderHeroImage,
13160
13230
  renderContent,
@@ -13184,13 +13254,13 @@ function PDPLayout({
13184
13254
  };
13185
13255
  return /* @__PURE__ */ jsxs54("div", { className: `pdp-layout ${className}`, children: [
13186
13256
  (isDesktop === false || isDesktop === null) && /* @__PURE__ */ jsxs54("div", { className: "md:hidden", children: [
13187
- renderMobileCarousel && /* @__PURE__ */ jsx78("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13188
- /* @__PURE__ */ jsx78("div", { className: "mobile-content p-4", children: renderContent(contentProps) })
13257
+ renderMobileCarousel && /* @__PURE__ */ jsx79("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13258
+ /* @__PURE__ */ jsx79("div", { className: "mobile-content p-4", children: renderContent(contentProps) })
13189
13259
  ] }),
13190
13260
  (isDesktop === true || isDesktop === null) && /* @__PURE__ */ jsxs54("div", { className: "hidden md:block relative", children: [
13191
13261
  /* @__PURE__ */ jsxs54("div", { className: "desktop-hero relative", children: [
13192
13262
  renderHeroImage(heroProps),
13193
- showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ jsx78(
13263
+ showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ jsx79(
13194
13264
  ImageEdgeBlur,
13195
13265
  {
13196
13266
  imageSrc: blurImageSrc,
@@ -13201,7 +13271,7 @@ function PDPLayout({
13201
13271
  }
13202
13272
  )
13203
13273
  ] }),
13204
- /* @__PURE__ */ jsx78(
13274
+ /* @__PURE__ */ jsx79(
13205
13275
  "div",
13206
13276
  {
13207
13277
  className: "desktop-sidebar",
@@ -13218,8 +13288,8 @@ function PDPLayout({
13218
13288
  }
13219
13289
 
13220
13290
  // src/layouts/pdp/SimpleImageBlur.tsx
13221
- import React51 from "react";
13222
- import { jsx as jsx79 } from "react/jsx-runtime";
13291
+ import React52 from "react";
13292
+ import { jsx as jsx80 } from "react/jsx-runtime";
13223
13293
  var BLUR_CONFIG2 = {
13224
13294
  blur: 24,
13225
13295
  crossfade: 60
@@ -13242,7 +13312,7 @@ function getFadeInMask(crossfadeWidth) {
13242
13312
  black ${crossfadeWidth + 10}px
13243
13313
  )`;
13244
13314
  }
13245
- var SimpleImageBlur = React51.memo(function SimpleImageBlur2({
13315
+ var SimpleImageBlur = React52.memo(function SimpleImageBlur2({
13246
13316
  imageSrc,
13247
13317
  width,
13248
13318
  height = "100%",
@@ -13252,7 +13322,7 @@ var SimpleImageBlur = React51.memo(function SimpleImageBlur2({
13252
13322
  if (!imageSrc || width <= 0) return null;
13253
13323
  const fadeInMask = getFadeInMask(BLUR_CONFIG2.crossfade);
13254
13324
  const extendedWidth = width + BLUR_CONFIG2.blur * 2;
13255
- return /* @__PURE__ */ jsx79(
13325
+ return /* @__PURE__ */ jsx80(
13256
13326
  "div",
13257
13327
  {
13258
13328
  className: `relative overflow-hidden ${className}`,
@@ -13265,7 +13335,7 @@ var SimpleImageBlur = React51.memo(function SimpleImageBlur2({
13265
13335
  black 0%,
13266
13336
  black ${layer.zone * 100}%,
13267
13337
  transparent ${layer.zone * 100 + 10}%)`;
13268
- return /* @__PURE__ */ jsx79(
13338
+ return /* @__PURE__ */ jsx80(
13269
13339
  "img",
13270
13340
  {
13271
13341
  src: imageSrc,
@@ -13295,8 +13365,8 @@ var SimpleImageBlur = React51.memo(function SimpleImageBlur2({
13295
13365
  });
13296
13366
 
13297
13367
  // src/layouts/pdp/EdgeBlurBox.tsx
13298
- import React52 from "react";
13299
- import { jsx as jsx80, jsxs as jsxs55 } from "react/jsx-runtime";
13368
+ import React53 from "react";
13369
+ import { jsx as jsx81, jsxs as jsxs55 } from "react/jsx-runtime";
13300
13370
  var BLUR_CONFIG3 = {
13301
13371
  blur: 24,
13302
13372
  crossfade: 60
@@ -13320,7 +13390,7 @@ function getFadeOutMask(crossfadeWidth) {
13320
13390
  transparent 100%
13321
13391
  )`;
13322
13392
  }
13323
- var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13393
+ var EdgeBlurBox = React53.memo(function EdgeBlurBox2({
13324
13394
  imageSrc,
13325
13395
  width,
13326
13396
  height = "100%",
@@ -13346,7 +13416,7 @@ var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13346
13416
  overflow: hasOverlap ? "visible" : "hidden"
13347
13417
  },
13348
13418
  children: [
13349
- /* @__PURE__ */ jsx80(
13419
+ /* @__PURE__ */ jsx81(
13350
13420
  "div",
13351
13421
  {
13352
13422
  style: {
@@ -13360,7 +13430,7 @@ var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13360
13430
  transparent ${100 - (layer.zone * 100 + 10)}%,
13361
13431
  black ${100 - layer.zone * 100}%,
13362
13432
  black 100%)`;
13363
- return /* @__PURE__ */ jsx80(
13433
+ return /* @__PURE__ */ jsx81(
13364
13434
  "img",
13365
13435
  {
13366
13436
  src: imageSrc,
@@ -13388,7 +13458,7 @@ var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13388
13458
  })
13389
13459
  }
13390
13460
  ),
13391
- /* @__PURE__ */ jsx80(
13461
+ /* @__PURE__ */ jsx81(
13392
13462
  "img",
13393
13463
  {
13394
13464
  src: imageSrc,
@@ -13416,8 +13486,8 @@ var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13416
13486
  });
13417
13487
 
13418
13488
  // src/layouts/pdp/ImageBlurExtension.tsx
13419
- import React53 from "react";
13420
- import { jsx as jsx81, jsxs as jsxs56 } from "react/jsx-runtime";
13489
+ import React54 from "react";
13490
+ import { jsx as jsx82, jsxs as jsxs56 } from "react/jsx-runtime";
13421
13491
  var BLUR_CONFIG4 = {
13422
13492
  blur: 24,
13423
13493
  crossfadeWidth: 80
@@ -13440,7 +13510,7 @@ function getFadeOutMask2(crossfadeWidth) {
13440
13510
  transparent 100%
13441
13511
  )`;
13442
13512
  }
13443
- var ImageBlurExtension = React53.memo(function ImageBlurExtension2({
13513
+ var ImageBlurExtension = React54.memo(function ImageBlurExtension2({
13444
13514
  imageSrc,
13445
13515
  width,
13446
13516
  height,
@@ -13463,7 +13533,7 @@ var ImageBlurExtension = React53.memo(function ImageBlurExtension2({
13463
13533
  height: heightValue
13464
13534
  },
13465
13535
  children: [
13466
- BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ jsx81(
13536
+ BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ jsx82(
13467
13537
  "img",
13468
13538
  {
13469
13539
  src: imageSrc,
@@ -13487,7 +13557,7 @@ var ImageBlurExtension = React53.memo(function ImageBlurExtension2({
13487
13557
  },
13488
13558
  `blur-${index}`
13489
13559
  )),
13490
- /* @__PURE__ */ jsx81(
13560
+ /* @__PURE__ */ jsx82(
13491
13561
  "img",
13492
13562
  {
13493
13563
  src: imageSrc,
@@ -13515,23 +13585,23 @@ var ImageBlurExtension = React53.memo(function ImageBlurExtension2({
13515
13585
  });
13516
13586
 
13517
13587
  // src/design-system/ColorSwatch.tsx
13518
- import { jsx as jsx82, jsxs as jsxs57 } from "react/jsx-runtime";
13588
+ import { jsx as jsx83, jsxs as jsxs57 } from "react/jsx-runtime";
13519
13589
  function ColorTokenSwatch({ name, cssVar, className = "" }) {
13520
13590
  return /* @__PURE__ */ jsxs57("div", { className: `flex flex-col gap-1 ${className}`, children: [
13521
- /* @__PURE__ */ jsx82(
13591
+ /* @__PURE__ */ jsx83(
13522
13592
  "div",
13523
13593
  {
13524
13594
  className: "h-16 w-full rounded-lg border border-border shadow-sm",
13525
13595
  style: { backgroundColor: `var(${cssVar})` }
13526
13596
  }
13527
13597
  ),
13528
- /* @__PURE__ */ jsx82("div", { className: "text-sm font-medium text-foreground", children: name }),
13529
- /* @__PURE__ */ jsx82("code", { className: "text-xs text-muted-foreground font-mono", children: cssVar })
13598
+ /* @__PURE__ */ jsx83("div", { className: "text-sm font-medium text-foreground", children: name }),
13599
+ /* @__PURE__ */ jsx83("code", { className: "text-xs text-muted-foreground font-mono", children: cssVar })
13530
13600
  ] });
13531
13601
  }
13532
13602
  function ColorRow({ name, cssVar, description }) {
13533
13603
  return /* @__PURE__ */ jsxs57("div", { className: "flex items-center gap-4 py-2", children: [
13534
- /* @__PURE__ */ jsx82(
13604
+ /* @__PURE__ */ jsx83(
13535
13605
  "div",
13536
13606
  {
13537
13607
  className: "h-10 w-10 rounded-lg border border-border shadow-sm flex-shrink-0",
@@ -13539,15 +13609,15 @@ function ColorRow({ name, cssVar, description }) {
13539
13609
  }
13540
13610
  ),
13541
13611
  /* @__PURE__ */ jsxs57("div", { className: "flex-1 min-w-0", children: [
13542
- /* @__PURE__ */ jsx82("div", { className: "text-sm font-medium text-foreground", children: name }),
13543
- description && /* @__PURE__ */ jsx82("div", { className: "text-xs text-muted-foreground", children: description })
13612
+ /* @__PURE__ */ jsx83("div", { className: "text-sm font-medium text-foreground", children: name }),
13613
+ description && /* @__PURE__ */ jsx83("div", { className: "text-xs text-muted-foreground", children: description })
13544
13614
  ] }),
13545
- /* @__PURE__ */ jsx82("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: cssVar })
13615
+ /* @__PURE__ */ jsx83("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: cssVar })
13546
13616
  ] });
13547
13617
  }
13548
13618
 
13549
13619
  // src/design-system/ColorPalette.tsx
13550
- import { jsx as jsx83, jsxs as jsxs58 } from "react/jsx-runtime";
13620
+ import { jsx as jsx84, jsxs as jsxs58 } from "react/jsx-runtime";
13551
13621
  var COLOR_GROUPS = [
13552
13622
  {
13553
13623
  name: "Base",
@@ -13628,17 +13698,17 @@ var COLOR_GROUPS = [
13628
13698
  }
13629
13699
  ];
13630
13700
  function ColorPalette({ layout = "list", className = "" }) {
13631
- return /* @__PURE__ */ jsx83("div", { className: `space-y-8 ${className}`, children: COLOR_GROUPS.map((group) => /* @__PURE__ */ jsxs58("section", { children: [
13632
- /* @__PURE__ */ jsx83("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
13633
- /* @__PURE__ */ jsx83("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
13634
- layout === "grid" ? /* @__PURE__ */ jsx83("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-4", children: group.colors.map((color) => /* @__PURE__ */ jsx83(
13701
+ return /* @__PURE__ */ jsx84("div", { className: `space-y-8 ${className}`, children: COLOR_GROUPS.map((group) => /* @__PURE__ */ jsxs58("section", { children: [
13702
+ /* @__PURE__ */ jsx84("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
13703
+ /* @__PURE__ */ jsx84("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
13704
+ layout === "grid" ? /* @__PURE__ */ jsx84("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-4", children: group.colors.map((color) => /* @__PURE__ */ jsx84(
13635
13705
  ColorTokenSwatch,
13636
13706
  {
13637
13707
  name: color.name,
13638
13708
  cssVar: color.cssVar
13639
13709
  },
13640
13710
  color.cssVar
13641
- )) }) : /* @__PURE__ */ jsx83("div", { className: "bg-card rounded-lg border border-border p-4 divide-y divide-border", children: group.colors.map((color) => /* @__PURE__ */ jsx83(
13711
+ )) }) : /* @__PURE__ */ jsx84("div", { className: "bg-card rounded-lg border border-border p-4 divide-y divide-border", children: group.colors.map((color) => /* @__PURE__ */ jsx84(
13642
13712
  ColorRow,
13643
13713
  {
13644
13714
  name: color.name,
@@ -13651,7 +13721,7 @@ function ColorPalette({ layout = "list", className = "" }) {
13651
13721
  }
13652
13722
 
13653
13723
  // src/design-system/TypographyScale.tsx
13654
- import { jsx as jsx84, jsxs as jsxs59 } from "react/jsx-runtime";
13724
+ import { jsx as jsx85, jsxs as jsxs59 } from "react/jsx-runtime";
13655
13725
  var FONT_SAMPLES = [
13656
13726
  {
13657
13727
  name: "Heading",
@@ -13685,14 +13755,14 @@ var FONT_SAMPLES = [
13685
13755
  }
13686
13756
  ];
13687
13757
  function TypographyScale({ className = "" }) {
13688
- return /* @__PURE__ */ jsx84("div", { className: `space-y-8 ${className}`, children: FONT_SAMPLES.map((font) => /* @__PURE__ */ jsxs59("section", { className: "bg-card rounded-lg border border-border p-6", children: [
13758
+ return /* @__PURE__ */ jsx85("div", { className: `space-y-8 ${className}`, children: FONT_SAMPLES.map((font) => /* @__PURE__ */ jsxs59("section", { className: "bg-card rounded-lg border border-border p-6", children: [
13689
13759
  /* @__PURE__ */ jsxs59("div", { className: "flex items-center justify-between mb-4", children: [
13690
- /* @__PURE__ */ jsx84("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
13691
- /* @__PURE__ */ jsx84("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: font.cssVar })
13760
+ /* @__PURE__ */ jsx85("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
13761
+ /* @__PURE__ */ jsx85("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: font.cssVar })
13692
13762
  ] }),
13693
- /* @__PURE__ */ jsx84("div", { className: "space-y-4", children: font.sizes.map((size) => /* @__PURE__ */ jsxs59("div", { className: "flex items-baseline gap-4", children: [
13694
- /* @__PURE__ */ jsx84("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
13695
- /* @__PURE__ */ jsx84(
13763
+ /* @__PURE__ */ jsx85("div", { className: "space-y-4", children: font.sizes.map((size) => /* @__PURE__ */ jsxs59("div", { className: "flex items-baseline gap-4", children: [
13764
+ /* @__PURE__ */ jsx85("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
13765
+ /* @__PURE__ */ jsx85(
13696
13766
  "p",
13697
13767
  {
13698
13768
  className: `${size} text-foreground`,
@@ -13711,8 +13781,8 @@ var RADIUS_SAMPLES = [
13711
13781
  { name: "Full", value: "9999px" }
13712
13782
  ];
13713
13783
  function RadiusScale({ className = "" }) {
13714
- return /* @__PURE__ */ jsx84("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ jsx84("div", { className: "grid grid-cols-5 gap-4", children: RADIUS_SAMPLES.map((radius) => /* @__PURE__ */ jsxs59("div", { className: "flex flex-col items-center gap-2", children: [
13715
- /* @__PURE__ */ jsx84(
13784
+ return /* @__PURE__ */ jsx85("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ jsx85("div", { className: "grid grid-cols-5 gap-4", children: RADIUS_SAMPLES.map((radius) => /* @__PURE__ */ jsxs59("div", { className: "flex flex-col items-center gap-2", children: [
13785
+ /* @__PURE__ */ jsx85(
13716
13786
  "div",
13717
13787
  {
13718
13788
  className: "h-16 w-16 bg-primary",
@@ -13721,14 +13791,14 @@ function RadiusScale({ className = "" }) {
13721
13791
  }
13722
13792
  }
13723
13793
  ),
13724
- /* @__PURE__ */ jsx84("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
13725
- /* @__PURE__ */ jsx84("code", { className: "text-xs text-muted-foreground font-mono", children: radius.cssVar || radius.value })
13794
+ /* @__PURE__ */ jsx85("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
13795
+ /* @__PURE__ */ jsx85("code", { className: "text-xs text-muted-foreground font-mono", children: radius.cssVar || radius.value })
13726
13796
  ] }, radius.name)) }) });
13727
13797
  }
13728
13798
 
13729
13799
  // src/design-system/ThemeSwitcher.tsx
13730
- import { useState as useState44, useEffect as useEffect45 } from "react";
13731
- import { Fragment as Fragment18, jsx as jsx85, jsxs as jsxs60 } from "react/jsx-runtime";
13800
+ import { useState as useState45, useEffect as useEffect46 } from "react";
13801
+ import { Fragment as Fragment19, jsx as jsx86, jsxs as jsxs60 } from "react/jsx-runtime";
13732
13802
  function readThemeFromDOM() {
13733
13803
  if (typeof document === "undefined") {
13734
13804
  return { themeName: "Linear", isDark: false };
@@ -13746,10 +13816,10 @@ function readThemeFromDOM() {
13746
13816
  return { themeName: "Linear", isDark: dark };
13747
13817
  }
13748
13818
  function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
13749
- const [currentTheme, setCurrentTheme] = useState44("Linear");
13750
- const [isDark, setIsDark] = useState44(false);
13751
- const [isOpen, setIsOpen] = useState44(false);
13752
- useEffect45(() => {
13819
+ const [currentTheme, setCurrentTheme] = useState45("Linear");
13820
+ const [isDark, setIsDark] = useState45(false);
13821
+ const [isOpen, setIsOpen] = useState45(false);
13822
+ useEffect46(() => {
13753
13823
  const { themeName, isDark: dark } = readThemeFromDOM();
13754
13824
  setCurrentTheme(themeName);
13755
13825
  setIsDark(dark);
@@ -13796,35 +13866,35 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
13796
13866
  onClick: () => setIsOpen(!isOpen),
13797
13867
  className: "flex items-center gap-2 px-4 py-2 bg-card border border-border rounded-lg hover:bg-muted transition-colors text-foreground",
13798
13868
  children: [
13799
- /* @__PURE__ */ jsx85("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx85("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" }) }),
13800
- /* @__PURE__ */ jsx85("span", { className: "font-medium", children: currentTheme }),
13801
- /* @__PURE__ */ jsx85("svg", { className: `w-4 h-4 transition-transform ${isOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx85("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
13869
+ /* @__PURE__ */ jsx86("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx86("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" }) }),
13870
+ /* @__PURE__ */ jsx86("span", { className: "font-medium", children: currentTheme }),
13871
+ /* @__PURE__ */ jsx86("svg", { className: `w-4 h-4 transition-transform ${isOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx86("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
13802
13872
  ]
13803
13873
  }
13804
13874
  ),
13805
- isOpen && /* @__PURE__ */ jsxs60(Fragment18, { children: [
13806
- /* @__PURE__ */ jsx85(
13875
+ isOpen && /* @__PURE__ */ jsxs60(Fragment19, { children: [
13876
+ /* @__PURE__ */ jsx86(
13807
13877
  "div",
13808
13878
  {
13809
13879
  className: "fixed inset-0 z-40",
13810
13880
  onClick: () => setIsOpen(false)
13811
13881
  }
13812
13882
  ),
13813
- /* @__PURE__ */ jsx85("div", { className: "absolute top-full left-0 mt-2 w-56 max-h-80 overflow-auto bg-card border border-border rounded-lg shadow-lg z-50", children: themes.map((theme) => /* @__PURE__ */ jsxs60(
13883
+ /* @__PURE__ */ jsx86("div", { className: "absolute top-full left-0 mt-2 w-56 max-h-80 overflow-auto bg-card border border-border rounded-lg shadow-lg z-50", children: themes.map((theme) => /* @__PURE__ */ jsxs60(
13814
13884
  "button",
13815
13885
  {
13816
13886
  onClick: () => handleThemeSelect(theme.name),
13817
13887
  className: `w-full px-4 py-2 text-left hover:bg-muted transition-colors flex items-center gap-3 ${currentTheme === theme.name ? "bg-muted" : ""}`,
13818
13888
  children: [
13819
- /* @__PURE__ */ jsx85(
13889
+ /* @__PURE__ */ jsx86(
13820
13890
  "div",
13821
13891
  {
13822
13892
  className: "w-4 h-4 rounded-full border border-border",
13823
13893
  style: { backgroundColor: theme.primaryColor || "#888" }
13824
13894
  }
13825
13895
  ),
13826
- /* @__PURE__ */ jsx85("span", { className: "text-foreground", children: theme.name }),
13827
- currentTheme === theme.name && /* @__PURE__ */ jsx85("svg", { className: "w-4 h-4 ml-auto text-primary", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx85("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) })
13896
+ /* @__PURE__ */ jsx86("span", { className: "text-foreground", children: theme.name }),
13897
+ currentTheme === theme.name && /* @__PURE__ */ jsx86("svg", { className: "w-4 h-4 ml-auto text-primary", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx86("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) })
13828
13898
  ]
13829
13899
  },
13830
13900
  theme.name
@@ -13839,10 +13909,10 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
13839
13909
  title: `Switch to ${isDark ? "light" : "dark"} mode`,
13840
13910
  children: [
13841
13911
  isDark ? /* @__PURE__ */ jsxs60("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
13842
- /* @__PURE__ */ jsx85("circle", { cx: "12", cy: "12", r: "5" }),
13843
- /* @__PURE__ */ jsx85("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })
13844
- ] }) : /* @__PURE__ */ jsx85("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx85("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }),
13845
- /* @__PURE__ */ jsx85("span", { className: "text-sm", children: isDark ? "Light" : "Dark" })
13912
+ /* @__PURE__ */ jsx86("circle", { cx: "12", cy: "12", r: "5" }),
13913
+ /* @__PURE__ */ jsx86("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })
13914
+ ] }) : /* @__PURE__ */ jsx86("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx86("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }),
13915
+ /* @__PURE__ */ jsx86("span", { className: "text-sm", children: isDark ? "Light" : "Dark" })
13846
13916
  ]
13847
13917
  }
13848
13918
  )
@@ -13850,7 +13920,7 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
13850
13920
  }
13851
13921
 
13852
13922
  // src/design-system/DesignSystemPage.tsx
13853
- import { jsx as jsx86, jsxs as jsxs61 } from "react/jsx-runtime";
13923
+ import { jsx as jsx87, jsxs as jsxs61 } from "react/jsx-runtime";
13854
13924
  function DesignSystemPage({
13855
13925
  showThemeSwitcher = true,
13856
13926
  showColors = true,
@@ -13861,28 +13931,28 @@ function DesignSystemPage({
13861
13931
  className = ""
13862
13932
  }) {
13863
13933
  return /* @__PURE__ */ jsxs61("div", { className: `max-w-4xl mx-auto px-4 py-8 ${className}`, children: [
13864
- /* @__PURE__ */ jsx86("header", { className: "mb-12", children: /* @__PURE__ */ jsxs61("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4", children: [
13934
+ /* @__PURE__ */ jsx87("header", { className: "mb-12", children: /* @__PURE__ */ jsxs61("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4", children: [
13865
13935
  /* @__PURE__ */ jsxs61("div", { children: [
13866
- /* @__PURE__ */ jsx86("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
13867
- /* @__PURE__ */ jsx86("p", { className: "text-lg text-muted-foreground", children: "Visual reference for theme tokens and styles" })
13936
+ /* @__PURE__ */ jsx87("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
13937
+ /* @__PURE__ */ jsx87("p", { className: "text-lg text-muted-foreground", children: "Visual reference for theme tokens and styles" })
13868
13938
  ] }),
13869
- showThemeSwitcher && /* @__PURE__ */ jsx86(ThemeSwitcher, {})
13939
+ showThemeSwitcher && /* @__PURE__ */ jsx87(ThemeSwitcher, {})
13870
13940
  ] }) }),
13871
13941
  showColors && /* @__PURE__ */ jsxs61("section", { className: "mb-16", children: [
13872
- /* @__PURE__ */ jsx86("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Color Palette" }),
13873
- /* @__PURE__ */ jsx86(ColorPalette, { layout: colorLayout })
13942
+ /* @__PURE__ */ jsx87("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Color Palette" }),
13943
+ /* @__PURE__ */ jsx87(ColorPalette, { layout: colorLayout })
13874
13944
  ] }),
13875
13945
  showTypography && /* @__PURE__ */ jsxs61("section", { className: "mb-16", children: [
13876
- /* @__PURE__ */ jsx86("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
13877
- /* @__PURE__ */ jsx86(TypographyScale, {})
13946
+ /* @__PURE__ */ jsx87("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
13947
+ /* @__PURE__ */ jsx87(TypographyScale, {})
13878
13948
  ] }),
13879
13949
  showRadius && /* @__PURE__ */ jsxs61("section", { className: "mb-16", children: [
13880
- /* @__PURE__ */ jsx86("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Border Radius" }),
13881
- /* @__PURE__ */ jsx86(RadiusScale, {})
13950
+ /* @__PURE__ */ jsx87("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Border Radius" }),
13951
+ /* @__PURE__ */ jsx87(RadiusScale, {})
13882
13952
  ] }),
13883
13953
  showSpacing && /* @__PURE__ */ jsxs61("section", { className: "mb-16", children: [
13884
- /* @__PURE__ */ jsx86("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Spacing Scale" }),
13885
- /* @__PURE__ */ jsx86(SpacingScale, {})
13954
+ /* @__PURE__ */ jsx87("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Spacing Scale" }),
13955
+ /* @__PURE__ */ jsx87(SpacingScale, {})
13886
13956
  ] })
13887
13957
  ] });
13888
13958
  }
@@ -13897,25 +13967,25 @@ function SpacingScale() {
13897
13967
  { name: "12", value: "3rem" },
13898
13968
  { name: "16", value: "4rem" }
13899
13969
  ];
13900
- return /* @__PURE__ */ jsx86("div", { className: "space-y-2", children: spaces.map((space) => /* @__PURE__ */ jsxs61("div", { className: "flex items-center gap-4", children: [
13901
- /* @__PURE__ */ jsx86("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
13902
- /* @__PURE__ */ jsx86(
13970
+ return /* @__PURE__ */ jsx87("div", { className: "space-y-2", children: spaces.map((space) => /* @__PURE__ */ jsxs61("div", { className: "flex items-center gap-4", children: [
13971
+ /* @__PURE__ */ jsx87("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
13972
+ /* @__PURE__ */ jsx87(
13903
13973
  "div",
13904
13974
  {
13905
13975
  className: "h-4 bg-primary rounded",
13906
13976
  style: { width: space.value }
13907
13977
  }
13908
13978
  ),
13909
- /* @__PURE__ */ jsx86("span", { className: "text-sm text-muted-foreground", children: space.value })
13979
+ /* @__PURE__ */ jsx87("span", { className: "text-sm text-muted-foreground", children: space.value })
13910
13980
  ] }, space.name)) });
13911
13981
  }
13912
13982
 
13913
13983
  // src/personalization/PersonalizationProvider.tsx
13914
- import React54, {
13915
- useState as useState45,
13984
+ import React55, {
13985
+ useState as useState46,
13916
13986
  useCallback as useCallback26,
13917
13987
  useRef as useRef30,
13918
- useEffect as useEffect46
13988
+ useEffect as useEffect47
13919
13989
  } from "react";
13920
13990
 
13921
13991
  // src/personalization/PersonalizationContext.ts
@@ -13926,18 +13996,18 @@ function usePersonalizationContext() {
13926
13996
  }
13927
13997
 
13928
13998
  // src/personalization/PersonalizationProvider.tsx
13929
- import { Fragment as Fragment19, jsx as jsx87, jsxs as jsxs62 } from "react/jsx-runtime";
13999
+ import { Fragment as Fragment20, jsx as jsx88, jsxs as jsxs62 } from "react/jsx-runtime";
13930
14000
  function createBridgeFromCanvas(canvasModule) {
13931
14001
  const { useEditor, useCommands, useImageBinding } = canvasModule;
13932
14002
  function TextBinder({ name, value }) {
13933
14003
  const { elements } = useEditor();
13934
14004
  const { executeElementUpdate } = useCommands();
13935
- const elementsRef = React54.useRef(elements);
14005
+ const elementsRef = React55.useRef(elements);
13936
14006
  elementsRef.current = elements;
13937
- const executeRef = React54.useRef(executeElementUpdate);
14007
+ const executeRef = React55.useRef(executeElementUpdate);
13938
14008
  executeRef.current = executeElementUpdate;
13939
- const hasUserInput = React54.useRef(false);
13940
- React54.useEffect(() => {
14009
+ const hasUserInput = React55.useRef(false);
14010
+ React55.useEffect(() => {
13941
14011
  if (value == null) return;
13942
14012
  if (value === "" && !hasUserInput.current) return;
13943
14013
  hasUserInput.current = true;
@@ -13955,12 +14025,12 @@ function createBridgeFromCanvas(canvasModule) {
13955
14025
  function ColorBinder({ originalColor, newColor }) {
13956
14026
  const { elements } = useEditor();
13957
14027
  const { executeElementUpdate } = useCommands();
13958
- const elementsRef = React54.useRef(elements);
14028
+ const elementsRef = React55.useRef(elements);
13959
14029
  elementsRef.current = elements;
13960
- const executeRef = React54.useRef(executeElementUpdate);
14030
+ const executeRef = React55.useRef(executeElementUpdate);
13961
14031
  executeRef.current = executeElementUpdate;
13962
- const appliedColorRef = React54.useRef(normalizeHex(originalColor));
13963
- React54.useEffect(() => {
14032
+ const appliedColorRef = React55.useRef(normalizeHex(originalColor));
14033
+ React55.useEffect(() => {
13964
14034
  const normalizedNew = normalizeHex(newColor);
13965
14035
  if (normalizedNew === appliedColorRef.current) return;
13966
14036
  const matchColor = appliedColorRef.current;
@@ -14000,11 +14070,11 @@ function createBridgeFromCanvas(canvasModule) {
14000
14070
  }
14001
14071
  function ImageBinder({ name, value, fit = "cover" }) {
14002
14072
  const { setImageUrl } = useImageBinding(name, { fit });
14003
- const hasUserInput = React54.useRef(false);
14073
+ const hasUserInput = React55.useRef(false);
14004
14074
  const debouncedValue = useDebouncedValue(value, 500);
14005
- const setImageUrlRef = React54.useRef(setImageUrl);
14075
+ const setImageUrlRef = React55.useRef(setImageUrl);
14006
14076
  setImageUrlRef.current = setImageUrl;
14007
- React54.useEffect(() => {
14077
+ React55.useEffect(() => {
14008
14078
  if (debouncedValue == null) return;
14009
14079
  if (debouncedValue === "" && !hasUserInput.current) return;
14010
14080
  hasUserInput.current = true;
@@ -14014,15 +14084,15 @@ function createBridgeFromCanvas(canvasModule) {
14014
14084
  return null;
14015
14085
  }
14016
14086
  return function PersonalizationBridge({ fields = [], values = {} } = {}) {
14017
- return /* @__PURE__ */ jsx87(Fragment19, { children: fields.map((field) => {
14087
+ return /* @__PURE__ */ jsx88(Fragment20, { children: fields.map((field) => {
14018
14088
  if (field.type === "text") {
14019
- return /* @__PURE__ */ jsx87(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
14089
+ return /* @__PURE__ */ jsx88(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
14020
14090
  }
14021
14091
  if (field.type === "color") {
14022
- return /* @__PURE__ */ jsx87(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
14092
+ return /* @__PURE__ */ jsx88(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
14023
14093
  }
14024
14094
  if (field.type === "image") {
14025
- return /* @__PURE__ */ jsx87(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
14095
+ return /* @__PURE__ */ jsx88(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
14026
14096
  }
14027
14097
  return null;
14028
14098
  }) });
@@ -14044,19 +14114,19 @@ function PersonalizationProvider({
14044
14114
  children
14045
14115
  }) {
14046
14116
  const realtime = useRealtimeOptional();
14047
- const [personValues, setPersonValues] = useState45(initialValues ?? {});
14048
- const [isActive, setIsActive] = useState45(!!(initialValues && Object.keys(initialValues).length > 0));
14049
- const [isExporting, setIsExporting] = useState45(false);
14050
- const [exportedBlobUrls, setExportedBlobUrls] = useState45({});
14051
- const [exportCount, setExportCount] = useState45(0);
14117
+ const [personValues, setPersonValues] = useState46(initialValues ?? {});
14118
+ const [isActive, setIsActive] = useState46(!!(initialValues && Object.keys(initialValues).length > 0));
14119
+ const [isExporting, setIsExporting] = useState46(false);
14120
+ const [exportedBlobUrls, setExportedBlobUrls] = useState46({});
14121
+ const [exportCount, setExportCount] = useState46(0);
14052
14122
  const blobUrlsRef = useRef30({});
14053
- const [CanvasComponent, setCanvasComponent] = useState45(
14123
+ const [CanvasComponent, setCanvasComponent] = useState46(
14054
14124
  cachedCanvasComponent
14055
14125
  );
14056
- const [BridgeComponent, setBridgeComponent] = useState45(
14126
+ const [BridgeComponent, setBridgeComponent] = useState46(
14057
14127
  cachedBridgeComponent
14058
14128
  );
14059
- useEffect46(() => {
14129
+ useEffect47(() => {
14060
14130
  if (CanvasComponent && BridgeComponent) return;
14061
14131
  if (!canvasImport) return;
14062
14132
  if (!canvasLoadPromise) {
@@ -14075,7 +14145,7 @@ function PersonalizationProvider({
14075
14145
  });
14076
14146
  }, [CanvasComponent, BridgeComponent, canvasImport]);
14077
14147
  const realtimeEnabledRef = useRef30(false);
14078
- useEffect46(() => {
14148
+ useEffect47(() => {
14079
14149
  return () => {
14080
14150
  for (const url of Object.values(blobUrlsRef.current)) {
14081
14151
  try {
@@ -14132,7 +14202,7 @@ function PersonalizationProvider({
14132
14202
  setIsExporting(true);
14133
14203
  }, []);
14134
14204
  const shouldMountCanvas = CanvasComponent && BridgeComponent && canvasState?.elements && canvasState.elements.length > 0 && (!lazy || isActive);
14135
- const contextValue = React54.useMemo(
14205
+ const contextValue = React55.useMemo(
14136
14206
  () => ({
14137
14207
  fields,
14138
14208
  personValues,
@@ -14146,7 +14216,7 @@ function PersonalizationProvider({
14146
14216
  [fields, personValues, updateField, isActive, isExporting, exportedBlobUrls, exportCount, reset]
14147
14217
  );
14148
14218
  return /* @__PURE__ */ jsxs62(PersonalizationContext.Provider, { value: contextValue, children: [
14149
- shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ jsx87(
14219
+ shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ jsx88(
14150
14220
  "div",
14151
14221
  {
14152
14222
  style: {
@@ -14159,7 +14229,7 @@ function PersonalizationProvider({
14159
14229
  pointerEvents: "none"
14160
14230
  },
14161
14231
  "aria-hidden": true,
14162
- children: /* @__PURE__ */ jsx87(
14232
+ children: /* @__PURE__ */ jsx88(
14163
14233
  CanvasComponent,
14164
14234
  {
14165
14235
  initialElements: canvasState?.elements,
@@ -14179,7 +14249,7 @@ function PersonalizationProvider({
14179
14249
  exportImageQuality: exportConfig?.imageQuality ?? 0.85,
14180
14250
  onExport: handleExport,
14181
14251
  onExportScheduled: handleExportScheduled,
14182
- overlay: /* @__PURE__ */ jsx87(BridgeComponent, { fields, values: personValues })
14252
+ overlay: /* @__PURE__ */ jsx88(BridgeComponent, { fields, values: personValues })
14183
14253
  }
14184
14254
  )
14185
14255
  },
@@ -14204,7 +14274,7 @@ function usePersonalizationOptional() {
14204
14274
  }
14205
14275
 
14206
14276
  // src/personalization/PersonalizationInputs.tsx
14207
- import { jsx as jsx88, jsxs as jsxs63 } from "react/jsx-runtime";
14277
+ import { jsx as jsx89, jsxs as jsxs63 } from "react/jsx-runtime";
14208
14278
  function PersonalizationInputs({
14209
14279
  className,
14210
14280
  inputClassName = "w-full px-4 py-3 rounded-lg border text-base text-foreground placeholder:text-muted-foreground bg-white/50 outline-none focus:ring-2 focus:ring-foreground/20",
@@ -14229,7 +14299,7 @@ function PersonalizationInputs({
14229
14299
  }
14230
14300
  };
14231
14301
  return /* @__PURE__ */ jsxs63("div", { className: className || "flex flex-col gap-3", children: [
14232
- textFields.map((field) => /* @__PURE__ */ jsx88(
14302
+ textFields.map((field) => /* @__PURE__ */ jsx89(
14233
14303
  "input",
14234
14304
  {
14235
14305
  type: "text",
@@ -14244,7 +14314,7 @@ function PersonalizationInputs({
14244
14314
  `text-${field.name}`
14245
14315
  )),
14246
14316
  colorFields.map((field) => /* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-3", children: [
14247
- /* @__PURE__ */ jsx88(
14317
+ /* @__PURE__ */ jsx89(
14248
14318
  "input",
14249
14319
  {
14250
14320
  type: "color",
@@ -14253,9 +14323,9 @@ function PersonalizationInputs({
14253
14323
  onChange: (e) => updateField(field.color, e.target.value)
14254
14324
  }
14255
14325
  ),
14256
- /* @__PURE__ */ jsx88("span", { className: "text-base text-muted-foreground", children: field.label })
14326
+ /* @__PURE__ */ jsx89("span", { className: "text-base text-muted-foreground", children: field.label })
14257
14327
  ] }, `color-${field.color}`)),
14258
- imageFields.map((field) => /* @__PURE__ */ jsx88(
14328
+ imageFields.map((field) => /* @__PURE__ */ jsx89(
14259
14329
  "input",
14260
14330
  {
14261
14331
  type: "text",
@@ -14273,11 +14343,11 @@ function PersonalizationInputs({
14273
14343
  }
14274
14344
 
14275
14345
  // src/personalization/usePersonalizationShimmer.ts
14276
- import { useState as useState46, useEffect as useEffect47, useRef as useRef31, useCallback as useCallback27 } from "react";
14346
+ import { useState as useState47, useEffect as useEffect48, useRef as useRef31, useCallback as useCallback27 } from "react";
14277
14347
  function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
14278
14348
  const personCtx = usePersonalizationContext();
14279
14349
  const realtime = useRealtimeOptional();
14280
- const [shimmerActive, setShimmerActive] = useState46(false);
14350
+ const [shimmerActive, setShimmerActive] = useState47(false);
14281
14351
  const sdkSettledRef = useRef31(false);
14282
14352
  const manualTriggerRef = useRef31(false);
14283
14353
  const safetyTimeoutRef = useRef31(void 0);
@@ -14293,7 +14363,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
14293
14363
  safetyTimeoutMs
14294
14364
  );
14295
14365
  }, [safetyTimeoutMs]);
14296
- useEffect47(() => {
14366
+ useEffect48(() => {
14297
14367
  if (!personCtx?.isActive) return;
14298
14368
  sdkSettledRef.current = false;
14299
14369
  manualTriggerRef.current = false;
@@ -14305,13 +14375,13 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
14305
14375
  manualTriggerRef.current = true;
14306
14376
  startShimmer();
14307
14377
  }, [startShimmer]);
14308
- useEffect47(() => {
14378
+ useEffect48(() => {
14309
14379
  if (!realtime?.subscribePipelineSettled) return;
14310
14380
  return realtime.subscribePipelineSettled(() => {
14311
14381
  sdkSettledRef.current = true;
14312
14382
  });
14313
14383
  }, [realtime]);
14314
- useEffect47(() => {
14384
+ useEffect48(() => {
14315
14385
  const container = containerRef.current;
14316
14386
  if (!container) return;
14317
14387
  const observer = new MutationObserver((mutations) => {
@@ -14354,7 +14424,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
14354
14424
  });
14355
14425
  return () => observer.disconnect();
14356
14426
  }, [containerRef]);
14357
- useEffect47(() => {
14427
+ useEffect48(() => {
14358
14428
  return () => {
14359
14429
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
14360
14430
  };
@@ -14495,6 +14565,7 @@ export {
14495
14565
  RealtimeProvider,
14496
14566
  ResponsiveZoom,
14497
14567
  RightToLeftProgressiveBlur,
14568
+ SafeImg,
14498
14569
  ScrollFade,
14499
14570
  SearchBox,
14500
14571
  SearchProvider,