@snowcone-app/ui 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -271,6 +271,7 @@ __export(src_exports, {
271
271
  RealtimeProvider: () => RealtimeProvider,
272
272
  ResponsiveZoom: () => ResponsiveZoom,
273
273
  RightToLeftProgressiveBlur: () => RightToLeftProgressiveBlur,
274
+ SafeImg: () => SafeImg,
274
275
  ScrollFade: () => ScrollFade,
275
276
  SearchBox: () => SearchBox,
276
277
  SearchProvider: () => SearchProvider,
@@ -378,7 +379,7 @@ __export(src_exports, {
378
379
  useProductSelection: () => useProductSelection,
379
380
  useProviderStatus: () => useProviderStatus,
380
381
  useRealtime: () => useRealtime,
381
- useRealtimeMockup: () => import_react69.useRealtimeMockup,
382
+ useRealtimeMockup: () => import_react70.useRealtimeMockup,
382
383
  useRealtimeOptional: () => useRealtimeOptional,
383
384
  useRenderCount: () => useRenderCount,
384
385
  useRenderGuard: () => useRenderGuard,
@@ -9341,7 +9342,7 @@ var LoadingOverlayPrismCandyInline = (0, import_react40.memo)(
9341
9342
  );
9342
9343
 
9343
9344
  // src/index.ts
9344
- var import_react69 = require("@snowcone-app/sdk/react");
9345
+ var import_react70 = require("@snowcone-app/sdk/react");
9345
9346
  var import_sdk11 = require("@snowcone-app/sdk");
9346
9347
 
9347
9348
  // src/patterns/ProductPageProvider.tsx
@@ -10415,12 +10416,18 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10415
10416
  const [showNew, setShowNew] = (0, import_react45.useState)(false);
10416
10417
  const [renderedUrl, setRenderedUrl] = (0, import_react45.useState)(displayUrl);
10417
10418
  const [firstImageLoaded, setFirstImageLoaded] = (0, import_react45.useState)(false);
10419
+ const [loaderMounted, setLoaderMounted] = (0, import_react45.useState)(true);
10420
+ const [imgFailed, setImgFailed] = (0, import_react45.useState)(false);
10421
+ const [retryNonce, setRetryNonce] = (0, import_react45.useState)(0);
10422
+ const retriedUrlRef = (0, import_react45.useRef)(null);
10418
10423
  const prevDisplayUrlRef = (0, import_react45.useRef)(displayUrl);
10419
10424
  const signHintShownRef = (0, import_react45.useRef)(false);
10420
10425
  (0, import_react45.useEffect)(() => {
10421
10426
  if (!displayUrl || displayUrl === prevDisplayUrlRef.current) return;
10422
10427
  const oldUrl = prevDisplayUrlRef.current;
10423
10428
  prevDisplayUrlRef.current = displayUrl;
10429
+ setImgFailed(false);
10430
+ retriedUrlRef.current = null;
10424
10431
  if (!oldUrl) {
10425
10432
  setRenderedUrl(displayUrl);
10426
10433
  return;
@@ -10446,6 +10453,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10446
10453
  setPrevUrl(null);
10447
10454
  setShowNew(false);
10448
10455
  }, []);
10456
+ const handleLoaderExited = (0, import_react45.useCallback)(() => setLoaderMounted(false), []);
10449
10457
  if (!hasArtwork) {
10450
10458
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10451
10459
  "div",
@@ -10494,19 +10502,19 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10494
10502
  style,
10495
10503
  "data-hero-image": "true",
10496
10504
  children: [
10497
- !firstImageLoaded && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "absolute inset-0 bg-muted-foreground/20 animate-pulse" }),
10498
- renderedUrl && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10505
+ renderedUrl && !imgFailed && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10499
10506
  "img",
10500
10507
  {
10501
10508
  alt: `Product mockup${placement ? ` - ${placement}` : ""}`,
10502
10509
  crossOrigin: "anonymous",
10503
10510
  className: "absolute inset-0 w-full h-full object-cover",
10504
10511
  draggable,
10505
- src: renderedUrl,
10512
+ src: retriedUrlRef.current === renderedUrl ? `${renderedUrl}${renderedUrl.includes("?") ? "&" : "?"}_cb=${retryNonce}` : renderedUrl,
10506
10513
  loading: "eager",
10507
10514
  fetchPriority: "high",
10508
10515
  onClick,
10509
10516
  onLoad: () => {
10517
+ setImgFailed(false);
10510
10518
  setFirstImageLoaded(true);
10511
10519
  if (!onLoadCalledRef.current && onLoad) {
10512
10520
  onLoadCalledRef.current = true;
@@ -10515,6 +10523,12 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10515
10523
  onUrlGeneratedRef.current?.(renderedUrl);
10516
10524
  },
10517
10525
  onError: () => {
10526
+ if (renderedUrl && retriedUrlRef.current !== renderedUrl) {
10527
+ retriedUrlRef.current = renderedUrl;
10528
+ setRetryNonce((n) => n + 1);
10529
+ return;
10530
+ }
10531
+ setImgFailed(true);
10518
10532
  setFirstImageLoaded(true);
10519
10533
  onError?.();
10520
10534
  if (process.env.NODE_ENV !== "production" && !signHintShownRef.current && renderedUrl && /\/[A-Za-z0-9]+\?/.test(renderedUrl) && !/[?&]signature=/.test(renderedUrl)) {
@@ -10527,6 +10541,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10527
10541
  }
10528
10542
  }
10529
10543
  ),
10544
+ imgFailed && !prevUrl && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-muted-foreground text-xs", children: "Preview unavailable" }) }),
10530
10545
  realtimeContext?.renderError && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10531
10546
  "div",
10532
10547
  {
@@ -10550,12 +10565,45 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10550
10565
  },
10551
10566
  onTransitionEnd: handleCrossfadeEnd
10552
10567
  }
10568
+ ),
10569
+ loaderMounted && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10570
+ LoadingOverlayPrismCandyInline,
10571
+ {
10572
+ visible: !firstImageLoaded,
10573
+ variant: "light",
10574
+ onExited: handleLoaderExited
10575
+ }
10553
10576
  )
10554
10577
  ]
10555
10578
  }
10556
10579
  );
10557
10580
  });
10558
10581
 
10582
+ // src/composed/SafeImg.tsx
10583
+ var import_react46 = __toESM(require("react"), 1);
10584
+ var import_jsx_runtime61 = require("react/jsx-runtime");
10585
+ var SafeImg = import_react46.default.forwardRef(
10586
+ function SafeImg2({ fallback = null, onError, src, ...rest }, ref) {
10587
+ const [failed, setFailed] = (0, import_react46.useState)(false);
10588
+ (0, import_react46.useEffect)(() => {
10589
+ setFailed(false);
10590
+ }, [src]);
10591
+ if (failed) return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_jsx_runtime61.Fragment, { children: fallback });
10592
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10593
+ "img",
10594
+ {
10595
+ ...rest,
10596
+ ref,
10597
+ src,
10598
+ onError: (e) => {
10599
+ setFailed(true);
10600
+ onError?.(e);
10601
+ }
10602
+ }
10603
+ );
10604
+ }
10605
+ );
10606
+
10559
10607
  // src/index.ts
10560
10608
  var import_sdk12 = require("@snowcone-app/sdk");
10561
10609
 
@@ -10565,7 +10613,7 @@ var import_react_instantsearch = require("react-instantsearch");
10565
10613
  // src/composed/search/meilisearchAdapter.ts
10566
10614
  var import_instant_meilisearch = require("@meilisearch/instant-meilisearch");
10567
10615
  var MEILISEARCH_HOST = readEnv("NEXT_PUBLIC_MEILISEARCH_HOST") || "https://ms-e5d999b2eaca-15654.sfo.meilisearch.io";
