@snowcone-app/ui 0.3.1 → 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
@@ -5624,8 +5624,8 @@ function RealtimeProvider({
5624
5624
  },
5625
5625
  onAllMockupsRendered: (results) => {
5626
5626
  },
5627
- onError: (error) => {
5628
- console.error("[RealtimeProvider] Error:", error);
5627
+ onError: (error, detail) => {
5628
+ console.error(`[RealtimeProvider] Render error [${detail.code}]:`, error);
5629
5629
  }
5630
5630
  });
5631
5631
  const subscribeRTCTiming = useCallback10((_callback) => {
@@ -5635,6 +5635,7 @@ function RealtimeProvider({
5635
5635
  const {
5636
5636
  isConnected,
5637
5637
  isConfigured,
5638
+ renderError,
5638
5639
  mockupResults: rawMockupResults,
5639
5640
  sendCanvasBlob: sendCanvasBlobRaw,
5640
5641
  sendCanvasState: sendCanvasStateRaw,
@@ -6154,6 +6155,7 @@ function RealtimeProvider({
6154
6155
  isEnabled,
6155
6156
  isConnected,
6156
6157
  isConfigured,
6158
+ renderError,
6157
6159
  // Read from ref - this is a snapshot at render time, NOT reactive
6158
6160
  // For reactive updates, use getMockupResultsImmediate() or subscribe functions
6159
6161
  get mockupResults() {
@@ -6197,6 +6199,7 @@ function RealtimeProvider({
6197
6199
  isEnabled,
6198
6200
  isConnected,
6199
6201
  isConfigured,
6202
+ renderError,
6200
6203
  // mockupResults removed from deps - it's a getter that reads from ref
6201
6204
  canvasExportSize,
6202
6205
  mockupWidth,
@@ -10097,12 +10100,18 @@ var HeroProductImage = memo3(function HeroProductImage2({
10097
10100
  const [showNew, setShowNew] = useState31(false);
10098
10101
  const [renderedUrl, setRenderedUrl] = useState31(displayUrl);
10099
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);
10100
10107
  const prevDisplayUrlRef = useRef23(displayUrl);
10101
10108
  const signHintShownRef = useRef23(false);
10102
10109
  useEffect32(() => {
10103
10110
  if (!displayUrl || displayUrl === prevDisplayUrlRef.current) return;
10104
10111
  const oldUrl = prevDisplayUrlRef.current;
10105
10112
  prevDisplayUrlRef.current = displayUrl;
10113
+ setImgFailed(false);
10114
+ retriedUrlRef.current = null;
10106
10115
  if (!oldUrl) {
10107
10116
  setRenderedUrl(displayUrl);
10108
10117
  return;
@@ -10128,6 +10137,7 @@ var HeroProductImage = memo3(function HeroProductImage2({
10128
10137
  setPrevUrl(null);
10129
10138
  setShowNew(false);
10130
10139
  }, []);
10140
+ const handleLoaderExited = useCallback18(() => setLoaderMounted(false), []);
10131
10141
  if (!hasArtwork) {
10132
10142
  return /* @__PURE__ */ jsx60(
10133
10143
  "div",
@@ -10176,19 +10186,19 @@ var HeroProductImage = memo3(function HeroProductImage2({
10176
10186
  style,
10177
10187
  "data-hero-image": "true",
10178
10188
  children: [
10179
- !firstImageLoaded && /* @__PURE__ */ jsx60("div", { className: "absolute inset-0 bg-muted-foreground/20 animate-pulse" }),
10180
- renderedUrl && /* @__PURE__ */ jsx60(
10189
+ renderedUrl && !imgFailed && /* @__PURE__ */ jsx60(
10181
10190
  "img",
10182
10191
  {
10183
10192
  alt: `Product mockup${placement ? ` - ${placement}` : ""}`,
10184
10193
  crossOrigin: "anonymous",
10185
10194
  className: "absolute inset-0 w-full h-full object-cover",
10186
10195
  draggable,
10187
- src: renderedUrl,
10196
+ src: retriedUrlRef.current === renderedUrl ? `${renderedUrl}${renderedUrl.includes("?") ? "&" : "?"}_cb=${retryNonce}` : renderedUrl,
10188
10197
  loading: "eager",
10189
10198
  fetchPriority: "high",
10190
10199
  onClick,
10191
10200
  onLoad: () => {
10201
+ setImgFailed(false);
10192
10202
  setFirstImageLoaded(true);
10193
10203
  if (!onLoadCalledRef.current && onLoad) {
10194
10204
  onLoadCalledRef.current = true;
@@ -10197,6 +10207,12 @@ var HeroProductImage = memo3(function HeroProductImage2({
10197
10207
  onUrlGeneratedRef.current?.(renderedUrl);
10198
10208
  },
10199
10209
  onError: () => {
10210
+ if (renderedUrl && retriedUrlRef.current !== renderedUrl) {
10211
+ retriedUrlRef.current = renderedUrl;
10212
+ setRetryNonce((n) => n + 1);
10213
+ return;
10214
+ }
10215
+ setImgFailed(true);
10200
10216
  setFirstImageLoaded(true);
10201
10217
  onError?.();
10202
10218
  if (process.env.NODE_ENV !== "production" && !signHintShownRef.current && renderedUrl && /\/[A-Za-z0-9]+\?/.test(renderedUrl) && !/[?&]signature=/.test(renderedUrl)) {
@@ -10209,6 +10225,16 @@ var HeroProductImage = memo3(function HeroProductImage2({
10209
10225
  }
10210
10226
  }
10211
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" }) }),
10229
+ realtimeContext?.renderError && /* @__PURE__ */ jsx60(
10230
+ "div",
10231
+ {
10232
+ role: "alert",
10233
+ "data-render-error": realtimeContext.renderError.code,
10234
+ className: "absolute inset-x-0 bottom-0 z-20 bg-red-600/90 text-white text-xs font-medium px-3 py-2 pointer-events-none",
10235
+ children: `Render blocked: ${realtimeContext.renderError.code} \u2014 ${realtimeContext.renderError.message}`
10236
+ }
10237
+ ),
10212
10238
  prevUrl && /* @__PURE__ */ jsx60(
10213
10239
  "img",
10214
10240
  {
@@ -10223,12 +10249,45 @@ var HeroProductImage = memo3(function HeroProductImage2({
10223
10249
  },
10224
10250
  onTransitionEnd: handleCrossfadeEnd
10225
10251
  }
10252
+ ),
10253
+ loaderMounted && /* @__PURE__ */ jsx60(
10254
+ LoadingOverlayPrismCandyInline,
10255
+ {
10256
+ visible: !firstImageLoaded,
10257
+ variant: "light",
10258
+ onExited: handleLoaderExited
10259
+ }
10226
10260
  )
10227
10261
  ]
10228
10262
  }
10229
10263
  );
10230
10264
  });
10231
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
+
10232
10291
  // src/index.ts
10233
10292
  import {
10234
10293
  describeProductArtAlignment as describeProductArtAlignment2,
@@ -10241,7 +10300,7 @@ import { InstantSearch, Configure, useSearchBox } from "react-instantsearch";
10241
10300
  // src/composed/search/meilisearchAdapter.ts
10242
10301
  import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";
10243
10302
  var MEILISEARCH_HOST = readEnv("NEXT_PUBLIC_MEILISEARCH_HOST") || "https://ms-e5d999b2eaca-15654.sfo.meilisearch.io";
10244
- var MEILISEARCH_API_KEY = readEnv("NEXT_PUBLIC_MEILISEARCH_API_KEY") || "eee819b849798ad9091228c486ec05d0931e5292";
10303
+ var MEILISEARCH_API_KEY = readEnv("NEXT_PUBLIC_MEILISEARCH_API_KEY") || "4a11f6599e39af365f6289dab46b77a30ef78ba1ac078f7d74e152c099b3b63c";
10245
10304
  var { searchClient } = instantMeiliSearch(
10246
10305
  MEILISEARCH_HOST,
10247
10306
  MEILISEARCH_API_KEY,
@@ -10252,11 +10311,11 @@ var { searchClient } = instantMeiliSearch(
10252
10311
  );
10253
10312
 
10254
10313
  // src/composed/search/SearchProvider.tsx
10255
- import { useEffect as useEffect33 } from "react";
10256
- 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";
10257
10316
  function InitialSearchTrigger() {
10258
10317
  const { refine } = useSearchBox();
10259
- useEffect33(() => {
10318
+ useEffect34(() => {
10260
10319
  refine("");
10261
10320
  }, [refine]);
10262
10321
  return null;
@@ -10308,7 +10367,7 @@ function SearchProvider({
10308
10367
  }
10309
10368
  },
10310
10369
  children: [
10311
- /* @__PURE__ */ jsx61(
10370
+ /* @__PURE__ */ jsx62(
10312
10371
  Configure,
10313
10372
  {
10314
10373
  hitsPerPage,
@@ -10317,7 +10376,7 @@ function SearchProvider({
10317
10376
  attributesToRetrieve
10318
10377
  }
10319
10378
  ),
10320
- /* @__PURE__ */ jsx61(InitialSearchTrigger, {}),
10379
+ /* @__PURE__ */ jsx62(InitialSearchTrigger, {}),
10321
10380
  children
10322
10381
  ]
10323
10382
  }
@@ -10327,17 +10386,17 @@ function SearchProvider({
10327
10386
  // src/composed/search/SearchBox.tsx
10328
10387
  import { useSearchBox as useSearchBox2 } from "react-instantsearch";
10329
10388
  import { Search, X } from "lucide-react";
10330
- import { useEffect as useEffect34, useRef as useRef24, useState as useState32 } from "react";
10331
- 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";
10332
10391
  function SearchBox() {
10333
10392
  const { query, refine, clear } = useSearchBox2();
10334
10393
  const searchParams = useUiSearchParams();
10335
10394
  const router = useUiRouter();
10336
10395
  const inputRef = useRef24(null);
10337
- const [showShimmer, setShowShimmer] = useState32(false);
10396
+ const [showShimmer, setShowShimmer] = useState33(false);
10338
10397
  const inputId = "search-products-input";
10339
10398
  const descriptionId = "search-description";
10340
- useEffect34(() => {
10399
+ useEffect35(() => {
10341
10400
  const handleSpotlight = () => {
10342
10401
  inputRef.current?.focus();
10343
10402
  inputRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
@@ -10347,7 +10406,7 @@ function SearchBox() {
10347
10406
  window.addEventListener("search-spotlight", handleSpotlight);
10348
10407
  return () => window.removeEventListener("search-spotlight", handleSpotlight);
10349
10408
  }, []);
10350
- useEffect34(() => {
10409
+ useEffect35(() => {
10351
10410
  const shouldFocus = searchParams.get("focus") === "search";
10352
10411
  if (shouldFocus && inputRef.current) {
10353
10412
  const timer = setTimeout(() => {
@@ -10362,8 +10421,8 @@ function SearchBox() {
10362
10421
  return () => clearTimeout(timer);
10363
10422
  }
10364
10423
  }, [searchParams, router]);
10365
- return /* @__PURE__ */ jsx62("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ jsxs41("div", { className: "relative", children: [
10366
- /* @__PURE__ */ jsx62(
10424
+ return /* @__PURE__ */ jsx63("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ jsxs41("div", { className: "relative", children: [
10425
+ /* @__PURE__ */ jsx63(
10367
10426
  Input,
10368
10427
  {
10369
10428
  ref: inputRef,
@@ -10372,15 +10431,15 @@ function SearchBox() {
10372
10431
  value: query,
10373
10432
  onChange: (e) => refine(e.target.value),
10374
10433
  placeholder: "Search products...",
10375
- startContent: /* @__PURE__ */ jsx62(Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10376
- 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(
10377
10436
  "button",
10378
10437
  {
10379
10438
  type: "button",
10380
10439
  onClick: clear,
10381
10440
  className: "hover:text-foreground transition-colors",
10382
10441
  "aria-label": "Clear search",
10383
- 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" })
10384
10443
  }
10385
10444
  ) : void 0,
10386
10445
  "aria-label": "Search products",
@@ -10390,11 +10449,11 @@ function SearchBox() {
10390
10449
  className: "[&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden"
10391
10450
  }
10392
10451
  ),
10393
- showShimmer && /* @__PURE__ */ jsx62(
10452
+ showShimmer && /* @__PURE__ */ jsx63(
10394
10453
  "div",
10395
10454
  {
10396
10455
  className: "absolute inset-0 pointer-events-none rounded-input z-20 overflow-hidden",
10397
- children: /* @__PURE__ */ jsx62(
10456
+ children: /* @__PURE__ */ jsx63(
10398
10457
  "div",
10399
10458
  {
10400
10459
  className: "absolute inset-0",
@@ -10407,13 +10466,13 @@ function SearchBox() {
10407
10466
  )
10408
10467
  }
10409
10468
  ),
10410
- /* @__PURE__ */ jsx62("style", { dangerouslySetInnerHTML: { __html: `
10469
+ /* @__PURE__ */ jsx63("style", { dangerouslySetInnerHTML: { __html: `
10411
10470
  @keyframes searchShimmer {
10412
10471
  0% { transform: translateX(-100%); }
10413
10472
  100% { transform: translateX(100%); }
10414
10473
  }
10415
10474
  ` } }),
10416
- /* @__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" })
10417
10476
  ] }) });
10418
10477
  }
10419
10478
 
@@ -10421,7 +10480,7 @@ function SearchBox() {
10421
10480
  import { Hits, useStats, useInstantSearch } from "react-instantsearch";
10422
10481
 
10423
10482
  // src/composed/search/ProductHit.tsx
10424
- import { jsx as jsx63 } from "react/jsx-runtime";
10483
+ import { jsx as jsx64 } from "react/jsx-runtime";
10425
10484
  function ProductHitComponent({
10426
10485
  hit: product,
10427
10486
  variant = "overlay"
@@ -10438,12 +10497,12 @@ function ProductHitComponent({
10438
10497
  }
10439
10498
  return "";
10440
10499
  };
10441
- return /* @__PURE__ */ jsx63(
10500
+ return /* @__PURE__ */ jsx64(
10442
10501
  Product,
10443
10502
  {
10444
10503
  productId,
10445
10504
  productData: product,
10446
- children: /* @__PURE__ */ jsx63(
10505
+ children: /* @__PURE__ */ jsx64(
10447
10506
  ProductCard,
10448
10507
  {
10449
10508
  variant,
@@ -10464,10 +10523,10 @@ function ProductHitComponent({
10464
10523
  }
10465
10524
 
10466
10525
  // src/composed/search/ProductGrid.tsx
10467
- import { useState as useState33, useEffect as useEffect35, useCallback as useCallback19 } from "react";
10468
- 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";
10469
10528
  function ProductGridSkeletonItem() {
10470
- return /* @__PURE__ */ jsx64("div", { className: "aspect-square bg-muted animate-pulse" });
10529
+ return /* @__PURE__ */ jsx65("div", { className: "aspect-square bg-muted animate-pulse" });
10471
10530
  }
10472
10531
  function ProductGrid({
10473
10532
  className = "",
@@ -10477,16 +10536,16 @@ function ProductGrid({
10477
10536
  }) {
10478
10537
  const { nbHits } = useStats();
10479
10538
  const { status, results } = useInstantSearch();
10480
- const [announcement, setAnnouncement] = useState33("");
10539
+ const [announcement, setAnnouncement] = useState34("");
10481
10540
  const hitsCount = results?.hits?.length ?? 0;
10482
10541
  const showSkeleton = hitsCount === 0 && status !== "error";
10483
- useEffect35(() => {
10542
+ useEffect36(() => {
10484
10543
  const timer = setTimeout(() => {
10485
10544
  setAnnouncement(`${nbHits} ${nbHits === 1 ? "product" : "products"} found`);
10486
10545
  }, 1e3);
10487
10546
  return () => clearTimeout(timer);
10488
10547
  }, [nbHits]);
10489
- const HitComponent = useCallback19(({ hit }) => /* @__PURE__ */ jsx64(
10548
+ const HitComponent = useCallback19(({ hit }) => /* @__PURE__ */ jsx65(
10490
10549
  ProductHitComponent,
10491
10550
  {
10492
10551
  hit,
@@ -10494,9 +10553,9 @@ function ProductGrid({
10494
10553
  }
10495
10554
  ), [variant]);
10496
10555
  return /* @__PURE__ */ jsxs42("div", { className, children: [
10497
- /* @__PURE__ */ jsx64("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10498
- showSkeleton && /* @__PURE__ */ jsx64("div", { className: `grid ${gridClassName}`, children: Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ jsx64(ProductGridSkeletonItem, {}, i)) }),
10499
- /* @__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(
10500
10559
  Hits,
10501
10560
  {
10502
10561
  hitComponent: HitComponent,
@@ -10511,11 +10570,11 @@ function ProductGrid({
10511
10570
  }
10512
10571
 
10513
10572
  // src/composed/search/Filters.tsx
10514
- import { useState as useState35 } from "react";
10573
+ import { useState as useState36 } from "react";
10515
10574
 
10516
10575
  // src/composed/search/FiltersButton.tsx
10517
10576
  import { SlidersHorizontal as LucideSlidersHorizontal } from "lucide-react";
10518
- import { jsx as jsx65, jsxs as jsxs43 } from "react/jsx-runtime";
10577
+ import { jsx as jsx66, jsxs as jsxs43 } from "react/jsx-runtime";
10519
10578
  var SlidersHorizontalIcon = LucideSlidersHorizontal;
10520
10579
  function FiltersButton({
10521
10580
  onClick,
@@ -10530,8 +10589,8 @@ function FiltersButton({
10530
10589
  className,
10531
10590
  "aria-label": "Open filters",
10532
10591
  children: [
10533
- /* @__PURE__ */ jsx65(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10534
- /* @__PURE__ */ jsx65("span", { children })
10592
+ /* @__PURE__ */ jsx66(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10593
+ /* @__PURE__ */ jsx66("span", { children })
10535
10594
  ]
10536
10595
  }
10537
10596
  );
@@ -10540,15 +10599,15 @@ function FiltersButton({
10540
10599
  // src/composed/search/FiltersDrawer.tsx
10541
10600
  import { useRefinementList, useRange, useStats as useStats2 } from "react-instantsearch";
10542
10601
  import { X as LucideX2, SlidersHorizontal as LucideSlidersHorizontal2 } from "lucide-react";
10543
- import { useState as useState34, useEffect as useEffect36 } from "react";
10602
+ import { useState as useState35, useEffect as useEffect37 } from "react";
10544
10603
  import * as Slider2 from "@radix-ui/react-slider";
10545
- 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";
10546
10605
  var XIcon2 = LucideX2;
10547
10606
  function FiltersDrawer({ isOpen, onClose }) {
10548
- const [showCounts, setShowCounts] = useState34(false);
10607
+ const [showCounts, setShowCounts] = useState35(false);
10549
10608
  const { nbHits } = useStats2();
10550
10609
  const containerRef = useFocusTrap(isOpen, onClose);
10551
- useEffect36(() => {
10610
+ useEffect37(() => {
10552
10611
  if (isOpen) {
10553
10612
  document.body.style.overflow = "hidden";
10554
10613
  } else {
@@ -10558,7 +10617,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10558
10617
  document.body.style.overflow = "";
10559
10618
  };
10560
10619
  }, [isOpen]);
10561
- useEffect36(() => {
10620
+ useEffect37(() => {
10562
10621
  const handleEscape = (e) => {
10563
10622
  if (e.key === "Escape" && isOpen) {
10564
10623
  onClose();
@@ -10567,8 +10626,8 @@ function FiltersDrawer({ isOpen, onClose }) {
10567
10626
  document.addEventListener("keydown", handleEscape);
10568
10627
  return () => document.removeEventListener("keydown", handleEscape);
10569
10628
  }, [isOpen, onClose]);
10570
- return /* @__PURE__ */ jsxs44(Fragment12, { children: [
10571
- /* @__PURE__ */ jsx66(
10629
+ return /* @__PURE__ */ jsxs44(Fragment13, { children: [
10630
+ /* @__PURE__ */ jsx67(
10572
10631
  "div",
10573
10632
  {
10574
10633
  className: `fixed inset-0 bg-black/50 z-40 transition-opacity ${isOpen ? "opacity-100" : "opacity-0 pointer-events-none"}`,
@@ -10586,25 +10645,25 @@ function FiltersDrawer({ isOpen, onClose }) {
10586
10645
  "aria-labelledby": "filters-drawer-title",
10587
10646
  children: [
10588
10647
  /* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-between px-4 py-4", children: [
10589
- /* @__PURE__ */ jsx66("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10590
- /* @__PURE__ */ jsx66(
10648
+ /* @__PURE__ */ jsx67("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10649
+ /* @__PURE__ */ jsx67(
10591
10650
  "button",
10592
10651
  {
10593
10652
  onClick: onClose,
10594
10653
  className: "p-2 hover:bg-foreground/5 rounded-full transition-colors",
10595
10654
  "aria-label": "Close filters",
10596
- children: /* @__PURE__ */ jsx66(XIcon2, { className: "w-5 h-5" })
10655
+ children: /* @__PURE__ */ jsx67(XIcon2, { className: "w-5 h-5" })
10597
10656
  }
10598
10657
  )
10599
10658
  ] }),
10600
- /* @__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: [
10601
10660
  nbHits.toLocaleString(),
10602
10661
  " ",
10603
10662
  nbHits === 1 ? "result" : "results"
10604
10663
  ] }) }),
10605
- /* @__PURE__ */ jsx66("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: /* @__PURE__ */ jsxs44("div", { className: "flex flex-col gap-8", children: [
10606
- /* @__PURE__ */ jsx66(TagsSection, { showCounts, setShowCounts }),
10607
- /* @__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, {})
10608
10667
  ] }) })
10609
10668
  ]
10610
10669
  }
@@ -10620,7 +10679,7 @@ function TagsSection({
10620
10679
  sortBy: ["count:desc", "name:asc"],
10621
10680
  limit: 100
10622
10681
  });
10623
- const [isExpanded, setIsExpanded] = useState34(true);
10682
+ const [isExpanded, setIsExpanded] = useState35(true);
10624
10683
  return /* @__PURE__ */ jsxs44("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
10625
10684
  /* @__PURE__ */ jsxs44(
10626
10685
  "button",
@@ -10630,8 +10689,8 @@ function TagsSection({
10630
10689
  "aria-expanded": isExpanded,
10631
10690
  "aria-controls": "tags-content",
10632
10691
  children: [
10633
- /* @__PURE__ */ jsx66("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
10634
- /* @__PURE__ */ jsx66(
10692
+ /* @__PURE__ */ jsx67("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
10693
+ /* @__PURE__ */ jsx67(
10635
10694
  "svg",
10636
10695
  {
10637
10696
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -10640,14 +10699,14 @@ function TagsSection({
10640
10699
  stroke: "currentColor",
10641
10700
  strokeWidth: 2.5,
10642
10701
  "aria-hidden": "true",
10643
- 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" })
10644
10703
  }
10645
10704
  )
10646
10705
  ]
10647
10706
  }
10648
10707
  ),
10649
10708
  isExpanded && /* @__PURE__ */ jsxs44("div", { className: "space-y-4", id: "tags-content", children: [
10650
- /* @__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(
10651
10710
  "button",
10652
10711
  {
10653
10712
  onClick: () => refine(item.value),
@@ -10658,15 +10717,15 @@ function TagsSection({
10658
10717
  "aria-label": `${item.isRefined ? "Remove" : "Apply"} ${item.label} filter${showCounts ? ` (${item.count} products)` : ""}`,
10659
10718
  "aria-pressed": item.isRefined,
10660
10719
  children: [
10661
- /* @__PURE__ */ jsx66("span", { "aria-hidden": "true", children: item.label }),
10662
- 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 })
10663
10722
  ]
10664
10723
  },
10665
10724
  item.value
10666
10725
  )) }),
10667
10726
  /* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-between pt-2", children: [
10668
- /* @__PURE__ */ jsx66("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
10669
- /* @__PURE__ */ jsx66(
10727
+ /* @__PURE__ */ jsx67("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
10728
+ /* @__PURE__ */ jsx67(
10670
10729
  "button",
10671
10730
  {
10672
10731
  onClick: () => setShowCounts(!showCounts),
@@ -10674,7 +10733,7 @@ function TagsSection({
10674
10733
  role: "switch",
10675
10734
  "aria-checked": showCounts,
10676
10735
  "aria-labelledby": "show-counts-label",
10677
- children: /* @__PURE__ */ jsx66(
10736
+ children: /* @__PURE__ */ jsx67(
10678
10737
  "span",
10679
10738
  {
10680
10739
  className: `inline-block h-4 w-4 transform rounded-full bg-background shadow-sm transition-transform ${showCounts ? "translate-x-6" : "translate-x-1"}`,
@@ -10691,11 +10750,11 @@ function PriceSection() {
10691
10750
  const { range, refine, start, canRefine } = useRange({ attribute: "price" });
10692
10751
  const rangeMin = typeof range.min === "number" && isFinite(range.min) ? range.min : 0;
10693
10752
  const rangeMax = typeof range.max === "number" && isFinite(range.max) ? range.max : 15e3;
10694
- const [localRange, setLocalRange] = useState34([
10753
+ const [localRange, setLocalRange] = useState35([
10695
10754
  typeof start?.[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
10696
10755
  typeof start?.[1] === "number" && isFinite(start[1]) ? start[1] : rangeMax
10697
10756
  ]);
10698
- useEffect36(() => {
10757
+ useEffect37(() => {
10699
10758
  if (start && Array.isArray(start)) {
10700
10759
  setLocalRange([
10701
10760
  typeof start[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
@@ -10705,7 +10764,7 @@ function PriceSection() {
10705
10764
  setLocalRange([rangeMin, rangeMax]);
10706
10765
  }
10707
10766
  }, [start, rangeMin, rangeMax]);
10708
- const [isExpanded, setIsExpanded] = useState34(true);
10767
+ const [isExpanded, setIsExpanded] = useState35(true);
10709
10768
  if (!canRefine) {
10710
10769
  return null;
10711
10770
  }
@@ -10729,8 +10788,8 @@ function PriceSection() {
10729
10788
  "aria-expanded": isExpanded,
10730
10789
  "aria-controls": "price-content",
10731
10790
  children: [
10732
- /* @__PURE__ */ jsx66("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
10733
- /* @__PURE__ */ jsx66(
10791
+ /* @__PURE__ */ jsx67("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
10792
+ /* @__PURE__ */ jsx67(
10734
10793
  "svg",
10735
10794
  {
10736
10795
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -10739,7 +10798,7 @@ function PriceSection() {
10739
10798
  stroke: "currentColor",
10740
10799
  strokeWidth: 2.5,
10741
10800
  "aria-hidden": "true",
10742
- 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" })
10743
10802
  }
10744
10803
  )
10745
10804
  ]
@@ -10747,14 +10806,14 @@ function PriceSection() {
10747
10806
  ),
10748
10807
  isExpanded && /* @__PURE__ */ jsxs44("div", { className: "space-y-6", id: "price-content", children: [
10749
10808
  /* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-between text-sm font-display", children: [
10750
- /* @__PURE__ */ jsx66("span", { children: formatPrice2(localRange[0]) }),
10751
- /* @__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]) })
10752
10811
  ] }),
10753
- /* @__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) => {
10754
10813
  const totalBars = 19;
10755
10814
  const barPrice = rangeMin + (rangeMax - rangeMin) / totalBars * i;
10756
10815
  const isInRange = barPrice >= localRange[0] && barPrice <= localRange[1];
10757
- return /* @__PURE__ */ jsx66(
10816
+ return /* @__PURE__ */ jsx67(
10758
10817
  "div",
10759
10818
  {
10760
10819
  className: `flex-1 rounded-t-sm transition-opacity ${isInRange ? "bg-foreground" : "bg-foreground/20"}`,
@@ -10763,7 +10822,7 @@ function PriceSection() {
10763
10822
  i
10764
10823
  );
10765
10824
  }) }),
10766
- /* @__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(
10767
10826
  Slider2.Root,
10768
10827
  {
10769
10828
  className: "relative flex w-full touch-none select-none items-center",
@@ -10781,8 +10840,8 @@ function PriceSection() {
10781
10840
  step: 1,
10782
10841
  minStepsBetweenThumbs: 1,
10783
10842
  children: [
10784
- /* @__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" }) }),
10785
- /* @__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(
10786
10845
  Slider2.Thumb,
10787
10846
  {
10788
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",
@@ -10796,7 +10855,7 @@ function PriceSection() {
10796
10855
  "aria-valuetext": formatPrice2(localRange[0])
10797
10856
  }
10798
10857
  ),
10799
- /* @__PURE__ */ jsx66(
10858
+ /* @__PURE__ */ jsx67(
10800
10859
  Slider2.Thumb,
10801
10860
  {
10802
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",
@@ -10815,8 +10874,8 @@ function PriceSection() {
10815
10874
  ) }),
10816
10875
  /* @__PURE__ */ jsxs44("div", { className: "grid grid-cols-2 gap-3", children: [
10817
10876
  /* @__PURE__ */ jsxs44("div", { children: [
10818
- /* @__PURE__ */ jsx66("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
10819
- /* @__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(
10820
10879
  "input",
10821
10880
  {
10822
10881
  id: "price-min",
@@ -10835,8 +10894,8 @@ function PriceSection() {
10835
10894
  )
10836
10895
  ] }),
10837
10896
  /* @__PURE__ */ jsxs44("div", { children: [
10838
- /* @__PURE__ */ jsx66("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
10839
- /* @__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(
10840
10899
  "input",
10841
10900
  {
10842
10901
  id: "price-max",
@@ -10860,11 +10919,11 @@ function PriceSection() {
10860
10919
  }
10861
10920
 
10862
10921
  // src/composed/search/Filters.tsx
10863
- 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";
10864
10923
  function Filters({ buttonClassName, buttonText }) {
10865
- const [isOpen, setIsOpen] = useState35(false);
10866
- return /* @__PURE__ */ jsxs45(Fragment13, { children: [
10867
- /* @__PURE__ */ jsx67(
10924
+ const [isOpen, setIsOpen] = useState36(false);
10925
+ return /* @__PURE__ */ jsxs45(Fragment14, { children: [
10926
+ /* @__PURE__ */ jsx68(
10868
10927
  FiltersButton,
10869
10928
  {
10870
10929
  onClick: () => setIsOpen(true),
@@ -10872,14 +10931,14 @@ function Filters({ buttonClassName, buttonText }) {
10872
10931
  children: buttonText
10873
10932
  }
10874
10933
  ),
10875
- /* @__PURE__ */ jsx67(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
10934
+ /* @__PURE__ */ jsx68(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
10876
10935
  ] });
10877
10936
  }
10878
10937
 
10879
10938
  // src/composed/search/CurrentRefinements.tsx
10880
10939
  import { useCurrentRefinements } from "react-instantsearch";
10881
10940
  import { X as LucideX3 } from "lucide-react";
10882
- import { jsx as jsx68, jsxs as jsxs46 } from "react/jsx-runtime";
10941
+ import { jsx as jsx69, jsxs as jsxs46 } from "react/jsx-runtime";
10883
10942
  var XIcon3 = LucideX3;
10884
10943
  function CurrentRefinements() {
10885
10944
  const { items, refine } = useCurrentRefinements();
@@ -10925,15 +10984,15 @@ function CurrentRefinements() {
10925
10984
  if (allRefinements.length === 0) {
10926
10985
  return null;
10927
10986
  }
10928
- 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(
10929
10988
  "button",
10930
10989
  {
10931
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",
10932
10991
  onClick: () => refinement.refine(),
10933
10992
  "aria-label": `Remove filter: ${refinement.displayLabel}`,
10934
10993
  children: [
10935
- /* @__PURE__ */ jsx68("span", { className: "truncate", children: refinement.displayLabel }),
10936
- /* @__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" })
10937
10996
  ]
10938
10997
  },
10939
10998
  `${refinement.attribute}-${refinement.value}-${index}`
@@ -10957,12 +11016,12 @@ var FACET_SECTIONS = [
10957
11016
  ];
10958
11017
 
10959
11018
  // src/composed/zoom/ResponsiveZoom.tsx
10960
- import { useState as useState38, useEffect as useEffect38 } from "react";
11019
+ import { useState as useState39, useEffect as useEffect39 } from "react";
10961
11020
 
10962
11021
  // src/composed/zoom/ZoomOverlay.tsx
10963
- import { useState as useState36, useCallback as useCallback20 } from "react";
11022
+ import { useState as useState37, useCallback as useCallback20 } from "react";
10964
11023
  import { Plus as LucidePlus2, Minus as LucideMinus2 } from "lucide-react";
10965
- 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";
10966
11025
  var PlusIcon2 = LucidePlus2;
10967
11026
  var MinusIcon2 = LucideMinus2;
10968
11027
  function ZoomOverlay({
@@ -10974,12 +11033,12 @@ function ZoomOverlay({
10974
11033
  className,
10975
11034
  style
10976
11035
  }) {
10977
- const [zoomedImageIndex, setZoomedImageIndex] = useState36(null);
10978
- const [zoomOrigin, setZoomOrigin] = useState36({ x: 50, y: 50 });
10979
- const [hoveredImageIndex, setHoveredImageIndex] = useState36(null);
10980
- const [cursorPos, setCursorPos] = useState36({ x: 0, y: 0 });
10981
- const [announcement, setAnnouncement] = useState36("");
10982
- 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);
10983
11042
  const handleZoomClick = useCallback20(
10984
11043
  (e) => {
10985
11044
  e.stopPropagation();
@@ -11021,9 +11080,9 @@ function ZoomOverlay({
11021
11080
  const isZoomed = zoomedImageIndex === imageIndex;
11022
11081
  const isHovered = hoveredImageIndex === imageIndex;
11023
11082
  const cursorStyle = isLargeTouchDevice ? "pointer" : isTouchDevice ? "default" : "none";
11024
- return /* @__PURE__ */ jsxs47(Fragment14, { children: [
11025
- /* @__PURE__ */ jsx69("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11026
- /* @__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(
11027
11086
  "div",
11028
11087
  {
11029
11088
  className,
@@ -11031,7 +11090,7 @@ function ZoomOverlay({
11031
11090
  ...style,
11032
11091
  position: "relative"
11033
11092
  },
11034
- children: /* @__PURE__ */ jsx69(
11093
+ children: /* @__PURE__ */ jsx70(
11035
11094
  "div",
11036
11095
  {
11037
11096
  style: {
@@ -11054,7 +11113,7 @@ function ZoomOverlay({
11054
11113
  handleZoomClick(e);
11055
11114
  }
11056
11115
  },
11057
- children: /* @__PURE__ */ jsx69(
11116
+ children: /* @__PURE__ */ jsx70(
11058
11117
  "div",
11059
11118
  {
11060
11119
  style: {
@@ -11070,7 +11129,7 @@ function ZoomOverlay({
11070
11129
  )
11071
11130
  }
11072
11131
  ),
11073
- isHovered && !isTouchDevice && /* @__PURE__ */ jsx69(
11132
+ isHovered && !isTouchDevice && /* @__PURE__ */ jsx70(
11074
11133
  "div",
11075
11134
  {
11076
11135
  className: "fixed pointer-events-none z-50 hidden md:block",
@@ -11080,7 +11139,7 @@ function ZoomOverlay({
11080
11139
  transform: "translate(-50%, -50%)"
11081
11140
  },
11082
11141
  "aria-hidden": "true",
11083
- 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(
11084
11143
  MinusIcon2,
11085
11144
  {
11086
11145
  size: 20,
@@ -11088,7 +11147,7 @@ function ZoomOverlay({
11088
11147
  strokeWidth: 1.5,
11089
11148
  "aria-hidden": "true"
11090
11149
  }
11091
- ) : /* @__PURE__ */ jsx69(
11150
+ ) : /* @__PURE__ */ jsx70(
11092
11151
  PlusIcon2,
11093
11152
  {
11094
11153
  size: 20,
@@ -11104,9 +11163,9 @@ function ZoomOverlay({
11104
11163
 
11105
11164
  // src/composed/zoom/EnhancedImageViewer.tsx
11106
11165
  import {
11107
- useState as useState37,
11166
+ useState as useState38,
11108
11167
  useRef as useRef25,
11109
- useEffect as useEffect37,
11168
+ useEffect as useEffect38,
11110
11169
  useLayoutEffect as useLayoutEffect6,
11111
11170
  useCallback as useCallback21
11112
11171
  } from "react";
@@ -11116,7 +11175,7 @@ import {
11116
11175
  TransformComponent as OriginalTransformComponent
11117
11176
  } from "react-zoom-pan-pinch";
11118
11177
  import { X as X2 } from "lucide-react";
11119
- 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";
11120
11179
  var TransformWrapper = OriginalTransformWrapper;
11121
11180
  var TransformComponent = OriginalTransformComponent;
11122
11181
  var EnhancedImageViewer = ({
@@ -11127,11 +11186,11 @@ var EnhancedImageViewer = ({
11127
11186
  onIndexChange,
11128
11187
  currentIndex: propCurrentIndex
11129
11188
  }) => {
11130
- const [isMounted, setIsMounted] = useState37(false);
11131
- const [isClient, setIsClient] = useState37(false);
11132
- const [scale, setScale] = useState37({ initial: 1, min: 1, max: 8 });
11133
- const [cropDimensions, setCropDimensions] = useState37({ width: 0, height: 0 });
11134
- 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);
11135
11194
  const imgRef = useRef25(null);
11136
11195
  const touchStartRef = useRef25(
11137
11196
  null
@@ -11161,17 +11220,17 @@ var EnhancedImageViewer = ({
11161
11220
  document.body.style.overflow = "";
11162
11221
  };
11163
11222
  }, [calculateScale]);
11164
- useEffect37(() => {
11223
+ useEffect38(() => {
11165
11224
  calculateScale();
11166
11225
  }, [calculateScale]);
11167
- useEffect37(() => {
11226
+ useEffect38(() => {
11168
11227
  const handleResize = () => {
11169
11228
  calculateScale();
11170
11229
  };
11171
11230
  window.addEventListener("resize", handleResize);
11172
11231
  return () => window.removeEventListener("resize", handleResize);
11173
11232
  }, [calculateScale]);
11174
- useEffect37(() => {
11233
+ useEffect38(() => {
11175
11234
  const handleKeyDown = (e) => {
11176
11235
  if (e.key === "Escape") {
11177
11236
  onClose();
@@ -11256,12 +11315,12 @@ var EnhancedImageViewer = ({
11256
11315
  );
11257
11316
  if (!isMounted || !isClient) {
11258
11317
  return createPortal3(
11259
- /* @__PURE__ */ jsx70(
11318
+ /* @__PURE__ */ jsx71(
11260
11319
  "div",
11261
11320
  {
11262
11321
  className: "fixed inset-0 bg-black flex items-center justify-center",
11263
11322
  style: { zIndex: 999999 },
11264
- children: /* @__PURE__ */ jsx70(
11323
+ children: /* @__PURE__ */ jsx71(
11265
11324
  "div",
11266
11325
  {
11267
11326
  style: {
@@ -11286,7 +11345,7 @@ var EnhancedImageViewer = ({
11286
11345
  "aria-modal": "true",
11287
11346
  "aria-label": "Image viewer",
11288
11347
  children: [
11289
- /* @__PURE__ */ jsx70(
11348
+ /* @__PURE__ */ jsx71(
11290
11349
  "button",
11291
11350
  {
11292
11351
  onClick: (e) => {
@@ -11312,10 +11371,10 @@ var EnhancedImageViewer = ({
11312
11371
  touchAction: "manipulation",
11313
11372
  marginBottom: "env(safe-area-inset-bottom, 0px)"
11314
11373
  },
11315
- 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 })
11316
11375
  }
11317
11376
  ),
11318
- /* @__PURE__ */ jsx70(
11377
+ /* @__PURE__ */ jsx71(
11319
11378
  TransformWrapper,
11320
11379
  {
11321
11380
  initialScale: scale.initial,
@@ -11362,14 +11421,14 @@ var EnhancedImageViewer = ({
11362
11421
  onTouchStart: handleTouchStart,
11363
11422
  onTouchEnd: handleTouchEnd,
11364
11423
  children: [
11365
- /* @__PURE__ */ jsx70(
11424
+ /* @__PURE__ */ jsx71(
11366
11425
  TransformComponent,
11367
11426
  {
11368
11427
  wrapperStyle: {
11369
11428
  width: "100%",
11370
11429
  height: "100%"
11371
11430
  },
11372
- children: /* @__PURE__ */ jsx70(
11431
+ children: /* @__PURE__ */ jsx71(
11373
11432
  "div",
11374
11433
  {
11375
11434
  style: {
@@ -11380,8 +11439,8 @@ var EnhancedImageViewer = ({
11380
11439
  alignItems: "center",
11381
11440
  justifyContent: "center"
11382
11441
  },
11383
- children: /* @__PURE__ */ jsx70(
11384
- "img",
11442
+ children: /* @__PURE__ */ jsx71(
11443
+ SafeImg,
11385
11444
  {
11386
11445
  ref: imgRef,
11387
11446
  src: imageUrl,
@@ -11402,7 +11461,7 @@ var EnhancedImageViewer = ({
11402
11461
  }
11403
11462
  ),
11404
11463
  /* @__PURE__ */ jsxs48("div", { className: "fixed bottom-5 left-0 right-0 z-50", children: [
11405
- /* @__PURE__ */ jsx70("div", { className: "flex justify-center gap-2", children: (() => {
11464
+ /* @__PURE__ */ jsx71("div", { className: "flex justify-center gap-2", children: (() => {
11406
11465
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11407
11466
  if (currentIndex === -1) {
11408
11467
  currentIndex = images.findIndex(
@@ -11435,8 +11494,8 @@ var EnhancedImageViewer = ({
11435
11494
  };
11436
11495
  const nextIndex = findNextAvailableIndex(currentIndex, 1);
11437
11496
  const prevIndex = findNextAvailableIndex(currentIndex, -1);
11438
- return /* @__PURE__ */ jsxs48(Fragment15, { children: [
11439
- /* @__PURE__ */ jsx70(
11497
+ return /* @__PURE__ */ jsxs48(Fragment16, { children: [
11498
+ /* @__PURE__ */ jsx71(
11440
11499
  "button",
11441
11500
  {
11442
11501
  onClick: () => {
@@ -11449,7 +11508,7 @@ var EnhancedImageViewer = ({
11449
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"}`,
11450
11509
  style: { touchAction: "manipulation" },
11451
11510
  "aria-label": "Previous image",
11452
- children: /* @__PURE__ */ jsx70(
11511
+ children: /* @__PURE__ */ jsx71(
11453
11512
  "svg",
11454
11513
  {
11455
11514
  className: "w-4 h-4",
@@ -11457,7 +11516,7 @@ var EnhancedImageViewer = ({
11457
11516
  stroke: "currentColor",
11458
11517
  viewBox: "0 0 24 24",
11459
11518
  "aria-hidden": "true",
11460
- children: /* @__PURE__ */ jsx70(
11519
+ children: /* @__PURE__ */ jsx71(
11461
11520
  "path",
11462
11521
  {
11463
11522
  strokeLinecap: "round",
@@ -11470,7 +11529,7 @@ var EnhancedImageViewer = ({
11470
11529
  )
11471
11530
  }
11472
11531
  ),
11473
- /* @__PURE__ */ jsx70(
11532
+ /* @__PURE__ */ jsx71(
11474
11533
  "button",
11475
11534
  {
11476
11535
  onClick: () => {
@@ -11483,7 +11542,7 @@ var EnhancedImageViewer = ({
11483
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"}`,
11484
11543
  style: { touchAction: "manipulation" },
11485
11544
  "aria-label": "Next image",
11486
- children: /* @__PURE__ */ jsx70(
11545
+ children: /* @__PURE__ */ jsx71(
11487
11546
  "svg",
11488
11547
  {
11489
11548
  className: "w-4 h-4",
@@ -11491,7 +11550,7 @@ var EnhancedImageViewer = ({
11491
11550
  stroke: "currentColor",
11492
11551
  viewBox: "0 0 24 24",
11493
11552
  "aria-hidden": "true",
11494
- children: /* @__PURE__ */ jsx70(
11553
+ children: /* @__PURE__ */ jsx71(
11495
11554
  "path",
11496
11555
  {
11497
11556
  strokeLinecap: "round",
@@ -11506,7 +11565,7 @@ var EnhancedImageViewer = ({
11506
11565
  )
11507
11566
  ] });
11508
11567
  })() }),
11509
- /* @__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: (() => {
11510
11569
  const total = Math.max(images.length, 1);
11511
11570
  const current = propCurrentIndex !== void 0 ? Math.min(propCurrentIndex + 1, total) : 1;
11512
11571
  return `${current} / ${total}`;
@@ -11518,7 +11577,7 @@ var EnhancedImageViewer = ({
11518
11577
  },
11519
11578
  `${scale.initial}-${scale.min}-${scale.max}`
11520
11579
  ),
11521
- /* @__PURE__ */ jsx70(
11580
+ /* @__PURE__ */ jsx71(
11522
11581
  "div",
11523
11582
  {
11524
11583
  className: "absolute inset-0 bg-black",
@@ -11537,7 +11596,7 @@ var EnhancedImageViewer = ({
11537
11596
  };
11538
11597
 
11539
11598
  // src/composed/zoom/ResponsiveZoom.tsx
11540
- 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";
11541
11600
  function ResponsiveZoom({
11542
11601
  imageIndex,
11543
11602
  children,
@@ -11547,11 +11606,11 @@ function ResponsiveZoom({
11547
11606
  imageUrl,
11548
11607
  alt = "Product image"
11549
11608
  }) {
11550
- const [isTouchDevice, setIsTouchDevice] = useState38(false);
11551
- const [showEnhancedViewer, setShowEnhancedViewer] = useState38(false);
11552
- const [viewerIndex, setViewerIndex] = useState38(0);
11553
- const [currentImageUrl, setCurrentImageUrl] = useState38(imageUrl || "");
11554
- 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(() => {
11555
11614
  const checkDeviceType = () => {
11556
11615
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
11557
11616
  setIsTouchDevice(hasTouch);
@@ -11578,8 +11637,8 @@ function ResponsiveZoom({
11578
11637
  }
11579
11638
  }
11580
11639
  };
11581
- return /* @__PURE__ */ jsxs49(Fragment16, { children: [
11582
- isTouchDevice ? /* @__PURE__ */ jsx71(
11640
+ return /* @__PURE__ */ jsxs49(Fragment17, { children: [
11641
+ isTouchDevice ? /* @__PURE__ */ jsx72(
11583
11642
  "div",
11584
11643
  {
11585
11644
  className,
@@ -11596,7 +11655,7 @@ function ResponsiveZoom({
11596
11655
  },
11597
11656
  children
11598
11657
  }
11599
- ) : /* @__PURE__ */ jsx71(
11658
+ ) : /* @__PURE__ */ jsx72(
11600
11659
  ZoomOverlay,
11601
11660
  {
11602
11661
  imageIndex,
@@ -11607,7 +11666,7 @@ function ResponsiveZoom({
11607
11666
  children
11608
11667
  }
11609
11668
  ),
11610
- showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ jsx71(
11669
+ showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ jsx72(
11611
11670
  EnhancedImageViewer,
11612
11671
  {
11613
11672
  imageUrl: currentImageUrl,
@@ -11631,14 +11690,37 @@ function ResponsiveZoom({
11631
11690
 
11632
11691
  // src/composed/carousels/MobileProductCarousel.tsx
11633
11692
  import {
11634
- useState as useState39,
11693
+ useState as useState40,
11635
11694
  useRef as useRef26,
11636
- useEffect as useEffect39,
11695
+ useEffect as useEffect40,
11637
11696
  useCallback as useCallback22,
11638
11697
  useMemo as useMemo15,
11639
11698
  memo as memo4
11640
11699
  } from "react";
11641
- 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
+ }
11642
11724
  var MobileProductCarousel = memo4(function MobileProductCarousel2({
11643
11725
  images,
11644
11726
  currentIndex = 0,
@@ -11654,23 +11736,23 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11654
11736
  mockupWidth,
11655
11737
  onMockupUrlGenerated
11656
11738
  }) {
11657
- const [activeIndex, setActiveIndex] = useState39(currentIndex);
11658
- const [touchStart, setTouchStart] = useState39(
11739
+ const [activeIndex, setActiveIndex] = useState40(currentIndex);
11740
+ const [touchStart, setTouchStart] = useState40(
11659
11741
  null
11660
11742
  );
11661
- const [touchEnd, setTouchEnd] = useState39(
11743
+ const [touchEnd, setTouchEnd] = useState40(
11662
11744
  null
11663
11745
  );
11664
- const [showImageViewer, setShowImageViewer] = useState39(false);
11665
- const [viewerKey, setViewerKey] = useState39(0);
11666
- const [isDragging, setIsDragging] = useState39(false);
11667
- const [dragOffset, setDragOffset] = useState39(0);
11668
- const [isTransitioning, setIsTransitioning] = useState39(false);
11669
- 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(
11670
11752
  null
11671
11753
  );
11672
- const [isPeeking, setIsPeeking] = useState39(false);
11673
- const [isPeekReturning, setIsPeekReturning] = useState39(false);
11754
+ const [isPeeking, setIsPeeking] = useState40(false);
11755
+ const [isPeekReturning, setIsPeekReturning] = useState40(false);
11674
11756
  const carouselRef = useRef26(null);
11675
11757
  const indicatorRef = useRef26(null);
11676
11758
  const touchStartRef = useRef26(
@@ -11681,7 +11763,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11681
11763
  const hasSwipedThisSessionRef = useRef26(false);
11682
11764
  const generatedUrlsRef = useRef26(/* @__PURE__ */ new Map());
11683
11765
  const prevArtworkSrcRef = useRef26(currentArtwork?.src);
11684
- useEffect39(() => {
11766
+ useEffect40(() => {
11685
11767
  if (currentArtwork?.src !== prevArtworkSrcRef.current) {
11686
11768
  generatedUrlsRef.current.clear();
11687
11769
  prevArtworkSrcRef.current = currentArtwork?.src;
@@ -11697,8 +11779,8 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11697
11779
  const shouldHideDots = stickyHeroContext?.shouldHideDots ?? false;
11698
11780
  const priorityContext = useMockupPriorityOptional();
11699
11781
  const realtimeContext = useRealtimeOptional();
11700
- const [urlUpdateCounter, setUrlUpdateCounter] = useState39(0);
11701
- useEffect39(() => {
11782
+ const [urlUpdateCounter, setUrlUpdateCounter] = useState40(0);
11783
+ useEffect40(() => {
11702
11784
  if (!realtimeContext?.subscribeMockupResults) return;
11703
11785
  const unsubscribe = realtimeContext.subscribeMockupResults(() => {
11704
11786
  setUrlUpdateCounter((c) => c + 1);
@@ -11726,10 +11808,10 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11726
11808
  });
11727
11809
  }, [images, realtimeMockupUrls]);
11728
11810
  const minSwipeDistance = 50;
11729
- useEffect39(() => {
11811
+ useEffect40(() => {
11730
11812
  setActiveIndex(currentIndex);
11731
11813
  }, [currentIndex]);
11732
- useEffect39(() => {
11814
+ useEffect40(() => {
11733
11815
  if (!priorityContext) return;
11734
11816
  const realMockups = images.map((img, idx) => ({ img, originalIdx: idx })).filter(({ img }) => img.isRealMockup && img.mockupId);
11735
11817
  const mockupIdsList = realMockups.map(({ img }) => img.mockupId);
@@ -11757,7 +11839,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11757
11839
  priorityContext.clearMobileCarouselMode?.();
11758
11840
  };
11759
11841
  }, [priorityContext, activeIndex, images]);
11760
- useEffect39(() => {
11842
+ useEffect40(() => {
11761
11843
  const indicator = indicatorRef.current;
11762
11844
  if (!indicator) return;
11763
11845
  let ticking = false;
@@ -11822,7 +11904,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11822
11904
  } catch {
11823
11905
  }
11824
11906
  }, []);
11825
- useEffect39(() => {
11907
+ useEffect40(() => {
11826
11908
  if (!enablePeekAnimation || images.length <= 1) return;
11827
11909
  const tracking = getSwipeTracking();
11828
11910
  const newViewCount = tracking.viewsWithoutSwipe + 1;
@@ -11926,7 +12008,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
11926
12008
  },
11927
12009
  [activeIndex, images.length, onIndexChange, recordSwipe]
11928
12010
  );
11929
- useEffect39(() => {
12011
+ useEffect40(() => {
11930
12012
  const container = carouselRef.current;
11931
12013
  if (!container) return;
11932
12014
  const handleTouchStart = (e) => {
@@ -12019,7 +12101,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12019
12101
  null
12020
12102
  );
12021
12103
  const isMouseDraggingRef = useRef26(false);
12022
- useEffect39(() => {
12104
+ useEffect40(() => {
12023
12105
  const container = carouselRef.current;
12024
12106
  if (!container) return;
12025
12107
  const handleMouseDown = (e) => {
@@ -12113,16 +12195,16 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12113
12195
  },
12114
12196
  [onIndexChange]
12115
12197
  );
12116
- useEffect39(() => {
12198
+ useEffect40(() => {
12117
12199
  if (stickyHeroContext?.setCarouselIndicator && images.length > 1) {
12118
- const indicator = /* @__PURE__ */ jsx72(
12200
+ const indicator = /* @__PURE__ */ jsx73(
12119
12201
  "div",
12120
12202
  {
12121
12203
  className: "w-full",
12122
12204
  role: "group",
12123
12205
  "aria-label": "Product image navigation",
12124
12206
  children: /* @__PURE__ */ jsxs50("div", { className: "relative h-1", children: [
12125
- /* @__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(
12126
12208
  "button",
12127
12209
  {
12128
12210
  onClick: () => goToSlide(index),
@@ -12132,7 +12214,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12132
12214
  },
12133
12215
  index
12134
12216
  )) }),
12135
- /* @__PURE__ */ jsx72(
12217
+ /* @__PURE__ */ jsx73(
12136
12218
  "div",
12137
12219
  {
12138
12220
  className: "absolute top-0 h-full bg-primary transition-all duration-300 ease-out",
@@ -12155,10 +12237,10 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12155
12237
  };
12156
12238
  }, [activeIndex, images.length, goToSlide, stickyHeroContext]);
12157
12239
  if (!images || images.length === 0) {
12158
- 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" });
12159
12241
  }
12160
12242
  return /* @__PURE__ */ jsxs50("div", { className: `relative w-full h-full ${className}`, children: [
12161
- /* @__PURE__ */ jsx72(
12243
+ /* @__PURE__ */ jsx73(
12162
12244
  "div",
12163
12245
  {
12164
12246
  ref: carouselRef,
@@ -12176,7 +12258,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12176
12258
  role: "region",
12177
12259
  "aria-roledescription": "carousel",
12178
12260
  "aria-label": "Product images",
12179
- children: /* @__PURE__ */ jsx72(
12261
+ children: /* @__PURE__ */ jsx73(
12180
12262
  "div",
12181
12263
  {
12182
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)]" : ""}`,
@@ -12186,11 +12268,15 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12186
12268
  children: images.map((image, index) => {
12187
12269
  const DECODE_WINDOW = 1;
12188
12270
  const isWithinDecodeWindow = Math.abs(index - activeIndex) <= DECODE_WINDOW;
12189
- return /* @__PURE__ */ jsx72(
12271
+ return /* @__PURE__ */ jsx73(
12190
12272
  "div",
12191
12273
  {
12192
12274
  className: "w-full h-full flex-shrink-0 relative select-none",
12193
- 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(
12194
12280
  HeroProductImage,
12195
12281
  {
12196
12282
  productId,
@@ -12202,16 +12288,12 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12202
12288
  onUrlGenerated: image.mockupId ? (url) => handleUrlGenerated(image.mockupId, url) : void 0,
12203
12289
  className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12204
12290
  }
12205
- ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ jsx72("div", { className: "w-full h-full bg-muted animate-pulse" }) : /* @__PURE__ */ jsx72(
12206
- "img",
12291
+ ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ jsx73(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" }) : /* @__PURE__ */ jsx73(
12292
+ StaticCarouselImage,
12207
12293
  {
12208
12294
  src: image.src,
12209
- alt: image.label,
12210
- crossOrigin: "anonymous",
12211
- className: "w-full h-full object-cover cursor-pointer pointer-events-none",
12212
- loading: "lazy",
12213
- decoding: "async",
12214
- draggable: false
12295
+ alt: image.label ?? "",
12296
+ className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12215
12297
  }
12216
12298
  )
12217
12299
  },
@@ -12222,7 +12304,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12222
12304
  )
12223
12305
  }
12224
12306
  ),
12225
- showIndicators && images.length > 1 && /* @__PURE__ */ jsx72(
12307
+ showIndicators && images.length > 1 && /* @__PURE__ */ jsx73(
12226
12308
  "div",
12227
12309
  {
12228
12310
  ref: indicatorRef,
@@ -12231,7 +12313,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12231
12313
  role: "group",
12232
12314
  "aria-label": "Product image navigation",
12233
12315
  children: /* @__PURE__ */ jsxs50("div", { className: "relative h-1", children: [
12234
- /* @__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(
12235
12317
  "button",
12236
12318
  {
12237
12319
  onClick: () => goToSlide(index),
@@ -12241,7 +12323,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12241
12323
  },
12242
12324
  index
12243
12325
  )) }),
12244
- /* @__PURE__ */ jsx72(
12326
+ /* @__PURE__ */ jsx73(
12245
12327
  "div",
12246
12328
  {
12247
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"}`,
@@ -12276,7 +12358,7 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12276
12358
  naturalHeight: img.naturalHeight
12277
12359
  } : null;
12278
12360
  }).filter((img) => img !== null);
12279
- return /* @__PURE__ */ jsx72(
12361
+ return /* @__PURE__ */ jsx73(
12280
12362
  EnhancedImageViewer,
12281
12363
  {
12282
12364
  imageUrl,
@@ -12315,8 +12397,8 @@ var MobileProductCarousel = memo4(function MobileProductCarousel2({
12315
12397
  });
12316
12398
 
12317
12399
  // src/composed/carousels/HeroCarousel.tsx
12318
- import { useState as useState40, useRef as useRef27, useCallback as useCallback23, useEffect as useEffect40 } from "react";
12319
- 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";
12320
12402
  function HeroCarousel({
12321
12403
  images,
12322
12404
  currentIndex = 0,
@@ -12326,13 +12408,13 @@ function HeroCarousel({
12326
12408
  productId,
12327
12409
  onImageTap
12328
12410
  }) {
12329
- const [activeIndex, setActiveIndex] = useState40(currentIndex);
12411
+ const [activeIndex, setActiveIndex] = useState41(currentIndex);
12330
12412
  const containerRef = useRef27(null);
12331
12413
  const touchStartRef = useRef27(
12332
12414
  null
12333
12415
  );
12334
12416
  const isSwipingRef = useRef27(false);
12335
- useEffect40(() => {
12417
+ useEffect41(() => {
12336
12418
  setActiveIndex(currentIndex);
12337
12419
  }, [currentIndex]);
12338
12420
  const goToSlide = useCallback23(
@@ -12343,7 +12425,7 @@ function HeroCarousel({
12343
12425
  },
12344
12426
  [images.length, onIndexChange]
12345
12427
  );
12346
- useEffect40(() => {
12428
+ useEffect41(() => {
12347
12429
  const container = containerRef.current;
12348
12430
  if (!container) return;
12349
12431
  const handleTouchStart = (e) => {
@@ -12395,7 +12477,7 @@ function HeroCarousel({
12395
12477
  };
12396
12478
  }, [activeIndex, images.length, goToSlide, onImageTap]);
12397
12479
  if (!images || images.length === 0) {
12398
- return /* @__PURE__ */ jsx73("div", { className: "w-full h-full bg-muted" });
12480
+ return /* @__PURE__ */ jsx74("div", { className: "w-full h-full bg-muted" });
12399
12481
  }
12400
12482
  return /* @__PURE__ */ jsxs51(
12401
12483
  "div",
@@ -12408,7 +12490,7 @@ function HeroCarousel({
12408
12490
  overflow: "hidden"
12409
12491
  },
12410
12492
  children: [
12411
- /* @__PURE__ */ jsx73(
12493
+ /* @__PURE__ */ jsx74(
12412
12494
  "div",
12413
12495
  {
12414
12496
  className: "flex h-full transition-transform duration-300 ease-out",
@@ -12419,14 +12501,14 @@ function HeroCarousel({
12419
12501
  backfaceVisibility: "hidden",
12420
12502
  WebkitBackfaceVisibility: "hidden"
12421
12503
  },
12422
- children: images.map((image, index) => /* @__PURE__ */ jsx73(
12504
+ children: images.map((image, index) => /* @__PURE__ */ jsx74(
12423
12505
  "div",
12424
12506
  {
12425
12507
  className: "w-full h-full flex-shrink-0",
12426
12508
  style: {
12427
12509
  contain: "layout paint"
12428
12510
  },
12429
- children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ jsx73(
12511
+ children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ jsx74(
12430
12512
  HeroProductImage,
12431
12513
  {
12432
12514
  productId,
@@ -12435,7 +12517,7 @@ function HeroCarousel({
12435
12517
  mockupId: image.mockupId,
12436
12518
  className: "w-full h-full object-cover"
12437
12519
  }
12438
- ) : /* @__PURE__ */ jsx73(
12520
+ ) : /* @__PURE__ */ jsx74(
12439
12521
  "img",
12440
12522
  {
12441
12523
  src: image.src,
@@ -12452,12 +12534,12 @@ function HeroCarousel({
12452
12534
  ))
12453
12535
  }
12454
12536
  ),
12455
- images.length > 1 && /* @__PURE__ */ jsx73(
12537
+ images.length > 1 && /* @__PURE__ */ jsx74(
12456
12538
  "div",
12457
12539
  {
12458
12540
  className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 z-10",
12459
12541
  style: { contain: "layout style" },
12460
- children: images.map((_, index) => /* @__PURE__ */ jsx73(
12542
+ children: images.map((_, index) => /* @__PURE__ */ jsx74(
12461
12543
  "button",
12462
12544
  {
12463
12545
  onClick: () => goToSlide(index),
@@ -12474,8 +12556,8 @@ function HeroCarousel({
12474
12556
  }
12475
12557
 
12476
12558
  // src/composed/grids/MasonryGrid.tsx
12477
- import { useState as useState41, useEffect as useEffect41, useMemo as useMemo16 } from "react";
12478
- 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";
12479
12561
  var BREAKPOINTS = {
12480
12562
  sm: 640,
12481
12563
  md: 768,
@@ -12527,13 +12609,13 @@ function MasonryGrid({
12527
12609
  className = "",
12528
12610
  emptyContent
12529
12611
  }) {
12530
- const [columnCount, setColumnCount] = useState41(
12612
+ const [columnCount, setColumnCount] = useState42(
12531
12613
  () => typeof columns === "number" ? columns : getColumnCount(
12532
12614
  typeof window !== "undefined" ? window.innerWidth : 1024,
12533
12615
  columns
12534
12616
  )
12535
12617
  );
12536
- useEffect41(() => {
12618
+ useEffect42(() => {
12537
12619
  const updateColumnCount = () => {
12538
12620
  setColumnCount(getColumnCount(window.innerWidth, columns));
12539
12621
  };
@@ -12547,24 +12629,24 @@ function MasonryGrid({
12547
12629
  );
12548
12630
  if (items.length === 0) {
12549
12631
  if (emptyContent) {
12550
- return /* @__PURE__ */ jsx74(Fragment17, { children: emptyContent });
12632
+ return /* @__PURE__ */ jsx75(Fragment18, { children: emptyContent });
12551
12633
  }
12552
12634
  return null;
12553
12635
  }
12554
- return /* @__PURE__ */ jsx74(
12636
+ return /* @__PURE__ */ jsx75(
12555
12637
  "div",
12556
12638
  {
12557
12639
  className: `flex ${className}`,
12558
12640
  style: { gap: `${gap}px` },
12559
12641
  role: "list",
12560
- children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ jsx74(
12642
+ children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ jsx75(
12561
12643
  "div",
12562
12644
  {
12563
12645
  className: "flex-1 flex flex-col",
12564
12646
  style: { gap: `${gap}px` },
12565
12647
  children: columnItems.map((item, itemIndex) => {
12566
12648
  const originalIndex = itemIndex * columnCount + columnIndex;
12567
- return /* @__PURE__ */ jsx74("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12649
+ return /* @__PURE__ */ jsx75("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12568
12650
  })
12569
12651
  },
12570
12652
  columnIndex
@@ -12574,7 +12656,7 @@ function MasonryGrid({
12574
12656
  }
12575
12657
 
12576
12658
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12577
- import { useEffect as useEffect43, useRef as useRef28 } from "react";
12659
+ import { useEffect as useEffect44, useRef as useRef28 } from "react";
12578
12660
 
12579
12661
  // src/layouts/hero-zoom/types.ts
12580
12662
  var DEFAULT_HERO_ZOOM_CONFIG = {
@@ -12586,15 +12668,15 @@ var DEFAULT_HERO_ZOOM_CONFIG = {
12586
12668
  };
12587
12669
 
12588
12670
  // src/layouts/hero-zoom/useHeroZoomScales.ts
12589
- 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";
12590
12672
  function useHeroZoomScales(config = {}) {
12591
12673
  const { initialScale, accountForRetina, maxRetinaMultiplier } = {
12592
12674
  ...DEFAULT_HERO_ZOOM_CONFIG,
12593
12675
  ...config
12594
12676
  };
12595
- const [isHydrated, setIsHydrated] = useState42(false);
12677
+ const [isHydrated, setIsHydrated] = useState43(false);
12596
12678
  const ssrMultiplier = accountForRetina ? maxRetinaMultiplier : 2;
12597
- const [scales, setScales] = useState42(() => ({
12679
+ const [scales, setScales] = useState43(() => ({
12598
12680
  visual: initialScale,
12599
12681
  render: initialScale * ssrMultiplier
12600
12682
  }));
@@ -12613,7 +12695,7 @@ function useHeroZoomScales(config = {}) {
12613
12695
  renderScale = Math.max(1, Math.min(8, renderScale));
12614
12696
  return { visual: visualScale, render: renderScale };
12615
12697
  }, [initialScale, accountForRetina, maxRetinaMultiplier]);
12616
- useEffect42(() => {
12698
+ useEffect43(() => {
12617
12699
  const supportsScrollTimeline = CSS.supports(
12618
12700
  "animation-timeline",
12619
12701
  "scroll()"
@@ -12663,7 +12745,7 @@ function useHeroZoomScales(config = {}) {
12663
12745
  }
12664
12746
 
12665
12747
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12666
- import { jsx as jsx75, jsxs as jsxs52 } from "react/jsx-runtime";
12748
+ import { jsx as jsx76, jsxs as jsxs52 } from "react/jsx-runtime";
12667
12749
  function HeroZoomLayout({
12668
12750
  config = {},
12669
12751
  header,
@@ -12680,7 +12762,7 @@ function HeroZoomLayout({
12680
12762
  const { visual, render, isHydrated } = useHeroZoomScales(mergedConfig);
12681
12763
  const imageContainerRef = useRef28(null);
12682
12764
  const headerRef = useRef28(null);
12683
- useEffect43(() => {
12765
+ useEffect44(() => {
12684
12766
  if (typeof window === "undefined") return;
12685
12767
  const originalRestoration = "scrollRestoration" in history ? history.scrollRestoration : "auto";
12686
12768
  if ("scrollRestoration" in history) {
@@ -12693,7 +12775,7 @@ function HeroZoomLayout({
12693
12775
  }
12694
12776
  };
12695
12777
  }, []);
12696
- useEffect43(() => {
12778
+ useEffect44(() => {
12697
12779
  const supportsScrollTimeline = CSS.supports(
12698
12780
  "animation-timeline",
12699
12781
  "scroll()"
@@ -12836,8 +12918,8 @@ function HeroZoomLayout({
12836
12918
  "--hero-zoom-final-transform": 1 / activeRender
12837
12919
  },
12838
12920
  children: [
12839
- /* @__PURE__ */ jsx75("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
12840
- /* @__PURE__ */ jsx75(
12921
+ /* @__PURE__ */ jsx76("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
12922
+ /* @__PURE__ */ jsx76(
12841
12923
  "div",
12842
12924
  {
12843
12925
  style: {
@@ -12845,7 +12927,7 @@ function HeroZoomLayout({
12845
12927
  }
12846
12928
  }
12847
12929
  ),
12848
- header && /* @__PURE__ */ jsx75(
12930
+ header && /* @__PURE__ */ jsx76(
12849
12931
  "div",
12850
12932
  {
12851
12933
  ref: headerRef,
@@ -12858,7 +12940,7 @@ function HeroZoomLayout({
12858
12940
  children: header
12859
12941
  }
12860
12942
  ),
12861
- /* @__PURE__ */ jsx75(
12943
+ /* @__PURE__ */ jsx76(
12862
12944
  "div",
12863
12945
  {
12864
12946
  ref: imageContainerRef,
@@ -12878,15 +12960,15 @@ function HeroZoomLayout({
12878
12960
  children: hero
12879
12961
  }
12880
12962
  ),
12881
- /* @__PURE__ */ jsx75("div", { className: "relative z-10", children })
12963
+ /* @__PURE__ */ jsx76("div", { className: "relative z-10", children })
12882
12964
  ]
12883
12965
  }
12884
12966
  );
12885
12967
  }
12886
12968
 
12887
12969
  // src/layouts/hero-zoom/HeroShrinkLayout.tsx
12888
- import { useEffect as useEffect44, useRef as useRef29, useState as useState43 } from "react";
12889
- 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";
12890
12972
  var DEFAULT_CONFIG = {
12891
12973
  aspectRatio: 16 / 9,
12892
12974
  initialHeightPercent: 70,
@@ -12908,11 +12990,11 @@ function HeroShrinkLayout({
12908
12990
  const { aspectRatio, initialHeightPercent, minHeightPercent, headerHeight } = mergedConfig;
12909
12991
  const heroRef = useRef29(null);
12910
12992
  const headerRef = useRef29(null);
12911
- const [isClient, setIsClient] = useState43(false);
12912
- useEffect44(() => {
12993
+ const [isClient, setIsClient] = useState44(false);
12994
+ useEffect45(() => {
12913
12995
  setIsClient(true);
12914
12996
  }, []);
12915
- useEffect44(() => {
12997
+ useEffect45(() => {
12916
12998
  if (!isClient) return;
12917
12999
  const supportsScrollTimeline = CSS.supports("animation-timeline", "scroll()");
12918
13000
  if (supportsScrollTimeline) return;
@@ -13005,9 +13087,9 @@ function HeroShrinkLayout({
13005
13087
  className: `relative min-h-screen ${className}`,
13006
13088
  style: { ...style, ...cssVars },
13007
13089
  children: [
13008
- /* @__PURE__ */ jsx76("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13009
- /* @__PURE__ */ jsx76("div", { style: { height: spacerHeight } }),
13010
- header && /* @__PURE__ */ jsx76(
13090
+ /* @__PURE__ */ jsx77("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13091
+ /* @__PURE__ */ jsx77("div", { style: { height: spacerHeight } }),
13092
+ header && /* @__PURE__ */ jsx77(
13011
13093
  "div",
13012
13094
  {
13013
13095
  ref: headerRef,
@@ -13016,7 +13098,7 @@ function HeroShrinkLayout({
13016
13098
  children: header
13017
13099
  }
13018
13100
  ),
13019
- /* @__PURE__ */ jsx76(
13101
+ /* @__PURE__ */ jsx77(
13020
13102
  "div",
13021
13103
  {
13022
13104
  ref: heroRef,
@@ -13024,15 +13106,15 @@ function HeroShrinkLayout({
13024
13106
  children: hero
13025
13107
  }
13026
13108
  ),
13027
- /* @__PURE__ */ jsx76("div", { className: "relative z-10 bg-background", children })
13109
+ /* @__PURE__ */ jsx77("div", { className: "relative z-10 bg-background", children })
13028
13110
  ]
13029
13111
  }
13030
13112
  );
13031
13113
  }
13032
13114
 
13033
13115
  // src/layouts/pdp/ImageEdgeBlur.tsx
13034
- import React50 from "react";
13035
- import { jsx as jsx77 } from "react/jsx-runtime";
13116
+ import React51 from "react";
13117
+ import { jsx as jsx78 } from "react/jsx-runtime";
13036
13118
  var BLUR_CONFIG = {
13037
13119
  blur: 24,
13038
13120
  crossfade: 68
@@ -13056,7 +13138,7 @@ var BLUR_LAYERS = [
13056
13138
  { blur: Math.round(BLUR_CONFIG.blur * 0.5), zone: 0.6 },
13057
13139
  { blur: BLUR_CONFIG.blur, zone: 1 }
13058
13140
  ];
13059
- var ImageEdgeBlur = React50.memo(
13141
+ var ImageEdgeBlur = React51.memo(
13060
13142
  function ImageEdgeBlur2({
13061
13143
  imageSrc,
13062
13144
  imageCapInfo,
@@ -13087,7 +13169,7 @@ var ImageEdgeBlur = React50.memo(
13087
13169
  viewportWidth / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO,
13088
13170
  maxWidthPx / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO
13089
13171
  );
13090
- return /* @__PURE__ */ jsx77(
13172
+ return /* @__PURE__ */ jsx78(
13091
13173
  "div",
13092
13174
  {
13093
13175
  className: `absolute inset-0 pointer-events-none overflow-hidden ${className}`,
@@ -13095,7 +13177,7 @@ var ImageEdgeBlur = React50.memo(
13095
13177
  children: BLUR_LAYERS.map((layer, index) => {
13096
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}%)`;
13097
13179
  const blurScale = 1 + layer.blur * 3 / containerHeightPx;
13098
- return /* @__PURE__ */ jsx77(
13180
+ return /* @__PURE__ */ jsx78(
13099
13181
  "img",
13100
13182
  {
13101
13183
  src: imageSrc,
@@ -13142,7 +13224,7 @@ var ImageEdgeBlur = React50.memo(
13142
13224
  );
13143
13225
 
13144
13226
  // src/layouts/pdp/PDPLayout.tsx
13145
- import { jsx as jsx78, jsxs as jsxs54 } from "react/jsx-runtime";
13227
+ import { jsx as jsx79, jsxs as jsxs54 } from "react/jsx-runtime";
13146
13228
  function PDPLayout({
13147
13229
  renderHeroImage,
13148
13230
  renderContent,
@@ -13172,13 +13254,13 @@ function PDPLayout({
13172
13254
  };
13173
13255
  return /* @__PURE__ */ jsxs54("div", { className: `pdp-layout ${className}`, children: [
13174
13256
  (isDesktop === false || isDesktop === null) && /* @__PURE__ */ jsxs54("div", { className: "md:hidden", children: [
13175
- renderMobileCarousel && /* @__PURE__ */ jsx78("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13176
- /* @__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) })
13177
13259
  ] }),
13178
13260
  (isDesktop === true || isDesktop === null) && /* @__PURE__ */ jsxs54("div", { className: "hidden md:block relative", children: [
13179
13261
  /* @__PURE__ */ jsxs54("div", { className: "desktop-hero relative", children: [
13180
13262
  renderHeroImage(heroProps),
13181
- showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ jsx78(
13263
+ showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ jsx79(
13182
13264
  ImageEdgeBlur,
13183
13265
  {
13184
13266
  imageSrc: blurImageSrc,
@@ -13189,7 +13271,7 @@ function PDPLayout({
13189
13271
  }
13190
13272
  )
13191
13273
  ] }),
13192
- /* @__PURE__ */ jsx78(
13274
+ /* @__PURE__ */ jsx79(
13193
13275
  "div",
13194
13276
  {
13195
13277
  className: "desktop-sidebar",
@@ -13206,8 +13288,8 @@ function PDPLayout({
13206
13288
  }
13207
13289
 
13208
13290
  // src/layouts/pdp/SimpleImageBlur.tsx
13209
- import React51 from "react";
13210
- import { jsx as jsx79 } from "react/jsx-runtime";
13291
+ import React52 from "react";
13292
+ import { jsx as jsx80 } from "react/jsx-runtime";
13211
13293
  var BLUR_CONFIG2 = {
13212
13294
  blur: 24,
13213
13295
  crossfade: 60
@@ -13230,7 +13312,7 @@ function getFadeInMask(crossfadeWidth) {
13230
13312
  black ${crossfadeWidth + 10}px
13231
13313
  )`;
13232
13314
  }
13233
- var SimpleImageBlur = React51.memo(function SimpleImageBlur2({
13315
+ var SimpleImageBlur = React52.memo(function SimpleImageBlur2({
13234
13316
  imageSrc,
13235
13317
  width,
13236
13318
  height = "100%",
@@ -13240,7 +13322,7 @@ var SimpleImageBlur = React51.memo(function SimpleImageBlur2({
13240
13322
  if (!imageSrc || width <= 0) return null;
13241
13323
  const fadeInMask = getFadeInMask(BLUR_CONFIG2.crossfade);
13242
13324
  const extendedWidth = width + BLUR_CONFIG2.blur * 2;
13243
- return /* @__PURE__ */ jsx79(
13325
+ return /* @__PURE__ */ jsx80(
13244
13326
  "div",
13245
13327
  {
13246
13328
  className: `relative overflow-hidden ${className}`,
@@ -13253,7 +13335,7 @@ var SimpleImageBlur = React51.memo(function SimpleImageBlur2({
13253
13335
  black 0%,
13254
13336
  black ${layer.zone * 100}%,
13255
13337
  transparent ${layer.zone * 100 + 10}%)`;
13256
- return /* @__PURE__ */ jsx79(
13338
+ return /* @__PURE__ */ jsx80(
13257
13339
  "img",
13258
13340
  {
13259
13341
  src: imageSrc,
@@ -13283,8 +13365,8 @@ var SimpleImageBlur = React51.memo(function SimpleImageBlur2({
13283
13365
  });
13284
13366
 
13285
13367
  // src/layouts/pdp/EdgeBlurBox.tsx
13286
- import React52 from "react";
13287
- 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";
13288
13370
  var BLUR_CONFIG3 = {
13289
13371
  blur: 24,
13290
13372
  crossfade: 60
@@ -13308,7 +13390,7 @@ function getFadeOutMask(crossfadeWidth) {
13308
13390
  transparent 100%
13309
13391
  )`;
13310
13392
  }
13311
- var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13393
+ var EdgeBlurBox = React53.memo(function EdgeBlurBox2({
13312
13394
  imageSrc,
13313
13395
  width,
13314
13396
  height = "100%",
@@ -13334,7 +13416,7 @@ var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13334
13416
  overflow: hasOverlap ? "visible" : "hidden"
13335
13417
  },
13336
13418
  children: [
13337
- /* @__PURE__ */ jsx80(
13419
+ /* @__PURE__ */ jsx81(
13338
13420
  "div",
13339
13421
  {
13340
13422
  style: {
@@ -13348,7 +13430,7 @@ var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13348
13430
  transparent ${100 - (layer.zone * 100 + 10)}%,
13349
13431
  black ${100 - layer.zone * 100}%,
13350
13432
  black 100%)`;
13351
- return /* @__PURE__ */ jsx80(
13433
+ return /* @__PURE__ */ jsx81(
13352
13434
  "img",
13353
13435
  {
13354
13436
  src: imageSrc,
@@ -13376,7 +13458,7 @@ var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13376
13458
  })
13377
13459
  }
13378
13460
  ),
13379
- /* @__PURE__ */ jsx80(
13461
+ /* @__PURE__ */ jsx81(
13380
13462
  "img",
13381
13463
  {
13382
13464
  src: imageSrc,
@@ -13404,8 +13486,8 @@ var EdgeBlurBox = React52.memo(function EdgeBlurBox2({
13404
13486
  });
13405
13487
 
13406
13488
  // src/layouts/pdp/ImageBlurExtension.tsx
13407
- import React53 from "react";
13408
- 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";
13409
13491
  var BLUR_CONFIG4 = {
13410
13492
  blur: 24,
13411
13493
  crossfadeWidth: 80
@@ -13428,7 +13510,7 @@ function getFadeOutMask2(crossfadeWidth) {
13428
13510
  transparent 100%
13429
13511
  )`;
13430
13512
  }
13431
- var ImageBlurExtension = React53.memo(function ImageBlurExtension2({
13513
+ var ImageBlurExtension = React54.memo(function ImageBlurExtension2({
13432
13514
  imageSrc,
13433
13515
  width,
13434
13516
  height,
@@ -13451,7 +13533,7 @@ var ImageBlurExtension = React53.memo(function ImageBlurExtension2({
13451
13533
  height: heightValue
13452
13534
  },
13453
13535
  children: [
13454
- BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ jsx81(
13536
+ BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ jsx82(
13455
13537
  "img",
13456
13538
  {
13457
13539
  src: imageSrc,
@@ -13475,7 +13557,7 @@ var ImageBlurExtension = React53.memo(function ImageBlurExtension2({
13475
13557
  },
13476
13558
  `blur-${index}`
13477
13559
  )),
13478
- /* @__PURE__ */ jsx81(
13560
+ /* @__PURE__ */ jsx82(
13479
13561
  "img",
13480
13562
  {
13481
13563
  src: imageSrc,
@@ -13503,23 +13585,23 @@ var ImageBlurExtension = React53.memo(function ImageBlurExtension2({
13503
13585
  });
13504
13586
 
13505
13587
  // src/design-system/ColorSwatch.tsx
13506
- import { jsx as jsx82, jsxs as jsxs57 } from "react/jsx-runtime";
13588
+ import { jsx as jsx83, jsxs as jsxs57 } from "react/jsx-runtime";
13507
13589
  function ColorTokenSwatch({ name, cssVar, className = "" }) {
13508
13590
  return /* @__PURE__ */ jsxs57("div", { className: `flex flex-col gap-1 ${className}`, children: [
13509
- /* @__PURE__ */ jsx82(
13591
+ /* @__PURE__ */ jsx83(
13510
13592
  "div",
13511
13593
  {
13512
13594
  className: "h-16 w-full rounded-lg border border-border shadow-sm",
13513
13595
  style: { backgroundColor: `var(${cssVar})` }
13514
13596
  }
13515
13597
  ),
13516
- /* @__PURE__ */ jsx82("div", { className: "text-sm font-medium text-foreground", children: name }),
13517
- /* @__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 })
13518
13600
  ] });
13519
13601
  }
13520
13602
  function ColorRow({ name, cssVar, description }) {
13521
13603
  return /* @__PURE__ */ jsxs57("div", { className: "flex items-center gap-4 py-2", children: [
13522
- /* @__PURE__ */ jsx82(
13604
+ /* @__PURE__ */ jsx83(
13523
13605
  "div",
13524
13606
  {
13525
13607
  className: "h-10 w-10 rounded-lg border border-border shadow-sm flex-shrink-0",
@@ -13527,15 +13609,15 @@ function ColorRow({ name, cssVar, description }) {
13527
13609
  }
13528
13610
  ),
13529
13611
  /* @__PURE__ */ jsxs57("div", { className: "flex-1 min-w-0", children: [
13530
- /* @__PURE__ */ jsx82("div", { className: "text-sm font-medium text-foreground", children: name }),
13531
- 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 })
13532
13614
  ] }),
13533
- /* @__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 })
13534
13616
  ] });
13535
13617
  }
13536
13618
 
13537
13619
  // src/design-system/ColorPalette.tsx
13538
- import { jsx as jsx83, jsxs as jsxs58 } from "react/jsx-runtime";
13620
+ import { jsx as jsx84, jsxs as jsxs58 } from "react/jsx-runtime";
13539
13621
  var COLOR_GROUPS = [
13540
13622
  {
13541
13623
  name: "Base",
@@ -13616,17 +13698,17 @@ var COLOR_GROUPS = [
13616
13698
  }
13617
13699
  ];
13618
13700
  function ColorPalette({ layout = "list", className = "" }) {
13619
- return /* @__PURE__ */ jsx83("div", { className: `space-y-8 ${className}`, children: COLOR_GROUPS.map((group) => /* @__PURE__ */ jsxs58("section", { children: [
13620
- /* @__PURE__ */ jsx83("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
13621
- /* @__PURE__ */ jsx83("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
13622
- 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(
13623
13705
  ColorTokenSwatch,
13624
13706
  {
13625
13707
  name: color.name,
13626
13708
  cssVar: color.cssVar
13627
13709
  },
13628
13710
  color.cssVar
13629
- )) }) : /* @__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(
13630
13712
  ColorRow,
13631
13713
  {
13632
13714
  name: color.name,
@@ -13639,7 +13721,7 @@ function ColorPalette({ layout = "list", className = "" }) {
13639
13721
  }
13640
13722
 
13641
13723
  // src/design-system/TypographyScale.tsx
13642
- import { jsx as jsx84, jsxs as jsxs59 } from "react/jsx-runtime";
13724
+ import { jsx as jsx85, jsxs as jsxs59 } from "react/jsx-runtime";
13643
13725
  var FONT_SAMPLES = [
13644
13726
  {
13645
13727
  name: "Heading",
@@ -13673,14 +13755,14 @@ var FONT_SAMPLES = [
13673
13755
  }
13674
13756
  ];
13675
13757
  function TypographyScale({ className = "" }) {
13676
- 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: [
13677
13759
  /* @__PURE__ */ jsxs59("div", { className: "flex items-center justify-between mb-4", children: [
13678
- /* @__PURE__ */ jsx84("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
13679
- /* @__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 })
13680
13762
  ] }),
13681
- /* @__PURE__ */ jsx84("div", { className: "space-y-4", children: font.sizes.map((size) => /* @__PURE__ */ jsxs59("div", { className: "flex items-baseline gap-4", children: [
13682
- /* @__PURE__ */ jsx84("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
13683
- /* @__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(
13684
13766
  "p",
13685
13767
  {
13686
13768
  className: `${size} text-foreground`,
@@ -13699,8 +13781,8 @@ var RADIUS_SAMPLES = [
13699
13781
  { name: "Full", value: "9999px" }
13700
13782
  ];
13701
13783
  function RadiusScale({ className = "" }) {
13702
- 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: [
13703
- /* @__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(
13704
13786
  "div",
13705
13787
  {
13706
13788
  className: "h-16 w-16 bg-primary",
@@ -13709,14 +13791,14 @@ function RadiusScale({ className = "" }) {
13709
13791
  }
13710
13792
  }
13711
13793
  ),
13712
- /* @__PURE__ */ jsx84("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
13713
- /* @__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 })
13714
13796
  ] }, radius.name)) }) });
13715
13797
  }
13716
13798
 
13717
13799
  // src/design-system/ThemeSwitcher.tsx
13718
- import { useState as useState44, useEffect as useEffect45 } from "react";
13719
- 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";
13720
13802
  function readThemeFromDOM() {
13721
13803
  if (typeof document === "undefined") {
13722
13804
  return { themeName: "Linear", isDark: false };
@@ -13734,10 +13816,10 @@ function readThemeFromDOM() {
13734
13816
  return { themeName: "Linear", isDark: dark };
13735
13817
  }
13736
13818
  function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
13737
- const [currentTheme, setCurrentTheme] = useState44("Linear");
13738
- const [isDark, setIsDark] = useState44(false);
13739
- const [isOpen, setIsOpen] = useState44(false);
13740
- useEffect45(() => {
13819
+ const [currentTheme, setCurrentTheme] = useState45("Linear");
13820
+ const [isDark, setIsDark] = useState45(false);
13821
+ const [isOpen, setIsOpen] = useState45(false);
13822
+ useEffect46(() => {
13741
13823
  const { themeName, isDark: dark } = readThemeFromDOM();
13742
13824
  setCurrentTheme(themeName);
13743
13825
  setIsDark(dark);
@@ -13784,35 +13866,35 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
13784
13866
  onClick: () => setIsOpen(!isOpen),
13785
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",
13786
13868
  children: [
13787
- /* @__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" }) }),
13788
- /* @__PURE__ */ jsx85("span", { className: "font-medium", children: currentTheme }),
13789
- /* @__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" }) })
13790
13872
  ]
13791
13873
  }
13792
13874
  ),
13793
- isOpen && /* @__PURE__ */ jsxs60(Fragment18, { children: [
13794
- /* @__PURE__ */ jsx85(
13875
+ isOpen && /* @__PURE__ */ jsxs60(Fragment19, { children: [
13876
+ /* @__PURE__ */ jsx86(
13795
13877
  "div",
13796
13878
  {
13797
13879
  className: "fixed inset-0 z-40",
13798
13880
  onClick: () => setIsOpen(false)
13799
13881
  }
13800
13882
  ),
13801
- /* @__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(
13802
13884
  "button",
13803
13885
  {
13804
13886
  onClick: () => handleThemeSelect(theme.name),
13805
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" : ""}`,
13806
13888
  children: [
13807
- /* @__PURE__ */ jsx85(
13889
+ /* @__PURE__ */ jsx86(
13808
13890
  "div",
13809
13891
  {
13810
13892
  className: "w-4 h-4 rounded-full border border-border",
13811
13893
  style: { backgroundColor: theme.primaryColor || "#888" }
13812
13894
  }
13813
13895
  ),
13814
- /* @__PURE__ */ jsx85("span", { className: "text-foreground", children: theme.name }),
13815
- 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" }) })
13816
13898
  ]
13817
13899
  },
13818
13900
  theme.name
@@ -13827,10 +13909,10 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
13827
13909
  title: `Switch to ${isDark ? "light" : "dark"} mode`,
13828
13910
  children: [
13829
13911
  isDark ? /* @__PURE__ */ jsxs60("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
13830
- /* @__PURE__ */ jsx85("circle", { cx: "12", cy: "12", r: "5" }),
13831
- /* @__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" })
13832
- ] }) : /* @__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" }) }),
13833
- /* @__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" })
13834
13916
  ]
13835
13917
  }
13836
13918
  )
@@ -13838,7 +13920,7 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
13838
13920
  }
13839
13921
 
13840
13922
  // src/design-system/DesignSystemPage.tsx
13841
- import { jsx as jsx86, jsxs as jsxs61 } from "react/jsx-runtime";
13923
+ import { jsx as jsx87, jsxs as jsxs61 } from "react/jsx-runtime";
13842
13924
  function DesignSystemPage({
13843
13925
  showThemeSwitcher = true,
13844
13926
  showColors = true,
@@ -13849,28 +13931,28 @@ function DesignSystemPage({
13849
13931
  className = ""
13850
13932
  }) {
13851
13933
  return /* @__PURE__ */ jsxs61("div", { className: `max-w-4xl mx-auto px-4 py-8 ${className}`, children: [
13852
- /* @__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: [
13853
13935
  /* @__PURE__ */ jsxs61("div", { children: [
13854
- /* @__PURE__ */ jsx86("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
13855
- /* @__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" })
13856
13938
  ] }),
13857
- showThemeSwitcher && /* @__PURE__ */ jsx86(ThemeSwitcher, {})
13939
+ showThemeSwitcher && /* @__PURE__ */ jsx87(ThemeSwitcher, {})
13858
13940
  ] }) }),
13859
13941
  showColors && /* @__PURE__ */ jsxs61("section", { className: "mb-16", children: [
13860
- /* @__PURE__ */ jsx86("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Color Palette" }),
13861
- /* @__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 })
13862
13944
  ] }),
13863
13945
  showTypography && /* @__PURE__ */ jsxs61("section", { className: "mb-16", children: [
13864
- /* @__PURE__ */ jsx86("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
13865
- /* @__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, {})
13866
13948
  ] }),
13867
13949
  showRadius && /* @__PURE__ */ jsxs61("section", { className: "mb-16", children: [
13868
- /* @__PURE__ */ jsx86("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Border Radius" }),
13869
- /* @__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, {})
13870
13952
  ] }),
13871
13953
  showSpacing && /* @__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: "Spacing Scale" }),
13873
- /* @__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, {})
13874
13956
  ] })
13875
13957
  ] });
13876
13958
  }
@@ -13885,25 +13967,25 @@ function SpacingScale() {
13885
13967
  { name: "12", value: "3rem" },
13886
13968
  { name: "16", value: "4rem" }
13887
13969
  ];
13888
- return /* @__PURE__ */ jsx86("div", { className: "space-y-2", children: spaces.map((space) => /* @__PURE__ */ jsxs61("div", { className: "flex items-center gap-4", children: [
13889
- /* @__PURE__ */ jsx86("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
13890
- /* @__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(
13891
13973
  "div",
13892
13974
  {
13893
13975
  className: "h-4 bg-primary rounded",
13894
13976
  style: { width: space.value }
13895
13977
  }
13896
13978
  ),
13897
- /* @__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 })
13898
13980
  ] }, space.name)) });
13899
13981
  }
13900
13982
 
13901
13983
  // src/personalization/PersonalizationProvider.tsx
13902
- import React54, {
13903
- useState as useState45,
13984
+ import React55, {
13985
+ useState as useState46,
13904
13986
  useCallback as useCallback26,
13905
13987
  useRef as useRef30,
13906
- useEffect as useEffect46
13988
+ useEffect as useEffect47
13907
13989
  } from "react";
13908
13990
 
13909
13991
  // src/personalization/PersonalizationContext.ts
@@ -13914,18 +13996,18 @@ function usePersonalizationContext() {
13914
13996
  }
13915
13997
 
13916
13998
  // src/personalization/PersonalizationProvider.tsx
13917
- 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";
13918
14000
  function createBridgeFromCanvas(canvasModule) {
13919
14001
  const { useEditor, useCommands, useImageBinding } = canvasModule;
13920
14002
  function TextBinder({ name, value }) {
13921
14003
  const { elements } = useEditor();
13922
14004
  const { executeElementUpdate } = useCommands();
13923
- const elementsRef = React54.useRef(elements);
14005
+ const elementsRef = React55.useRef(elements);
13924
14006
  elementsRef.current = elements;
13925
- const executeRef = React54.useRef(executeElementUpdate);
14007
+ const executeRef = React55.useRef(executeElementUpdate);
13926
14008
  executeRef.current = executeElementUpdate;
13927
- const hasUserInput = React54.useRef(false);
13928
- React54.useEffect(() => {
14009
+ const hasUserInput = React55.useRef(false);
14010
+ React55.useEffect(() => {
13929
14011
  if (value == null) return;
13930
14012
  if (value === "" && !hasUserInput.current) return;
13931
14013
  hasUserInput.current = true;
@@ -13943,12 +14025,12 @@ function createBridgeFromCanvas(canvasModule) {
13943
14025
  function ColorBinder({ originalColor, newColor }) {
13944
14026
  const { elements } = useEditor();
13945
14027
  const { executeElementUpdate } = useCommands();
13946
- const elementsRef = React54.useRef(elements);
14028
+ const elementsRef = React55.useRef(elements);
13947
14029
  elementsRef.current = elements;
13948
- const executeRef = React54.useRef(executeElementUpdate);
14030
+ const executeRef = React55.useRef(executeElementUpdate);
13949
14031
  executeRef.current = executeElementUpdate;
13950
- const appliedColorRef = React54.useRef(normalizeHex(originalColor));
13951
- React54.useEffect(() => {
14032
+ const appliedColorRef = React55.useRef(normalizeHex(originalColor));
14033
+ React55.useEffect(() => {
13952
14034
  const normalizedNew = normalizeHex(newColor);
13953
14035
  if (normalizedNew === appliedColorRef.current) return;
13954
14036
  const matchColor = appliedColorRef.current;
@@ -13988,11 +14070,11 @@ function createBridgeFromCanvas(canvasModule) {
13988
14070
  }
13989
14071
  function ImageBinder({ name, value, fit = "cover" }) {
13990
14072
  const { setImageUrl } = useImageBinding(name, { fit });
13991
- const hasUserInput = React54.useRef(false);
14073
+ const hasUserInput = React55.useRef(false);
13992
14074
  const debouncedValue = useDebouncedValue(value, 500);
13993
- const setImageUrlRef = React54.useRef(setImageUrl);
14075
+ const setImageUrlRef = React55.useRef(setImageUrl);
13994
14076
  setImageUrlRef.current = setImageUrl;
13995
- React54.useEffect(() => {
14077
+ React55.useEffect(() => {
13996
14078
  if (debouncedValue == null) return;
13997
14079
  if (debouncedValue === "" && !hasUserInput.current) return;
13998
14080
  hasUserInput.current = true;
@@ -14002,15 +14084,15 @@ function createBridgeFromCanvas(canvasModule) {
14002
14084
  return null;
14003
14085
  }
14004
14086
  return function PersonalizationBridge({ fields = [], values = {} } = {}) {
14005
- return /* @__PURE__ */ jsx87(Fragment19, { children: fields.map((field) => {
14087
+ return /* @__PURE__ */ jsx88(Fragment20, { children: fields.map((field) => {
14006
14088
  if (field.type === "text") {
14007
- 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}`);
14008
14090
  }
14009
14091
  if (field.type === "color") {
14010
- 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}`);
14011
14093
  }
14012
14094
  if (field.type === "image") {
14013
- 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}`);
14014
14096
  }
14015
14097
  return null;
14016
14098
  }) });
@@ -14032,19 +14114,19 @@ function PersonalizationProvider({
14032
14114
  children
14033
14115
  }) {
14034
14116
  const realtime = useRealtimeOptional();
14035
- const [personValues, setPersonValues] = useState45(initialValues ?? {});
14036
- const [isActive, setIsActive] = useState45(!!(initialValues && Object.keys(initialValues).length > 0));
14037
- const [isExporting, setIsExporting] = useState45(false);
14038
- const [exportedBlobUrls, setExportedBlobUrls] = useState45({});
14039
- 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);
14040
14122
  const blobUrlsRef = useRef30({});
14041
- const [CanvasComponent, setCanvasComponent] = useState45(
14123
+ const [CanvasComponent, setCanvasComponent] = useState46(
14042
14124
  cachedCanvasComponent
14043
14125
  );
14044
- const [BridgeComponent, setBridgeComponent] = useState45(
14126
+ const [BridgeComponent, setBridgeComponent] = useState46(
14045
14127
  cachedBridgeComponent
14046
14128
  );
14047
- useEffect46(() => {
14129
+ useEffect47(() => {
14048
14130
  if (CanvasComponent && BridgeComponent) return;
14049
14131
  if (!canvasImport) return;
14050
14132
  if (!canvasLoadPromise) {
@@ -14063,7 +14145,7 @@ function PersonalizationProvider({
14063
14145
  });
14064
14146
  }, [CanvasComponent, BridgeComponent, canvasImport]);
14065
14147
  const realtimeEnabledRef = useRef30(false);
14066
- useEffect46(() => {
14148
+ useEffect47(() => {
14067
14149
  return () => {
14068
14150
  for (const url of Object.values(blobUrlsRef.current)) {
14069
14151
  try {
@@ -14120,7 +14202,7 @@ function PersonalizationProvider({
14120
14202
  setIsExporting(true);
14121
14203
  }, []);
14122
14204
  const shouldMountCanvas = CanvasComponent && BridgeComponent && canvasState?.elements && canvasState.elements.length > 0 && (!lazy || isActive);
14123
- const contextValue = React54.useMemo(
14205
+ const contextValue = React55.useMemo(
14124
14206
  () => ({
14125
14207
  fields,
14126
14208
  personValues,
@@ -14134,7 +14216,7 @@ function PersonalizationProvider({
14134
14216
  [fields, personValues, updateField, isActive, isExporting, exportedBlobUrls, exportCount, reset]
14135
14217
  );
14136
14218
  return /* @__PURE__ */ jsxs62(PersonalizationContext.Provider, { value: contextValue, children: [
14137
- shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ jsx87(
14219
+ shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ jsx88(
14138
14220
  "div",
14139
14221
  {
14140
14222
  style: {
@@ -14147,7 +14229,7 @@ function PersonalizationProvider({
14147
14229
  pointerEvents: "none"
14148
14230
  },
14149
14231
  "aria-hidden": true,
14150
- children: /* @__PURE__ */ jsx87(
14232
+ children: /* @__PURE__ */ jsx88(
14151
14233
  CanvasComponent,
14152
14234
  {
14153
14235
  initialElements: canvasState?.elements,
@@ -14167,7 +14249,7 @@ function PersonalizationProvider({
14167
14249
  exportImageQuality: exportConfig?.imageQuality ?? 0.85,
14168
14250
  onExport: handleExport,
14169
14251
  onExportScheduled: handleExportScheduled,
14170
- overlay: /* @__PURE__ */ jsx87(BridgeComponent, { fields, values: personValues })
14252
+ overlay: /* @__PURE__ */ jsx88(BridgeComponent, { fields, values: personValues })
14171
14253
  }
14172
14254
  )
14173
14255
  },
@@ -14192,7 +14274,7 @@ function usePersonalizationOptional() {
14192
14274
  }
14193
14275
 
14194
14276
  // src/personalization/PersonalizationInputs.tsx
14195
- import { jsx as jsx88, jsxs as jsxs63 } from "react/jsx-runtime";
14277
+ import { jsx as jsx89, jsxs as jsxs63 } from "react/jsx-runtime";
14196
14278
  function PersonalizationInputs({
14197
14279
  className,
14198
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",
@@ -14217,7 +14299,7 @@ function PersonalizationInputs({
14217
14299
  }
14218
14300
  };
14219
14301
  return /* @__PURE__ */ jsxs63("div", { className: className || "flex flex-col gap-3", children: [
14220
- textFields.map((field) => /* @__PURE__ */ jsx88(
14302
+ textFields.map((field) => /* @__PURE__ */ jsx89(
14221
14303
  "input",
14222
14304
  {
14223
14305
  type: "text",
@@ -14232,7 +14314,7 @@ function PersonalizationInputs({
14232
14314
  `text-${field.name}`
14233
14315
  )),
14234
14316
  colorFields.map((field) => /* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-3", children: [
14235
- /* @__PURE__ */ jsx88(
14317
+ /* @__PURE__ */ jsx89(
14236
14318
  "input",
14237
14319
  {
14238
14320
  type: "color",
@@ -14241,9 +14323,9 @@ function PersonalizationInputs({
14241
14323
  onChange: (e) => updateField(field.color, e.target.value)
14242
14324
  }
14243
14325
  ),
14244
- /* @__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 })
14245
14327
  ] }, `color-${field.color}`)),
14246
- imageFields.map((field) => /* @__PURE__ */ jsx88(
14328
+ imageFields.map((field) => /* @__PURE__ */ jsx89(
14247
14329
  "input",
14248
14330
  {
14249
14331
  type: "text",
@@ -14261,11 +14343,11 @@ function PersonalizationInputs({
14261
14343
  }
14262
14344
 
14263
14345
  // src/personalization/usePersonalizationShimmer.ts
14264
- 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";
14265
14347
  function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
14266
14348
  const personCtx = usePersonalizationContext();
14267
14349
  const realtime = useRealtimeOptional();
14268
- const [shimmerActive, setShimmerActive] = useState46(false);
14350
+ const [shimmerActive, setShimmerActive] = useState47(false);
14269
14351
  const sdkSettledRef = useRef31(false);
14270
14352
  const manualTriggerRef = useRef31(false);
14271
14353
  const safetyTimeoutRef = useRef31(void 0);
@@ -14281,7 +14363,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
14281
14363
  safetyTimeoutMs
14282
14364
  );
14283
14365
  }, [safetyTimeoutMs]);
14284
- useEffect47(() => {
14366
+ useEffect48(() => {
14285
14367
  if (!personCtx?.isActive) return;
14286
14368
  sdkSettledRef.current = false;
14287
14369
  manualTriggerRef.current = false;
@@ -14293,13 +14375,13 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
14293
14375
  manualTriggerRef.current = true;
14294
14376
  startShimmer();
14295
14377
  }, [startShimmer]);
14296
- useEffect47(() => {
14378
+ useEffect48(() => {
14297
14379
  if (!realtime?.subscribePipelineSettled) return;
14298
14380
  return realtime.subscribePipelineSettled(() => {
14299
14381
  sdkSettledRef.current = true;
14300
14382
  });
14301
14383
  }, [realtime]);
14302
- useEffect47(() => {
14384
+ useEffect48(() => {
14303
14385
  const container = containerRef.current;
14304
14386
  if (!container) return;
14305
14387
  const observer = new MutationObserver((mutations) => {
@@ -14342,7 +14424,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
14342
14424
  });
14343
14425
  return () => observer.disconnect();
14344
14426
  }, [containerRef]);
14345
- useEffect47(() => {
14427
+ useEffect48(() => {
14346
14428
  return () => {
14347
14429
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
14348
14430
  };
@@ -14483,6 +14565,7 @@ export {
14483
14565
  RealtimeProvider,
14484
14566
  ResponsiveZoom,
14485
14567
  RightToLeftProgressiveBlur,
14568
+ SafeImg,
14486
14569
  ScrollFade,
14487
14570
  SearchBox,
14488
14571
  SearchProvider,