10568
- var MEILISEARCH_API_KEY = readEnv("NEXT_PUBLIC_MEILISEARCH_API_KEY") || "eee819b849798ad9091228c486ec05d0931e5292";
10616
+ var MEILISEARCH_API_KEY = readEnv("NEXT_PUBLIC_MEILISEARCH_API_KEY") || "c4f053bf342250c472c2ef564628ab675543f46d0c1e606b09f41616a21c8fa7";
10569
10617
  var { searchClient } = (0, import_instant_meilisearch.instantMeiliSearch)(
10570
10618
  MEILISEARCH_HOST,
10571
10619
  MEILISEARCH_API_KEY,
@@ -10576,11 +10624,11 @@ var { searchClient } = (0, import_instant_meilisearch.instantMeiliSearch)(
10576
10624
  );
10577
10625
 
10578
10626
  // src/composed/search/SearchProvider.tsx
10579
- var import_react46 = require("react");
10580
- var import_jsx_runtime61 = require("react/jsx-runtime");
10627
+ var import_react47 = require("react");
10628
+ var import_jsx_runtime62 = require("react/jsx-runtime");
10581
10629
  function InitialSearchTrigger() {
10582
10630
  const { refine } = (0, import_react_instantsearch.useSearchBox)();
10583
- (0, import_react46.useEffect)(() => {
10631
+ (0, import_react47.useEffect)(() => {
10584
10632
  refine("");
10585
10633
  }, [refine]);
10586
10634
  return null;
@@ -10604,7 +10652,7 @@ function SearchProvider({
10604
10652
  ],
10605
10653
  children
10606
10654
  }) {
10607
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
10655
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
10608
10656
  import_react_instantsearch.InstantSearch,
10609
10657
  {
10610
10658
  searchClient,
@@ -10632,7 +10680,7 @@ function SearchProvider({
10632
10680
  }
10633
10681
  },
10634
10682
  children: [
10635
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10683
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10636
10684
  import_react_instantsearch.Configure,
10637
10685
  {
10638
10686
  hitsPerPage,
@@ -10641,7 +10689,7 @@ function SearchProvider({
10641
10689
  attributesToRetrieve
10642
10690
  }
10643
10691
  ),
10644
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(InitialSearchTrigger, {}),
10692
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(InitialSearchTrigger, {}),
10645
10693
  children
10646
10694
  ]
10647
10695
  }
@@ -10651,17 +10699,17 @@ function SearchProvider({
10651
10699
  // src/composed/search/SearchBox.tsx
10652
10700
  var import_react_instantsearch2 = require("react-instantsearch");
10653
10701
  var import_lucide_react3 = require("lucide-react");
10654
- var import_react47 = require("react");
10655
- var import_jsx_runtime62 = require("react/jsx-runtime");
10702
+ var import_react48 = require("react");
10703
+ var import_jsx_runtime63 = require("react/jsx-runtime");
10656
10704
  function SearchBox() {
10657
10705
  const { query, refine, clear } = (0, import_react_instantsearch2.useSearchBox)();
10658
10706
  const searchParams = useUiSearchParams();
10659
10707
  const router = useUiRouter();
10660
- const inputRef = (0, import_react47.useRef)(null);
10661
- const [showShimmer, setShowShimmer] = (0, import_react47.useState)(false);
10708
+ const inputRef = (0, import_react48.useRef)(null);
10709
+ const [showShimmer, setShowShimmer] = (0, import_react48.useState)(false);
10662
10710
  const inputId = "search-products-input";
10663
10711
  const descriptionId = "search-description";
10664
- (0, import_react47.useEffect)(() => {
10712
+ (0, import_react48.useEffect)(() => {
10665
10713
  const handleSpotlight = () => {
10666
10714
  inputRef.current?.focus();
10667
10715
  inputRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
@@ -10671,7 +10719,7 @@ function SearchBox() {
10671
10719
  window.addEventListener("search-spotlight", handleSpotlight);
10672
10720
  return () => window.removeEventListener("search-spotlight", handleSpotlight);
10673
10721
  }, []);
10674
- (0, import_react47.useEffect)(() => {
10722
+ (0, import_react48.useEffect)(() => {
10675
10723
  const shouldFocus = searchParams.get("focus") === "search";
10676
10724
  if (shouldFocus && inputRef.current) {
10677
10725
  const timer = setTimeout(() => {
@@ -10686,8 +10734,8 @@ function SearchBox() {
10686
10734
  return () => clearTimeout(timer);
10687
10735
  }
10688
10736
  }, [searchParams, router]);
10689
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "relative", children: [
10690
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10737
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "relative", children: [
10738
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10691
10739
  Input,
10692
10740
  {
10693
10741
  ref: inputRef,
@@ -10696,15 +10744,15 @@ function SearchBox() {
10696
10744
  value: query,
10697
10745
  onChange: (e) => refine(e.target.value),
10698
10746
  placeholder: "Search products...",
10699
- startContent: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react3.Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10700
- endContent: query ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10747
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_lucide_react3.Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10748
+ endContent: query ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10701
10749
  "button",
10702
10750
  {
10703
10751
  type: "button",
10704
10752
  onClick: clear,
10705
10753
  className: "hover:text-foreground transition-colors",
10706
10754
  "aria-label": "Clear search",
10707
- children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react3.X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10755
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_lucide_react3.X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10708
10756
  }
10709
10757
  ) : void 0,
10710
10758
  "aria-label": "Search products",
@@ -10714,11 +10762,11 @@ function SearchBox() {
10714
10762
  className: "[&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden"
10715
10763
  }
10716
10764
  ),
10717
- showShimmer && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10765
+ showShimmer && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10718
10766
  "div",
10719
10767
  {
10720
10768
  className: "absolute inset-0 pointer-events-none rounded-input z-20 overflow-hidden",
10721
- children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10769
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10722
10770
  "div",
10723
10771
  {
10724
10772
  className: "absolute inset-0",
@@ -10731,13 +10779,13 @@ function SearchBox() {
10731
10779
  )
10732
10780
  }
10733
10781
  ),
10734
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("style", { dangerouslySetInnerHTML: { __html: `
10782
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("style", { dangerouslySetInnerHTML: { __html: `
10735
10783
  @keyframes searchShimmer {
10736
10784
  0% { transform: translateX(-100%); }
10737
10785
  100% { transform: translateX(100%); }
10738
10786
  }
10739
10787
  ` } }),
10740
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10788
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10741
10789
  ] }) });
10742
10790
  }
10743
10791
 
@@ -10745,7 +10793,7 @@ function SearchBox() {
10745
10793
  var import_react_instantsearch3 = require("react-instantsearch");
10746
10794
 
10747
10795
  // src/composed/search/ProductHit.tsx
10748
- var import_jsx_runtime63 = require("react/jsx-runtime");
10796
+ var import_jsx_runtime64 = require("react/jsx-runtime");
10749
10797
  function ProductHitComponent({
10750
10798
  hit: product,
10751
10799
  variant = "overlay"
@@ -10762,12 +10810,12 @@ function ProductHitComponent({
10762
10810
  }
10763
10811
  return "";
10764
10812
  };
10765
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10813
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10766
10814
  Product,
10767
10815
  {
10768
10816
  productId,
10769
10817
  productData: product,
10770
- children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10818
+ children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10771
10819
  ProductCard,
10772
10820
  {
10773
10821
  variant,
@@ -10788,10 +10836,10 @@ function ProductHitComponent({
10788
10836
  }
10789
10837
 
10790
10838
  // src/composed/search/ProductGrid.tsx
10791
- var import_react48 = require("react");
10792
- var import_jsx_runtime64 = require("react/jsx-runtime");
10839
+ var import_react49 = require("react");
10840
+ var import_jsx_runtime65 = require("react/jsx-runtime");
10793
10841
  function ProductGridSkeletonItem() {
10794
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "aspect-square bg-muted animate-pulse" });
10842
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "aspect-square bg-muted animate-pulse" });
10795
10843
  }
10796
10844
  function ProductGrid({
10797
10845
  className = "",
@@ -10801,26 +10849,26 @@ function ProductGrid({
10801
10849
  }) {
10802
10850
  const { nbHits } = (0, import_react_instantsearch3.useStats)();
10803
10851
  const { status, results } = (0, import_react_instantsearch3.useInstantSearch)();
10804
- const [announcement, setAnnouncement] = (0, import_react48.useState)("");
10852
+ const [announcement, setAnnouncement] = (0, import_react49.useState)("");
10805
10853
  const hitsCount = results?.hits?.length ?? 0;
10806
10854
  const showSkeleton = hitsCount === 0 && status !== "error";
10807
- (0, import_react48.useEffect)(() => {
10855
+ (0, import_react49.useEffect)(() => {
10808
10856
  const timer = setTimeout(() => {
10809
10857
  setAnnouncement(`${nbHits} ${nbHits === 1 ? "product" : "products"} found`);
10810
10858
  }, 1e3);
10811
10859
  return () => clearTimeout(timer);
10812
10860
  }, [nbHits]);
10813
- const HitComponent = (0, import_react48.useCallback)(({ hit }) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10861
+ const HitComponent = (0, import_react49.useCallback)(({ hit }) => /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10814
10862
  ProductHitComponent,
10815
10863
  {
10816
10864
  hit,
10817
10865
  variant
10818
10866
  }
10819
10867
  ), [variant]);
10820
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className, children: [
10821
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10822
- showSkeleton && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: `grid ${gridClassName}`, children: Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(ProductGridSkeletonItem, {}, i)) }),
10823
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: showSkeleton ? "hidden" : "", children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10868
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className, children: [
10869
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10870
+ showSkeleton && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: `grid ${gridClassName}`, children: Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(ProductGridSkeletonItem, {}, i)) }),
10871
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: showSkeleton ? "hidden" : "", children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10824
10872
  import_react_instantsearch3.Hits,
10825
10873
  {
10826
10874
  hitComponent: HitComponent,
@@ -10835,18 +10883,18 @@ function ProductGrid({
10835
10883
  }
10836
10884
 
10837
10885
  // src/composed/search/Filters.tsx
10838
- var import_react50 = require("react");
10886
+ var import_react51 = require("react");
10839
10887
 
10840
10888
  // src/composed/search/FiltersButton.tsx
10841
10889
  var import_lucide_react4 = require("lucide-react");
10842
- var import_jsx_runtime65 = require("react/jsx-runtime");
10890
+ var import_jsx_runtime66 = require("react/jsx-runtime");
10843
10891
  var SlidersHorizontalIcon = import_lucide_react4.SlidersHorizontal;
10844
10892
  function FiltersButton({
10845
10893
  onClick,
10846
10894
  className = "",
10847
10895
  children = "Filters"
10848
10896
  }) {
10849
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
10897
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10850
10898
  Button,
10851
10899
  {
10852
10900
  variant: "field",
@@ -10854,8 +10902,8 @@ function FiltersButton({
10854
10902
  className,
10855
10903
  "aria-label": "Open filters",
10856
10904
  children: [
10857
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10858
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { children })
10905
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10906
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children })
10859
10907
  ]
10860
10908
  }
10861
10909
  );
@@ -10864,15 +10912,15 @@ function FiltersButton({
10864
10912
  // src/composed/search/FiltersDrawer.tsx
10865
10913
  var import_react_instantsearch4 = require("react-instantsearch");
10866
10914
  var import_lucide_react5 = require("lucide-react");
10867
- var import_react49 = require("react");
10915
+ var import_react50 = require("react");
10868
10916
  var Slider2 = __toESM(require("@radix-ui/react-slider"), 1);
10869
- var import_jsx_runtime66 = require("react/jsx-runtime");
10917
+ var import_jsx_runtime67 = require("react/jsx-runtime");
10870
10918
  var XIcon2 = import_lucide_react5.X;
10871
10919
  function FiltersDrawer({ isOpen, onClose }) {
10872
- const [showCounts, setShowCounts] = (0, import_react49.useState)(false);
10920
+ const [showCounts, setShowCounts] = (0, import_react50.useState)(false);
10873
10921
  const { nbHits } = (0, import_react_instantsearch4.useStats)();
10874
10922
  const containerRef = useFocusTrap(isOpen, onClose);
10875
- (0, import_react49.useEffect)(() => {
10923
+ (0, import_react50.useEffect)(() => {
10876
10924
  if (isOpen) {
10877
10925
  document.body.style.overflow = "hidden";
10878
10926
  } else {
@@ -10882,7 +10930,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10882
10930
  document.body.style.overflow = "";
10883
10931
  };
10884
10932
  }, [isOpen]);
10885
- (0, import_react49.useEffect)(() => {
10933
+ (0, import_react50.useEffect)(() => {
10886
10934
  const handleEscape = (e) => {
10887
10935
  if (e.key === "Escape" && isOpen) {
10888
10936
  onClose();
@@ -10891,8 +10939,8 @@ function FiltersDrawer({ isOpen, onClose }) {
10891
10939
  document.addEventListener("keydown", handleEscape);
10892
10940
  return () => document.removeEventListener("keydown", handleEscape);
10893
10941
  }, [isOpen, onClose]);
10894
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(import_jsx_runtime66.Fragment, { children: [
10895
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10942
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
10943
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
10896
10944
  "div",
10897
10945
  {
10898
10946
  className: `fixed inset-0 bg-black/50 z-40 transition-opacity ${isOpen ? "opacity-100" : "opacity-0 pointer-events-none"}`,
@@ -10900,7 +10948,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10900
10948
  "aria-hidden": "true"
10901
10949
  }
10902
10950
  ),
10903
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10951
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
10904
10952
  "div",
10905
10953
  {
10906
10954
  ref: containerRef,
@@ -10909,26 +10957,26 @@ function FiltersDrawer({ isOpen, onClose }) {
10909
10957
  "aria-modal": "true",
10910
10958
  "aria-labelledby": "filters-drawer-title",
10911
10959
  children: [
10912
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center justify-between px-4 py-4", children: [
10913
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10914
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10960
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "flex items-center justify-between px-4 py-4", children: [
10961
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10962
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
10915
10963
  "button",
10916
10964
  {
10917
10965
  onClick: onClose,
10918
10966
  className: "p-2 hover:bg-foreground/5 rounded-full transition-colors",
10919
10967
  "aria-label": "Close filters",
10920
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(XIcon2, { className: "w-5 h-5" })
10968
+ children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(XIcon2, { className: "w-5 h-5" })
10921
10969
  }
10922
10970
  )
10923
10971
  ] }),
10924
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("p", { className: "text-sm font-caption text-foreground/60", role: "status", "aria-live": "polite", children: [
10972
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("p", { className: "text-sm font-caption text-foreground/60", role: "status", "aria-live": "polite", children: [
10925
10973
  nbHits.toLocaleString(),
10926
10974
  " ",
10927
10975
  nbHits === 1 ? "result" : "results"
10928
10976
  ] }) }),
10929
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "flex flex-col gap-8", children: [
10930
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(TagsSection, { showCounts, setShowCounts }),
10931
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(PriceSection, {})
10977
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "flex flex-col gap-8", children: [
10978
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(TagsSection, { showCounts, setShowCounts }),
10979
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(PriceSection, {})
10932
10980
  ] }) })
10933
10981
  ]
10934
10982
  }
@@ -10944,9 +10992,9 @@ function TagsSection({
10944
10992
  sortBy: ["count:desc", "name:asc"],
10945
10993
  limit: 100
10946
10994
  });
10947
- const [isExpanded, setIsExpanded] = (0, import_react49.useState)(true);
10948
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
10949
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10995
+ const [isExpanded, setIsExpanded] = (0, import_react50.useState)(true);
10996
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
10997
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
10950
10998
  "button",
10951
10999
  {
10952
11000
  onClick: () => setIsExpanded(!isExpanded),
@@ -10954,8 +11002,8 @@ function TagsSection({
10954
11002
  "aria-expanded": isExpanded,
10955
11003
  "aria-controls": "tags-content",
10956
11004
  children: [
10957
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
10958
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11005
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
11006
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
10959
11007
  "svg",
10960
11008
  {
10961
11009
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -10964,14 +11012,14 @@ function TagsSection({
10964
11012
  stroke: "currentColor",
10965
11013
  strokeWidth: 2.5,
10966
11014
  "aria-hidden": "true",
10967
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11015
+ children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
10968
11016
  }
10969
11017
  )
10970
11018
  ]
10971
11019
  }
10972
11020
  ),
10973
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "space-y-4", id: "tags-content", children: [
10974
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "flex flex-wrap gap-2", role: "group", "aria-label": "Product tags filter", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
11021
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "space-y-4", id: "tags-content", children: [
11022
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "flex flex-wrap gap-2", role: "group", "aria-label": "Product tags filter", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
10975
11023
  "button",
10976
11024
  {
10977
11025
  onClick: () => refine(item.value),
@@ -10982,15 +11030,15 @@ function TagsSection({
10982
11030
  "aria-label": `${item.isRefined ? "Remove" : "Apply"} ${item.label} filter${showCounts ? ` (${item.count} products)` : ""}`,
10983
11031
  "aria-pressed": item.isRefined,
10984
11032
  children: [
10985
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { "aria-hidden": "true", children: item.label }),
10986
- showCounts && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: `text-xs font-caption ${item.isRefined ? "opacity-80" : "opacity-60"}`, "aria-hidden": "true", children: item.count })
11033
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { "aria-hidden": "true", children: item.label }),
11034
+ showCounts && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: `text-xs font-caption ${item.isRefined ? "opacity-80" : "opacity-60"}`, "aria-hidden": "true", children: item.count })
10987
11035
  ]
10988
11036
  },
10989
11037
  item.value
10990
11038
  )) }),
10991
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center justify-between pt-2", children: [
10992
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
10993
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11039
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "flex items-center justify-between pt-2", children: [
11040
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
11041
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
10994
11042
  "button",
10995
11043
  {
10996
11044
  onClick: () => setShowCounts(!showCounts),
@@ -10998,7 +11046,7 @@ function TagsSection({
10998
11046
  role: "switch",
10999
11047
  "aria-checked": showCounts,
11000
11048
  "aria-labelledby": "show-counts-label",
11001
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11049
+ children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11002
11050
  "span",
11003
11051
  {
11004
11052
  className: `inline-block h-4 w-4 transform rounded-full bg-background shadow-sm transition-transform ${showCounts ? "translate-x-6" : "translate-x-1"}`,
@@ -11015,11 +11063,11 @@ function PriceSection() {
11015
11063
  const { range, refine, start, canRefine } = (0, import_react_instantsearch4.useRange)({ attribute: "price" });
11016
11064
  const rangeMin = typeof range.min === "number" && isFinite(range.min) ? range.min : 0;
11017
11065
  const rangeMax = typeof range.max === "number" && isFinite(range.max) ? range.max : 15e3;
11018
- const [localRange, setLocalRange] = (0, import_react49.useState)([
11066
+ const [localRange, setLocalRange] = (0, import_react50.useState)([
11019
11067
  typeof start?.[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
11020
11068
  typeof start?.[1] === "number" && isFinite(start[1]) ? start[1] : rangeMax
11021
11069
  ]);
11022
- (0, import_react49.useEffect)(() => {
11070
+ (0, import_react50.useEffect)(() => {
11023
11071
  if (start && Array.isArray(start)) {
11024
11072
  setLocalRange([
11025
11073
  typeof start[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
@@ -11029,7 +11077,7 @@ function PriceSection() {
11029
11077
  setLocalRange([rangeMin, rangeMax]);
11030
11078
  }
11031
11079
  }, [start, rangeMin, rangeMax]);
11032
- const [isExpanded, setIsExpanded] = (0, import_react49.useState)(true);
11080
+ const [isExpanded, setIsExpanded] = (0, import_react50.useState)(true);
11033
11081
  if (!canRefine) {
11034
11082
  return null;
11035
11083
  }
@@ -11044,8 +11092,8 @@ function PriceSection() {
11044
11092
  return `$${priceInDollars.toFixed(2)}`;
11045
11093
  }
11046
11094
  };
11047
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
11048
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
11095
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
11096
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
11049
11097
  "button",
11050
11098
  {
11051
11099
  onClick: () => setIsExpanded(!isExpanded),
@@ -11053,8 +11101,8 @@ function PriceSection() {
11053
11101
  "aria-expanded": isExpanded,
11054
11102
  "aria-controls": "price-content",
11055
11103
  children: [
11056
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
11057
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11104
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
11105
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11058
11106
  "svg",
11059
11107
  {
11060
11108
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -11063,22 +11111,22 @@ function PriceSection() {
11063
11111
  stroke: "currentColor",
11064
11112
  strokeWidth: 2.5,
11065
11113
  "aria-hidden": "true",
11066
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11114
+ children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11067
11115
  }
11068
11116
  )
11069
11117
  ]
11070
11118
  }
11071
11119
  ),
11072
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "space-y-6", id: "price-content", children: [
11073
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center justify-between text-sm font-display", children: [
11074
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: formatPrice2(localRange[0]) }),
11075
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "text-foreground/70", children: formatPrice2(localRange[1]) })
11120
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "space-y-6", id: "price-content", children: [
11121
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "flex items-center justify-between text-sm font-display", children: [
11122
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { children: formatPrice2(localRange[0]) }),
11123
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "text-foreground/70", children: formatPrice2(localRange[1]) })
11076
11124
  ] }),
11077
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("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) => {
11125
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("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) => {
11078
11126
  const totalBars = 19;
11079
11127
  const barPrice = rangeMin + (rangeMax - rangeMin) / totalBars * i;
11080
11128
  const isInRange = barPrice >= localRange[0] && barPrice <= localRange[1];
11081
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11129
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11082
11130
  "div",
11083
11131
  {
11084
11132
  className: `flex-1 rounded-t-sm transition-opacity ${isInRange ? "bg-foreground" : "bg-foreground/20"}`,
@@ -11087,7 +11135,7 @@ function PriceSection() {
11087
11135
  i
11088
11136
  );
11089
11137
  }) }),
11090
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
11138
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
11091
11139
  Slider2.Root,
11092
11140
  {
11093
11141
  className: "relative flex w-full touch-none select-none items-center",
@@ -11105,8 +11153,8 @@ function PriceSection() {
11105
11153
  step: 1,
11106
11154
  minStepsBetweenThumbs: 1,
11107
11155
  children: [
11108
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Slider2.Track, { className: "relative h-3 w-full grow overflow-hidden rounded-full bg-foreground/20", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Slider2.Range, { className: "absolute h-full bg-foreground" }) }),
11109
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11156
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(Slider2.Track, { className: "relative h-3 w-full grow overflow-hidden rounded-full bg-foreground/20", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(Slider2.Range, { className: "absolute h-full bg-foreground" }) }),
11157
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11110
11158
  Slider2.Thumb,
11111
11159
  {
11112
11160
  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",
@@ -11120,7 +11168,7 @@ function PriceSection() {
11120
11168
  "aria-valuetext": formatPrice2(localRange[0])
11121
11169
  }
11122
11170
  ),
11123
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11171
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11124
11172
  Slider2.Thumb,
11125
11173
  {
11126
11174
  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",
@@ -11137,10 +11185,10 @@ function PriceSection() {
11137
11185
  ]
11138
11186
  }
11139
11187
  ) }),
11140
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "grid grid-cols-2 gap-3", children: [
11141
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { children: [
11142
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
11143
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11188
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "grid grid-cols-2 gap-3", children: [
11189
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { children: [
11190
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
11191
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11144
11192
  "input",
11145
11193
  {
11146
11194
  id: "price-min",
@@ -11158,9 +11206,9 @@ function PriceSection() {
11158
11206
  }
11159
11207
  )
11160
11208
  ] }),
11161
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { children: [
11162
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
11163
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11209
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { children: [
11210
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
11211
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11164
11212
  "input",
11165
11213
  {
11166
11214
  id: "price-max",
@@ -11184,11 +11232,11 @@ function PriceSection() {
11184
11232
  }
11185
11233
 
11186
11234
  // src/composed/search/Filters.tsx
11187
- var import_jsx_runtime67 = require("react/jsx-runtime");
11235
+ var import_jsx_runtime68 = require("react/jsx-runtime");
11188
11236
  function Filters({ buttonClassName, buttonText }) {
11189
- const [isOpen, setIsOpen] = (0, import_react50.useState)(false);
11190
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
11191
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11237
+ const [isOpen, setIsOpen] = (0, import_react51.useState)(false);
11238
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
11239
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11192
11240
  FiltersButton,
11193
11241
  {
11194
11242
  onClick: () => setIsOpen(true),
@@ -11196,14 +11244,14 @@ function Filters({ buttonClassName, buttonText }) {
11196
11244
  children: buttonText
11197
11245
  }
11198
11246
  ),
11199
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
11247
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
11200
11248
  ] });
11201
11249
  }
11202
11250
 
11203
11251
  // src/composed/search/CurrentRefinements.tsx
11204
11252
  var import_react_instantsearch5 = require("react-instantsearch");
11205
11253
  var import_lucide_react6 = require("lucide-react");
11206
- var import_jsx_runtime68 = require("react/jsx-runtime");
11254
+ var import_jsx_runtime69 = require("react/jsx-runtime");
11207
11255
  var XIcon3 = import_lucide_react6.X;
11208
11256
  function CurrentRefinements() {
11209
11257
  const { items, refine } = (0, import_react_instantsearch5.useCurrentRefinements)();
@@ -11249,15 +11297,15 @@ function CurrentRefinements() {
11249
11297
  if (allRefinements.length === 0) {
11250
11298
  return null;
11251
11299
  }
11252
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("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__ */ (0, import_jsx_runtime68.jsxs)(
11300
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("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__ */ (0, import_jsx_runtime69.jsxs)(
11253
11301
  "button",
11254
11302
  {
11255
11303
  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",
11256
11304
  onClick: () => refinement.refine(),
11257
11305
  "aria-label": `Remove filter: ${refinement.displayLabel}`,
11258
11306
  children: [
11259
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "truncate", children: refinement.displayLabel }),
11260
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(XIcon3, { className: "w-3 h-3" })
11307
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "truncate", children: refinement.displayLabel }),
11308
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(XIcon3, { className: "w-3 h-3" })
11261
11309
  ]
11262
11310
  },
11263
11311
  `${refinement.attribute}-${refinement.value}-${index}`
@@ -11281,12 +11329,12 @@ var FACET_SECTIONS = [
11281
11329
  ];
11282
11330
 
11283
11331
  // src/composed/zoom/ResponsiveZoom.tsx
11284
- var import_react53 = require("react");
11332
+ var import_react54 = require("react");
11285
11333
 
11286
11334
  // src/composed/zoom/ZoomOverlay.tsx
11287
- var import_react51 = require("react");
11335
+ var import_react52 = require("react");
11288
11336
  var import_lucide_react7 = require("lucide-react");
11289
- var import_jsx_runtime69 = require("react/jsx-runtime");
11337
+ var import_jsx_runtime70 = require("react/jsx-runtime");
11290
11338
  var PlusIcon2 = import_lucide_react7.Plus;
11291
11339
  var MinusIcon2 = import_lucide_react7.Minus;
11292
11340
  function ZoomOverlay({
@@ -11298,13 +11346,13 @@ function ZoomOverlay({
11298
11346
  className,
11299
11347
  style
11300
11348
  }) {
11301
- const [zoomedImageIndex, setZoomedImageIndex] = (0, import_react51.useState)(null);
11302
- const [zoomOrigin, setZoomOrigin] = (0, import_react51.useState)({ x: 50, y: 50 });
11303
- const [hoveredImageIndex, setHoveredImageIndex] = (0, import_react51.useState)(null);
11304
- const [cursorPos, setCursorPos] = (0, import_react51.useState)({ x: 0, y: 0 });
11305
- const [announcement, setAnnouncement] = (0, import_react51.useState)("");
11306
- const [isZooming, setIsZooming] = (0, import_react51.useState)(false);
11307
- const handleZoomClick = (0, import_react51.useCallback)(
11349
+ const [zoomedImageIndex, setZoomedImageIndex] = (0, import_react52.useState)(null);
11350
+ const [zoomOrigin, setZoomOrigin] = (0, import_react52.useState)({ x: 50, y: 50 });
11351
+ const [hoveredImageIndex, setHoveredImageIndex] = (0, import_react52.useState)(null);
11352
+ const [cursorPos, setCursorPos] = (0, import_react52.useState)({ x: 0, y: 0 });
11353
+ const [announcement, setAnnouncement] = (0, import_react52.useState)("");
11354
+ const [isZooming, setIsZooming] = (0, import_react52.useState)(false);
11355
+ const handleZoomClick = (0, import_react52.useCallback)(
11308
11356
  (e) => {
11309
11357
  e.stopPropagation();
11310
11358
  if (isLargeTouchDevice && onEnhancedViewer) {
@@ -11329,7 +11377,7 @@ function ZoomOverlay({
11329
11377
  },
11330
11378
  [zoomedImageIndex, isLargeTouchDevice, onEnhancedViewer, imageIndex]
11331
11379
  );
11332
- const handleZoomMouseMove = (0, import_react51.useCallback)(
11380
+ const handleZoomMouseMove = (0, import_react52.useCallback)(
11333
11381
  (e) => {
11334
11382
  setCursorPos({ x: e.clientX, y: e.clientY });
11335
11383
  if (zoomedImageIndex === imageIndex) {
@@ -11345,9 +11393,9 @@ function ZoomOverlay({
11345
11393
  const isZoomed = zoomedImageIndex === imageIndex;
11346
11394
  const isHovered = hoveredImageIndex === imageIndex;
11347
11395
  const cursorStyle = isLargeTouchDevice ? "pointer" : isTouchDevice ? "default" : "none";
11348
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
11349
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11350
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11396
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(import_jsx_runtime70.Fragment, { children: [
11397
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11398
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11351
11399
  "div",
11352
11400
  {
11353
11401
  className,
@@ -11355,7 +11403,7 @@ function ZoomOverlay({
11355
11403
  ...style,
11356
11404
  position: "relative"
11357
11405
  },
11358
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11406
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11359
11407
  "div",
11360
11408
  {
11361
11409
  style: {
@@ -11378,7 +11426,7 @@ function ZoomOverlay({
11378
11426
  handleZoomClick(e);
11379
11427
  }
11380
11428
  },
11381
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11429
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11382
11430
  "div",
11383
11431
  {
11384
11432
  style: {
@@ -11394,7 +11442,7 @@ function ZoomOverlay({
11394
11442
  )
11395
11443
  }
11396
11444
  ),
11397
- isHovered && !isTouchDevice && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11445
+ isHovered && !isTouchDevice && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11398
11446
  "div",
11399
11447
  {
11400
11448
  className: "fixed pointer-events-none z-50 hidden md:block",
@@ -11404,7 +11452,7 @@ function ZoomOverlay({
11404
11452
  transform: "translate(-50%, -50%)"
11405
11453
  },
11406
11454
  "aria-hidden": "true",
11407
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "bg-white dark:bg-gray-800 rounded-full p-2 shadow-sm dark:shadow-gray-950/50", children: isZoomed ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11455
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "bg-white dark:bg-gray-800 rounded-full p-2 shadow-sm dark:shadow-gray-950/50", children: isZoomed ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11408
11456
  MinusIcon2,
11409
11457
  {
11410
11458
  size: 20,
@@ -11412,7 +11460,7 @@ function ZoomOverlay({
11412
11460
  strokeWidth: 1.5,
11413
11461
  "aria-hidden": "true"
11414
11462
  }
11415
- ) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11463
+ ) : /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11416
11464
  PlusIcon2,
11417
11465
  {
11418
11466
  size: 20,
@@ -11427,11 +11475,11 @@ function ZoomOverlay({
11427
11475
  }
11428
11476
 
11429
11477
  // src/composed/zoom/EnhancedImageViewer.tsx
11430
- var import_react52 = require("react");
11478
+ var import_react53 = require("react");
11431
11479
  var import_react_dom3 = require("react-dom");
11432
11480
  var import_react_zoom_pan_pinch = require("react-zoom-pan-pinch");
11433
11481
  var import_lucide_react8 = require("lucide-react");
11434
- var import_jsx_runtime70 = require("react/jsx-runtime");
11482
+ var import_jsx_runtime71 = require("react/jsx-runtime");
11435
11483
  var TransformWrapper = import_react_zoom_pan_pinch.TransformWrapper;
11436
11484
  var TransformComponent = import_react_zoom_pan_pinch.TransformComponent;
11437
11485
  var EnhancedImageViewer = ({
@@ -11442,17 +11490,17 @@ var EnhancedImageViewer = ({
11442
11490
  onIndexChange,
11443
11491
  currentIndex: propCurrentIndex
11444
11492
  }) => {
11445
- const [isMounted, setIsMounted] = (0, import_react52.useState)(false);
11446
- const [isClient, setIsClient] = (0, import_react52.useState)(false);
11447
- const [scale, setScale] = (0, import_react52.useState)({ initial: 1, min: 1, max: 8 });
11448
- const [cropDimensions, setCropDimensions] = (0, import_react52.useState)({ width: 0, height: 0 });
11449
- const [currentZoomScale, setCurrentZoomScale] = (0, import_react52.useState)(1);
11450
- const imgRef = (0, import_react52.useRef)(null);
11451
- const touchStartRef = (0, import_react52.useRef)(
11493
+ const [isMounted, setIsMounted] = (0, import_react53.useState)(false);
11494
+ const [isClient, setIsClient] = (0, import_react53.useState)(false);
11495
+ const [scale, setScale] = (0, import_react53.useState)({ initial: 1, min: 1, max: 8 });
11496
+ const [cropDimensions, setCropDimensions] = (0, import_react53.useState)({ width: 0, height: 0 });
11497
+ const [currentZoomScale, setCurrentZoomScale] = (0, import_react53.useState)(1);
11498
+ const imgRef = (0, import_react53.useRef)(null);
11499
+ const touchStartRef = (0, import_react53.useRef)(
11452
11500
  null
11453
11501
  );
11454
- const isSwipingRef = (0, import_react52.useRef)(false);
11455
- const calculateScale = (0, import_react52.useCallback)(() => {
11502
+ const isSwipingRef = (0, import_react53.useRef)(false);
11503
+ const calculateScale = (0, import_react53.useCallback)(() => {
11456
11504
  const viewport = {
11457
11505
  width: window.innerWidth,
11458
11506
  height: window.innerHeight
@@ -11464,10 +11512,10 @@ var EnhancedImageViewer = ({
11464
11512
  max: 8
11465
11513
  });
11466
11514
  }, []);
11467
- const handleImageLoad = (0, import_react52.useCallback)(() => {
11515
+ const handleImageLoad = (0, import_react53.useCallback)(() => {
11468
11516
  calculateScale();
11469
11517
  }, [calculateScale]);
11470
- (0, import_react52.useLayoutEffect)(() => {
11518
+ (0, import_react53.useLayoutEffect)(() => {
11471
11519
  setIsClient(true);
11472
11520
  setIsMounted(true);
11473
11521
  document.body.style.overflow = "hidden";
@@ -11476,17 +11524,17 @@ var EnhancedImageViewer = ({
11476
11524
  document.body.style.overflow = "";
11477
11525
  };
11478
11526
  }, [calculateScale]);
11479
- (0, import_react52.useEffect)(() => {
11527
+ (0, import_react53.useEffect)(() => {
11480
11528
  calculateScale();
11481
11529
  }, [calculateScale]);
11482
- (0, import_react52.useEffect)(() => {
11530
+ (0, import_react53.useEffect)(() => {
11483
11531
  const handleResize = () => {
11484
11532
  calculateScale();
11485
11533
  };
11486
11534
  window.addEventListener("resize", handleResize);
11487
11535
  return () => window.removeEventListener("resize", handleResize);
11488
11536
  }, [calculateScale]);
11489
- (0, import_react52.useEffect)(() => {
11537
+ (0, import_react53.useEffect)(() => {
11490
11538
  const handleKeyDown = (e) => {
11491
11539
  if (e.key === "Escape") {
11492
11540
  onClose();
@@ -11512,7 +11560,7 @@ var EnhancedImageViewer = ({
11512
11560
  document.addEventListener("keydown", handleKeyDown);
11513
11561
  return () => document.removeEventListener("keydown", handleKeyDown);
11514
11562
  }, [onClose, imageUrl, images, onIndexChange, propCurrentIndex]);
11515
- const handleSwipeNavigation = (0, import_react52.useCallback)(
11563
+ const handleSwipeNavigation = (0, import_react53.useCallback)(
11516
11564
  (direction) => {
11517
11565
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11518
11566
  if (currentIndex === -1) {
@@ -11533,7 +11581,7 @@ var EnhancedImageViewer = ({
11533
11581
  },
11534
11582
  [propCurrentIndex, images, imageUrl, onIndexChange]
11535
11583
  );
11536
- const handleTouchStart = (0, import_react52.useCallback)(
11584
+ const handleTouchStart = (0, import_react53.useCallback)(
11537
11585
  (e) => {
11538
11586
  const isAtInitialZoom = Math.abs(currentZoomScale - scale.initial) < 0.1;
11539
11587
  if (!isAtInitialZoom) return;
@@ -11547,7 +11595,7 @@ var EnhancedImageViewer = ({
11547
11595
  },
11548
11596
  [currentZoomScale, scale.initial]
11549
11597
  );
11550
- const handleTouchEnd = (0, import_react52.useCallback)(
11598
+ const handleTouchEnd = (0, import_react53.useCallback)(
11551
11599
  (e) => {
11552
11600
  if (!touchStartRef.current) return;
11553
11601
  const touch = e.changedTouches[0];
@@ -11571,12 +11619,12 @@ var EnhancedImageViewer = ({
11571
11619
  );
11572
11620
  if (!isMounted || !isClient) {
11573
11621
  return (0, import_react_dom3.createPortal)(
11574
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11622
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11575
11623
  "div",
11576
11624
  {
11577
11625
  className: "fixed inset-0 bg-black flex items-center justify-center",
11578
11626
  style: { zIndex: 999999 },
11579
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11627
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11580
11628
  "div",
11581
11629
  {
11582
11630
  style: {
@@ -11592,7 +11640,7 @@ var EnhancedImageViewer = ({
11592
11640
  );
11593
11641
  }
11594
11642
  return (0, import_react_dom3.createPortal)(
11595
- /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
11643
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
11596
11644
  "div",
11597
11645
  {
11598
11646
  className: "fixed inset-0 bg-black flex items-center justify-center",
@@ -11601,7 +11649,7 @@ var EnhancedImageViewer = ({
11601
11649
  "aria-modal": "true",
11602
11650
  "aria-label": "Image viewer",
11603
11651
  children: [
11604
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11652
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11605
11653
  "button",
11606
11654
  {
11607
11655
  onClick: (e) => {
@@ -11627,10 +11675,10 @@ var EnhancedImageViewer = ({
11627
11675
  touchAction: "manipulation",
11628
11676
  marginBottom: "env(safe-area-inset-bottom, 0px)"
11629
11677
  },
11630
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(import_lucide_react8.X, { className: "w-7 h-7", strokeWidth: 2.5 })
11678
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react8.X, { className: "w-7 h-7", strokeWidth: 2.5 })
11631
11679
  }
11632
11680
  ),
11633
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11681
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11634
11682
  TransformWrapper,
11635
11683
  {
11636
11684
  initialScale: scale.initial,
@@ -11664,7 +11712,7 @@ var EnhancedImageViewer = ({
11664
11712
  onTransformed: (ref) => {
11665
11713
  setCurrentZoomScale(ref.state.scale);
11666
11714
  },
11667
- children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
11715
+ children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
11668
11716
  "div",
11669
11717
  {
11670
11718
  style: {
@@ -11677,14 +11725,14 @@ var EnhancedImageViewer = ({
11677
11725
  onTouchStart: handleTouchStart,
11678
11726
  onTouchEnd: handleTouchEnd,
11679
11727
  children: [
11680
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11728
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11681
11729
  TransformComponent,
11682
11730
  {
11683
11731
  wrapperStyle: {
11684
11732
  width: "100%",
11685
11733
  height: "100%"
11686
11734
  },
11687
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11735
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11688
11736
  "div",
11689
11737
  {
11690
11738
  style: {
@@ -11695,8 +11743,8 @@ var EnhancedImageViewer = ({
11695
11743
  alignItems: "center",
11696
11744
  justifyContent: "center"
11697
11745
  },
11698
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11699
- "img",
11746
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11747
+ SafeImg,
11700
11748
  {
11701
11749
  ref: imgRef,
11702
11750
  src: imageUrl,
@@ -11716,8 +11764,8 @@ var EnhancedImageViewer = ({
11716
11764
  )
11717
11765
  }
11718
11766
  ),
11719
- /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fixed bottom-5 left-0 right-0 z-50", children: [
11720
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "flex justify-center gap-2", children: (() => {
11767
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fixed bottom-5 left-0 right-0 z-50", children: [
11768
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "flex justify-center gap-2", children: (() => {
11721
11769
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11722
11770
  if (currentIndex === -1) {
11723
11771
  currentIndex = images.findIndex(
@@ -11750,8 +11798,8 @@ var EnhancedImageViewer = ({
11750
11798
  };
11751
11799
  const nextIndex = findNextAvailableIndex(currentIndex, 1);
11752
11800
  const prevIndex = findNextAvailableIndex(currentIndex, -1);
11753
- return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(import_jsx_runtime70.Fragment, { children: [
11754
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11801
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_jsx_runtime71.Fragment, { children: [
11802
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11755
11803
  "button",
11756
11804
  {
11757
11805
  onClick: () => {
@@ -11764,7 +11812,7 @@ var EnhancedImageViewer = ({
11764
11812
  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"}`,
11765
11813
  style: { touchAction: "manipulation" },
11766
11814
  "aria-label": "Previous image",
11767
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11815
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11768
11816
  "svg",
11769
11817
  {
11770
11818
  className: "w-4 h-4",
@@ -11772,7 +11820,7 @@ var EnhancedImageViewer = ({
11772
11820
  stroke: "currentColor",
11773
11821
  viewBox: "0 0 24 24",
11774
11822
  "aria-hidden": "true",
11775
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11823
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11776
11824
  "path",
11777
11825
  {
11778
11826
  strokeLinecap: "round",
@@ -11785,7 +11833,7 @@ var EnhancedImageViewer = ({
11785
11833
  )
11786
11834
  }
11787
11835
  ),
11788
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11836
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11789
11837
  "button",
11790
11838
  {
11791
11839
  onClick: () => {
@@ -11798,7 +11846,7 @@ var EnhancedImageViewer = ({
11798
11846
  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"}`,
11799
11847
  style: { touchAction: "manipulation" },
11800
11848
  "aria-label": "Next image",
11801
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11849
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11802
11850
  "svg",
11803
11851
  {
11804
11852
  className: "w-4 h-4",
@@ -11806,7 +11854,7 @@ var EnhancedImageViewer = ({
11806
11854
  stroke: "currentColor",
11807
11855
  viewBox: "0 0 24 24",
11808
11856
  "aria-hidden": "true",
11809
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11857
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11810
11858
  "path",
11811
11859
  {
11812
11860
  strokeLinecap: "round",
@@ -11821,7 +11869,7 @@ var EnhancedImageViewer = ({
11821
11869
  )
11822
11870
  ] });
11823
11871
  })() }),
11824
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("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: (() => {
11872
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("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: (() => {
11825
11873
  const total = Math.max(images.length, 1);
11826
11874
  const current = propCurrentIndex !== void 0 ? Math.min(propCurrentIndex + 1, total) : 1;
11827
11875
  return `${current} / ${total}`;
@@ -11833,7 +11881,7 @@ var EnhancedImageViewer = ({
11833
11881
  },
11834
11882
  `${scale.initial}-${scale.min}-${scale.max}`
11835
11883
  ),
11836
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11884
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11837
11885
  "div",
11838
11886
  {
11839
11887
  className: "absolute inset-0 bg-black",
@@ -11852,7 +11900,7 @@ var EnhancedImageViewer = ({
11852
11900
  };
11853
11901
 
11854
11902
  // src/composed/zoom/ResponsiveZoom.tsx
11855
- var import_jsx_runtime71 = require("react/jsx-runtime");
11903
+ var import_jsx_runtime72 = require("react/jsx-runtime");
11856
11904
  function ResponsiveZoom({
11857
11905
  imageIndex,
11858
11906
  children,
@@ -11862,11 +11910,11 @@ function ResponsiveZoom({
11862
11910
  imageUrl,
11863
11911
  alt = "Product image"
11864
11912
  }) {
11865
- const [isTouchDevice, setIsTouchDevice] = (0, import_react53.useState)(false);
11866
- const [showEnhancedViewer, setShowEnhancedViewer] = (0, import_react53.useState)(false);
11867
- const [viewerIndex, setViewerIndex] = (0, import_react53.useState)(0);
11868
- const [currentImageUrl, setCurrentImageUrl] = (0, import_react53.useState)(imageUrl || "");
11869
- (0, import_react53.useEffect)(() => {
11913
+ const [isTouchDevice, setIsTouchDevice] = (0, import_react54.useState)(false);
11914
+ const [showEnhancedViewer, setShowEnhancedViewer] = (0, import_react54.useState)(false);
11915
+ const [viewerIndex, setViewerIndex] = (0, import_react54.useState)(0);
11916
+ const [currentImageUrl, setCurrentImageUrl] = (0, import_react54.useState)(imageUrl || "");
11917
+ (0, import_react54.useEffect)(() => {
11870
11918
  const checkDeviceType = () => {
11871
11919
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
11872
11920
  setIsTouchDevice(hasTouch);
@@ -11893,8 +11941,8 @@ function ResponsiveZoom({
11893
11941
  }
11894
11942
  }
11895
11943
  };
11896
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_jsx_runtime71.Fragment, { children: [
11897
- isTouchDevice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11944
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
11945
+ isTouchDevice ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11898
11946
  "div",
11899
11947
  {
11900
11948
  className,
@@ -11911,7 +11959,7 @@ function ResponsiveZoom({
11911
11959
  },
11912
11960
  children
11913
11961
  }
11914
- ) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11962
+ ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11915
11963
  ZoomOverlay,
11916
11964
  {
11917
11965
  imageIndex,
@@ -11922,7 +11970,7 @@ function ResponsiveZoom({
11922
11970
  children
11923
11971
  }
11924
11972
  ),
11925
- showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11973
+ showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11926
11974
  EnhancedImageViewer,
11927
11975
  {
11928
11976
  imageUrl: currentImageUrl,
@@ -11945,9 +11993,32 @@ function ResponsiveZoom({
11945
11993
  }
11946
11994
 
11947
11995
  // src/composed/carousels/MobileProductCarousel.tsx
11948
- var import_react54 = require("react");
11949
- var import_jsx_runtime72 = require("react/jsx-runtime");
11950
- var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarousel2({
11996
+ var import_react55 = require("react");
11997
+ var import_jsx_runtime73 = require("react/jsx-runtime");
11998
+ function StaticCarouselImage({
11999
+ src,
12000
+ alt,
12001
+ className
12002
+ }) {
12003
+ const [failed, setFailed] = (0, import_react55.useState)(false);
12004
+ if (failed || !src) {
12005
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: `bg-muted ${className ?? ""}`, role: "img", "aria-label": alt });
12006
+ }
12007
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12008
+ "img",
12009
+ {
12010
+ src,
12011
+ alt,
12012
+ crossOrigin: "anonymous",
12013
+ className,
12014
+ loading: "lazy",
12015
+ decoding: "async",
12016
+ draggable: false,
12017
+ onError: () => setFailed(true)
12018
+ }
12019
+ );
12020
+ }
12021
+ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarousel2({
11951
12022
  images,
11952
12023
  currentIndex = 0,
11953
12024
  onIndexChange,
@@ -11962,42 +12033,42 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
11962
12033
  mockupWidth,
11963
12034
  onMockupUrlGenerated
11964
12035
  }) {
11965
- const [activeIndex, setActiveIndex] = (0, import_react54.useState)(currentIndex);
11966
- const [touchStart, setTouchStart] = (0, import_react54.useState)(
12036
+ const [activeIndex, setActiveIndex] = (0, import_react55.useState)(currentIndex);
12037
+ const [touchStart, setTouchStart] = (0, import_react55.useState)(
11967
12038
  null
11968
12039
  );
11969
- const [touchEnd, setTouchEnd] = (0, import_react54.useState)(
12040
+ const [touchEnd, setTouchEnd] = (0, import_react55.useState)(
11970
12041
  null
11971
12042
  );
11972
- const [showImageViewer, setShowImageViewer] = (0, import_react54.useState)(false);
11973
- const [viewerKey, setViewerKey] = (0, import_react54.useState)(0);
11974
- const [isDragging, setIsDragging] = (0, import_react54.useState)(false);
11975
- const [dragOffset, setDragOffset] = (0, import_react54.useState)(0);
11976
- const [isTransitioning, setIsTransitioning] = (0, import_react54.useState)(false);
11977
- const [isHorizontalSwipe, setIsHorizontalSwipe] = (0, import_react54.useState)(
12043
+ const [showImageViewer, setShowImageViewer] = (0, import_react55.useState)(false);
12044
+ const [viewerKey, setViewerKey] = (0, import_react55.useState)(0);
12045
+ const [isDragging, setIsDragging] = (0, import_react55.useState)(false);
12046
+ const [dragOffset, setDragOffset] = (0, import_react55.useState)(0);
12047
+ const [isTransitioning, setIsTransitioning] = (0, import_react55.useState)(false);
12048
+ const [isHorizontalSwipe, setIsHorizontalSwipe] = (0, import_react55.useState)(
11978
12049
  null
11979
12050
  );
11980
- const [isPeeking, setIsPeeking] = (0, import_react54.useState)(false);
11981
- const [isPeekReturning, setIsPeekReturning] = (0, import_react54.useState)(false);
11982
- const carouselRef = (0, import_react54.useRef)(null);
11983
- const indicatorRef = (0, import_react54.useRef)(null);
11984
- const touchStartRef = (0, import_react54.useRef)(
12051
+ const [isPeeking, setIsPeeking] = (0, import_react55.useState)(false);
12052
+ const [isPeekReturning, setIsPeekReturning] = (0, import_react55.useState)(false);
12053
+ const carouselRef = (0, import_react55.useRef)(null);
12054
+ const indicatorRef = (0, import_react55.useRef)(null);
12055
+ const touchStartRef = (0, import_react55.useRef)(
11985
12056
  null
11986
12057
  );
11987
- const horizontalGestureRef = (0, import_react54.useRef)(false);
11988
- const hasShownPeekRef = (0, import_react54.useRef)(false);
11989
- const hasSwipedThisSessionRef = (0, import_react54.useRef)(false);
11990
- const generatedUrlsRef = (0, import_react54.useRef)(/* @__PURE__ */ new Map());
11991
- const prevArtworkSrcRef = (0, import_react54.useRef)(currentArtwork?.src);
11992
- (0, import_react54.useEffect)(() => {
12058
+ const horizontalGestureRef = (0, import_react55.useRef)(false);
12059
+ const hasShownPeekRef = (0, import_react55.useRef)(false);
12060
+ const hasSwipedThisSessionRef = (0, import_react55.useRef)(false);
12061
+ const generatedUrlsRef = (0, import_react55.useRef)(/* @__PURE__ */ new Map());
12062
+ const prevArtworkSrcRef = (0, import_react55.useRef)(currentArtwork?.src);
12063
+ (0, import_react55.useEffect)(() => {
11993
12064
  if (currentArtwork?.src !== prevArtworkSrcRef.current) {
11994
12065
  generatedUrlsRef.current.clear();
11995
12066
  prevArtworkSrcRef.current = currentArtwork?.src;
11996
12067
  }
11997
12068
  }, [currentArtwork?.src]);
11998
- const onMockupUrlGeneratedRef = (0, import_react54.useRef)(onMockupUrlGenerated);
12069
+ const onMockupUrlGeneratedRef = (0, import_react55.useRef)(onMockupUrlGenerated);
11999
12070
  onMockupUrlGeneratedRef.current = onMockupUrlGenerated;
12000
- const handleUrlGenerated = (0, import_react54.useCallback)((mockupId, url) => {
12071
+ const handleUrlGenerated = (0, import_react55.useCallback)((mockupId, url) => {
12001
12072
  generatedUrlsRef.current.set(mockupId, url);
12002
12073
  onMockupUrlGeneratedRef.current?.(mockupId, url);
12003
12074
  }, []);
@@ -12005,24 +12076,24 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12005
12076
  const shouldHideDots = stickyHeroContext?.shouldHideDots ?? false;
12006
12077
  const priorityContext = useMockupPriorityOptional();
12007
12078
  const realtimeContext = useRealtimeOptional();
12008
- const [urlUpdateCounter, setUrlUpdateCounter] = (0, import_react54.useState)(0);
12009
- (0, import_react54.useEffect)(() => {
12079
+ const [urlUpdateCounter, setUrlUpdateCounter] = (0, import_react55.useState)(0);
12080
+ (0, import_react55.useEffect)(() => {
12010
12081
  if (!realtimeContext?.subscribeMockupResults) return;
12011
12082
  const unsubscribe = realtimeContext.subscribeMockupResults(() => {
12012
12083
  setUrlUpdateCounter((c) => c + 1);
12013
12084
  });
12014
12085
  return unsubscribe;
12015
12086
  }, [realtimeContext?.subscribeMockupResults]);
12016
- const mockupIds = (0, import_react54.useMemo)(() => {
12087
+ const mockupIds = (0, import_react55.useMemo)(() => {
12017
12088
  return images.filter((img) => img.isRealMockup && img.mockupId).map((img) => img.mockupId);
12018
12089
  }, [images]);
12019
- const realtimeMockupUrls = (0, import_react54.useMemo)(() => {
12090
+ const realtimeMockupUrls = (0, import_react55.useMemo)(() => {
12020
12091
  if (!realtimeContext?.getMockupUrls || mockupIds.length === 0) {
12021
12092
  return {};
12022
12093
  }
12023
12094
  return realtimeContext.getMockupUrls(mockupIds);
12024
12095
  }, [realtimeContext?.getMockupUrls, mockupIds, urlUpdateCounter]);
12025
- const imagesWithRealtimeUrls = (0, import_react54.useMemo)(() => {
12096
+ const imagesWithRealtimeUrls = (0, import_react55.useMemo)(() => {
12026
12097
  return images.map((img) => {
12027
12098
  if (img.isRealMockup && img.mockupId && realtimeMockupUrls[img.mockupId]) {
12028
12099
  return {
@@ -12034,10 +12105,10 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12034
12105
  });
12035
12106
  }, [images, realtimeMockupUrls]);
12036
12107
  const minSwipeDistance = 50;
12037
- (0, import_react54.useEffect)(() => {
12108
+ (0, import_react55.useEffect)(() => {
12038
12109
  setActiveIndex(currentIndex);
12039
12110
  }, [currentIndex]);
12040
- (0, import_react54.useEffect)(() => {
12111
+ (0, import_react55.useEffect)(() => {
12041
12112
  if (!priorityContext) return;
12042
12113
  const realMockups = images.map((img, idx) => ({ img, originalIdx: idx })).filter(({ img }) => img.isRealMockup && img.mockupId);
12043
12114
  const mockupIdsList = realMockups.map(({ img }) => img.mockupId);
@@ -12065,7 +12136,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12065
12136
  priorityContext.clearMobileCarouselMode?.();
12066
12137
  };
12067
12138
  }, [priorityContext, activeIndex, images]);
12068
- (0, import_react54.useEffect)(() => {
12139
+ (0, import_react55.useEffect)(() => {
12069
12140
  const indicator = indicatorRef.current;
12070
12141
  if (!indicator) return;
12071
12142
  let ticking = false;
@@ -12106,7 +12177,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12106
12177
  }, []);
12107
12178
  const SWIPE_TRACKING_KEY = "carousel-swipe-tracking";
12108
12179
  const PDP_VIEWS_BEFORE_PEEK = 10;
12109
- const getSwipeTracking = (0, import_react54.useCallback)(() => {
12180
+ const getSwipeTracking = (0, import_react55.useCallback)(() => {
12110
12181
  try {
12111
12182
  const stored = localStorage.getItem(SWIPE_TRACKING_KEY);
12112
12183
  if (stored) {
@@ -12116,7 +12187,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12116
12187
  }
12117
12188
  return { viewsWithoutSwipe: 0, hasEverSwiped: false };
12118
12189
  }, []);
12119
- const recordSwipe = (0, import_react54.useCallback)(() => {
12190
+ const recordSwipe = (0, import_react55.useCallback)(() => {
12120
12191
  if (hasSwipedThisSessionRef.current) return;
12121
12192
  hasSwipedThisSessionRef.current = true;
12122
12193
  try {
@@ -12130,7 +12201,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12130
12201
  } catch {
12131
12202
  }
12132
12203
  }, []);
12133
- (0, import_react54.useEffect)(() => {
12204
+ (0, import_react55.useEffect)(() => {
12134
12205
  if (!enablePeekAnimation || images.length <= 1) return;
12135
12206
  const tracking = getSwipeTracking();
12136
12207
  const newViewCount = tracking.viewsWithoutSwipe + 1;
@@ -12171,14 +12242,14 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12171
12242
  clearTimeout(clearTimeout_);
12172
12243
  };
12173
12244
  }, [images.length, getSwipeTracking, enablePeekAnimation]);
12174
- const wasTapRef = (0, import_react54.useRef)(false);
12175
- const handleImageTap = (0, import_react54.useCallback)(() => {
12245
+ const wasTapRef = (0, import_react55.useRef)(false);
12246
+ const handleImageTap = (0, import_react55.useCallback)(() => {
12176
12247
  if (!enableZoom) return;
12177
12248
  setViewerKey((prev) => prev + 1);
12178
12249
  setShowImageViewer(true);
12179
12250
  onZoomChange?.(true);
12180
12251
  }, [enableZoom, onZoomChange]);
12181
- const calculateDragOffset = (0, import_react54.useCallback)(
12252
+ const calculateDragOffset = (0, import_react55.useCallback)(
12182
12253
  (startX, currentX, containerWidth) => {
12183
12254
  const distance = startX - currentX;
12184
12255
  const offsetPercent = distance / containerWidth * 100;
@@ -12203,7 +12274,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12203
12274
  },
12204
12275
  [activeIndex, images.length]
12205
12276
  );
12206
- const handleSwipeEnd = (0, import_react54.useCallback)(
12277
+ const handleSwipeEnd = (0, import_react55.useCallback)(
12207
12278
  (startX, endX, containerWidth) => {
12208
12279
  const distance = startX - endX;
12209
12280
  const distancePercent = Math.abs(distance) / containerWidth * 100;
@@ -12234,7 +12305,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12234
12305
  },
12235
12306
  [activeIndex, images.length, onIndexChange, recordSwipe]
12236
12307
  );
12237
- (0, import_react54.useEffect)(() => {
12308
+ (0, import_react55.useEffect)(() => {
12238
12309
  const container = carouselRef.current;
12239
12310
  if (!container) return;
12240
12311
  const handleTouchStart = (e) => {
@@ -12323,11 +12394,11 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12323
12394
  handleSwipeEnd,
12324
12395
  handleImageTap
12325
12396
  ]);
12326
- const mouseStartRef = (0, import_react54.useRef)(
12397
+ const mouseStartRef = (0, import_react55.useRef)(
12327
12398
  null
12328
12399
  );
12329
- const isMouseDraggingRef = (0, import_react54.useRef)(false);
12330
- (0, import_react54.useEffect)(() => {
12400
+ const isMouseDraggingRef = (0, import_react55.useRef)(false);
12401
+ (0, import_react55.useEffect)(() => {
12331
12402
  const container = carouselRef.current;
12332
12403
  if (!container) return;
12333
12404
  const handleMouseDown = (e) => {
@@ -12403,7 +12474,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12403
12474
  container.removeEventListener("mouseleave", handleMouseLeave);
12404
12475
  };
12405
12476
  }, [calculateDragOffset, handleSwipeEnd, handleImageTap]);
12406
- const goToSlide = (0, import_react54.useCallback)(
12477
+ const goToSlide = (0, import_react55.useCallback)(
12407
12478
  (index, withTransition = true) => {
12408
12479
  if (withTransition) {
12409
12480
  setIsTransitioning(true);
@@ -12421,16 +12492,16 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12421
12492
  },
12422
12493
  [onIndexChange]
12423
12494
  );
12424
- (0, import_react54.useEffect)(() => {
12495
+ (0, import_react55.useEffect)(() => {
12425
12496
  if (stickyHeroContext?.setCarouselIndicator && images.length > 1) {
12426
- const indicator = /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12497
+ const indicator = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12427
12498
  "div",
12428
12499
  {
12429
12500
  className: "w-full",
12430
12501
  role: "group",
12431
12502
  "aria-label": "Product image navigation",
12432
- children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "relative h-1", children: [
12433
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "flex h-full", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12503
+ children: /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "relative h-1", children: [
12504
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "flex h-full", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12434
12505
  "button",
12435
12506
  {
12436
12507
  onClick: () => goToSlide(index),
@@ -12440,7 +12511,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12440
12511
  },
12441
12512
  index
12442
12513
  )) }),
12443
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12514
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12444
12515
  "div",
12445
12516
  {
12446
12517
  className: "absolute top-0 h-full bg-primary transition-all duration-300 ease-out",
@@ -12463,10 +12534,10 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12463
12534
  };
12464
12535
  }, [activeIndex, images.length, goToSlide, stickyHeroContext]);
12465
12536
  if (!images || images.length === 0) {
12466
- return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12537
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12467
12538
  }
12468
- return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: `relative w-full h-full ${className}`, children: [
12469
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12539
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: `relative w-full h-full ${className}`, children: [
12540
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12470
12541
  "div",
12471
12542
  {
12472
12543
  ref: carouselRef,
@@ -12484,7 +12555,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12484
12555
  role: "region",
12485
12556
  "aria-roledescription": "carousel",
12486
12557
  "aria-label": "Product images",
12487
- children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12558
+ children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12488
12559
  "div",
12489
12560
  {
12490
12561
  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)]" : ""}`,
@@ -12494,11 +12565,15 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12494
12565
  children: images.map((image, index) => {
12495
12566
  const DECODE_WINDOW = 1;
12496
12567
  const isWithinDecodeWindow = Math.abs(index - activeIndex) <= DECODE_WINDOW;
12497
- return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12568
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12498
12569
  "div",
12499
12570
  {
12500
12571
  className: "w-full h-full flex-shrink-0 relative select-none",
12501
- children: !isWithinDecodeWindow ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full h-full bg-muted-foreground/20 animate-pulse" }) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12572
+ children: !isWithinDecodeWindow ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? (
12573
+ // Rainbow prism loader (same as the /create route) instead of
12574
+ // a flat pulse; fills this relative slide via inset:0.
12575
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" })
12576
+ ) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12502
12577
  HeroProductImage,
12503
12578
  {
12504
12579
  productId,
@@ -12510,16 +12585,12 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12510
12585
  onUrlGenerated: image.mockupId ? (url) => handleUrlGenerated(image.mockupId, url) : void 0,
12511
12586
  className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12512
12587
  }
12513
- ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full h-full bg-muted animate-pulse" }) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12514
- "img",
12588
+ ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12589
+ StaticCarouselImage,
12515
12590
  {
12516
12591
  src: image.src,
12517
- alt: image.label,
12518
- crossOrigin: "anonymous",
12519
- className: "w-full h-full object-cover cursor-pointer pointer-events-none",
12520
- loading: "lazy",
12521
- decoding: "async",
12522
- draggable: false
12592
+ alt: image.label ?? "",
12593
+ className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12523
12594
  }
12524
12595
  )
12525
12596
  },
@@ -12530,7 +12601,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12530
12601
  )
12531
12602
  }
12532
12603
  ),
12533
- showIndicators && images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12604
+ showIndicators && images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12534
12605
  "div",
12535
12606
  {
12536
12607
  ref: indicatorRef,
@@ -12538,8 +12609,8 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12538
12609
  className: "relative z-20 w-full",
12539
12610
  role: "group",
12540
12611
  "aria-label": "Product image navigation",
12541
- children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "relative h-1", children: [
12542
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "flex h-full absolute inset-0", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12612
+ children: /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "relative h-1", children: [
12613
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "flex h-full absolute inset-0", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12543
12614
  "button",
12544
12615
  {
12545
12616
  onClick: () => goToSlide(index),
@@ -12549,7 +12620,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12549
12620
  },
12550
12621
  index
12551
12622
  )) }),
12552
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12623
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12553
12624
  "div",
12554
12625
  {
12555
12626
  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"}`,
@@ -12584,7 +12655,7 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12584
12655
  naturalHeight: img.naturalHeight
12585
12656
  } : null;
12586
12657
  }).filter((img) => img !== null);
12587
- return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12658
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12588
12659
  EnhancedImageViewer,
12589
12660
  {
12590
12661
  imageUrl,
@@ -12623,8 +12694,8 @@ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarou
12623
12694
  });
12624
12695
 
12625
12696
  // src/composed/carousels/HeroCarousel.tsx
12626
- var import_react55 = require("react");
12627
- var import_jsx_runtime73 = require("react/jsx-runtime");
12697
+ var import_react56 = require("react");
12698
+ var import_jsx_runtime74 = require("react/jsx-runtime");
12628
12699
  function HeroCarousel({
12629
12700
  images,
12630
12701
  currentIndex = 0,
@@ -12634,16 +12705,16 @@ function HeroCarousel({
12634
12705
  productId,
12635
12706
  onImageTap
12636
12707
  }) {
12637
- const [activeIndex, setActiveIndex] = (0, import_react55.useState)(currentIndex);
12638
- const containerRef = (0, import_react55.useRef)(null);
12639
- const touchStartRef = (0, import_react55.useRef)(
12708
+ const [activeIndex, setActiveIndex] = (0, import_react56.useState)(currentIndex);
12709
+ const containerRef = (0, import_react56.useRef)(null);
12710
+ const touchStartRef = (0, import_react56.useRef)(
12640
12711
  null
12641
12712
  );
12642
- const isSwipingRef = (0, import_react55.useRef)(false);
12643
- (0, import_react55.useEffect)(() => {
12713
+ const isSwipingRef = (0, import_react56.useRef)(false);
12714
+ (0, import_react56.useEffect)(() => {
12644
12715
  setActiveIndex(currentIndex);
12645
12716
  }, [currentIndex]);
12646
- const goToSlide = (0, import_react55.useCallback)(
12717
+ const goToSlide = (0, import_react56.useCallback)(
12647
12718
  (index) => {
12648
12719
  const clampedIndex = Math.max(0, Math.min(images.length - 1, index));
12649
12720
  setActiveIndex(clampedIndex);
@@ -12651,7 +12722,7 @@ function HeroCarousel({
12651
12722
  },
12652
12723
  [images.length, onIndexChange]
12653
12724
  );
12654
- (0, import_react55.useEffect)(() => {
12725
+ (0, import_react56.useEffect)(() => {
12655
12726
  const container = containerRef.current;
12656
12727
  if (!container) return;
12657
12728
  const handleTouchStart = (e) => {
@@ -12703,9 +12774,9 @@ function HeroCarousel({
12703
12774
  };
12704
12775
  }, [activeIndex, images.length, goToSlide, onImageTap]);
12705
12776
  if (!images || images.length === 0) {
12706
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "w-full h-full bg-muted" });
12777
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "w-full h-full bg-muted" });
12707
12778
  }
12708
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
12779
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
12709
12780
  "div",
12710
12781
  {
12711
12782
  ref: containerRef,
@@ -12716,7 +12787,7 @@ function HeroCarousel({
12716
12787
  overflow: "hidden"
12717
12788
  },
12718
12789
  children: [
12719
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12790
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12720
12791
  "div",
12721
12792
  {
12722
12793
  className: "flex h-full transition-transform duration-300 ease-out",
@@ -12727,14 +12798,14 @@ function HeroCarousel({
12727
12798
  backfaceVisibility: "hidden",
12728
12799
  WebkitBackfaceVisibility: "hidden"
12729
12800
  },
12730
- children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12801
+ children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12731
12802
  "div",
12732
12803
  {
12733
12804
  className: "w-full h-full flex-shrink-0",
12734
12805
  style: {
12735
12806
  contain: "layout paint"
12736
12807
  },
12737
- children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12808
+ children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12738
12809
  HeroProductImage,
12739
12810
  {
12740
12811
  productId,
@@ -12743,7 +12814,7 @@ function HeroCarousel({
12743
12814
  mockupId: image.mockupId,
12744
12815
  className: "w-full h-full object-cover"
12745
12816
  }
12746
- ) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12817
+ ) : /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12747
12818
  "img",
12748
12819
  {
12749
12820
  src: image.src,
@@ -12760,12 +12831,12 @@ function HeroCarousel({
12760
12831
  ))
12761
12832
  }
12762
12833
  ),
12763
- images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12834
+ images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12764
12835
  "div",
12765
12836
  {
12766
12837
  className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 z-10",
12767
12838
  style: { contain: "layout style" },
12768
- children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12839
+ children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12769
12840
  "button",
12770
12841
  {
12771
12842
  onClick: () => goToSlide(index),
@@ -12782,8 +12853,8 @@ function HeroCarousel({
12782
12853
  }
12783
12854
 
12784
12855
  // src/composed/grids/MasonryGrid.tsx
12785
- var import_react56 = require("react");
12786
- var import_jsx_runtime74 = require("react/jsx-runtime");
12856
+ var import_react57 = require("react");
12857
+ var import_jsx_runtime75 = require("react/jsx-runtime");
12787
12858
  var BREAKPOINTS = {
12788
12859
  sm: 640,
12789
12860
  md: 768,
@@ -12835,13 +12906,13 @@ function MasonryGrid({
12835
12906
  className = "",
12836
12907
  emptyContent
12837
12908
  }) {
12838
- const [columnCount, setColumnCount] = (0, import_react56.useState)(
12909
+ const [columnCount, setColumnCount] = (0, import_react57.useState)(
12839
12910
  () => typeof columns === "number" ? columns : getColumnCount(
12840
12911
  typeof window !== "undefined" ? window.innerWidth : 1024,
12841
12912
  columns
12842
12913
  )
12843
12914
  );
12844
- (0, import_react56.useEffect)(() => {
12915
+ (0, import_react57.useEffect)(() => {
12845
12916
  const updateColumnCount = () => {
12846
12917
  setColumnCount(getColumnCount(window.innerWidth, columns));
12847
12918
  };
@@ -12849,30 +12920,30 @@ function MasonryGrid({
12849
12920
  window.addEventListener("resize", updateColumnCount);
12850
12921
  return () => window.removeEventListener("resize", updateColumnCount);
12851
12922
  }, [columns]);
12852
- const distributedColumns = (0, import_react56.useMemo)(
12923
+ const distributedColumns = (0, import_react57.useMemo)(
12853
12924
  () => distributeItems(items, columnCount),
12854
12925
  [items, columnCount]
12855
12926
  );
12856
12927
  if (items.length === 0) {
12857
12928
  if (emptyContent) {
12858
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(import_jsx_runtime74.Fragment, { children: emptyContent });
12929
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(import_jsx_runtime75.Fragment, { children: emptyContent });
12859
12930
  }
12860
12931
  return null;
12861
12932
  }
12862
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12933
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12863
12934
  "div",
12864
12935
  {
12865
12936
  className: `flex ${className}`,
12866
12937
  style: { gap: `${gap}px` },
12867
12938
  role: "list",
12868
- children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12939
+ children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12869
12940
  "div",
12870
12941
  {
12871
12942
  className: "flex-1 flex flex-col",
12872
12943
  style: { gap: `${gap}px` },
12873
12944
  children: columnItems.map((item, itemIndex) => {
12874
12945
  const originalIndex = itemIndex * columnCount + columnIndex;
12875
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12946
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12876
12947
  })
12877
12948
  },
12878
12949
  columnIndex
@@ -12885,7 +12956,7 @@ function MasonryGrid({
12885
12956
  init_dev_warnings();
12886
12957
 
12887
12958
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12888
- var import_react58 = require("react");
12959
+ var import_react59 = require("react");
12889
12960
 
12890
12961
  // src/layouts/hero-zoom/types.ts
12891
12962
  var DEFAULT_HERO_ZOOM_CONFIG = {
@@ -12897,19 +12968,19 @@ var DEFAULT_HERO_ZOOM_CONFIG = {
12897
12968
  };
12898
12969
 
12899
12970
  // src/layouts/hero-zoom/useHeroZoomScales.ts
12900
- var import_react57 = require("react");
12971
+ var import_react58 = require("react");
12901
12972
  function useHeroZoomScales(config = {}) {
12902
12973
  const { initialScale, accountForRetina, maxRetinaMultiplier } = {
12903
12974
  ...DEFAULT_HERO_ZOOM_CONFIG,
12904
12975
  ...config
12905
12976
  };
12906
- const [isHydrated, setIsHydrated] = (0, import_react57.useState)(false);
12977
+ const [isHydrated, setIsHydrated] = (0, import_react58.useState)(false);
12907
12978
  const ssrMultiplier = accountForRetina ? maxRetinaMultiplier : 2;
12908
- const [scales, setScales] = (0, import_react57.useState)(() => ({
12979
+ const [scales, setScales] = (0, import_react58.useState)(() => ({
12909
12980
  visual: initialScale,
12910
12981
  render: initialScale * ssrMultiplier
12911
12982
  }));
12912
- const calculateScales = (0, import_react57.useCallback)(() => {
12983
+ const calculateScales = (0, import_react58.useCallback)(() => {
12913
12984
  const visualScale = Math.max(1, Math.min(4, initialScale));
12914
12985
  let renderScale;
12915
12986
  if (accountForRetina) {
@@ -12924,7 +12995,7 @@ function useHeroZoomScales(config = {}) {
12924
12995
  renderScale = Math.max(1, Math.min(8, renderScale));
12925
12996
  return { visual: visualScale, render: renderScale };
12926
12997
  }, [initialScale, accountForRetina, maxRetinaMultiplier]);
12927
- (0, import_react57.useEffect)(() => {
12998
+ (0, import_react58.useEffect)(() => {
12928
12999
  const supportsScrollTimeline = CSS.supports(
12929
13000
  "animation-timeline",
12930
13001
  "scroll()"
@@ -12974,7 +13045,7 @@ function useHeroZoomScales(config = {}) {
12974
13045
  }
12975
13046
 
12976
13047
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12977
- var import_jsx_runtime75 = require("react/jsx-runtime");
13048
+ var import_jsx_runtime76 = require("react/jsx-runtime");
12978
13049
  function HeroZoomLayout({
12979
13050
  config = {},
12980
13051
  header,
@@ -12989,9 +13060,9 @@ function HeroZoomLayout({
12989
13060
  };
12990
13061
  const { aspectRatio, initialScale, headerHeight } = mergedConfig;
12991
13062
  const { visual, render, isHydrated } = useHeroZoomScales(mergedConfig);
12992
- const imageContainerRef = (0, import_react58.useRef)(null);
12993
- const headerRef = (0, import_react58.useRef)(null);
12994
- (0, import_react58.useEffect)(() => {
13063
+ const imageContainerRef = (0, import_react59.useRef)(null);
13064
+ const headerRef = (0, import_react59.useRef)(null);
13065
+ (0, import_react59.useEffect)(() => {
12995
13066
  if (typeof window === "undefined") return;
12996
13067
  const originalRestoration = "scrollRestoration" in history ? history.scrollRestoration : "auto";
12997
13068
  if ("scrollRestoration" in history) {
@@ -13004,7 +13075,7 @@ function HeroZoomLayout({
13004
13075
  }
13005
13076
  };
13006
13077
  }, []);
13007
- (0, import_react58.useEffect)(() => {
13078
+ (0, import_react59.useEffect)(() => {
13008
13079
  const supportsScrollTimeline = CSS.supports(
13009
13080
  "animation-timeline",
13010
13081
  "scroll()"
@@ -13133,7 +13204,7 @@ function HeroZoomLayout({
13133
13204
  The drawer covers the hero completely, so let animation run continuously. */
13134
13205
  }
13135
13206
  `;
13136
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(
13207
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
13137
13208
  "div",
13138
13209
  {
13139
13210
  className: `relative min-h-screen ${className}`,
@@ -13147,8 +13218,8 @@ function HeroZoomLayout({
13147
13218
  "--hero-zoom-final-transform": 1 / activeRender
13148
13219
  },
13149
13220
  children: [
13150
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13151
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
13221
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13222
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13152
13223
  "div",
13153
13224
  {
13154
13225
  style: {
@@ -13156,7 +13227,7 @@ function HeroZoomLayout({
13156
13227
  }
13157
13228
  }
13158
13229
  ),
13159
- header && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
13230
+ header && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13160
13231
  "div",
13161
13232
  {
13162
13233
  ref: headerRef,
@@ -13169,7 +13240,7 @@ function HeroZoomLayout({
13169
13240
  children: header
13170
13241
  }
13171
13242
  ),
13172
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
13243
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13173
13244
  "div",
13174
13245
  {
13175
13246
  ref: imageContainerRef,
@@ -13189,15 +13260,15 @@ function HeroZoomLayout({
13189
13260
  children: hero
13190
13261
  }
13191
13262
  ),
13192
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "relative z-10", children })
13263
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "relative z-10", children })
13193
13264
  ]
13194
13265
  }
13195
13266
  );
13196
13267
  }
13197
13268
 
13198
13269
  // src/layouts/hero-zoom/HeroShrinkLayout.tsx
13199
- var import_react59 = require("react");
13200
- var import_jsx_runtime76 = require("react/jsx-runtime");
13270
+ var import_react60 = require("react");
13271
+ var import_jsx_runtime77 = require("react/jsx-runtime");
13201
13272
  var DEFAULT_CONFIG = {
13202
13273
  aspectRatio: 16 / 9,
13203
13274
  initialHeightPercent: 70,
@@ -13217,13 +13288,13 @@ function HeroShrinkLayout({
13217
13288
  ...config
13218
13289
  };
13219
13290
  const { aspectRatio, initialHeightPercent, minHeightPercent, headerHeight } = mergedConfig;
13220
- const heroRef = (0, import_react59.useRef)(null);
13221
- const headerRef = (0, import_react59.useRef)(null);
13222
- const [isClient, setIsClient] = (0, import_react59.useState)(false);
13223
- (0, import_react59.useEffect)(() => {
13291
+ const heroRef = (0, import_react60.useRef)(null);
13292
+ const headerRef = (0, import_react60.useRef)(null);
13293
+ const [isClient, setIsClient] = (0, import_react60.useState)(false);
13294
+ (0, import_react60.useEffect)(() => {
13224
13295
  setIsClient(true);
13225
13296
  }, []);
13226
- (0, import_react59.useEffect)(() => {
13297
+ (0, import_react60.useEffect)(() => {
13227
13298
  if (!isClient) return;
13228
13299
  const supportsScrollTimeline = CSS.supports("animation-timeline", "scroll()");
13229
13300
  if (supportsScrollTimeline) return;
@@ -13310,15 +13381,15 @@ function HeroShrinkLayout({
13310
13381
  }
13311
13382
  `;
13312
13383
  const spacerHeight = `calc(${initialHeightPercent}svh + ${headerHeight}px)`;
13313
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
13384
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
13314
13385
  "div",
13315
13386
  {
13316
13387
  className: `relative min-h-screen ${className}`,
13317
13388
  style: { ...style, ...cssVars },
13318
13389
  children: [
13319
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13320
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { style: { height: spacerHeight } }),
13321
- header && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13390
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13391
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { style: { height: spacerHeight } }),
13392
+ header && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13322
13393
  "div",
13323
13394
  {
13324
13395
  ref: headerRef,
@@ -13327,7 +13398,7 @@ function HeroShrinkLayout({
13327
13398
  children: header
13328
13399
  }
13329
13400
  ),
13330
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13401
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13331
13402
  "div",
13332
13403
  {
13333
13404
  ref: heroRef,
@@ -13335,15 +13406,15 @@ function HeroShrinkLayout({
13335
13406
  children: hero
13336
13407
  }
13337
13408
  ),
13338
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "relative z-10 bg-background", children })
13409
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "relative z-10 bg-background", children })
13339
13410
  ]
13340
13411
  }
13341
13412
  );
13342
13413
  }
13343
13414
 
13344
13415
  // src/layouts/pdp/ImageEdgeBlur.tsx
13345
- var import_react60 = __toESM(require("react"), 1);
13346
- var import_jsx_runtime77 = require("react/jsx-runtime");
13416
+ var import_react61 = __toESM(require("react"), 1);
13417
+ var import_jsx_runtime78 = require("react/jsx-runtime");
13347
13418
  var BLUR_CONFIG = {
13348
13419
  blur: 24,
13349
13420
  crossfade: 68
@@ -13367,7 +13438,7 @@ var BLUR_LAYERS = [
13367
13438
  { blur: Math.round(BLUR_CONFIG.blur * 0.5), zone: 0.6 },
13368
13439
  { blur: BLUR_CONFIG.blur, zone: 1 }
13369
13440
  ];
13370
- var ImageEdgeBlur = import_react60.default.memo(
13441
+ var ImageEdgeBlur = import_react61.default.memo(
13371
13442
  function ImageEdgeBlur2({
13372
13443
  imageSrc,
13373
13444
  imageCapInfo,
@@ -13398,7 +13469,7 @@ var ImageEdgeBlur = import_react60.default.memo(
13398
13469
  viewportWidth / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO,
13399
13470
  maxWidthPx / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO
13400
13471
  );
13401
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13472
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13402
13473
  "div",
13403
13474
  {
13404
13475
  className: `absolute inset-0 pointer-events-none overflow-hidden ${className}`,
@@ -13406,7 +13477,7 @@ var ImageEdgeBlur = import_react60.default.memo(
13406
13477
  children: BLUR_LAYERS.map((layer, index) => {
13407
13478
  const layerMask = index === BLUR_LAYERS.length - 1 ? void 0 : `linear-gradient(to right, black 0%, black ${layer.zone * 100}%, transparent ${layer.zone * 100 + 10}%)`;
13408
13479
  const blurScale = 1 + layer.blur * 3 / containerHeightPx;
13409
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13480
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13410
13481
  "img",
13411
13482
  {
13412
13483
  src: imageSrc,
@@ -13453,7 +13524,7 @@ var ImageEdgeBlur = import_react60.default.memo(
13453
13524
  );
13454
13525
 
13455
13526
  // src/layouts/pdp/PDPLayout.tsx
13456
- var import_jsx_runtime78 = require("react/jsx-runtime");
13527
+ var import_jsx_runtime79 = require("react/jsx-runtime");
13457
13528
  function PDPLayout({
13458
13529
  renderHeroImage,
13459
13530
  renderContent,
@@ -13481,15 +13552,15 @@ function PDPLayout({
13481
13552
  isDesktop,
13482
13553
  isWideMonitor: isWideMonitor2
13483
13554
  };
13484
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: `pdp-layout ${className}`, children: [
13485
- (isDesktop === false || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "md:hidden", children: [
13486
- renderMobileCarousel && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13487
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "mobile-content p-4", children: renderContent(contentProps) })
13555
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: `pdp-layout ${className}`, children: [
13556
+ (isDesktop === false || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "md:hidden", children: [
13557
+ renderMobileCarousel && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13558
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "mobile-content p-4", children: renderContent(contentProps) })
13488
13559
  ] }),
13489
- (isDesktop === true || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "hidden md:block relative", children: [
13490
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "desktop-hero relative", children: [
13560
+ (isDesktop === true || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "hidden md:block relative", children: [
13561
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "desktop-hero relative", children: [
13491
13562
  renderHeroImage(heroProps),
13492
- showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13563
+ showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13493
13564
  ImageEdgeBlur,
13494
13565
  {
13495
13566
  imageSrc: blurImageSrc,
@@ -13500,7 +13571,7 @@ function PDPLayout({
13500
13571
  }
13501
13572
  )
13502
13573
  ] }),
13503
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13574
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13504
13575
  "div",
13505
13576
  {
13506
13577
  className: "desktop-sidebar",
@@ -13517,8 +13588,8 @@ function PDPLayout({
13517
13588
  }
13518
13589
 
13519
13590
  // src/layouts/pdp/SimpleImageBlur.tsx
13520
- var import_react61 = __toESM(require("react"), 1);
13521
- var import_jsx_runtime79 = require("react/jsx-runtime");
13591
+ var import_react62 = __toESM(require("react"), 1);
13592
+ var import_jsx_runtime80 = require("react/jsx-runtime");
13522
13593
  var BLUR_CONFIG2 = {
13523
13594
  blur: 24,
13524
13595
  crossfade: 60
@@ -13541,7 +13612,7 @@ function getFadeInMask(crossfadeWidth) {
13541
13612
  black ${crossfadeWidth + 10}px
13542
13613
  )`;
13543
13614
  }
13544
- var SimpleImageBlur = import_react61.default.memo(function SimpleImageBlur2({
13615
+ var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13545
13616
  imageSrc,
13546
13617
  width,
13547
13618
  height = "100%",
@@ -13551,7 +13622,7 @@ var SimpleImageBlur = import_react61.default.memo(function SimpleImageBlur2({
13551
13622
  if (!imageSrc || width <= 0) return null;
13552
13623
  const fadeInMask = getFadeInMask(BLUR_CONFIG2.crossfade);
13553
13624
  const extendedWidth = width + BLUR_CONFIG2.blur * 2;
13554
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13625
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13555
13626
  "div",
13556
13627
  {
13557
13628
  className: `relative overflow-hidden ${className}`,
@@ -13564,7 +13635,7 @@ var SimpleImageBlur = import_react61.default.memo(function SimpleImageBlur2({
13564
13635
  black 0%,
13565
13636
  black ${layer.zone * 100}%,
13566
13637
  transparent ${layer.zone * 100 + 10}%)`;
13567
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13638
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13568
13639
  "img",
13569
13640
  {
13570
13641
  src: imageSrc,
@@ -13594,8 +13665,8 @@ var SimpleImageBlur = import_react61.default.memo(function SimpleImageBlur2({
13594
13665
  });
13595
13666
 
13596
13667
  // src/layouts/pdp/EdgeBlurBox.tsx
13597
- var import_react62 = __toESM(require("react"), 1);
13598
- var import_jsx_runtime80 = require("react/jsx-runtime");
13668
+ var import_react63 = __toESM(require("react"), 1);
13669
+ var import_jsx_runtime81 = require("react/jsx-runtime");
13599
13670
  var BLUR_CONFIG3 = {
13600
13671
  blur: 24,
13601
13672
  crossfade: 60
@@ -13619,7 +13690,7 @@ function getFadeOutMask(crossfadeWidth) {
13619
13690
  transparent 100%
13620
13691
  )`;
13621
13692
  }
13622
- var EdgeBlurBox = import_react62.default.memo(function EdgeBlurBox2({
13693
+ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13623
13694
  imageSrc,
13624
13695
  width,
13625
13696
  height = "100%",
@@ -13634,7 +13705,7 @@ var EdgeBlurBox = import_react62.default.memo(function EdgeBlurBox2({
13634
13705
  const blurExtend = BLUR_CONFIG3.blur * 2;
13635
13706
  const actualSharpWidth = sharpImageWidth ?? width + overlapLeft;
13636
13707
  const hasOverlap = overlapLeft > 0;
13637
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
13708
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
13638
13709
  "div",
13639
13710
  {
13640
13711
  className: `relative ${className}`,
@@ -13645,7 +13716,7 @@ var EdgeBlurBox = import_react62.default.memo(function EdgeBlurBox2({
13645
13716
  overflow: hasOverlap ? "visible" : "hidden"
13646
13717
  },
13647
13718
  children: [
13648
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13719
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13649
13720
  "div",
13650
13721
  {
13651
13722
  style: {
@@ -13659,7 +13730,7 @@ var EdgeBlurBox = import_react62.default.memo(function EdgeBlurBox2({
13659
13730
  transparent ${100 - (layer.zone * 100 + 10)}%,
13660
13731
  black ${100 - layer.zone * 100}%,
13661
13732
  black 100%)`;
13662
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13733
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13663
13734
  "img",
13664
13735
  {
13665
13736
  src: imageSrc,
@@ -13687,7 +13758,7 @@ var EdgeBlurBox = import_react62.default.memo(function EdgeBlurBox2({
13687
13758
  })
13688
13759
  }
13689
13760
  ),
13690
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13761
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13691
13762
  "img",
13692
13763
  {
13693
13764
  src: imageSrc,
@@ -13715,8 +13786,8 @@ var EdgeBlurBox = import_react62.default.memo(function EdgeBlurBox2({
13715
13786
  });
13716
13787
 
13717
13788
  // src/layouts/pdp/ImageBlurExtension.tsx
13718
- var import_react63 = __toESM(require("react"), 1);
13719
- var import_jsx_runtime81 = require("react/jsx-runtime");
13789
+ var import_react64 = __toESM(require("react"), 1);
13790
+ var import_jsx_runtime82 = require("react/jsx-runtime");
13720
13791
  var BLUR_CONFIG4 = {
13721
13792
  blur: 24,
13722
13793
  crossfadeWidth: 80
@@ -13739,7 +13810,7 @@ function getFadeOutMask2(crossfadeWidth) {
13739
13810
  transparent 100%
13740
13811
  )`;
13741
13812
  }
13742
- var ImageBlurExtension = import_react63.default.memo(function ImageBlurExtension2({
13813
+ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension2({
13743
13814
  imageSrc,
13744
13815
  width,
13745
13816
  height,
@@ -13753,7 +13824,7 @@ var ImageBlurExtension = import_react63.default.memo(function ImageBlurExtension
13753
13824
  const internalImageLeft = `calc(${heroImageLeft} - 100vw + ${width}px)`;
13754
13825
  const fadeOutMask = getFadeOutMask2(crossfadeWidth);
13755
13826
  const heightValue = typeof height === "number" ? `${height}px` : height;
13756
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
13827
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
13757
13828
  "div",
13758
13829
  {
13759
13830
  className: `relative overflow-hidden ${className}`,
@@ -13762,7 +13833,7 @@ var ImageBlurExtension = import_react63.default.memo(function ImageBlurExtension
13762
13833
  height: heightValue
13763
13834
  },
13764
13835
  children: [
13765
- BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13836
+ BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13766
13837
  "img",
13767
13838
  {
13768
13839
  src: imageSrc,
@@ -13786,7 +13857,7 @@ var ImageBlurExtension = import_react63.default.memo(function ImageBlurExtension
13786
13857
  },
13787
13858
  `blur-${index}`
13788
13859
  )),
13789
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13860
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13790
13861
  "img",
13791
13862
  {
13792
13863
  src: imageSrc,
@@ -13814,39 +13885,39 @@ var ImageBlurExtension = import_react63.default.memo(function ImageBlurExtension
13814
13885
  });
13815
13886
 
13816
13887
  // src/design-system/ColorSwatch.tsx
13817
- var import_jsx_runtime82 = require("react/jsx-runtime");
13888
+ var import_jsx_runtime83 = require("react/jsx-runtime");
13818
13889
  function ColorTokenSwatch({ name, cssVar, className = "" }) {
13819
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: `flex flex-col gap-1 ${className}`, children: [
13820
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13890
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: `flex flex-col gap-1 ${className}`, children: [
13891
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13821
13892
  "div",
13822
13893
  {
13823
13894
  className: "h-16 w-full rounded-lg border border-border shadow-sm",
13824
13895
  style: { backgroundColor: `var(${cssVar})` }
13825
13896
  }
13826
13897
  ),
13827
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13828
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: cssVar })
13898
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13899
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: cssVar })
13829
13900
  ] });
13830
13901
  }
13831
13902
  function ColorRow({ name, cssVar, description }) {
13832
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex items-center gap-4 py-2", children: [
13833
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13903
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex items-center gap-4 py-2", children: [
13904
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13834
13905
  "div",
13835
13906
  {
13836
13907
  className: "h-10 w-10 rounded-lg border border-border shadow-sm flex-shrink-0",
13837
13908
  style: { backgroundColor: `var(${cssVar})` }
13838
13909
  }
13839
13910
  ),
13840
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex-1 min-w-0", children: [
13841
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13842
- description && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-xs text-muted-foreground", children: description })
13911
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex-1 min-w-0", children: [
13912
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13913
+ description && /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "text-xs text-muted-foreground", children: description })
13843
13914
  ] }),
13844
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: cssVar })
13915
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: cssVar })
13845
13916
  ] });
13846
13917
  }
13847
13918
 
13848
13919
  // src/design-system/ColorPalette.tsx
13849
- var import_jsx_runtime83 = require("react/jsx-runtime");
13920
+ var import_jsx_runtime84 = require("react/jsx-runtime");
13850
13921
  var COLOR_GROUPS = [
13851
13922
  {
13852
13923
  name: "Base",
@@ -13927,17 +13998,17 @@ var COLOR_GROUPS = [
13927
13998
  }
13928
13999
  ];
13929
14000
  function ColorPalette({ layout = "list", className = "" }) {
13930
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: `space-y-8 ${className}`, children: COLOR_GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("section", { children: [
13931
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
13932
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
13933
- layout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-4", children: group.colors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
14001
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: `space-y-8 ${className}`, children: COLOR_GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("section", { children: [
14002
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
14003
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
14004
+ layout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-4", children: group.colors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
13934
14005
  ColorTokenSwatch,
13935
14006
  {
13936
14007
  name: color.name,
13937
14008
  cssVar: color.cssVar
13938
14009
  },
13939
14010
  color.cssVar
13940
- )) }) : /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "bg-card rounded-lg border border-border p-4 divide-y divide-border", children: group.colors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
14011
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "bg-card rounded-lg border border-border p-4 divide-y divide-border", children: group.colors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
13941
14012
  ColorRow,
13942
14013
  {
13943
14014
  name: color.name,
@@ -13950,7 +14021,7 @@ function ColorPalette({ layout = "list", className = "" }) {
13950
14021
  }
13951
14022
 
13952
14023
  // src/design-system/TypographyScale.tsx
13953
- var import_jsx_runtime84 = require("react/jsx-runtime");
14024
+ var import_jsx_runtime85 = require("react/jsx-runtime");
13954
14025
  var FONT_SAMPLES = [
13955
14026
  {
13956
14027
  name: "Heading",
@@ -13984,14 +14055,14 @@ var FONT_SAMPLES = [
13984
14055
  }
13985
14056
  ];
13986
14057
  function TypographyScale({ className = "" }) {
13987
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: `space-y-8 ${className}`, children: FONT_SAMPLES.map((font) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("section", { className: "bg-card rounded-lg border border-border p-6", children: [
13988
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
13989
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
13990
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: font.cssVar })
14058
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: `space-y-8 ${className}`, children: FONT_SAMPLES.map((font) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("section", { className: "bg-card rounded-lg border border-border p-6", children: [
14059
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
14060
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
14061
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: font.cssVar })
13991
14062
  ] }),
13992
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "space-y-4", children: font.sizes.map((size) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex items-baseline gap-4", children: [
13993
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
13994
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
14063
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "space-y-4", children: font.sizes.map((size) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex items-baseline gap-4", children: [
14064
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
14065
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
13995
14066
  "p",
13996
14067
  {
13997
14068
  className: `${size} text-foreground`,
@@ -14010,8 +14081,8 @@ var RADIUS_SAMPLES = [
14010
14081
  { name: "Full", value: "9999px" }
14011
14082
  ];
14012
14083
  function RadiusScale({ className = "" }) {
14013
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "grid grid-cols-5 gap-4", children: RADIUS_SAMPLES.map((radius) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex flex-col items-center gap-2", children: [
14014
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
14084
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "grid grid-cols-5 gap-4", children: RADIUS_SAMPLES.map((radius) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex flex-col items-center gap-2", children: [
14085
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
14015
14086
  "div",
14016
14087
  {
14017
14088
  className: "h-16 w-16 bg-primary",
@@ -14020,13 +14091,13 @@ function RadiusScale({ className = "" }) {
14020
14091
  }
14021
14092
  }
14022
14093
  ),
14023
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
14024
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: radius.cssVar || radius.value })
14094
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
14095
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: radius.cssVar || radius.value })
14025
14096
  ] }, radius.name)) }) });
14026
14097
  }
14027
14098
 
14028
14099
  // src/design-system/ThemeSwitcher.tsx
14029
- var import_react64 = require("react");
14100
+ var import_react65 = require("react");
14030
14101
 
14031
14102
  // src/themes/types.ts
14032
14103
  var RADIUS_PRESETS = {
@@ -15194,7 +15265,7 @@ function applyTheme(config) {
15194
15265
  }
15195
15266
 
15196
15267
  // src/design-system/ThemeSwitcher.tsx
15197
- var import_jsx_runtime85 = require("react/jsx-runtime");
15268
+ var import_jsx_runtime86 = require("react/jsx-runtime");
15198
15269
  function readThemeFromDOM() {
15199
15270
  if (typeof document === "undefined") {
15200
15271
  return { themeName: "Linear", isDark: false };
@@ -15212,10 +15283,10 @@ function readThemeFromDOM() {
15212
15283
  return { themeName: "Linear", isDark: dark };
15213
15284
  }
15214
15285
  function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
15215
- const [currentTheme, setCurrentTheme] = (0, import_react64.useState)("Linear");
15216
- const [isDark, setIsDark] = (0, import_react64.useState)(false);
15217
- const [isOpen, setIsOpen] = (0, import_react64.useState)(false);
15218
- (0, import_react64.useEffect)(() => {
15286
+ const [currentTheme, setCurrentTheme] = (0, import_react65.useState)("Linear");
15287
+ const [isDark, setIsDark] = (0, import_react65.useState)(false);
15288
+ const [isOpen, setIsOpen] = (0, import_react65.useState)(false);
15289
+ (0, import_react65.useEffect)(() => {
15219
15290
  const { themeName, isDark: dark } = readThemeFromDOM();
15220
15291
  setCurrentTheme(themeName);
15221
15292
  setIsDark(dark);
@@ -15254,61 +15325,61 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
15254
15325
  applyTheme(config);
15255
15326
  };
15256
15327
  const themes = showBaseThemesOnly ? baseThemes : baseThemes;
15257
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: `flex items-center gap-3 ${className}`, children: [
15258
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "relative", children: [
15259
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
15328
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: `flex items-center gap-3 ${className}`, children: [
15329
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "relative", children: [
15330
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
15260
15331
  "button",
15261
15332
  {
15262
15333
  onClick: () => setIsOpen(!isOpen),
15263
15334
  className: "flex items-center gap-2 px-4 py-2 bg-card border border-border rounded-lg hover:bg-muted transition-colors text-foreground",
15264
15335
  children: [
15265
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("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" }) }),
15266
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "font-medium", children: currentTheme }),
15267
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("svg", { className: `w-4 h-4 transition-transform ${isOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
15336
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("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" }) }),
15337
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "font-medium", children: currentTheme }),
15338
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("svg", { className: `w-4 h-4 transition-transform ${isOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
15268
15339
  ]
15269
15340
  }
15270
15341
  ),
15271
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(import_jsx_runtime85.Fragment, { children: [
15272
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
15342
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(import_jsx_runtime86.Fragment, { children: [
15343
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15273
15344
  "div",
15274
15345
  {
15275
15346
  className: "fixed inset-0 z-40",
15276
15347
  onClick: () => setIsOpen(false)
15277
15348
  }
15278
15349
  ),
15279
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("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__ */ (0, import_jsx_runtime85.jsxs)(
15350
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("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__ */ (0, import_jsx_runtime86.jsxs)(
15280
15351
  "button",
15281
15352
  {
15282
15353
  onClick: () => handleThemeSelect(theme.name),
15283
15354
  className: `w-full px-4 py-2 text-left hover:bg-muted transition-colors flex items-center gap-3 ${currentTheme === theme.name ? "bg-muted" : ""}`,
15284
15355
  children: [
15285
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
15356
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15286
15357
  "div",
15287
15358
  {
15288
15359
  className: "w-4 h-4 rounded-full border border-border",
15289
15360
  style: { backgroundColor: theme.primaryColor || "#888" }
15290
15361
  }
15291
15362
  ),
15292
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "text-foreground", children: theme.name }),
15293
- currentTheme === theme.name && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("svg", { className: "w-4 h-4 ml-auto text-primary", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) })
15363
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-foreground", children: theme.name }),
15364
+ currentTheme === theme.name && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("svg", { className: "w-4 h-4 ml-auto text-primary", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) })
15294
15365
  ]
15295
15366
  },
15296
15367
  theme.name
15297
15368
  )) })
15298
15369
  ] })
15299
15370
  ] }),
15300
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
15371
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
15301
15372
  "button",
15302
15373
  {
15303
15374
  onClick: handleDarkModeToggle,
15304
15375
  className: "flex items-center gap-2 px-4 py-2 bg-card border border-border rounded-lg hover:bg-muted transition-colors text-foreground",
15305
15376
  title: `Switch to ${isDark ? "light" : "dark"} mode`,
15306
15377
  children: [
15307
- isDark ? /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
15308
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
15309
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("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" })
15310
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }),
15311
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "text-sm", children: isDark ? "Light" : "Dark" })
15378
+ isDark ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
15379
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
15380
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("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" })
15381
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }),
15382
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-sm", children: isDark ? "Light" : "Dark" })
15312
15383
  ]
15313
15384
  }
15314
15385
  )
@@ -15316,7 +15387,7 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
15316
15387
  }
15317
15388
 
15318
15389
  // src/design-system/DesignSystemPage.tsx
15319
- var import_jsx_runtime86 = require("react/jsx-runtime");
15390
+ var import_jsx_runtime87 = require("react/jsx-runtime");
15320
15391
  function DesignSystemPage({
15321
15392
  showThemeSwitcher = true,
15322
15393
  showColors = true,
@@ -15326,29 +15397,29 @@ function DesignSystemPage({
15326
15397
  colorLayout = "list",
15327
15398
  className = ""
15328
15399
  }) {
15329
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: `max-w-4xl mx-auto px-4 py-8 ${className}`, children: [
15330
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("header", { className: "mb-12", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4", children: [
15331
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { children: [
15332
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
15333
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "text-lg text-muted-foreground", children: "Visual reference for theme tokens and styles" })
15400
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: `max-w-4xl mx-auto px-4 py-8 ${className}`, children: [
15401
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("header", { className: "mb-12", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4", children: [
15402
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { children: [
15403
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
15404
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "text-lg text-muted-foreground", children: "Visual reference for theme tokens and styles" })
15334
15405
  ] }),
15335
- showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ThemeSwitcher, {})
15406
+ showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ThemeSwitcher, {})
15336
15407
  ] }) }),
15337
- showColors && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "mb-16", children: [
15338
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Color Palette" }),
15339
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ColorPalette, { layout: colorLayout })
15408
+ showColors && /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("section", { className: "mb-16", children: [
15409
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Color Palette" }),
15410
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ColorPalette, { layout: colorLayout })
15340
15411
  ] }),
15341
- showTypography && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "mb-16", children: [
15342
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
15343
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(TypographyScale, {})
15412
+ showTypography && /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("section", { className: "mb-16", children: [
15413
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
15414
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(TypographyScale, {})
15344
15415
  ] }),
15345
- showRadius && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "mb-16", children: [
15346
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Border Radius" }),
15347
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(RadiusScale, {})
15416
+ showRadius && /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("section", { className: "mb-16", children: [
15417
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Border Radius" }),
15418
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(RadiusScale, {})
15348
15419
  ] }),
15349
- showSpacing && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "mb-16", children: [
15350
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Spacing Scale" }),
15351
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(SpacingScale, {})
15420
+ showSpacing && /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("section", { className: "mb-16", children: [
15421
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Spacing Scale" }),
15422
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(SpacingScale, {})
15352
15423
  ] })
15353
15424
  ] });
15354
15425
  }
@@ -15363,31 +15434,31 @@ function SpacingScale() {
15363
15434
  { name: "12", value: "3rem" },
15364
15435
  { name: "16", value: "4rem" }
15365
15436
  ];
15366
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "space-y-2", children: spaces.map((space) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex items-center gap-4", children: [
15367
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
15368
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15437
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "space-y-2", children: spaces.map((space) => /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex items-center gap-4", children: [
15438
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
15439
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15369
15440
  "div",
15370
15441
  {
15371
15442
  className: "h-4 bg-primary rounded",
15372
15443
  style: { width: space.value }
15373
15444
  }
15374
15445
  ),
15375
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-sm text-muted-foreground", children: space.value })
15446
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "text-sm text-muted-foreground", children: space.value })
15376
15447
  ] }, space.name)) });
15377
15448
  }
15378
15449
 
15379
15450
  // src/personalization/PersonalizationProvider.tsx
15380
- var import_react67 = __toESM(require("react"), 1);
15451
+ var import_react68 = __toESM(require("react"), 1);
15381
15452
 
15382
15453
  // src/personalization/PersonalizationContext.ts
15383
- var import_react65 = require("react");
15384
- var PersonalizationContext = (0, import_react65.createContext)(null);
15454
+ var import_react66 = require("react");
15455
+ var PersonalizationContext = (0, import_react66.createContext)(null);
15385
15456
  function usePersonalizationContext() {
15386
- return (0, import_react65.useContext)(PersonalizationContext);
15457
+ return (0, import_react66.useContext)(PersonalizationContext);
15387
15458
  }
15388
15459
 
15389
15460
  // src/personalization/utils.ts
15390
- var import_react66 = require("react");
15461
+ var import_react67 = require("react");
15391
15462
  function normalizeHex(color) {
15392
15463
  let hex = color.trim().toUpperCase();
15393
15464
  if (hex.length === 4 && hex.startsWith("#")) {
@@ -15408,8 +15479,8 @@ function isValidImageUrl(url) {
15408
15479
  }
15409
15480
  }
15410
15481
  function useDebouncedValue(value, delay) {
15411
- const [debounced, setDebounced] = (0, import_react66.useState)(value);
15412
- (0, import_react66.useEffect)(() => {
15482
+ const [debounced, setDebounced] = (0, import_react67.useState)(value);
15483
+ (0, import_react67.useEffect)(() => {
15413
15484
  const timer = setTimeout(() => setDebounced(value), delay);
15414
15485
  return () => clearTimeout(timer);
15415
15486
  }, [value, delay]);
@@ -15430,18 +15501,18 @@ function scrollInputAboveKeyboard(input) {
15430
15501
  }
15431
15502
 
15432
15503
  // src/personalization/PersonalizationProvider.tsx
15433
- var import_jsx_runtime87 = require("react/jsx-runtime");
15504
+ var import_jsx_runtime88 = require("react/jsx-runtime");
15434
15505
  function createBridgeFromCanvas(canvasModule) {
15435
15506
  const { useEditor, useCommands, useImageBinding } = canvasModule;
15436
15507
  function TextBinder({ name, value }) {
15437
15508
  const { elements } = useEditor();
15438
15509
  const { executeElementUpdate } = useCommands();
15439
- const elementsRef = import_react67.default.useRef(elements);
15510
+ const elementsRef = import_react68.default.useRef(elements);
15440
15511
  elementsRef.current = elements;
15441
- const executeRef = import_react67.default.useRef(executeElementUpdate);
15512
+ const executeRef = import_react68.default.useRef(executeElementUpdate);
15442
15513
  executeRef.current = executeElementUpdate;
15443
- const hasUserInput = import_react67.default.useRef(false);
15444
- import_react67.default.useEffect(() => {
15514
+ const hasUserInput = import_react68.default.useRef(false);
15515
+ import_react68.default.useEffect(() => {
15445
15516
  if (value == null) return;
15446
15517
  if (value === "" && !hasUserInput.current) return;
15447
15518
  hasUserInput.current = true;
@@ -15459,12 +15530,12 @@ function createBridgeFromCanvas(canvasModule) {
15459
15530
  function ColorBinder({ originalColor, newColor }) {
15460
15531
  const { elements } = useEditor();
15461
15532
  const { executeElementUpdate } = useCommands();
15462
- const elementsRef = import_react67.default.useRef(elements);
15533
+ const elementsRef = import_react68.default.useRef(elements);
15463
15534
  elementsRef.current = elements;
15464
- const executeRef = import_react67.default.useRef(executeElementUpdate);
15535
+ const executeRef = import_react68.default.useRef(executeElementUpdate);
15465
15536
  executeRef.current = executeElementUpdate;
15466
- const appliedColorRef = import_react67.default.useRef(normalizeHex(originalColor));
15467
- import_react67.default.useEffect(() => {
15537
+ const appliedColorRef = import_react68.default.useRef(normalizeHex(originalColor));
15538
+ import_react68.default.useEffect(() => {
15468
15539
  const normalizedNew = normalizeHex(newColor);
15469
15540
  if (normalizedNew === appliedColorRef.current) return;
15470
15541
  const matchColor = appliedColorRef.current;
@@ -15504,11 +15575,11 @@ function createBridgeFromCanvas(canvasModule) {
15504
15575
  }
15505
15576
  function ImageBinder({ name, value, fit = "cover" }) {
15506
15577
  const { setImageUrl } = useImageBinding(name, { fit });
15507
- const hasUserInput = import_react67.default.useRef(false);
15578
+ const hasUserInput = import_react68.default.useRef(false);
15508
15579
  const debouncedValue = useDebouncedValue(value, 500);
15509
- const setImageUrlRef = import_react67.default.useRef(setImageUrl);
15580
+ const setImageUrlRef = import_react68.default.useRef(setImageUrl);
15510
15581
  setImageUrlRef.current = setImageUrl;
15511
- import_react67.default.useEffect(() => {
15582
+ import_react68.default.useEffect(() => {
15512
15583
  if (debouncedValue == null) return;
15513
15584
  if (debouncedValue === "" && !hasUserInput.current) return;
15514
15585
  hasUserInput.current = true;
@@ -15518,15 +15589,15 @@ function createBridgeFromCanvas(canvasModule) {
15518
15589
  return null;
15519
15590
  }
15520
15591
  return function PersonalizationBridge({ fields = [], values = {} } = {}) {
15521
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_jsx_runtime87.Fragment, { children: fields.map((field) => {
15592
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_jsx_runtime88.Fragment, { children: fields.map((field) => {
15522
15593
  if (field.type === "text") {
15523
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
15594
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
15524
15595
  }
15525
15596
  if (field.type === "color") {
15526
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
15597
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
15527
15598
  }
15528
15599
  if (field.type === "image") {
15529
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
15600
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
15530
15601
  }
15531
15602
  return null;
15532
15603
  }) });
@@ -15548,19 +15619,19 @@ function PersonalizationProvider({
15548
15619
  children
15549
15620
  }) {
15550
15621
  const realtime = useRealtimeOptional();
15551
- const [personValues, setPersonValues] = (0, import_react67.useState)(initialValues ?? {});
15552
- const [isActive, setIsActive] = (0, import_react67.useState)(!!(initialValues && Object.keys(initialValues).length > 0));
15553
- const [isExporting, setIsExporting] = (0, import_react67.useState)(false);
15554
- const [exportedBlobUrls, setExportedBlobUrls] = (0, import_react67.useState)({});
15555
- const [exportCount, setExportCount] = (0, import_react67.useState)(0);
15556
- const blobUrlsRef = (0, import_react67.useRef)({});
15557
- const [CanvasComponent, setCanvasComponent] = (0, import_react67.useState)(
15622
+ const [personValues, setPersonValues] = (0, import_react68.useState)(initialValues ?? {});
15623
+ const [isActive, setIsActive] = (0, import_react68.useState)(!!(initialValues && Object.keys(initialValues).length > 0));
15624
+ const [isExporting, setIsExporting] = (0, import_react68.useState)(false);
15625
+ const [exportedBlobUrls, setExportedBlobUrls] = (0, import_react68.useState)({});
15626
+ const [exportCount, setExportCount] = (0, import_react68.useState)(0);
15627
+ const blobUrlsRef = (0, import_react68.useRef)({});
15628
+ const [CanvasComponent, setCanvasComponent] = (0, import_react68.useState)(
15558
15629
  cachedCanvasComponent
15559
15630
  );
15560
- const [BridgeComponent, setBridgeComponent] = (0, import_react67.useState)(
15631
+ const [BridgeComponent, setBridgeComponent] = (0, import_react68.useState)(
15561
15632
  cachedBridgeComponent
15562
15633
  );
15563
- (0, import_react67.useEffect)(() => {
15634
+ (0, import_react68.useEffect)(() => {
15564
15635
  if (CanvasComponent && BridgeComponent) return;
15565
15636
  if (!canvasImport) return;
15566
15637
  if (!canvasLoadPromise) {
@@ -15578,8 +15649,8 @@ function PersonalizationProvider({
15578
15649
  }
15579
15650
  });
15580
15651
  }, [CanvasComponent, BridgeComponent, canvasImport]);
15581
- const realtimeEnabledRef = (0, import_react67.useRef)(false);
15582
- (0, import_react67.useEffect)(() => {
15652
+ const realtimeEnabledRef = (0, import_react68.useRef)(false);
15653
+ (0, import_react68.useEffect)(() => {
15583
15654
  return () => {
15584
15655
  for (const url of Object.values(blobUrlsRef.current)) {
15585
15656
  try {
@@ -15589,16 +15660,16 @@ function PersonalizationProvider({
15589
15660
  }
15590
15661
  };
15591
15662
  }, []);
15592
- const updateField = (0, import_react67.useCallback)((key, value) => {
15663
+ const updateField = (0, import_react68.useCallback)((key, value) => {
15593
15664
  setIsActive(true);
15594
15665
  setPersonValues((prev) => ({ ...prev, [key]: value }));
15595
15666
  }, []);
15596
- const reset = (0, import_react67.useCallback)(() => {
15667
+ const reset = (0, import_react68.useCallback)(() => {
15597
15668
  setPersonValues({});
15598
15669
  setIsActive(false);
15599
15670
  setIsExporting(false);
15600
15671
  }, []);
15601
- const handleExport = (0, import_react67.useCallback)(
15672
+ const handleExport = (0, import_react68.useCallback)(
15602
15673
  (exports2) => {
15603
15674
  const newUrls = {};
15604
15675
  for (const [name, data] of Object.entries(exports2)) {
@@ -15632,11 +15703,11 @@ function PersonalizationProvider({
15632
15703
  },
15633
15704
  [realtime, placementOverride]
15634
15705
  );
15635
- const handleExportScheduled = (0, import_react67.useCallback)(() => {
15706
+ const handleExportScheduled = (0, import_react68.useCallback)(() => {
15636
15707
  setIsExporting(true);
15637
15708
  }, []);
15638
15709
  const shouldMountCanvas = CanvasComponent && BridgeComponent && canvasState?.elements && canvasState.elements.length > 0 && (!lazy || isActive);
15639
- const contextValue = import_react67.default.useMemo(
15710
+ const contextValue = import_react68.default.useMemo(
15640
15711
  () => ({
15641
15712
  fields,
15642
15713
  personValues,
@@ -15649,8 +15720,8 @@ function PersonalizationProvider({
15649
15720
  }),
15650
15721
  [fields, personValues, updateField, isActive, isExporting, exportedBlobUrls, exportCount, reset]
15651
15722
  );
15652
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(PersonalizationContext.Provider, { value: contextValue, children: [
15653
- shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15723
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(PersonalizationContext.Provider, { value: contextValue, children: [
15724
+ shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15654
15725
  "div",
15655
15726
  {
15656
15727
  style: {
@@ -15663,7 +15734,7 @@ function PersonalizationProvider({
15663
15734
  pointerEvents: "none"
15664
15735
  },
15665
15736
  "aria-hidden": true,
15666
- children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15737
+ children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15667
15738
  CanvasComponent,
15668
15739
  {
15669
15740
  initialElements: canvasState?.elements,
@@ -15683,7 +15754,7 @@ function PersonalizationProvider({
15683
15754
  exportImageQuality: exportConfig?.imageQuality ?? 0.85,
15684
15755
  onExport: handleExport,
15685
15756
  onExportScheduled: handleExportScheduled,
15686
- overlay: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(BridgeComponent, { fields, values: personValues })
15757
+ overlay: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(BridgeComponent, { fields, values: personValues })
15687
15758
  }
15688
15759
  )
15689
15760
  },
@@ -15708,7 +15779,7 @@ function usePersonalizationOptional() {
15708
15779
  }
15709
15780
 
15710
15781
  // src/personalization/PersonalizationInputs.tsx
15711
- var import_jsx_runtime88 = require("react/jsx-runtime");
15782
+ var import_jsx_runtime89 = require("react/jsx-runtime");
15712
15783
  function PersonalizationInputs({
15713
15784
  className,
15714
15785
  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",
@@ -15732,8 +15803,8 @@ function PersonalizationInputs({
15732
15803
  scrollInputAboveKeyboard(e.target);
15733
15804
  }
15734
15805
  };
15735
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: className || "flex flex-col gap-3", children: [
15736
- textFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15806
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: className || "flex flex-col gap-3", children: [
15807
+ textFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15737
15808
  "input",
15738
15809
  {
15739
15810
  type: "text",
@@ -15747,8 +15818,8 @@ function PersonalizationInputs({
15747
15818
  },
15748
15819
  `text-${field.name}`
15749
15820
  )),
15750
- colorFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex items-center gap-3", children: [
15751
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15821
+ colorFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "flex items-center gap-3", children: [
15822
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15752
15823
  "input",
15753
15824
  {
15754
15825
  type: "color",
@@ -15757,9 +15828,9 @@ function PersonalizationInputs({
15757
15828
  onChange: (e) => updateField(field.color, e.target.value)
15758
15829
  }
15759
15830
  ),
15760
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "text-base text-muted-foreground", children: field.label })
15831
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "text-base text-muted-foreground", children: field.label })
15761
15832
  ] }, `color-${field.color}`)),
15762
- imageFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15833
+ imageFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15763
15834
  "input",
15764
15835
  {
15765
15836
  type: "text",
@@ -15777,15 +15848,15 @@ function PersonalizationInputs({
15777
15848
  }
15778
15849
 
15779
15850
  // src/personalization/usePersonalizationShimmer.ts
15780
- var import_react68 = require("react");
15851
+ var import_react69 = require("react");
15781
15852
  function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15782
15853
  const personCtx = usePersonalizationContext();
15783
15854
  const realtime = useRealtimeOptional();
15784
- const [shimmerActive, setShimmerActive] = (0, import_react68.useState)(false);
15785
- const sdkSettledRef = (0, import_react68.useRef)(false);
15786
- const manualTriggerRef = (0, import_react68.useRef)(false);
15787
- const safetyTimeoutRef = (0, import_react68.useRef)(void 0);
15788
- const startShimmer = (0, import_react68.useCallback)(() => {
15855
+ const [shimmerActive, setShimmerActive] = (0, import_react69.useState)(false);
15856
+ const sdkSettledRef = (0, import_react69.useRef)(false);
15857
+ const manualTriggerRef = (0, import_react69.useRef)(false);
15858
+ const safetyTimeoutRef = (0, import_react69.useRef)(void 0);
15859
+ const startShimmer = (0, import_react69.useCallback)(() => {
15789
15860
  setShimmerActive(true);
15790
15861
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
15791
15862
  safetyTimeoutRef.current = setTimeout(
@@ -15797,25 +15868,25 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15797
15868
  safetyTimeoutMs
15798
15869
  );
15799
15870
  }, [safetyTimeoutMs]);
15800
- (0, import_react68.useEffect)(() => {
15871
+ (0, import_react69.useEffect)(() => {
15801
15872
  if (!personCtx?.isActive) return;
15802
15873
  sdkSettledRef.current = false;
15803
15874
  manualTriggerRef.current = false;
15804
15875
  realtime?.resetPipelineSettled();
15805
15876
  startShimmer();
15806
15877
  }, [personCtx?.personValues, personCtx?.isActive, startShimmer]);
15807
- const triggerShimmer = (0, import_react68.useCallback)(() => {
15878
+ const triggerShimmer = (0, import_react69.useCallback)(() => {
15808
15879
  sdkSettledRef.current = false;
15809
15880
  manualTriggerRef.current = true;
15810
15881
  startShimmer();
15811
15882
  }, [startShimmer]);
15812
- (0, import_react68.useEffect)(() => {
15883
+ (0, import_react69.useEffect)(() => {
15813
15884
  if (!realtime?.subscribePipelineSettled) return;
15814
15885
  return realtime.subscribePipelineSettled(() => {
15815
15886
  sdkSettledRef.current = true;
15816
15887
  });
15817
15888
  }, [realtime]);
15818
- (0, import_react68.useEffect)(() => {
15889
+ (0, import_react69.useEffect)(() => {
15819
15890
  const container = containerRef.current;
15820
15891
  if (!container) return;
15821
15892
  const observer = new MutationObserver((mutations) => {
@@ -15858,7 +15929,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15858
15929
  });
15859
15930
  return () => observer.disconnect();
15860
15931
  }, [containerRef]);
15861
- (0, import_react68.useEffect)(() => {
15932
+ (0, import_react69.useEffect)(() => {
15862
15933
  return () => {
15863
15934
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
15864
15935
  };
@@ -16000,6 +16071,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
16000
16071
  RealtimeProvider,
16001
16072
  ResponsiveZoom,
16002
16073
  RightToLeftProgressiveBlur,
16074
+ SafeImg,
16003
16075
  ScrollFade,
16004
16076
  SearchBox,
16005
16077
  SearchProvider,