@snowcone-app/ui 0.4.5 → 0.4.7

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
@@ -239,6 +239,7 @@ __export(src_exports, {
239
239
  LoadingOverlayPrismCandyInline: () => LoadingOverlayPrismCandyInline,
240
240
  MasonryGrid: () => MasonryGrid,
241
241
  MobileProductCarousel: () => MobileProductCarousel,
242
+ MockupBackground: () => MockupBackground,
242
243
  MockupPriorityProvider: () => MockupPriorityProvider,
243
244
  PDPLayout: () => PDPLayout,
244
245
  PersonalizationInputs: () => PersonalizationInputs,
@@ -364,6 +365,7 @@ __export(src_exports, {
364
365
  useIsolatedCanvas: () => useIsolatedCanvas,
365
366
  useLoadingOverlay: () => useLoadingOverlay,
366
367
  useMediaQuery: () => useMediaQuery,
368
+ useMockupBackgroundOptional: () => useMockupBackgroundOptional,
367
369
  useMockupPriority: () => useMockupPriority,
368
370
  useMockupPriorityOptional: () => useMockupPriorityOptional,
369
371
  usePersonalization: () => usePersonalization,
@@ -379,7 +381,7 @@ __export(src_exports, {
379
381
  useProductSelection: () => useProductSelection,
380
382
  useProviderStatus: () => useProviderStatus,
381
383
  useRealtime: () => useRealtime,
382
- useRealtimeMockup: () => import_react70.useRealtimeMockup,
384
+ useRealtimeMockup: () => import_react71.useRealtimeMockup,
383
385
  useRealtimeOptional: () => useRealtimeOptional,
384
386
  useRenderCount: () => useRenderCount,
385
387
  useRenderGuard: () => useRenderGuard,
@@ -9342,11 +9344,22 @@ var LoadingOverlayPrismCandyInline = (0, import_react40.memo)(
9342
9344
  );
9343
9345
 
9344
9346
  // src/index.ts
9345
- var import_react70 = require("@snowcone-app/sdk/react");
9347
+ var import_react71 = require("@snowcone-app/sdk/react");
9346
9348
  var import_sdk11 = require("@snowcone-app/sdk");
9347
9349
 
9348
- // src/patterns/ProductPageProvider.tsx
9350
+ // src/patterns/MockupBackground.tsx
9351
+ var import_react41 = require("react");
9349
9352
  var import_jsx_runtime56 = require("react/jsx-runtime");
9353
+ var MockupBackgroundContext = (0, import_react41.createContext)(void 0);
9354
+ function MockupBackground({ bg, children }) {
9355
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(MockupBackgroundContext.Provider, { value: bg, children });
9356
+ }
9357
+ function useMockupBackgroundOptional() {
9358
+ return (0, import_react41.useContext)(MockupBackgroundContext);
9359
+ }
9360
+
9361
+ // src/patterns/ProductPageProvider.tsx
9362
+ var import_jsx_runtime57 = require("react/jsx-runtime");
9350
9363
  function ProductPageProvider({
9351
9364
  children,
9352
9365
  productId,
@@ -9360,12 +9373,12 @@ function ProductPageProvider({
9360
9373
  realtimeGrantUrl,
9361
9374
  enablePriority = true
9362
9375
  }) {
9363
- let content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Product, { productId, productData, children });
9376
+ let content = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Product, { productId, productData, children });
9364
9377
  if (enablePriority) {
9365
- content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(MockupPriorityProvider, { children: content });
9378
+ content = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(MockupPriorityProvider, { children: content });
9366
9379
  }
9367
9380
  if (enableRealtime) {
9368
- content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9381
+ content = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9369
9382
  RealtimeProvider,
9370
9383
  {
9371
9384
  wsUrl: realtimeWsUrl,
@@ -9375,7 +9388,7 @@ function ProductPageProvider({
9375
9388
  }
9376
9389
  );
9377
9390
  }
9378
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9391
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9379
9392
  Shop,
9380
9393
  {
9381
9394
  endpoint,
@@ -9395,23 +9408,23 @@ function ProductPageProviderMinimal({
9395
9408
  shop,
9396
9409
  initialArtwork
9397
9410
  }) {
9398
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9411
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9399
9412
  Shop,
9400
9413
  {
9401
9414
  endpoint,
9402
9415
  mockupUrl,
9403
9416
  shop,
9404
9417
  initialArtwork,
9405
- children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Product, { productId, productData, children })
9418
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Product, { productId, productData, children })
9406
9419
  }
9407
9420
  );
9408
9421
  }
9409
9422
 
9410
9423
  // src/composed/ArtAlignment.tsx
9411
- var import_react41 = require("react");
9412
- var import_react42 = require("@use-gesture/react");
9424
+ var import_react42 = require("react");
9425
+ var import_react43 = require("@use-gesture/react");
9413
9426
  var import_sdk9 = require("@snowcone-app/sdk");
9414
- var import_jsx_runtime57 = require("react/jsx-runtime");
9427
+ var import_jsx_runtime58 = require("react/jsx-runtime");
9415
9428
  function ArtAlignment({
9416
9429
  src: propSrc,
9417
9430
  artworkAspectRatio: propAspectRatio,
@@ -9445,16 +9458,16 @@ function ArtAlignment({
9445
9458
  selection: {}
9446
9459
  };
9447
9460
  }
9448
- const containerRef = (0, import_react41.useRef)(null);
9449
- const imageRef = (0, import_react41.useRef)(null);
9450
- const lastUserDragTimeRef = (0, import_react41.useRef)(0);
9451
- const [containerSize, setContainerSize] = (0, import_react41.useState)({ width: 0, height: 0 });
9452
- const [position, setPosition] = (0, import_react41.useState)({ x: 0, y: 0 });
9453
- const [isReady, setIsReady] = (0, import_react41.useState)(false);
9454
- const [detectedAspectRatio, setDetectedAspectRatio] = (0, import_react41.useState)();
9461
+ const containerRef = (0, import_react42.useRef)(null);
9462
+ const imageRef = (0, import_react42.useRef)(null);
9463
+ const lastUserDragTimeRef = (0, import_react42.useRef)(0);
9464
+ const [containerSize, setContainerSize] = (0, import_react42.useState)({ width: 0, height: 0 });
9465
+ const [position, setPosition] = (0, import_react42.useState)({ x: 0, y: 0 });
9466
+ const [isReady, setIsReady] = (0, import_react42.useState)(false);
9467
+ const [detectedAspectRatio, setDetectedAspectRatio] = (0, import_react42.useState)();
9455
9468
  const effectiveAspectRatio = artworkAspectRatio || detectedAspectRatio;
9456
9469
  const alignment = placementDesign?.alignment || propAlignment || "center";
9457
- const descriptor = (0, import_react41.useMemo)(
9470
+ const descriptor = (0, import_react42.useMemo)(
9458
9471
  () => (0, import_sdk9.describeProductArtAlignment)(
9459
9472
  {
9460
9473
  src,
@@ -9476,7 +9489,7 @@ function ArtAlignment({
9476
9489
  productContext
9477
9490
  ]
9478
9491
  );
9479
- const containerStyle = (0, import_react41.useMemo)(() => {
9492
+ const containerStyle = (0, import_react42.useMemo)(() => {
9480
9493
  const style = {};
9481
9494
  if (height !== void 0) {
9482
9495
  const heightValue = typeof height === "number" ? height : parseFloat(height);
@@ -9507,7 +9520,7 @@ function ArtAlignment({
9507
9520
  }
9508
9521
  return style;
9509
9522
  }, [effectiveAspectRatio, height, maxHeight, minHeight]);
9510
- (0, import_react41.useEffect)(() => {
9523
+ (0, import_react42.useEffect)(() => {
9511
9524
  if (!containerRef.current) return;
9512
9525
  const resizeObserver = new ResizeObserver((entries) => {
9513
9526
  const entry = entries[0];
@@ -9533,7 +9546,7 @@ function ArtAlignment({
9533
9546
  }
9534
9547
  }
9535
9548
  };
9536
- (0, import_react41.useEffect)(() => {
9549
+ (0, import_react42.useEffect)(() => {
9537
9550
  if (!imageRef.current || !descriptor) return;
9538
9551
  if (imageRef.current.complete) {
9539
9552
  setIsReady(true);
@@ -9558,7 +9571,7 @@ function ArtAlignment({
9558
9571
  img.removeEventListener("load", handleLoad);
9559
9572
  };
9560
9573
  }, [descriptor?.src, artworkAspectRatio]);
9561
- const maskDimensions = (0, import_react41.useMemo)(() => {
9574
+ const maskDimensions = (0, import_react42.useMemo)(() => {
9562
9575
  if (!isReady || containerSize.width === 0 || !descriptor) {
9563
9576
  return { width: 0, height: 0 };
9564
9577
  }
@@ -9573,14 +9586,14 @@ function ArtAlignment({
9573
9586
  descriptor?.effectiveAlignment,
9574
9587
  isReady
9575
9588
  ]);
9576
- const clipPathCoords = (0, import_react41.useMemo)(() => {
9589
+ const clipPathCoords = (0, import_react42.useMemo)(() => {
9577
9590
  const halfMaskW = maskDimensions.width / 2;
9578
9591
  const halfMaskH = maskDimensions.height / 2;
9579
9592
  const halfContainerW = containerSize.width / 2;
9580
9593
  const halfContainerH = containerSize.height / 2;
9581
9594
  return { halfMaskW, halfMaskH, halfContainerW, halfContainerH };
9582
9595
  }, [maskDimensions.width, maskDimensions.height, containerSize.width, containerSize.height]);
9583
- (0, import_react41.useEffect)(() => {
9596
+ (0, import_react42.useEffect)(() => {
9584
9597
  if (Date.now() - lastUserDragTimeRef.current < 500) return;
9585
9598
  if (!isReady || maskDimensions.width === 0 || !descriptor) return;
9586
9599
  const points = (0, import_sdk9.getSnapPoints)(
@@ -9602,7 +9615,7 @@ function ArtAlignment({
9602
9615
  maskDimensions.height,
9603
9616
  isReady
9604
9617
  ]);
9605
- const overlayStyle = (0, import_react41.useMemo)(() => {
9618
+ const overlayStyle = (0, import_react42.useMemo)(() => {
9606
9619
  const { halfMaskW, halfMaskH, halfContainerW, halfContainerH } = clipPathCoords;
9607
9620
  const cx = position.x + halfContainerW;
9608
9621
  const cy = position.y + halfContainerH;
@@ -9623,7 +9636,7 @@ function ArtAlignment({
9623
9636
  clipPath: isReady ? `polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 0% 0%, ${right}px ${bottom}px, ${right}px ${top}px, ${left}px ${top}px, ${left}px ${bottom}px, ${right}px ${bottom}px)` : "none"
9624
9637
  };
9625
9638
  }, [isReady, position.x, position.y, clipPathCoords]);
9626
- const maskStyle = (0, import_react41.useMemo)(() => ({
9639
+ const maskStyle = (0, import_react42.useMemo)(() => ({
9627
9640
  width: `${maskDimensions.width}px`,
9628
9641
  height: `${maskDimensions.height}px`,
9629
9642
  boxShadow: `0 0 0 2px var(--color-background), 0 0 0 4px var(--color-primary)`,
@@ -9638,7 +9651,7 @@ function ArtAlignment({
9638
9651
  // GPU acceleration for smoother drag
9639
9652
  borderRadius: "var(--radius-image, 4px)"
9640
9653
  }), [maskDimensions.width, maskDimensions.height]);
9641
- const clearImageClipPath = (0, import_react41.useMemo)(() => {
9654
+ const clearImageClipPath = (0, import_react42.useMemo)(() => {
9642
9655
  if (!isReady) return "none";
9643
9656
  const { halfMaskW, halfMaskH, halfContainerW, halfContainerH } = clipPathCoords;
9644
9657
  const cx = position.x + halfContainerW;
@@ -9649,14 +9662,14 @@ function ArtAlignment({
9649
9662
  const top = cy - halfMaskH;
9650
9663
  return `polygon(${left}px ${top}px, ${right}px ${top}px, ${right}px ${bottom}px, ${left}px ${bottom}px)`;
9651
9664
  }, [isReady, position.x, position.y, clipPathCoords]);
9652
- const maskTransform = (0, import_react41.useMemo)(() => {
9665
+ const maskTransform = (0, import_react42.useMemo)(() => {
9653
9666
  return descriptor?.effectiveAlignment === "horizontal" ? `translate(calc(-50% + ${position.x}px), -50%)` : `translate(-50%, calc(-50% + ${position.y}px))`;
9654
9667
  }, [descriptor?.effectiveAlignment, position.x, position.y]);
9655
- const lastContextUpdateTimeRef = (0, import_react41.useRef)(0);
9656
- const pendingAlignmentRef = (0, import_react41.useRef)(null);
9657
- const throttleTimeoutRef = (0, import_react41.useRef)(null);
9668
+ const lastContextUpdateTimeRef = (0, import_react42.useRef)(0);
9669
+ const pendingAlignmentRef = (0, import_react42.useRef)(null);
9670
+ const throttleTimeoutRef = (0, import_react42.useRef)(null);
9658
9671
  const THROTTLE_MS = 150;
9659
- const bind = (0, import_react42.useDrag)(
9672
+ const bind = (0, import_react43.useDrag)(
9660
9673
  ({ offset: [ox, oy], last }) => {
9661
9674
  if (maskDimensions.width === 0 || maskDimensions.height === 0 || !descriptor) {
9662
9675
  return;
@@ -9749,7 +9762,7 @@ function ArtAlignment({
9749
9762
  if (!descriptor) {
9750
9763
  return null;
9751
9764
  }
9752
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9765
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9753
9766
  "div",
9754
9767
  {
9755
9768
  className: `relative ${className || ""}`,
@@ -9758,8 +9771,8 @@ function ArtAlignment({
9758
9771
  width: "fit-content",
9759
9772
  maxWidth: "100%"
9760
9773
  },
9761
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "overflow-hidden p-1", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { ref: containerRef, className: "relative", style: containerStyle, children: [
9762
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9774
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "overflow-hidden p-1", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { ref: containerRef, className: "relative", style: containerStyle, children: [
9775
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9763
9776
  "img",
9764
9777
  {
9765
9778
  ref: imageRef,
@@ -9784,9 +9797,9 @@ function ArtAlignment({
9784
9797
  loading: "eager"
9785
9798
  }
9786
9799
  ),
9787
- isReady && maskDimensions.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
9788
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { style: overlayStyle }),
9789
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9800
+ isReady && maskDimensions.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
9801
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { style: overlayStyle }),
9802
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9790
9803
  "img",
9791
9804
  {
9792
9805
  src: descriptor.src,
@@ -9814,7 +9827,7 @@ function ArtAlignment({
9814
9827
  loading: "eager"
9815
9828
  }
9816
9829
  ),
9817
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9830
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9818
9831
  "div",
9819
9832
  {
9820
9833
  ...bind(),
@@ -9831,8 +9844,8 @@ function ArtAlignment({
9831
9844
  }
9832
9845
 
9833
9846
  // src/composed/ArtworkCustomizer.tsx
9834
- var import_react43 = require("react");
9835
- var import_jsx_runtime58 = require("react/jsx-runtime");
9847
+ var import_react44 = require("react");
9848
+ var import_jsx_runtime59 = require("react/jsx-runtime");
9836
9849
  function ArtworkCustomizer(props) {
9837
9850
  const designContext = useDesign();
9838
9851
  const artwork = props.artwork || designContext.selectedArtwork;
@@ -9844,7 +9857,7 @@ function ArtworkCustomizer(props) {
9844
9857
  const placements = productCtx?.product?.placements || [];
9845
9858
  const selectedPlacement = productCtx?.selectedPlacement;
9846
9859
  const setSelectedPlacement = productCtx?.setSelectedPlacement;
9847
- (0, import_react43.useEffect)(() => {
9860
+ (0, import_react44.useEffect)(() => {
9848
9861
  if (placements.length > 0 && !selectedPlacement && setSelectedPlacement) {
9849
9862
  setSelectedPlacement(placements[0].label);
9850
9863
  }
@@ -9854,13 +9867,13 @@ function ArtworkCustomizer(props) {
9854
9867
  );
9855
9868
  const isColorPlacement = currentPlacement?.type === "color";
9856
9869
  const isFitMode = currentPlacement?.defaultScaleMode === "fit";
9857
- (0, import_react43.useEffect)(() => {
9870
+ (0, import_react44.useEffect)(() => {
9858
9871
  }, [selectedPlacement]);
9859
9872
  if (!artwork) {
9860
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: `text-sm text-muted-foreground ${props.className || ""}`, children: "Select artwork to customize" });
9873
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: `text-sm text-muted-foreground ${props.className || ""}`, children: "Select artwork to customize" });
9861
9874
  }
9862
9875
  if (artwork.type === "pattern") {
9863
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9876
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9864
9877
  TileCount,
9865
9878
  {
9866
9879
  artwork,
@@ -9871,8 +9884,8 @@ function ArtworkCustomizer(props) {
9871
9884
  );
9872
9885
  }
9873
9886
  const isCanvasEditorMode = props.mode === "canvas" || !!props.children && props.mode !== "alignment";
9874
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex flex-col gap-4", children: [
9875
- placements.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "text-sm leading-relaxed", children: placements.map((p) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9887
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex flex-col gap-4", children: [
9888
+ placements.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "text-sm leading-relaxed", children: placements.map((p) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9876
9889
  "button",
9877
9890
  {
9878
9891
  onClick: () => setSelectedPlacement?.(p.label),
@@ -9881,7 +9894,7 @@ function ArtworkCustomizer(props) {
9881
9894
  },
9882
9895
  p.label
9883
9896
  )) }),
9884
- isColorPlacement ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ColorPicker2, { placement: selectedPlacement }) : isFitMode ? null : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "relative", children: props.children || /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9897
+ isColorPlacement ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(ColorPicker2, { placement: selectedPlacement }) : isFitMode ? null : /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "relative", children: props.children || /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9885
9898
  ArtAlignment,
9886
9899
  {
9887
9900
  artwork: { src: artwork.src },
@@ -9897,7 +9910,7 @@ function ArtworkCustomizer(props) {
9897
9910
 
9898
9911
  // src/composed/CanvasEditor.tsx
9899
9912
  var import_lucide_react2 = require("lucide-react");
9900
- var import_jsx_runtime59 = require("react/jsx-runtime");
9913
+ var import_jsx_runtime60 = require("react/jsx-runtime");
9901
9914
  var ImageIcon = import_lucide_react2.Image;
9902
9915
  var TypeIcon = import_lucide_react2.Type;
9903
9916
  var ShapesIcon = import_lucide_react2.Shapes;
@@ -9908,43 +9921,43 @@ function CanvasEditor({
9908
9921
  onOpenTypography,
9909
9922
  children
9910
9923
  }) {
9911
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex flex-col gap-6", children: [
9912
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "bg-background border-2 border-border rounded-lg aspect-square overflow-hidden relative", children: children || /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "text-muted-foreground text-sm", children: "No editor provided" }) }) }),
9913
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex items-center justify-center gap-8 py-2", children: [
9914
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9924
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "flex flex-col gap-6", children: [
9925
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "bg-background border-2 border-border rounded-lg aspect-square overflow-hidden relative", children: children || /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "text-muted-foreground text-sm", children: "No editor provided" }) }) }),
9926
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "flex items-center justify-center gap-8 py-2", children: [
9927
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
9915
9928
  "button",
9916
9929
  {
9917
9930
  onClick: onOpenImageGallery,
9918
9931
  className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors",
9919
9932
  "aria-label": "Open image gallery",
9920
- children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(ImageIcon, { className: "w-6 h-6" }) })
9933
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ImageIcon, { className: "w-6 h-6" }) })
9921
9934
  }
9922
9935
  ),
9923
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9936
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
9924
9937
  "button",
9925
9938
  {
9926
9939
  onClick: onOpenTypography,
9927
9940
  className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors",
9928
9941
  "aria-label": "Add text",
9929
- children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TypeIcon, { className: "w-6 h-6" }) })
9942
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(TypeIcon, { className: "w-6 h-6" }) })
9930
9943
  }
9931
9944
  ),
9932
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(ShapesIcon, { className: "w-6 h-6" }) }) }),
9933
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(UploadIcon, { className: "w-6 h-6" }) }) })
9945
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ShapesIcon, { className: "w-6 h-6" }) }) }),
9946
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(UploadIcon, { className: "w-6 h-6" }) }) })
9934
9947
  ] })
9935
9948
  ] });
9936
9949
  }
9937
9950
 
9938
9951
  // src/composed/HeroProductImage.tsx
9939
- var import_react45 = require("react");
9952
+ var import_react46 = require("react");
9940
9953
  var import_sdk10 = require("@snowcone-app/sdk");
9941
9954
 
9942
9955
  // src/hooks/viewport/useContainerWidth.ts
9943
- var import_react44 = require("react");
9956
+ var import_react45 = require("react");
9944
9957
  function useContainerWidth(containerRef, maxWidth = 3e3) {
9945
- const [width, setWidth] = (0, import_react44.useState)(0);
9946
- const resizeTimeoutRef = (0, import_react44.useRef)(null);
9947
- (0, import_react44.useLayoutEffect)(() => {
9958
+ const [width, setWidth] = (0, import_react45.useState)(0);
9959
+ const resizeTimeoutRef = (0, import_react45.useRef)(null);
9960
+ (0, import_react45.useLayoutEffect)(() => {
9948
9961
  const el = containerRef.current;
9949
9962
  if (!el) return;
9950
9963
  const cssWidth = el.offsetWidth;
@@ -9952,7 +9965,7 @@ function useContainerWidth(containerRef, maxWidth = 3e3) {
9952
9965
  const dpr = window.devicePixelRatio ?? 1;
9953
9966
  setWidth(Math.min(Math.round(cssWidth * dpr), maxWidth));
9954
9967
  }, [containerRef, maxWidth]);
9955
- (0, import_react44.useEffect)(() => {
9968
+ (0, import_react45.useEffect)(() => {
9956
9969
  const measure = () => {
9957
9970
  const el = containerRef.current;
9958
9971
  if (!el) return;
@@ -9975,7 +9988,7 @@ function useContainerWidth(containerRef, maxWidth = 3e3) {
9975
9988
  }
9976
9989
 
9977
9990
  // src/composed/HeroProductImage.tsx
9978
- var import_jsx_runtime60 = require("react/jsx-runtime");
9991
+ var import_jsx_runtime61 = require("react/jsx-runtime");
9979
9992
  function slugifyPlacementKey(label) {
9980
9993
  return label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
9981
9994
  }
@@ -10009,11 +10022,12 @@ function buildHeroMockupUrl(args) {
10009
10022
  width: args.width,
10010
10023
  view: args.mockupId,
10011
10024
  variant: args.variantId,
10025
+ ...args.bg ? { bg: args.bg } : {},
10012
10026
  ...snow.resolver ? { base: snow.resolver } : {}
10013
10027
  });
10014
10028
  }
10015
10029
  var EMPTY_IMAGES = [];
10016
- var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10030
+ var HeroProductImage = (0, import_react46.memo)(function HeroProductImage2({
10017
10031
  productId,
10018
10032
  mockupId,
10019
10033
  variantId,
@@ -10046,24 +10060,25 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10046
10060
  const shopContext = useShopOptional();
10047
10061
  const realtimeContext = useRealtimeOptional();
10048
10062
  const priorityContext = useMockupPriorityOptional();
10049
- const priorityContextRef = (0, import_react45.useRef)(priorityContext);
10063
+ const mockupBg = useMockupBackgroundOptional();
10064
+ const priorityContextRef = (0, import_react46.useRef)(priorityContext);
10050
10065
  priorityContextRef.current = priorityContext;
10051
- const contextRef = (0, import_react45.useRef)(context);
10066
+ const contextRef = (0, import_react46.useRef)(context);
10052
10067
  contextRef.current = context;
10053
10068
  const actualProductId = product?.id || productId || context?.product?.id;
10054
- const actualGvid = (0, import_react45.useMemo)(() => {
10069
+ const actualGvid = (0, import_react46.useMemo)(() => {
10055
10070
  return (0, import_sdk10.resolveVariantId)(context, gvid, variantId);
10056
10071
  }, [gvid, variantId, context?.selection, context?.combinations]);
10057
- const actualMockupId = (0, import_react45.useMemo)(() => {
10072
+ const actualMockupId = (0, import_react46.useMemo)(() => {
10058
10073
  return (0, import_sdk10.resolveMockupId)(context, actualGvid, mockupId);
10059
10074
  }, [mockupId, actualGvid, context]);
10060
10075
  const artworkSrc = artwork?.src;
10061
10076
  const selectedArtworkSrc = designContext?.selectedArtwork?.src;
10062
10077
  const effectiveArtworkSrc = artworkSrc || selectedArtworkSrc;
10063
- const containerRef = (0, import_react45.useRef)(null);
10078
+ const containerRef = (0, import_react46.useRef)(null);
10064
10079
  const measuredWidth = useContainerWidth(containerRef);
10065
10080
  const width = widthProp ?? measuredWidth;
10066
- const initialStaticUrl = (0, import_react45.useMemo)(() => {
10081
+ const initialStaticUrl = (0, import_react46.useMemo)(() => {
10067
10082
  if (realtimeUrl) return null;
10068
10083
  if (mode === "realtime") return null;
10069
10084
  if (typeof window !== "undefined" && window.snowcone?.signMockupUrl) {
@@ -10096,7 +10111,8 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10096
10111
  placements: allPlacements,
10097
10112
  mockupId: actualMockupId,
10098
10113
  variantId: actualGvid,
10099
- width
10114
+ width,
10115
+ bg: mockupBg
10100
10116
  });
10101
10117
  }, [
10102
10118
  realtimeUrl,
@@ -10106,6 +10122,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10106
10122
  actualProductId,
10107
10123
  actualMockupId,
10108
10124
  actualGvid,
10125
+ mockupBg,
10109
10126
  product?.placements,
10110
10127
  context?.product?.placements,
10111
10128
  images,
@@ -10129,28 +10146,28 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10129
10146
  shimmerDelay,
10130
10147
  initialUrl: realtimeUrl || initialStaticUrl
10131
10148
  });
10132
- const [error, setError] = (0, import_react45.useState)(null);
10133
- const [isInPreloadZone, setIsInPreloadZone] = (0, import_react45.useState)(true);
10134
- const componentIdRef = (0, import_react45.useRef)(
10149
+ const [error, setError] = (0, import_react46.useState)(null);
10150
+ const [isInPreloadZone, setIsInPreloadZone] = (0, import_react46.useState)(true);
10151
+ const componentIdRef = (0, import_react46.useRef)(
10135
10152
  `hero-product-image-${Math.random().toString(36).substr(2, 9)}`
10136
10153
  );
10137
- const [containerMounted, setContainerMounted] = (0, import_react45.useState)(false);
10138
- const setContainerRef = (0, import_react45.useCallback)((node) => {
10154
+ const [containerMounted, setContainerMounted] = (0, import_react46.useState)(false);
10155
+ const setContainerRef = (0, import_react46.useCallback)((node) => {
10139
10156
  containerRef.current = node;
10140
10157
  setContainerMounted(!!node);
10141
10158
  }, []);
10142
- const lastUrlRef = (0, import_react45.useRef)(realtimeUrl ?? initialStaticUrl ?? null);
10143
- const priorityRegisteredRef = (0, import_react45.useRef)(false);
10144
- const onLoadCalledRef = (0, import_react45.useRef)(false);
10145
- const prevArtworkSrcRef = (0, import_react45.useRef)(void 0);
10146
- const realtimeArtworkSrcRef = (0, import_react45.useRef)(void 0);
10147
- const hasReceivedRealtimeRef = (0, import_react45.useRef)(false);
10148
- const isPendingExportRef = (0, import_react45.useRef)(false);
10149
- const onUrlGeneratedRef = (0, import_react45.useRef)(onUrlGenerated);
10159
+ const lastUrlRef = (0, import_react46.useRef)(realtimeUrl ?? initialStaticUrl ?? null);
10160
+ const priorityRegisteredRef = (0, import_react46.useRef)(false);
10161
+ const onLoadCalledRef = (0, import_react46.useRef)(false);
10162
+ const prevArtworkSrcRef = (0, import_react46.useRef)(void 0);
10163
+ const realtimeArtworkSrcRef = (0, import_react46.useRef)(void 0);
10164
+ const hasReceivedRealtimeRef = (0, import_react46.useRef)(false);
10165
+ const isPendingExportRef = (0, import_react46.useRef)(false);
10166
+ const onUrlGeneratedRef = (0, import_react46.useRef)(onUrlGenerated);
10150
10167
  onUrlGeneratedRef.current = onUrlGenerated;
10151
- const layersLengthRef = (0, import_react45.useRef)(layers.length);
10168
+ const layersLengthRef = (0, import_react46.useRef)(layers.length);
10152
10169
  layersLengthRef.current = layers.length;
10153
- (0, import_react45.useEffect)(() => {
10170
+ (0, import_react46.useEffect)(() => {
10154
10171
  if (initialPriority === 1) return;
10155
10172
  if (!containerMounted || !containerRef.current) return;
10156
10173
  if (isInPreloadZone) return;
@@ -10169,7 +10186,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10169
10186
  );
10170
10187
  return unobserve;
10171
10188
  }, [containerMounted, initialPriority, isInPreloadZone]);
10172
- (0, import_react45.useEffect)(() => {
10189
+ (0, import_react46.useEffect)(() => {
10173
10190
  if (!realtimeUrl) return;
10174
10191
  if (realtimeUrl === lastUrlRef.current) return;
10175
10192
  lastUrlRef.current = realtimeUrl;
@@ -10177,7 +10194,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10177
10194
  const isInitialLoad = layersLengthRef.current === 0;
10178
10195
  addLayerDirectly(realtimeUrl, { skipTransition: isInitialLoad });
10179
10196
  }, [realtimeUrl, addLayerDirectly, actualMockupId, placement]);
10180
- (0, import_react45.useEffect)(() => {
10197
+ (0, import_react46.useEffect)(() => {
10181
10198
  if (mode === "static") {
10182
10199
  return;
10183
10200
  }
@@ -10221,7 +10238,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10221
10238
  addLayerDirectly
10222
10239
  // NOTE: layers.length removed - use layersLengthRef instead to prevent duplicate requests
10223
10240
  ]);
10224
- (0, import_react45.useEffect)(() => {
10241
+ (0, import_react46.useEffect)(() => {
10225
10242
  if (mode === "static") return;
10226
10243
  if (!realtimeContext?.subscribePendingBlob || !placement) return;
10227
10244
  const handlePendingExport = (pendingPlacement) => {
@@ -10234,7 +10251,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10234
10251
  unsubscribe?.();
10235
10252
  };
10236
10253
  }, [mode, realtimeContext?.subscribePendingBlob, placement]);
10237
- (0, import_react45.useEffect)(() => {
10254
+ (0, import_react46.useEffect)(() => {
10238
10255
  if (!priorityContext || !actualMockupId || !placement) return;
10239
10256
  priorityContext.registerMockup(actualMockupId, placement, initialPriority);
10240
10257
  priorityRegisteredRef.current = true;
@@ -10245,7 +10262,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10245
10262
  }
10246
10263
  };
10247
10264
  }, [priorityContext, actualMockupId, placement, initialPriority]);
10248
- (0, import_react45.useEffect)(() => {
10265
+ (0, import_react46.useEffect)(() => {
10249
10266
  if (!priorityContext?.updateElementRef || !actualMockupId) return;
10250
10267
  if (containerMounted && containerRef.current) {
10251
10268
  priorityContext.updateElementRef(actualMockupId, containerRef.current);
@@ -10259,7 +10276,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10259
10276
  const artworkTileCount = artwork?.type === "pattern" ? artwork?.tileCount : void 0;
10260
10277
  const selectedArtworkType = designContext?.selectedArtwork?.type;
10261
10278
  const selectedArtworkTileCount = designContext?.selectedArtwork?.type === "pattern" ? designContext?.selectedArtwork?.tileCount : void 0;
10262
- (0, import_react45.useEffect)(() => {
10279
+ (0, import_react46.useEffect)(() => {
10263
10280
  const currentSrc = artworkSrc || selectedArtworkSrc;
10264
10281
  if (currentSrc !== prevArtworkSrcRef.current) {
10265
10282
  lastUrlRef.current = null;
@@ -10269,11 +10286,11 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10269
10286
  realtimeArtworkSrcRef.current = void 0;
10270
10287
  }
10271
10288
  }, [artworkSrc, selectedArtworkSrc]);
10272
- const contextSelectionRef = (0, import_react45.useRef)(context?.selection);
10273
- const contextOptionAttributesRef = (0, import_react45.useRef)(context?.optionAttributes);
10289
+ const contextSelectionRef = (0, import_react46.useRef)(context?.selection);
10290
+ const contextOptionAttributesRef = (0, import_react46.useRef)(context?.optionAttributes);
10274
10291
  contextSelectionRef.current = context?.selection;
10275
10292
  contextOptionAttributesRef.current = context?.optionAttributes;
10276
- const createDesignForPlacementsWrapper = (0, import_react45.useCallback)(
10293
+ const createDesignForPlacementsWrapper = (0, import_react46.useCallback)(
10277
10294
  (placements, providedImages) => {
10278
10295
  const effectiveArtworkSrc2 = artworkSrc || selectedArtworkSrc;
10279
10296
  if (!effectiveArtworkSrc2 || effectiveArtworkSrc2.trim() === "" || effectiveArtworkSrc2 === "undefined" || effectiveArtworkSrc2 === "null") {
@@ -10312,7 +10329,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10312
10329
  selectedArtworkTileCount
10313
10330
  ]
10314
10331
  );
10315
- (0, import_react45.useEffect)(() => {
10332
+ (0, import_react46.useEffect)(() => {
10316
10333
  if (mode === "realtime") return;
10317
10334
  if (initialStaticUrl && lastUrlRef.current === initialStaticUrl) {
10318
10335
  return;
@@ -10341,7 +10358,8 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10341
10358
  placements: allPlacements,
10342
10359
  mockupId: actualMockupId,
10343
10360
  variantId: actualGvid,
10344
- width
10361
+ width,
10362
+ bg: mockupBg
10345
10363
  });
10346
10364
  if (!url) return;
10347
10365
  if (url === lastUrlRef.current) return;
@@ -10382,6 +10400,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10382
10400
  actualProductId,
10383
10401
  actualMockupId,
10384
10402
  actualGvid,
10403
+ mockupBg,
10385
10404
  images,
10386
10405
  width,
10387
10406
  effects,
@@ -10412,17 +10431,17 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10412
10431
  const topLayer = layers[layers.length - 1];
10413
10432
  const displayUrl = topLayer?.url || realtimeUrl || initialStaticUrl;
10414
10433
  const CROSSFADE_MS = 400;
10415
- const [prevUrl, setPrevUrl] = (0, import_react45.useState)(null);
10416
- const [showNew, setShowNew] = (0, import_react45.useState)(false);
10417
- const [renderedUrl, setRenderedUrl] = (0, import_react45.useState)(displayUrl);
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);
10423
- const prevDisplayUrlRef = (0, import_react45.useRef)(displayUrl);
10424
- const signHintShownRef = (0, import_react45.useRef)(false);
10425
- (0, import_react45.useEffect)(() => {
10434
+ const [prevUrl, setPrevUrl] = (0, import_react46.useState)(null);
10435
+ const [showNew, setShowNew] = (0, import_react46.useState)(false);
10436
+ const [renderedUrl, setRenderedUrl] = (0, import_react46.useState)(displayUrl);
10437
+ const [firstImageLoaded, setFirstImageLoaded] = (0, import_react46.useState)(false);
10438
+ const [loaderMounted, setLoaderMounted] = (0, import_react46.useState)(true);
10439
+ const [imgFailed, setImgFailed] = (0, import_react46.useState)(false);
10440
+ const [retryNonce, setRetryNonce] = (0, import_react46.useState)(0);
10441
+ const retriedUrlRef = (0, import_react46.useRef)(null);
10442
+ const prevDisplayUrlRef = (0, import_react46.useRef)(displayUrl);
10443
+ const signHintShownRef = (0, import_react46.useRef)(false);
10444
+ (0, import_react46.useEffect)(() => {
10426
10445
  if (!displayUrl || displayUrl === prevDisplayUrlRef.current) return;
10427
10446
  const oldUrl = prevDisplayUrlRef.current;
10428
10447
  prevDisplayUrlRef.current = displayUrl;
@@ -10449,26 +10468,26 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10449
10468
  preload.onload = null;
10450
10469
  };
10451
10470
  }, [displayUrl]);
10452
- const handleCrossfadeEnd = (0, import_react45.useCallback)(() => {
10471
+ const handleCrossfadeEnd = (0, import_react46.useCallback)(() => {
10453
10472
  setPrevUrl(null);
10454
10473
  setShowNew(false);
10455
10474
  }, []);
10456
- const handleLoaderExited = (0, import_react45.useCallback)(() => setLoaderMounted(false), []);
10475
+ const handleLoaderExited = (0, import_react46.useCallback)(() => setLoaderMounted(false), []);
10457
10476
  if (!hasArtwork) {
10458
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10477
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10459
10478
  "div",
10460
10479
  {
10461
10480
  className: `bg-gray-100 flex items-center justify-center ${className || ""}`,
10462
10481
  style,
10463
- children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "text-gray-400 text-center p-4", children: [
10464
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10482
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "text-gray-400 text-center p-4", children: [
10483
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10465
10484
  "svg",
10466
10485
  {
10467
10486
  className: "w-8 h-8 mx-auto mb-2",
10468
10487
  fill: "none",
10469
10488
  stroke: "currentColor",
10470
10489
  viewBox: "0 0 24 24",
10471
- children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10490
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10472
10491
  "path",
10473
10492
  {
10474
10493
  strokeLinecap: "round",
@@ -10479,22 +10498,22 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10479
10498
  )
10480
10499
  }
10481
10500
  ),
10482
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-xs", children: "No artwork" })
10501
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "text-xs", children: "No artwork" })
10483
10502
  ] })
10484
10503
  }
10485
10504
  );
10486
10505
  }
10487
10506
  if (error) {
10488
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10507
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10489
10508
  "div",
10490
10509
  {
10491
10510
  className: `bg-red-50 flex items-center justify-center ${className || ""}`,
10492
10511
  style,
10493
- children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "text-red-600 text-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-xs", children: "Error loading" }) })
10512
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "text-red-600 text-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "text-xs", children: "Error loading" }) })
10494
10513
  }
10495
10514
  );
10496
10515
  }
10497
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
10516
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
10498
10517
  "div",
10499
10518
  {
10500
10519
  ref: setContainerRef,
@@ -10502,7 +10521,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10502
10521
  style,
10503
10522
  "data-hero-image": "true",
10504
10523
  children: [
10505
- renderedUrl && !imgFailed && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10524
+ renderedUrl && !imgFailed && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10506
10525
  "img",
10507
10526
  {
10508
10527
  alt: `Product mockup${placement ? ` - ${placement}` : ""}`,
@@ -10541,8 +10560,8 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10541
10560
  }
10542
10561
  }
10543
10562
  ),
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" }) }),
10545
- realtimeContext?.renderError && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10563
+ imgFailed && !prevUrl && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "text-muted-foreground text-xs", children: "Preview unavailable" }) }),
10564
+ realtimeContext?.renderError && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10546
10565
  "div",
10547
10566
  {
10548
10567
  role: "alert",
@@ -10551,7 +10570,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10551
10570
  children: `Render blocked: ${realtimeContext.renderError.code} \u2014 ${realtimeContext.renderError.message}`
10552
10571
  }
10553
10572
  ),
10554
- prevUrl && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10573
+ prevUrl && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10555
10574
  "img",
10556
10575
  {
10557
10576
  alt: "",
@@ -10566,7 +10585,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10566
10585
  onTransitionEnd: handleCrossfadeEnd
10567
10586
  }
10568
10587
  ),
10569
- loaderMounted && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10588
+ loaderMounted && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10570
10589
  LoadingOverlayPrismCandyInline,
10571
10590
  {
10572
10591
  visible: !firstImageLoaded,
@@ -10580,16 +10599,16 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10580
10599
  });
10581
10600
 
10582
10601
  // 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(
10602
+ var import_react47 = __toESM(require("react"), 1);
10603
+ var import_jsx_runtime62 = require("react/jsx-runtime");
10604
+ var SafeImg = import_react47.default.forwardRef(
10586
10605
  function SafeImg2({ fallback = null, onError, src, ...rest }, ref) {
10587
- const [failed, setFailed] = (0, import_react46.useState)(false);
10588
- (0, import_react46.useEffect)(() => {
10606
+ const [failed, setFailed] = (0, import_react47.useState)(false);
10607
+ (0, import_react47.useEffect)(() => {
10589
10608
  setFailed(false);
10590
10609
  }, [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)(
10610
+ if (failed) return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_jsx_runtime62.Fragment, { children: fallback });
10611
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10593
10612
  "img",
10594
10613
  {
10595
10614
  ...rest,
@@ -10624,11 +10643,11 @@ var { searchClient } = (0, import_instant_meilisearch.instantMeiliSearch)(
10624
10643
  );
10625
10644
 
10626
10645
  // src/composed/search/SearchProvider.tsx
10627
- var import_react47 = require("react");
10628
- var import_jsx_runtime62 = require("react/jsx-runtime");
10646
+ var import_react48 = require("react");
10647
+ var import_jsx_runtime63 = require("react/jsx-runtime");
10629
10648
  function InitialSearchTrigger() {
10630
10649
  const { refine } = (0, import_react_instantsearch.useSearchBox)();
10631
- (0, import_react47.useEffect)(() => {
10650
+ (0, import_react48.useEffect)(() => {
10632
10651
  refine("");
10633
10652
  }, [refine]);
10634
10653
  return null;
@@ -10652,7 +10671,7 @@ function SearchProvider({
10652
10671
  ],
10653
10672
  children
10654
10673
  }) {
10655
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
10674
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
10656
10675
  import_react_instantsearch.InstantSearch,
10657
10676
  {
10658
10677
  searchClient,
@@ -10680,7 +10699,7 @@ function SearchProvider({
10680
10699
  }
10681
10700
  },
10682
10701
  children: [
10683
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10702
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10684
10703
  import_react_instantsearch.Configure,
10685
10704
  {
10686
10705
  hitsPerPage,
@@ -10689,7 +10708,7 @@ function SearchProvider({
10689
10708
  attributesToRetrieve
10690
10709
  }
10691
10710
  ),
10692
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(InitialSearchTrigger, {}),
10711
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(InitialSearchTrigger, {}),
10693
10712
  children
10694
10713
  ]
10695
10714
  }
@@ -10699,17 +10718,17 @@ function SearchProvider({
10699
10718
  // src/composed/search/SearchBox.tsx
10700
10719
  var import_react_instantsearch2 = require("react-instantsearch");
10701
10720
  var import_lucide_react3 = require("lucide-react");
10702
- var import_react48 = require("react");
10703
- var import_jsx_runtime63 = require("react/jsx-runtime");
10721
+ var import_react49 = require("react");
10722
+ var import_jsx_runtime64 = require("react/jsx-runtime");
10704
10723
  function SearchBox() {
10705
10724
  const { query, refine, clear } = (0, import_react_instantsearch2.useSearchBox)();
10706
10725
  const searchParams = useUiSearchParams();
10707
10726
  const router = useUiRouter();
10708
- const inputRef = (0, import_react48.useRef)(null);
10709
- const [showShimmer, setShowShimmer] = (0, import_react48.useState)(false);
10727
+ const inputRef = (0, import_react49.useRef)(null);
10728
+ const [showShimmer, setShowShimmer] = (0, import_react49.useState)(false);
10710
10729
  const inputId = "search-products-input";
10711
10730
  const descriptionId = "search-description";
10712
- (0, import_react48.useEffect)(() => {
10731
+ (0, import_react49.useEffect)(() => {
10713
10732
  const handleSpotlight = () => {
10714
10733
  inputRef.current?.focus();
10715
10734
  inputRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
@@ -10719,7 +10738,7 @@ function SearchBox() {
10719
10738
  window.addEventListener("search-spotlight", handleSpotlight);
10720
10739
  return () => window.removeEventListener("search-spotlight", handleSpotlight);
10721
10740
  }, []);
10722
- (0, import_react48.useEffect)(() => {
10741
+ (0, import_react49.useEffect)(() => {
10723
10742
  const shouldFocus = searchParams.get("focus") === "search";
10724
10743
  if (shouldFocus && inputRef.current) {
10725
10744
  const timer = setTimeout(() => {
@@ -10734,8 +10753,8 @@ function SearchBox() {
10734
10753
  return () => clearTimeout(timer);
10735
10754
  }
10736
10755
  }, [searchParams, router]);
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)(
10756
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "relative", children: [
10757
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10739
10758
  Input,
10740
10759
  {
10741
10760
  ref: inputRef,
@@ -10744,15 +10763,15 @@ function SearchBox() {
10744
10763
  value: query,
10745
10764
  onChange: (e) => refine(e.target.value),
10746
10765
  placeholder: "Search products...",
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)(
10766
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(import_lucide_react3.Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10767
+ endContent: query ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10749
10768
  "button",
10750
10769
  {
10751
10770
  type: "button",
10752
10771
  onClick: clear,
10753
10772
  className: "hover:text-foreground transition-colors",
10754
10773
  "aria-label": "Clear search",
10755
- children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_lucide_react3.X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10774
+ children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(import_lucide_react3.X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10756
10775
  }
10757
10776
  ) : void 0,
10758
10777
  "aria-label": "Search products",
@@ -10762,11 +10781,11 @@ function SearchBox() {
10762
10781
  className: "[&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden"
10763
10782
  }
10764
10783
  ),
10765
- showShimmer && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10784
+ showShimmer && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10766
10785
  "div",
10767
10786
  {
10768
10787
  className: "absolute inset-0 pointer-events-none rounded-input z-20 overflow-hidden",
10769
- children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10788
+ children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10770
10789
  "div",
10771
10790
  {
10772
10791
  className: "absolute inset-0",
@@ -10779,13 +10798,13 @@ function SearchBox() {
10779
10798
  )
10780
10799
  }
10781
10800
  ),
10782
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("style", { dangerouslySetInnerHTML: { __html: `
10801
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("style", { dangerouslySetInnerHTML: { __html: `
10783
10802
  @keyframes searchShimmer {
10784
10803
  0% { transform: translateX(-100%); }
10785
10804
  100% { transform: translateX(100%); }
10786
10805
  }
10787
10806
  ` } }),
10788
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10807
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10789
10808
  ] }) });
10790
10809
  }
10791
10810
 
@@ -10793,7 +10812,7 @@ function SearchBox() {
10793
10812
  var import_react_instantsearch3 = require("react-instantsearch");
10794
10813
 
10795
10814
  // src/composed/search/ProductHit.tsx
10796
- var import_jsx_runtime64 = require("react/jsx-runtime");
10815
+ var import_jsx_runtime65 = require("react/jsx-runtime");
10797
10816
  function ProductHitComponent({
10798
10817
  hit: product,
10799
10818
  variant = "overlay"
@@ -10810,12 +10829,12 @@ function ProductHitComponent({
10810
10829
  }
10811
10830
  return "";
10812
10831
  };
10813
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10832
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10814
10833
  Product,
10815
10834
  {
10816
10835
  productId,
10817
10836
  productData: product,
10818
- children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10837
+ children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10819
10838
  ProductCard,
10820
10839
  {
10821
10840
  variant,
@@ -10836,10 +10855,10 @@ function ProductHitComponent({
10836
10855
  }
10837
10856
 
10838
10857
  // src/composed/search/ProductGrid.tsx
10839
- var import_react49 = require("react");
10840
- var import_jsx_runtime65 = require("react/jsx-runtime");
10858
+ var import_react50 = require("react");
10859
+ var import_jsx_runtime66 = require("react/jsx-runtime");
10841
10860
  function ProductGridSkeletonItem() {
10842
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "aspect-square bg-muted animate-pulse" });
10861
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "aspect-square bg-muted animate-pulse" });
10843
10862
  }
10844
10863
  function ProductGrid({
10845
10864
  className = "",
@@ -10849,26 +10868,26 @@ function ProductGrid({
10849
10868
  }) {
10850
10869
  const { nbHits } = (0, import_react_instantsearch3.useStats)();
10851
10870
  const { status, results } = (0, import_react_instantsearch3.useInstantSearch)();
10852
- const [announcement, setAnnouncement] = (0, import_react49.useState)("");
10871
+ const [announcement, setAnnouncement] = (0, import_react50.useState)("");
10853
10872
  const hitsCount = results?.hits?.length ?? 0;
10854
10873
  const showSkeleton = hitsCount === 0 && status !== "error";
10855
- (0, import_react49.useEffect)(() => {
10874
+ (0, import_react50.useEffect)(() => {
10856
10875
  const timer = setTimeout(() => {
10857
10876
  setAnnouncement(`${nbHits} ${nbHits === 1 ? "product" : "products"} found`);
10858
10877
  }, 1e3);
10859
10878
  return () => clearTimeout(timer);
10860
10879
  }, [nbHits]);
10861
- const HitComponent = (0, import_react49.useCallback)(({ hit }) => /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10880
+ const HitComponent = (0, import_react50.useCallback)(({ hit }) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10862
10881
  ProductHitComponent,
10863
10882
  {
10864
10883
  hit,
10865
10884
  variant
10866
10885
  }
10867
10886
  ), [variant]);
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)(
10887
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className, children: [
10888
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10889
+ showSkeleton && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: `grid ${gridClassName}`, children: Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ProductGridSkeletonItem, {}, i)) }),
10890
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: showSkeleton ? "hidden" : "", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10872
10891
  import_react_instantsearch3.Hits,
10873
10892
  {
10874
10893
  hitComponent: HitComponent,
@@ -10883,18 +10902,18 @@ function ProductGrid({
10883
10902
  }
10884
10903
 
10885
10904
  // src/composed/search/Filters.tsx
10886
- var import_react51 = require("react");
10905
+ var import_react52 = require("react");
10887
10906
 
10888
10907
  // src/composed/search/FiltersButton.tsx
10889
10908
  var import_lucide_react4 = require("lucide-react");
10890
- var import_jsx_runtime66 = require("react/jsx-runtime");
10909
+ var import_jsx_runtime67 = require("react/jsx-runtime");
10891
10910
  var SlidersHorizontalIcon = import_lucide_react4.SlidersHorizontal;
10892
10911
  function FiltersButton({
10893
10912
  onClick,
10894
10913
  className = "",
10895
10914
  children = "Filters"
10896
10915
  }) {
10897
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10916
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
10898
10917
  Button,
10899
10918
  {
10900
10919
  variant: "field",
@@ -10902,8 +10921,8 @@ function FiltersButton({
10902
10921
  className,
10903
10922
  "aria-label": "Open filters",
10904
10923
  children: [
10905
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10906
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children })
10924
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10925
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { children })
10907
10926
  ]
10908
10927
  }
10909
10928
  );
@@ -10912,15 +10931,15 @@ function FiltersButton({
10912
10931
  // src/composed/search/FiltersDrawer.tsx
10913
10932
  var import_react_instantsearch4 = require("react-instantsearch");
10914
10933
  var import_lucide_react5 = require("lucide-react");
10915
- var import_react50 = require("react");
10934
+ var import_react51 = require("react");
10916
10935
  var Slider2 = __toESM(require("@radix-ui/react-slider"), 1);
10917
- var import_jsx_runtime67 = require("react/jsx-runtime");
10936
+ var import_jsx_runtime68 = require("react/jsx-runtime");
10918
10937
  var XIcon2 = import_lucide_react5.X;
10919
10938
  function FiltersDrawer({ isOpen, onClose }) {
10920
- const [showCounts, setShowCounts] = (0, import_react50.useState)(false);
10939
+ const [showCounts, setShowCounts] = (0, import_react51.useState)(false);
10921
10940
  const { nbHits } = (0, import_react_instantsearch4.useStats)();
10922
10941
  const containerRef = useFocusTrap(isOpen, onClose);
10923
- (0, import_react50.useEffect)(() => {
10942
+ (0, import_react51.useEffect)(() => {
10924
10943
  if (isOpen) {
10925
10944
  document.body.style.overflow = "hidden";
10926
10945
  } else {
@@ -10930,7 +10949,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10930
10949
  document.body.style.overflow = "";
10931
10950
  };
10932
10951
  }, [isOpen]);
10933
- (0, import_react50.useEffect)(() => {
10952
+ (0, import_react51.useEffect)(() => {
10934
10953
  const handleEscape = (e) => {
10935
10954
  if (e.key === "Escape" && isOpen) {
10936
10955
  onClose();
@@ -10939,8 +10958,8 @@ function FiltersDrawer({ isOpen, onClose }) {
10939
10958
  document.addEventListener("keydown", handleEscape);
10940
10959
  return () => document.removeEventListener("keydown", handleEscape);
10941
10960
  }, [isOpen, onClose]);
10942
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
10943
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
10961
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
10962
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
10944
10963
  "div",
10945
10964
  {
10946
10965
  className: `fixed inset-0 bg-black/50 z-40 transition-opacity ${isOpen ? "opacity-100" : "opacity-0 pointer-events-none"}`,
@@ -10948,7 +10967,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10948
10967
  "aria-hidden": "true"
10949
10968
  }
10950
10969
  ),
10951
- /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
10970
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
10952
10971
  "div",
10953
10972
  {
10954
10973
  ref: containerRef,
@@ -10957,26 +10976,26 @@ function FiltersDrawer({ isOpen, onClose }) {
10957
10976
  "aria-modal": "true",
10958
10977
  "aria-labelledby": "filters-drawer-title",
10959
10978
  children: [
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)(
10979
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center justify-between px-4 py-4", children: [
10980
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10981
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
10963
10982
  "button",
10964
10983
  {
10965
10984
  onClick: onClose,
10966
10985
  className: "p-2 hover:bg-foreground/5 rounded-full transition-colors",
10967
10986
  "aria-label": "Close filters",
10968
- children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(XIcon2, { className: "w-5 h-5" })
10987
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(XIcon2, { className: "w-5 h-5" })
10969
10988
  }
10970
10989
  )
10971
10990
  ] }),
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: [
10991
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("p", { className: "text-sm font-caption text-foreground/60", role: "status", "aria-live": "polite", children: [
10973
10992
  nbHits.toLocaleString(),
10974
10993
  " ",
10975
10994
  nbHits === 1 ? "result" : "results"
10976
10995
  ] }) }),
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, {})
10996
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex flex-col gap-8", children: [
10997
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(TagsSection, { showCounts, setShowCounts }),
10998
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(PriceSection, {})
10980
10999
  ] }) })
10981
11000
  ]
10982
11001
  }
@@ -10992,9 +11011,9 @@ function TagsSection({
10992
11011
  sortBy: ["count:desc", "name:asc"],
10993
11012
  limit: 100
10994
11013
  });
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)(
11014
+ const [isExpanded, setIsExpanded] = (0, import_react51.useState)(true);
11015
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
11016
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
10998
11017
  "button",
10999
11018
  {
11000
11019
  onClick: () => setIsExpanded(!isExpanded),
@@ -11002,8 +11021,8 @@ function TagsSection({
11002
11021
  "aria-expanded": isExpanded,
11003
11022
  "aria-controls": "tags-content",
11004
11023
  children: [
11005
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
11006
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11024
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
11025
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11007
11026
  "svg",
11008
11027
  {
11009
11028
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -11012,14 +11031,14 @@ function TagsSection({
11012
11031
  stroke: "currentColor",
11013
11032
  strokeWidth: 2.5,
11014
11033
  "aria-hidden": "true",
11015
- children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11034
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11016
11035
  }
11017
11036
  )
11018
11037
  ]
11019
11038
  }
11020
11039
  ),
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)(
11040
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "space-y-4", id: "tags-content", children: [
11041
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "flex flex-wrap gap-2", role: "group", "aria-label": "Product tags filter", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
11023
11042
  "button",
11024
11043
  {
11025
11044
  onClick: () => refine(item.value),
@@ -11030,15 +11049,15 @@ function TagsSection({
11030
11049
  "aria-label": `${item.isRefined ? "Remove" : "Apply"} ${item.label} filter${showCounts ? ` (${item.count} products)` : ""}`,
11031
11050
  "aria-pressed": item.isRefined,
11032
11051
  children: [
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 })
11052
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { "aria-hidden": "true", children: item.label }),
11053
+ showCounts && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: `text-xs font-caption ${item.isRefined ? "opacity-80" : "opacity-60"}`, "aria-hidden": "true", children: item.count })
11035
11054
  ]
11036
11055
  },
11037
11056
  item.value
11038
11057
  )) }),
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)(
11058
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center justify-between pt-2", children: [
11059
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
11060
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11042
11061
  "button",
11043
11062
  {
11044
11063
  onClick: () => setShowCounts(!showCounts),
@@ -11046,7 +11065,7 @@ function TagsSection({
11046
11065
  role: "switch",
11047
11066
  "aria-checked": showCounts,
11048
11067
  "aria-labelledby": "show-counts-label",
11049
- children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11068
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11050
11069
  "span",
11051
11070
  {
11052
11071
  className: `inline-block h-4 w-4 transform rounded-full bg-background shadow-sm transition-transform ${showCounts ? "translate-x-6" : "translate-x-1"}`,
@@ -11063,11 +11082,11 @@ function PriceSection() {
11063
11082
  const { range, refine, start, canRefine } = (0, import_react_instantsearch4.useRange)({ attribute: "price" });
11064
11083
  const rangeMin = typeof range.min === "number" && isFinite(range.min) ? range.min : 0;
11065
11084
  const rangeMax = typeof range.max === "number" && isFinite(range.max) ? range.max : 15e3;
11066
- const [localRange, setLocalRange] = (0, import_react50.useState)([
11085
+ const [localRange, setLocalRange] = (0, import_react51.useState)([
11067
11086
  typeof start?.[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
11068
11087
  typeof start?.[1] === "number" && isFinite(start[1]) ? start[1] : rangeMax
11069
11088
  ]);
11070
- (0, import_react50.useEffect)(() => {
11089
+ (0, import_react51.useEffect)(() => {
11071
11090
  if (start && Array.isArray(start)) {
11072
11091
  setLocalRange([
11073
11092
  typeof start[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
@@ -11077,7 +11096,7 @@ function PriceSection() {
11077
11096
  setLocalRange([rangeMin, rangeMax]);
11078
11097
  }
11079
11098
  }, [start, rangeMin, rangeMax]);
11080
- const [isExpanded, setIsExpanded] = (0, import_react50.useState)(true);
11099
+ const [isExpanded, setIsExpanded] = (0, import_react51.useState)(true);
11081
11100
  if (!canRefine) {
11082
11101
  return null;
11083
11102
  }
@@ -11092,8 +11111,8 @@ function PriceSection() {
11092
11111
  return `$${priceInDollars.toFixed(2)}`;
11093
11112
  }
11094
11113
  };
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)(
11114
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
11115
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
11097
11116
  "button",
11098
11117
  {
11099
11118
  onClick: () => setIsExpanded(!isExpanded),
@@ -11101,8 +11120,8 @@ function PriceSection() {
11101
11120
  "aria-expanded": isExpanded,
11102
11121
  "aria-controls": "price-content",
11103
11122
  children: [
11104
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
11105
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11123
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
11124
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11106
11125
  "svg",
11107
11126
  {
11108
11127
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -11111,22 +11130,22 @@ function PriceSection() {
11111
11130
  stroke: "currentColor",
11112
11131
  strokeWidth: 2.5,
11113
11132
  "aria-hidden": "true",
11114
- children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11133
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11115
11134
  }
11116
11135
  )
11117
11136
  ]
11118
11137
  }
11119
11138
  ),
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]) })
11139
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "space-y-6", id: "price-content", children: [
11140
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center justify-between text-sm font-display", children: [
11141
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: formatPrice2(localRange[0]) }),
11142
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "text-foreground/70", children: formatPrice2(localRange[1]) })
11124
11143
  ] }),
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) => {
11144
+ /* @__PURE__ */ (0, import_jsx_runtime68.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) => {
11126
11145
  const totalBars = 19;
11127
11146
  const barPrice = rangeMin + (rangeMax - rangeMin) / totalBars * i;
11128
11147
  const isInRange = barPrice >= localRange[0] && barPrice <= localRange[1];
11129
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11148
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11130
11149
  "div",
11131
11150
  {
11132
11151
  className: `flex-1 rounded-t-sm transition-opacity ${isInRange ? "bg-foreground" : "bg-foreground/20"}`,
@@ -11135,7 +11154,7 @@ function PriceSection() {
11135
11154
  i
11136
11155
  );
11137
11156
  }) }),
11138
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
11157
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
11139
11158
  Slider2.Root,
11140
11159
  {
11141
11160
  className: "relative flex w-full touch-none select-none items-center",
@@ -11153,8 +11172,8 @@ function PriceSection() {
11153
11172
  step: 1,
11154
11173
  minStepsBetweenThumbs: 1,
11155
11174
  children: [
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)(
11175
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(Slider2.Track, { className: "relative h-3 w-full grow overflow-hidden rounded-full bg-foreground/20", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(Slider2.Range, { className: "absolute h-full bg-foreground" }) }),
11176
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11158
11177
  Slider2.Thumb,
11159
11178
  {
11160
11179
  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",
@@ -11168,7 +11187,7 @@ function PriceSection() {
11168
11187
  "aria-valuetext": formatPrice2(localRange[0])
11169
11188
  }
11170
11189
  ),
11171
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11190
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11172
11191
  Slider2.Thumb,
11173
11192
  {
11174
11193
  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",
@@ -11185,10 +11204,10 @@ function PriceSection() {
11185
11204
  ]
11186
11205
  }
11187
11206
  ) }),
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)(
11207
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "grid grid-cols-2 gap-3", children: [
11208
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { children: [
11209
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
11210
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11192
11211
  "input",
11193
11212
  {
11194
11213
  id: "price-min",
@@ -11206,9 +11225,9 @@ function PriceSection() {
11206
11225
  }
11207
11226
  )
11208
11227
  ] }),
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)(
11228
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { children: [
11229
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
11230
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11212
11231
  "input",
11213
11232
  {
11214
11233
  id: "price-max",
@@ -11232,11 +11251,11 @@ function PriceSection() {
11232
11251
  }
11233
11252
 
11234
11253
  // src/composed/search/Filters.tsx
11235
- var import_jsx_runtime68 = require("react/jsx-runtime");
11254
+ var import_jsx_runtime69 = require("react/jsx-runtime");
11236
11255
  function Filters({ buttonClassName, buttonText }) {
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)(
11256
+ const [isOpen, setIsOpen] = (0, import_react52.useState)(false);
11257
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
11258
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11240
11259
  FiltersButton,
11241
11260
  {
11242
11261
  onClick: () => setIsOpen(true),
@@ -11244,14 +11263,14 @@ function Filters({ buttonClassName, buttonText }) {
11244
11263
  children: buttonText
11245
11264
  }
11246
11265
  ),
11247
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
11266
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
11248
11267
  ] });
11249
11268
  }
11250
11269
 
11251
11270
  // src/composed/search/CurrentRefinements.tsx
11252
11271
  var import_react_instantsearch5 = require("react-instantsearch");
11253
11272
  var import_lucide_react6 = require("lucide-react");
11254
- var import_jsx_runtime69 = require("react/jsx-runtime");
11273
+ var import_jsx_runtime70 = require("react/jsx-runtime");
11255
11274
  var XIcon3 = import_lucide_react6.X;
11256
11275
  function CurrentRefinements() {
11257
11276
  const { items, refine } = (0, import_react_instantsearch5.useCurrentRefinements)();
@@ -11297,15 +11316,15 @@ function CurrentRefinements() {
11297
11316
  if (allRefinements.length === 0) {
11298
11317
  return null;
11299
11318
  }
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)(
11319
+ return /* @__PURE__ */ (0, import_jsx_runtime70.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_runtime70.jsxs)(
11301
11320
  "button",
11302
11321
  {
11303
11322
  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",
11304
11323
  onClick: () => refinement.refine(),
11305
11324
  "aria-label": `Remove filter: ${refinement.displayLabel}`,
11306
11325
  children: [
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" })
11326
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "truncate", children: refinement.displayLabel }),
11327
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(XIcon3, { className: "w-3 h-3" })
11309
11328
  ]
11310
11329
  },
11311
11330
  `${refinement.attribute}-${refinement.value}-${index}`
@@ -11329,12 +11348,12 @@ var FACET_SECTIONS = [
11329
11348
  ];
11330
11349
 
11331
11350
  // src/composed/zoom/ResponsiveZoom.tsx
11332
- var import_react54 = require("react");
11351
+ var import_react55 = require("react");
11333
11352
 
11334
11353
  // src/composed/zoom/ZoomOverlay.tsx
11335
- var import_react52 = require("react");
11354
+ var import_react53 = require("react");
11336
11355
  var import_lucide_react7 = require("lucide-react");
11337
- var import_jsx_runtime70 = require("react/jsx-runtime");
11356
+ var import_jsx_runtime71 = require("react/jsx-runtime");
11338
11357
  var PlusIcon2 = import_lucide_react7.Plus;
11339
11358
  var MinusIcon2 = import_lucide_react7.Minus;
11340
11359
  function ZoomOverlay({
@@ -11346,13 +11365,13 @@ function ZoomOverlay({
11346
11365
  className,
11347
11366
  style
11348
11367
  }) {
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)(
11368
+ const [zoomedImageIndex, setZoomedImageIndex] = (0, import_react53.useState)(null);
11369
+ const [zoomOrigin, setZoomOrigin] = (0, import_react53.useState)({ x: 50, y: 50 });
11370
+ const [hoveredImageIndex, setHoveredImageIndex] = (0, import_react53.useState)(null);
11371
+ const [cursorPos, setCursorPos] = (0, import_react53.useState)({ x: 0, y: 0 });
11372
+ const [announcement, setAnnouncement] = (0, import_react53.useState)("");
11373
+ const [isZooming, setIsZooming] = (0, import_react53.useState)(false);
11374
+ const handleZoomClick = (0, import_react53.useCallback)(
11356
11375
  (e) => {
11357
11376
  e.stopPropagation();
11358
11377
  if (isLargeTouchDevice && onEnhancedViewer) {
@@ -11377,7 +11396,7 @@ function ZoomOverlay({
11377
11396
  },
11378
11397
  [zoomedImageIndex, isLargeTouchDevice, onEnhancedViewer, imageIndex]
11379
11398
  );
11380
- const handleZoomMouseMove = (0, import_react52.useCallback)(
11399
+ const handleZoomMouseMove = (0, import_react53.useCallback)(
11381
11400
  (e) => {
11382
11401
  setCursorPos({ x: e.clientX, y: e.clientY });
11383
11402
  if (zoomedImageIndex === imageIndex) {
@@ -11393,9 +11412,9 @@ function ZoomOverlay({
11393
11412
  const isZoomed = zoomedImageIndex === imageIndex;
11394
11413
  const isHovered = hoveredImageIndex === imageIndex;
11395
11414
  const cursorStyle = isLargeTouchDevice ? "pointer" : isTouchDevice ? "default" : "none";
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)(
11415
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_jsx_runtime71.Fragment, { children: [
11416
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11417
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11399
11418
  "div",
11400
11419
  {
11401
11420
  className,
@@ -11403,7 +11422,7 @@ function ZoomOverlay({
11403
11422
  ...style,
11404
11423
  position: "relative"
11405
11424
  },
11406
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11425
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11407
11426
  "div",
11408
11427
  {
11409
11428
  style: {
@@ -11426,7 +11445,7 @@ function ZoomOverlay({
11426
11445
  handleZoomClick(e);
11427
11446
  }
11428
11447
  },
11429
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11448
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11430
11449
  "div",
11431
11450
  {
11432
11451
  style: {
@@ -11442,7 +11461,7 @@ function ZoomOverlay({
11442
11461
  )
11443
11462
  }
11444
11463
  ),
11445
- isHovered && !isTouchDevice && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11464
+ isHovered && !isTouchDevice && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11446
11465
  "div",
11447
11466
  {
11448
11467
  className: "fixed pointer-events-none z-50 hidden md:block",
@@ -11452,7 +11471,7 @@ function ZoomOverlay({
11452
11471
  transform: "translate(-50%, -50%)"
11453
11472
  },
11454
11473
  "aria-hidden": "true",
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)(
11474
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.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_runtime71.jsx)(
11456
11475
  MinusIcon2,
11457
11476
  {
11458
11477
  size: 20,
@@ -11460,7 +11479,7 @@ function ZoomOverlay({
11460
11479
  strokeWidth: 1.5,
11461
11480
  "aria-hidden": "true"
11462
11481
  }
11463
- ) : /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11482
+ ) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11464
11483
  PlusIcon2,
11465
11484
  {
11466
11485
  size: 20,
@@ -11475,11 +11494,11 @@ function ZoomOverlay({
11475
11494
  }
11476
11495
 
11477
11496
  // src/composed/zoom/EnhancedImageViewer.tsx
11478
- var import_react53 = require("react");
11497
+ var import_react54 = require("react");
11479
11498
  var import_react_dom3 = require("react-dom");
11480
11499
  var import_react_zoom_pan_pinch = require("react-zoom-pan-pinch");
11481
11500
  var import_lucide_react8 = require("lucide-react");
11482
- var import_jsx_runtime71 = require("react/jsx-runtime");
11501
+ var import_jsx_runtime72 = require("react/jsx-runtime");
11483
11502
  var TransformWrapper = import_react_zoom_pan_pinch.TransformWrapper;
11484
11503
  var TransformComponent = import_react_zoom_pan_pinch.TransformComponent;
11485
11504
  var EnhancedImageViewer = ({
@@ -11490,17 +11509,17 @@ var EnhancedImageViewer = ({
11490
11509
  onIndexChange,
11491
11510
  currentIndex: propCurrentIndex
11492
11511
  }) => {
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)(
11512
+ const [isMounted, setIsMounted] = (0, import_react54.useState)(false);
11513
+ const [isClient, setIsClient] = (0, import_react54.useState)(false);
11514
+ const [scale, setScale] = (0, import_react54.useState)({ initial: 1, min: 1, max: 8 });
11515
+ const [cropDimensions, setCropDimensions] = (0, import_react54.useState)({ width: 0, height: 0 });
11516
+ const [currentZoomScale, setCurrentZoomScale] = (0, import_react54.useState)(1);
11517
+ const imgRef = (0, import_react54.useRef)(null);
11518
+ const touchStartRef = (0, import_react54.useRef)(
11500
11519
  null
11501
11520
  );
11502
- const isSwipingRef = (0, import_react53.useRef)(false);
11503
- const calculateScale = (0, import_react53.useCallback)(() => {
11521
+ const isSwipingRef = (0, import_react54.useRef)(false);
11522
+ const calculateScale = (0, import_react54.useCallback)(() => {
11504
11523
  const viewport = {
11505
11524
  width: window.innerWidth,
11506
11525
  height: window.innerHeight
@@ -11512,10 +11531,10 @@ var EnhancedImageViewer = ({
11512
11531
  max: 8
11513
11532
  });
11514
11533
  }, []);
11515
- const handleImageLoad = (0, import_react53.useCallback)(() => {
11534
+ const handleImageLoad = (0, import_react54.useCallback)(() => {
11516
11535
  calculateScale();
11517
11536
  }, [calculateScale]);
11518
- (0, import_react53.useLayoutEffect)(() => {
11537
+ (0, import_react54.useLayoutEffect)(() => {
11519
11538
  setIsClient(true);
11520
11539
  setIsMounted(true);
11521
11540
  document.body.style.overflow = "hidden";
@@ -11524,17 +11543,17 @@ var EnhancedImageViewer = ({
11524
11543
  document.body.style.overflow = "";
11525
11544
  };
11526
11545
  }, [calculateScale]);
11527
- (0, import_react53.useEffect)(() => {
11546
+ (0, import_react54.useEffect)(() => {
11528
11547
  calculateScale();
11529
11548
  }, [calculateScale]);
11530
- (0, import_react53.useEffect)(() => {
11549
+ (0, import_react54.useEffect)(() => {
11531
11550
  const handleResize = () => {
11532
11551
  calculateScale();
11533
11552
  };
11534
11553
  window.addEventListener("resize", handleResize);
11535
11554
  return () => window.removeEventListener("resize", handleResize);
11536
11555
  }, [calculateScale]);
11537
- (0, import_react53.useEffect)(() => {
11556
+ (0, import_react54.useEffect)(() => {
11538
11557
  const handleKeyDown = (e) => {
11539
11558
  if (e.key === "Escape") {
11540
11559
  onClose();
@@ -11560,7 +11579,7 @@ var EnhancedImageViewer = ({
11560
11579
  document.addEventListener("keydown", handleKeyDown);
11561
11580
  return () => document.removeEventListener("keydown", handleKeyDown);
11562
11581
  }, [onClose, imageUrl, images, onIndexChange, propCurrentIndex]);
11563
- const handleSwipeNavigation = (0, import_react53.useCallback)(
11582
+ const handleSwipeNavigation = (0, import_react54.useCallback)(
11564
11583
  (direction) => {
11565
11584
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11566
11585
  if (currentIndex === -1) {
@@ -11581,7 +11600,7 @@ var EnhancedImageViewer = ({
11581
11600
  },
11582
11601
  [propCurrentIndex, images, imageUrl, onIndexChange]
11583
11602
  );
11584
- const handleTouchStart = (0, import_react53.useCallback)(
11603
+ const handleTouchStart = (0, import_react54.useCallback)(
11585
11604
  (e) => {
11586
11605
  const isAtInitialZoom = Math.abs(currentZoomScale - scale.initial) < 0.1;
11587
11606
  if (!isAtInitialZoom) return;
@@ -11595,7 +11614,7 @@ var EnhancedImageViewer = ({
11595
11614
  },
11596
11615
  [currentZoomScale, scale.initial]
11597
11616
  );
11598
- const handleTouchEnd = (0, import_react53.useCallback)(
11617
+ const handleTouchEnd = (0, import_react54.useCallback)(
11599
11618
  (e) => {
11600
11619
  if (!touchStartRef.current) return;
11601
11620
  const touch = e.changedTouches[0];
@@ -11619,12 +11638,12 @@ var EnhancedImageViewer = ({
11619
11638
  );
11620
11639
  if (!isMounted || !isClient) {
11621
11640
  return (0, import_react_dom3.createPortal)(
11622
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11641
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11623
11642
  "div",
11624
11643
  {
11625
11644
  className: "fixed inset-0 bg-black flex items-center justify-center",
11626
11645
  style: { zIndex: 999999 },
11627
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11646
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11628
11647
  "div",
11629
11648
  {
11630
11649
  style: {
@@ -11640,7 +11659,7 @@ var EnhancedImageViewer = ({
11640
11659
  );
11641
11660
  }
11642
11661
  return (0, import_react_dom3.createPortal)(
11643
- /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
11662
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
11644
11663
  "div",
11645
11664
  {
11646
11665
  className: "fixed inset-0 bg-black flex items-center justify-center",
@@ -11649,7 +11668,7 @@ var EnhancedImageViewer = ({
11649
11668
  "aria-modal": "true",
11650
11669
  "aria-label": "Image viewer",
11651
11670
  children: [
11652
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11671
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11653
11672
  "button",
11654
11673
  {
11655
11674
  onClick: (e) => {
@@ -11675,10 +11694,10 @@ var EnhancedImageViewer = ({
11675
11694
  touchAction: "manipulation",
11676
11695
  marginBottom: "env(safe-area-inset-bottom, 0px)"
11677
11696
  },
11678
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react8.X, { className: "w-7 h-7", strokeWidth: 2.5 })
11697
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react8.X, { className: "w-7 h-7", strokeWidth: 2.5 })
11679
11698
  }
11680
11699
  ),
11681
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11700
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11682
11701
  TransformWrapper,
11683
11702
  {
11684
11703
  initialScale: scale.initial,
@@ -11712,7 +11731,7 @@ var EnhancedImageViewer = ({
11712
11731
  onTransformed: (ref) => {
11713
11732
  setCurrentZoomScale(ref.state.scale);
11714
11733
  },
11715
- children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
11734
+ children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
11716
11735
  "div",
11717
11736
  {
11718
11737
  style: {
@@ -11725,14 +11744,14 @@ var EnhancedImageViewer = ({
11725
11744
  onTouchStart: handleTouchStart,
11726
11745
  onTouchEnd: handleTouchEnd,
11727
11746
  children: [
11728
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11747
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11729
11748
  TransformComponent,
11730
11749
  {
11731
11750
  wrapperStyle: {
11732
11751
  width: "100%",
11733
11752
  height: "100%"
11734
11753
  },
11735
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11754
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11736
11755
  "div",
11737
11756
  {
11738
11757
  style: {
@@ -11743,7 +11762,7 @@ var EnhancedImageViewer = ({
11743
11762
  alignItems: "center",
11744
11763
  justifyContent: "center"
11745
11764
  },
11746
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11765
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11747
11766
  SafeImg,
11748
11767
  {
11749
11768
  ref: imgRef,
@@ -11764,8 +11783,8 @@ var EnhancedImageViewer = ({
11764
11783
  )
11765
11784
  }
11766
11785
  ),
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: (() => {
11786
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fixed bottom-5 left-0 right-0 z-50", children: [
11787
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "flex justify-center gap-2", children: (() => {
11769
11788
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11770
11789
  if (currentIndex === -1) {
11771
11790
  currentIndex = images.findIndex(
@@ -11798,8 +11817,8 @@ var EnhancedImageViewer = ({
11798
11817
  };
11799
11818
  const nextIndex = findNextAvailableIndex(currentIndex, 1);
11800
11819
  const prevIndex = findNextAvailableIndex(currentIndex, -1);
11801
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_jsx_runtime71.Fragment, { children: [
11802
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11820
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
11821
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11803
11822
  "button",
11804
11823
  {
11805
11824
  onClick: () => {
@@ -11812,7 +11831,7 @@ var EnhancedImageViewer = ({
11812
11831
  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"}`,
11813
11832
  style: { touchAction: "manipulation" },
11814
11833
  "aria-label": "Previous image",
11815
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11834
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11816
11835
  "svg",
11817
11836
  {
11818
11837
  className: "w-4 h-4",
@@ -11820,7 +11839,7 @@ var EnhancedImageViewer = ({
11820
11839
  stroke: "currentColor",
11821
11840
  viewBox: "0 0 24 24",
11822
11841
  "aria-hidden": "true",
11823
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11842
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11824
11843
  "path",
11825
11844
  {
11826
11845
  strokeLinecap: "round",
@@ -11833,7 +11852,7 @@ var EnhancedImageViewer = ({
11833
11852
  )
11834
11853
  }
11835
11854
  ),
11836
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11855
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11837
11856
  "button",
11838
11857
  {
11839
11858
  onClick: () => {
@@ -11846,7 +11865,7 @@ var EnhancedImageViewer = ({
11846
11865
  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"}`,
11847
11866
  style: { touchAction: "manipulation" },
11848
11867
  "aria-label": "Next image",
11849
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11868
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11850
11869
  "svg",
11851
11870
  {
11852
11871
  className: "w-4 h-4",
@@ -11854,7 +11873,7 @@ var EnhancedImageViewer = ({
11854
11873
  stroke: "currentColor",
11855
11874
  viewBox: "0 0 24 24",
11856
11875
  "aria-hidden": "true",
11857
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11876
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11858
11877
  "path",
11859
11878
  {
11860
11879
  strokeLinecap: "round",
@@ -11869,7 +11888,7 @@ var EnhancedImageViewer = ({
11869
11888
  )
11870
11889
  ] });
11871
11890
  })() }),
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: (() => {
11891
+ /* @__PURE__ */ (0, import_jsx_runtime72.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: (() => {
11873
11892
  const total = Math.max(images.length, 1);
11874
11893
  const current = propCurrentIndex !== void 0 ? Math.min(propCurrentIndex + 1, total) : 1;
11875
11894
  return `${current} / ${total}`;
@@ -11881,7 +11900,7 @@ var EnhancedImageViewer = ({
11881
11900
  },
11882
11901
  `${scale.initial}-${scale.min}-${scale.max}`
11883
11902
  ),
11884
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11903
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11885
11904
  "div",
11886
11905
  {
11887
11906
  className: "absolute inset-0 bg-black",
@@ -11900,7 +11919,7 @@ var EnhancedImageViewer = ({
11900
11919
  };
11901
11920
 
11902
11921
  // src/composed/zoom/ResponsiveZoom.tsx
11903
- var import_jsx_runtime72 = require("react/jsx-runtime");
11922
+ var import_jsx_runtime73 = require("react/jsx-runtime");
11904
11923
  function ResponsiveZoom({
11905
11924
  imageIndex,
11906
11925
  children,
@@ -11910,11 +11929,11 @@ function ResponsiveZoom({
11910
11929
  imageUrl,
11911
11930
  alt = "Product image"
11912
11931
  }) {
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)(() => {
11932
+ const [isTouchDevice, setIsTouchDevice] = (0, import_react55.useState)(false);
11933
+ const [showEnhancedViewer, setShowEnhancedViewer] = (0, import_react55.useState)(false);
11934
+ const [viewerIndex, setViewerIndex] = (0, import_react55.useState)(0);
11935
+ const [currentImageUrl, setCurrentImageUrl] = (0, import_react55.useState)(imageUrl || "");
11936
+ (0, import_react55.useEffect)(() => {
11918
11937
  const checkDeviceType = () => {
11919
11938
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
11920
11939
  setIsTouchDevice(hasTouch);
@@ -11941,8 +11960,8 @@ function ResponsiveZoom({
11941
11960
  }
11942
11961
  }
11943
11962
  };
11944
- return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
11945
- isTouchDevice ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11963
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
11964
+ isTouchDevice ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
11946
11965
  "div",
11947
11966
  {
11948
11967
  className,
@@ -11959,7 +11978,7 @@ function ResponsiveZoom({
11959
11978
  },
11960
11979
  children
11961
11980
  }
11962
- ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11981
+ ) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
11963
11982
  ZoomOverlay,
11964
11983
  {
11965
11984
  imageIndex,
@@ -11970,7 +11989,7 @@ function ResponsiveZoom({
11970
11989
  children
11971
11990
  }
11972
11991
  ),
11973
- showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11992
+ showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
11974
11993
  EnhancedImageViewer,
11975
11994
  {
11976
11995
  imageUrl: currentImageUrl,
@@ -11993,18 +12012,18 @@ function ResponsiveZoom({
11993
12012
  }
11994
12013
 
11995
12014
  // src/composed/carousels/MobileProductCarousel.tsx
11996
- var import_react55 = require("react");
11997
- var import_jsx_runtime73 = require("react/jsx-runtime");
12015
+ var import_react56 = require("react");
12016
+ var import_jsx_runtime74 = require("react/jsx-runtime");
11998
12017
  function StaticCarouselImage({
11999
12018
  src,
12000
12019
  alt,
12001
12020
  className
12002
12021
  }) {
12003
- const [failed, setFailed] = (0, import_react55.useState)(false);
12022
+ const [failed, setFailed] = (0, import_react56.useState)(false);
12004
12023
  if (failed || !src) {
12005
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: `bg-muted ${className ?? ""}`, role: "img", "aria-label": alt });
12024
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: `bg-muted ${className ?? ""}`, role: "img", "aria-label": alt });
12006
12025
  }
12007
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12026
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12008
12027
  "img",
12009
12028
  {
12010
12029
  src,
@@ -12018,7 +12037,7 @@ function StaticCarouselImage({
12018
12037
  }
12019
12038
  );
12020
12039
  }
12021
- var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarousel2({
12040
+ var MobileProductCarousel = (0, import_react56.memo)(function MobileProductCarousel2({
12022
12041
  images,
12023
12042
  currentIndex = 0,
12024
12043
  onIndexChange,
@@ -12033,42 +12052,42 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12033
12052
  mockupWidth,
12034
12053
  onMockupUrlGenerated
12035
12054
  }) {
12036
- const [activeIndex, setActiveIndex] = (0, import_react55.useState)(currentIndex);
12037
- const [touchStart, setTouchStart] = (0, import_react55.useState)(
12055
+ const [activeIndex, setActiveIndex] = (0, import_react56.useState)(currentIndex);
12056
+ const [touchStart, setTouchStart] = (0, import_react56.useState)(
12038
12057
  null
12039
12058
  );
12040
- const [touchEnd, setTouchEnd] = (0, import_react55.useState)(
12059
+ const [touchEnd, setTouchEnd] = (0, import_react56.useState)(
12041
12060
  null
12042
12061
  );
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)(
12062
+ const [showImageViewer, setShowImageViewer] = (0, import_react56.useState)(false);
12063
+ const [viewerKey, setViewerKey] = (0, import_react56.useState)(0);
12064
+ const [isDragging, setIsDragging] = (0, import_react56.useState)(false);
12065
+ const [dragOffset, setDragOffset] = (0, import_react56.useState)(0);
12066
+ const [isTransitioning, setIsTransitioning] = (0, import_react56.useState)(false);
12067
+ const [isHorizontalSwipe, setIsHorizontalSwipe] = (0, import_react56.useState)(
12049
12068
  null
12050
12069
  );
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)(
12070
+ const [isPeeking, setIsPeeking] = (0, import_react56.useState)(false);
12071
+ const [isPeekReturning, setIsPeekReturning] = (0, import_react56.useState)(false);
12072
+ const carouselRef = (0, import_react56.useRef)(null);
12073
+ const indicatorRef = (0, import_react56.useRef)(null);
12074
+ const touchStartRef = (0, import_react56.useRef)(
12056
12075
  null
12057
12076
  );
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)(() => {
12077
+ const horizontalGestureRef = (0, import_react56.useRef)(false);
12078
+ const hasShownPeekRef = (0, import_react56.useRef)(false);
12079
+ const hasSwipedThisSessionRef = (0, import_react56.useRef)(false);
12080
+ const generatedUrlsRef = (0, import_react56.useRef)(/* @__PURE__ */ new Map());
12081
+ const prevArtworkSrcRef = (0, import_react56.useRef)(currentArtwork?.src);
12082
+ (0, import_react56.useEffect)(() => {
12064
12083
  if (currentArtwork?.src !== prevArtworkSrcRef.current) {
12065
12084
  generatedUrlsRef.current.clear();
12066
12085
  prevArtworkSrcRef.current = currentArtwork?.src;
12067
12086
  }
12068
12087
  }, [currentArtwork?.src]);
12069
- const onMockupUrlGeneratedRef = (0, import_react55.useRef)(onMockupUrlGenerated);
12088
+ const onMockupUrlGeneratedRef = (0, import_react56.useRef)(onMockupUrlGenerated);
12070
12089
  onMockupUrlGeneratedRef.current = onMockupUrlGenerated;
12071
- const handleUrlGenerated = (0, import_react55.useCallback)((mockupId, url) => {
12090
+ const handleUrlGenerated = (0, import_react56.useCallback)((mockupId, url) => {
12072
12091
  generatedUrlsRef.current.set(mockupId, url);
12073
12092
  onMockupUrlGeneratedRef.current?.(mockupId, url);
12074
12093
  }, []);
@@ -12076,24 +12095,24 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12076
12095
  const shouldHideDots = stickyHeroContext?.shouldHideDots ?? false;
12077
12096
  const priorityContext = useMockupPriorityOptional();
12078
12097
  const realtimeContext = useRealtimeOptional();
12079
- const [urlUpdateCounter, setUrlUpdateCounter] = (0, import_react55.useState)(0);
12080
- (0, import_react55.useEffect)(() => {
12098
+ const [urlUpdateCounter, setUrlUpdateCounter] = (0, import_react56.useState)(0);
12099
+ (0, import_react56.useEffect)(() => {
12081
12100
  if (!realtimeContext?.subscribeMockupResults) return;
12082
12101
  const unsubscribe = realtimeContext.subscribeMockupResults(() => {
12083
12102
  setUrlUpdateCounter((c) => c + 1);
12084
12103
  });
12085
12104
  return unsubscribe;
12086
12105
  }, [realtimeContext?.subscribeMockupResults]);
12087
- const mockupIds = (0, import_react55.useMemo)(() => {
12106
+ const mockupIds = (0, import_react56.useMemo)(() => {
12088
12107
  return images.filter((img) => img.isRealMockup && img.mockupId).map((img) => img.mockupId);
12089
12108
  }, [images]);
12090
- const realtimeMockupUrls = (0, import_react55.useMemo)(() => {
12109
+ const realtimeMockupUrls = (0, import_react56.useMemo)(() => {
12091
12110
  if (!realtimeContext?.getMockupUrls || mockupIds.length === 0) {
12092
12111
  return {};
12093
12112
  }
12094
12113
  return realtimeContext.getMockupUrls(mockupIds);
12095
12114
  }, [realtimeContext?.getMockupUrls, mockupIds, urlUpdateCounter]);
12096
- const imagesWithRealtimeUrls = (0, import_react55.useMemo)(() => {
12115
+ const imagesWithRealtimeUrls = (0, import_react56.useMemo)(() => {
12097
12116
  return images.map((img) => {
12098
12117
  if (img.isRealMockup && img.mockupId && realtimeMockupUrls[img.mockupId]) {
12099
12118
  return {
@@ -12105,10 +12124,10 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12105
12124
  });
12106
12125
  }, [images, realtimeMockupUrls]);
12107
12126
  const minSwipeDistance = 50;
12108
- (0, import_react55.useEffect)(() => {
12127
+ (0, import_react56.useEffect)(() => {
12109
12128
  setActiveIndex(currentIndex);
12110
12129
  }, [currentIndex]);
12111
- (0, import_react55.useEffect)(() => {
12130
+ (0, import_react56.useEffect)(() => {
12112
12131
  if (!priorityContext) return;
12113
12132
  const realMockups = images.map((img, idx) => ({ img, originalIdx: idx })).filter(({ img }) => img.isRealMockup && img.mockupId);
12114
12133
  const mockupIdsList = realMockups.map(({ img }) => img.mockupId);
@@ -12136,7 +12155,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12136
12155
  priorityContext.clearMobileCarouselMode?.();
12137
12156
  };
12138
12157
  }, [priorityContext, activeIndex, images]);
12139
- (0, import_react55.useEffect)(() => {
12158
+ (0, import_react56.useEffect)(() => {
12140
12159
  const indicator = indicatorRef.current;
12141
12160
  if (!indicator) return;
12142
12161
  let ticking = false;
@@ -12177,7 +12196,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12177
12196
  }, []);
12178
12197
  const SWIPE_TRACKING_KEY = "carousel-swipe-tracking";
12179
12198
  const PDP_VIEWS_BEFORE_PEEK = 10;
12180
- const getSwipeTracking = (0, import_react55.useCallback)(() => {
12199
+ const getSwipeTracking = (0, import_react56.useCallback)(() => {
12181
12200
  try {
12182
12201
  const stored = localStorage.getItem(SWIPE_TRACKING_KEY);
12183
12202
  if (stored) {
@@ -12187,7 +12206,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12187
12206
  }
12188
12207
  return { viewsWithoutSwipe: 0, hasEverSwiped: false };
12189
12208
  }, []);
12190
- const recordSwipe = (0, import_react55.useCallback)(() => {
12209
+ const recordSwipe = (0, import_react56.useCallback)(() => {
12191
12210
  if (hasSwipedThisSessionRef.current) return;
12192
12211
  hasSwipedThisSessionRef.current = true;
12193
12212
  try {
@@ -12201,7 +12220,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12201
12220
  } catch {
12202
12221
  }
12203
12222
  }, []);
12204
- (0, import_react55.useEffect)(() => {
12223
+ (0, import_react56.useEffect)(() => {
12205
12224
  if (!enablePeekAnimation || images.length <= 1) return;
12206
12225
  const tracking = getSwipeTracking();
12207
12226
  const newViewCount = tracking.viewsWithoutSwipe + 1;
@@ -12242,14 +12261,14 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12242
12261
  clearTimeout(clearTimeout_);
12243
12262
  };
12244
12263
  }, [images.length, getSwipeTracking, enablePeekAnimation]);
12245
- const wasTapRef = (0, import_react55.useRef)(false);
12246
- const handleImageTap = (0, import_react55.useCallback)(() => {
12264
+ const wasTapRef = (0, import_react56.useRef)(false);
12265
+ const handleImageTap = (0, import_react56.useCallback)(() => {
12247
12266
  if (!enableZoom) return;
12248
12267
  setViewerKey((prev) => prev + 1);
12249
12268
  setShowImageViewer(true);
12250
12269
  onZoomChange?.(true);
12251
12270
  }, [enableZoom, onZoomChange]);
12252
- const calculateDragOffset = (0, import_react55.useCallback)(
12271
+ const calculateDragOffset = (0, import_react56.useCallback)(
12253
12272
  (startX, currentX, containerWidth) => {
12254
12273
  const distance = startX - currentX;
12255
12274
  const offsetPercent = distance / containerWidth * 100;
@@ -12274,7 +12293,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12274
12293
  },
12275
12294
  [activeIndex, images.length]
12276
12295
  );
12277
- const handleSwipeEnd = (0, import_react55.useCallback)(
12296
+ const handleSwipeEnd = (0, import_react56.useCallback)(
12278
12297
  (startX, endX, containerWidth) => {
12279
12298
  const distance = startX - endX;
12280
12299
  const distancePercent = Math.abs(distance) / containerWidth * 100;
@@ -12305,7 +12324,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12305
12324
  },
12306
12325
  [activeIndex, images.length, onIndexChange, recordSwipe]
12307
12326
  );
12308
- (0, import_react55.useEffect)(() => {
12327
+ (0, import_react56.useEffect)(() => {
12309
12328
  const container = carouselRef.current;
12310
12329
  if (!container) return;
12311
12330
  const handleTouchStart = (e) => {
@@ -12394,11 +12413,11 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12394
12413
  handleSwipeEnd,
12395
12414
  handleImageTap
12396
12415
  ]);
12397
- const mouseStartRef = (0, import_react55.useRef)(
12416
+ const mouseStartRef = (0, import_react56.useRef)(
12398
12417
  null
12399
12418
  );
12400
- const isMouseDraggingRef = (0, import_react55.useRef)(false);
12401
- (0, import_react55.useEffect)(() => {
12419
+ const isMouseDraggingRef = (0, import_react56.useRef)(false);
12420
+ (0, import_react56.useEffect)(() => {
12402
12421
  const container = carouselRef.current;
12403
12422
  if (!container) return;
12404
12423
  const handleMouseDown = (e) => {
@@ -12474,7 +12493,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12474
12493
  container.removeEventListener("mouseleave", handleMouseLeave);
12475
12494
  };
12476
12495
  }, [calculateDragOffset, handleSwipeEnd, handleImageTap]);
12477
- const goToSlide = (0, import_react55.useCallback)(
12496
+ const goToSlide = (0, import_react56.useCallback)(
12478
12497
  (index, withTransition = true) => {
12479
12498
  if (withTransition) {
12480
12499
  setIsTransitioning(true);
@@ -12492,16 +12511,16 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12492
12511
  },
12493
12512
  [onIndexChange]
12494
12513
  );
12495
- (0, import_react55.useEffect)(() => {
12514
+ (0, import_react56.useEffect)(() => {
12496
12515
  if (stickyHeroContext?.setCarouselIndicator && images.length > 1) {
12497
- const indicator = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12516
+ const indicator = /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12498
12517
  "div",
12499
12518
  {
12500
12519
  className: "w-full",
12501
12520
  role: "group",
12502
12521
  "aria-label": "Product image navigation",
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)(
12522
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "relative h-1", children: [
12523
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "flex h-full", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12505
12524
  "button",
12506
12525
  {
12507
12526
  onClick: () => goToSlide(index),
@@ -12511,7 +12530,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12511
12530
  },
12512
12531
  index
12513
12532
  )) }),
12514
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12533
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12515
12534
  "div",
12516
12535
  {
12517
12536
  className: "absolute top-0 h-full bg-primary transition-all duration-300 ease-out",
@@ -12534,10 +12553,10 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12534
12553
  };
12535
12554
  }, [activeIndex, images.length, goToSlide, stickyHeroContext]);
12536
12555
  if (!images || images.length === 0) {
12537
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12556
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12538
12557
  }
12539
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: `relative w-full h-full ${className}`, children: [
12540
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12558
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: `relative w-full h-full ${className}`, children: [
12559
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12541
12560
  "div",
12542
12561
  {
12543
12562
  ref: carouselRef,
@@ -12555,7 +12574,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12555
12574
  role: "region",
12556
12575
  "aria-roledescription": "carousel",
12557
12576
  "aria-label": "Product images",
12558
- children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12577
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12559
12578
  "div",
12560
12579
  {
12561
12580
  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)]" : ""}`,
@@ -12565,15 +12584,15 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12565
12584
  children: images.map((image, index) => {
12566
12585
  const DECODE_WINDOW = 1;
12567
12586
  const isWithinDecodeWindow = Math.abs(index - activeIndex) <= DECODE_WINDOW;
12568
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12587
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12569
12588
  "div",
12570
12589
  {
12571
12590
  className: "w-full h-full flex-shrink-0 relative select-none",
12572
- children: !isWithinDecodeWindow ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? (
12591
+ children: !isWithinDecodeWindow ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? (
12573
12592
  // Rainbow prism loader (same as the /create route) instead of
12574
12593
  // 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)(
12594
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" })
12595
+ ) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12577
12596
  HeroProductImage,
12578
12597
  {
12579
12598
  productId,
@@ -12585,7 +12604,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12585
12604
  onUrlGenerated: image.mockupId ? (url) => handleUrlGenerated(image.mockupId, url) : void 0,
12586
12605
  className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12587
12606
  }
12588
- ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12607
+ ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" }) : /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12589
12608
  StaticCarouselImage,
12590
12609
  {
12591
12610
  src: image.src,
@@ -12601,7 +12620,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12601
12620
  )
12602
12621
  }
12603
12622
  ),
12604
- showIndicators && images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12623
+ showIndicators && images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12605
12624
  "div",
12606
12625
  {
12607
12626
  ref: indicatorRef,
@@ -12609,8 +12628,8 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12609
12628
  className: "relative z-20 w-full",
12610
12629
  role: "group",
12611
12630
  "aria-label": "Product image navigation",
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)(
12631
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "relative h-1", children: [
12632
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "flex h-full absolute inset-0", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12614
12633
  "button",
12615
12634
  {
12616
12635
  onClick: () => goToSlide(index),
@@ -12620,7 +12639,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12620
12639
  },
12621
12640
  index
12622
12641
  )) }),
12623
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12642
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12624
12643
  "div",
12625
12644
  {
12626
12645
  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"}`,
@@ -12655,7 +12674,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12655
12674
  naturalHeight: img.naturalHeight
12656
12675
  } : null;
12657
12676
  }).filter((img) => img !== null);
12658
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12677
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12659
12678
  EnhancedImageViewer,
12660
12679
  {
12661
12680
  imageUrl,
@@ -12694,8 +12713,8 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12694
12713
  });
12695
12714
 
12696
12715
  // src/composed/carousels/HeroCarousel.tsx
12697
- var import_react56 = require("react");
12698
- var import_jsx_runtime74 = require("react/jsx-runtime");
12716
+ var import_react57 = require("react");
12717
+ var import_jsx_runtime75 = require("react/jsx-runtime");
12699
12718
  function HeroCarousel({
12700
12719
  images,
12701
12720
  currentIndex = 0,
@@ -12705,16 +12724,16 @@ function HeroCarousel({
12705
12724
  productId,
12706
12725
  onImageTap
12707
12726
  }) {
12708
- const [activeIndex, setActiveIndex] = (0, import_react56.useState)(currentIndex);
12709
- const containerRef = (0, import_react56.useRef)(null);
12710
- const touchStartRef = (0, import_react56.useRef)(
12727
+ const [activeIndex, setActiveIndex] = (0, import_react57.useState)(currentIndex);
12728
+ const containerRef = (0, import_react57.useRef)(null);
12729
+ const touchStartRef = (0, import_react57.useRef)(
12711
12730
  null
12712
12731
  );
12713
- const isSwipingRef = (0, import_react56.useRef)(false);
12714
- (0, import_react56.useEffect)(() => {
12732
+ const isSwipingRef = (0, import_react57.useRef)(false);
12733
+ (0, import_react57.useEffect)(() => {
12715
12734
  setActiveIndex(currentIndex);
12716
12735
  }, [currentIndex]);
12717
- const goToSlide = (0, import_react56.useCallback)(
12736
+ const goToSlide = (0, import_react57.useCallback)(
12718
12737
  (index) => {
12719
12738
  const clampedIndex = Math.max(0, Math.min(images.length - 1, index));
12720
12739
  setActiveIndex(clampedIndex);
@@ -12722,7 +12741,7 @@ function HeroCarousel({
12722
12741
  },
12723
12742
  [images.length, onIndexChange]
12724
12743
  );
12725
- (0, import_react56.useEffect)(() => {
12744
+ (0, import_react57.useEffect)(() => {
12726
12745
  const container = containerRef.current;
12727
12746
  if (!container) return;
12728
12747
  const handleTouchStart = (e) => {
@@ -12774,9 +12793,9 @@ function HeroCarousel({
12774
12793
  };
12775
12794
  }, [activeIndex, images.length, goToSlide, onImageTap]);
12776
12795
  if (!images || images.length === 0) {
12777
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "w-full h-full bg-muted" });
12796
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "w-full h-full bg-muted" });
12778
12797
  }
12779
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
12798
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(
12780
12799
  "div",
12781
12800
  {
12782
12801
  ref: containerRef,
@@ -12787,7 +12806,7 @@ function HeroCarousel({
12787
12806
  overflow: "hidden"
12788
12807
  },
12789
12808
  children: [
12790
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12809
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12791
12810
  "div",
12792
12811
  {
12793
12812
  className: "flex h-full transition-transform duration-300 ease-out",
@@ -12798,14 +12817,14 @@ function HeroCarousel({
12798
12817
  backfaceVisibility: "hidden",
12799
12818
  WebkitBackfaceVisibility: "hidden"
12800
12819
  },
12801
- children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12820
+ children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12802
12821
  "div",
12803
12822
  {
12804
12823
  className: "w-full h-full flex-shrink-0",
12805
12824
  style: {
12806
12825
  contain: "layout paint"
12807
12826
  },
12808
- children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12827
+ children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12809
12828
  HeroProductImage,
12810
12829
  {
12811
12830
  productId,
@@ -12814,7 +12833,7 @@ function HeroCarousel({
12814
12833
  mockupId: image.mockupId,
12815
12834
  className: "w-full h-full object-cover"
12816
12835
  }
12817
- ) : /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12836
+ ) : /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12818
12837
  "img",
12819
12838
  {
12820
12839
  src: image.src,
@@ -12831,12 +12850,12 @@ function HeroCarousel({
12831
12850
  ))
12832
12851
  }
12833
12852
  ),
12834
- images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12853
+ images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12835
12854
  "div",
12836
12855
  {
12837
12856
  className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 z-10",
12838
12857
  style: { contain: "layout style" },
12839
- children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12858
+ children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12840
12859
  "button",
12841
12860
  {
12842
12861
  onClick: () => goToSlide(index),
@@ -12853,8 +12872,8 @@ function HeroCarousel({
12853
12872
  }
12854
12873
 
12855
12874
  // src/composed/grids/MasonryGrid.tsx
12856
- var import_react57 = require("react");
12857
- var import_jsx_runtime75 = require("react/jsx-runtime");
12875
+ var import_react58 = require("react");
12876
+ var import_jsx_runtime76 = require("react/jsx-runtime");
12858
12877
  var BREAKPOINTS = {
12859
12878
  sm: 640,
12860
12879
  md: 768,
@@ -12906,13 +12925,13 @@ function MasonryGrid({
12906
12925
  className = "",
12907
12926
  emptyContent
12908
12927
  }) {
12909
- const [columnCount, setColumnCount] = (0, import_react57.useState)(
12928
+ const [columnCount, setColumnCount] = (0, import_react58.useState)(
12910
12929
  () => typeof columns === "number" ? columns : getColumnCount(
12911
12930
  typeof window !== "undefined" ? window.innerWidth : 1024,
12912
12931
  columns
12913
12932
  )
12914
12933
  );
12915
- (0, import_react57.useEffect)(() => {
12934
+ (0, import_react58.useEffect)(() => {
12916
12935
  const updateColumnCount = () => {
12917
12936
  setColumnCount(getColumnCount(window.innerWidth, columns));
12918
12937
  };
@@ -12920,30 +12939,30 @@ function MasonryGrid({
12920
12939
  window.addEventListener("resize", updateColumnCount);
12921
12940
  return () => window.removeEventListener("resize", updateColumnCount);
12922
12941
  }, [columns]);
12923
- const distributedColumns = (0, import_react57.useMemo)(
12942
+ const distributedColumns = (0, import_react58.useMemo)(
12924
12943
  () => distributeItems(items, columnCount),
12925
12944
  [items, columnCount]
12926
12945
  );
12927
12946
  if (items.length === 0) {
12928
12947
  if (emptyContent) {
12929
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(import_jsx_runtime75.Fragment, { children: emptyContent });
12948
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(import_jsx_runtime76.Fragment, { children: emptyContent });
12930
12949
  }
12931
12950
  return null;
12932
12951
  }
12933
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12952
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
12934
12953
  "div",
12935
12954
  {
12936
12955
  className: `flex ${className}`,
12937
12956
  style: { gap: `${gap}px` },
12938
12957
  role: "list",
12939
- children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12958
+ children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
12940
12959
  "div",
12941
12960
  {
12942
12961
  className: "flex-1 flex flex-col",
12943
12962
  style: { gap: `${gap}px` },
12944
12963
  children: columnItems.map((item, itemIndex) => {
12945
12964
  const originalIndex = itemIndex * columnCount + columnIndex;
12946
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12965
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12947
12966
  })
12948
12967
  },
12949
12968
  columnIndex
@@ -12956,7 +12975,7 @@ function MasonryGrid({
12956
12975
  init_dev_warnings();
12957
12976
 
12958
12977
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12959
- var import_react59 = require("react");
12978
+ var import_react60 = require("react");
12960
12979
 
12961
12980
  // src/layouts/hero-zoom/types.ts
12962
12981
  var DEFAULT_HERO_ZOOM_CONFIG = {
@@ -12968,19 +12987,19 @@ var DEFAULT_HERO_ZOOM_CONFIG = {
12968
12987
  };
12969
12988
 
12970
12989
  // src/layouts/hero-zoom/useHeroZoomScales.ts
12971
- var import_react58 = require("react");
12990
+ var import_react59 = require("react");
12972
12991
  function useHeroZoomScales(config = {}) {
12973
12992
  const { initialScale, accountForRetina, maxRetinaMultiplier } = {
12974
12993
  ...DEFAULT_HERO_ZOOM_CONFIG,
12975
12994
  ...config
12976
12995
  };
12977
- const [isHydrated, setIsHydrated] = (0, import_react58.useState)(false);
12996
+ const [isHydrated, setIsHydrated] = (0, import_react59.useState)(false);
12978
12997
  const ssrMultiplier = accountForRetina ? maxRetinaMultiplier : 2;
12979
- const [scales, setScales] = (0, import_react58.useState)(() => ({
12998
+ const [scales, setScales] = (0, import_react59.useState)(() => ({
12980
12999
  visual: initialScale,
12981
13000
  render: initialScale * ssrMultiplier
12982
13001
  }));
12983
- const calculateScales = (0, import_react58.useCallback)(() => {
13002
+ const calculateScales = (0, import_react59.useCallback)(() => {
12984
13003
  const visualScale = Math.max(1, Math.min(4, initialScale));
12985
13004
  let renderScale;
12986
13005
  if (accountForRetina) {
@@ -12995,7 +13014,7 @@ function useHeroZoomScales(config = {}) {
12995
13014
  renderScale = Math.max(1, Math.min(8, renderScale));
12996
13015
  return { visual: visualScale, render: renderScale };
12997
13016
  }, [initialScale, accountForRetina, maxRetinaMultiplier]);
12998
- (0, import_react58.useEffect)(() => {
13017
+ (0, import_react59.useEffect)(() => {
12999
13018
  const supportsScrollTimeline = CSS.supports(
13000
13019
  "animation-timeline",
13001
13020
  "scroll()"
@@ -13045,7 +13064,7 @@ function useHeroZoomScales(config = {}) {
13045
13064
  }
13046
13065
 
13047
13066
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
13048
- var import_jsx_runtime76 = require("react/jsx-runtime");
13067
+ var import_jsx_runtime77 = require("react/jsx-runtime");
13049
13068
  function HeroZoomLayout({
13050
13069
  config = {},
13051
13070
  header,
@@ -13060,9 +13079,9 @@ function HeroZoomLayout({
13060
13079
  };
13061
13080
  const { aspectRatio, initialScale, headerHeight } = mergedConfig;
13062
13081
  const { visual, render, isHydrated } = useHeroZoomScales(mergedConfig);
13063
- const imageContainerRef = (0, import_react59.useRef)(null);
13064
- const headerRef = (0, import_react59.useRef)(null);
13065
- (0, import_react59.useEffect)(() => {
13082
+ const imageContainerRef = (0, import_react60.useRef)(null);
13083
+ const headerRef = (0, import_react60.useRef)(null);
13084
+ (0, import_react60.useEffect)(() => {
13066
13085
  if (typeof window === "undefined") return;
13067
13086
  const originalRestoration = "scrollRestoration" in history ? history.scrollRestoration : "auto";
13068
13087
  if ("scrollRestoration" in history) {
@@ -13075,7 +13094,7 @@ function HeroZoomLayout({
13075
13094
  }
13076
13095
  };
13077
13096
  }, []);
13078
- (0, import_react59.useEffect)(() => {
13097
+ (0, import_react60.useEffect)(() => {
13079
13098
  const supportsScrollTimeline = CSS.supports(
13080
13099
  "animation-timeline",
13081
13100
  "scroll()"
@@ -13204,7 +13223,7 @@ function HeroZoomLayout({
13204
13223
  The drawer covers the hero completely, so let animation run continuously. */
13205
13224
  }
13206
13225
  `;
13207
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
13226
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
13208
13227
  "div",
13209
13228
  {
13210
13229
  className: `relative min-h-screen ${className}`,
@@ -13218,8 +13237,8 @@ function HeroZoomLayout({
13218
13237
  "--hero-zoom-final-transform": 1 / activeRender
13219
13238
  },
13220
13239
  children: [
13221
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13222
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13240
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13241
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13223
13242
  "div",
13224
13243
  {
13225
13244
  style: {
@@ -13227,7 +13246,7 @@ function HeroZoomLayout({
13227
13246
  }
13228
13247
  }
13229
13248
  ),
13230
- header && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13249
+ header && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13231
13250
  "div",
13232
13251
  {
13233
13252
  ref: headerRef,
@@ -13240,7 +13259,7 @@ function HeroZoomLayout({
13240
13259
  children: header
13241
13260
  }
13242
13261
  ),
13243
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13262
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13244
13263
  "div",
13245
13264
  {
13246
13265
  ref: imageContainerRef,
@@ -13260,15 +13279,15 @@ function HeroZoomLayout({
13260
13279
  children: hero
13261
13280
  }
13262
13281
  ),
13263
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "relative z-10", children })
13282
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "relative z-10", children })
13264
13283
  ]
13265
13284
  }
13266
13285
  );
13267
13286
  }
13268
13287
 
13269
13288
  // src/layouts/hero-zoom/HeroShrinkLayout.tsx
13270
- var import_react60 = require("react");
13271
- var import_jsx_runtime77 = require("react/jsx-runtime");
13289
+ var import_react61 = require("react");
13290
+ var import_jsx_runtime78 = require("react/jsx-runtime");
13272
13291
  var DEFAULT_CONFIG = {
13273
13292
  aspectRatio: 16 / 9,
13274
13293
  initialHeightPercent: 70,
@@ -13288,13 +13307,13 @@ function HeroShrinkLayout({
13288
13307
  ...config
13289
13308
  };
13290
13309
  const { aspectRatio, initialHeightPercent, minHeightPercent, headerHeight } = mergedConfig;
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)(() => {
13310
+ const heroRef = (0, import_react61.useRef)(null);
13311
+ const headerRef = (0, import_react61.useRef)(null);
13312
+ const [isClient, setIsClient] = (0, import_react61.useState)(false);
13313
+ (0, import_react61.useEffect)(() => {
13295
13314
  setIsClient(true);
13296
13315
  }, []);
13297
- (0, import_react60.useEffect)(() => {
13316
+ (0, import_react61.useEffect)(() => {
13298
13317
  if (!isClient) return;
13299
13318
  const supportsScrollTimeline = CSS.supports("animation-timeline", "scroll()");
13300
13319
  if (supportsScrollTimeline) return;
@@ -13381,15 +13400,15 @@ function HeroShrinkLayout({
13381
13400
  }
13382
13401
  `;
13383
13402
  const spacerHeight = `calc(${initialHeightPercent}svh + ${headerHeight}px)`;
13384
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
13403
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
13385
13404
  "div",
13386
13405
  {
13387
13406
  className: `relative min-h-screen ${className}`,
13388
13407
  style: { ...style, ...cssVars },
13389
13408
  children: [
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)(
13409
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13410
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { style: { height: spacerHeight } }),
13411
+ header && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13393
13412
  "div",
13394
13413
  {
13395
13414
  ref: headerRef,
@@ -13398,7 +13417,7 @@ function HeroShrinkLayout({
13398
13417
  children: header
13399
13418
  }
13400
13419
  ),
13401
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13420
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13402
13421
  "div",
13403
13422
  {
13404
13423
  ref: heroRef,
@@ -13406,15 +13425,15 @@ function HeroShrinkLayout({
13406
13425
  children: hero
13407
13426
  }
13408
13427
  ),
13409
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "relative z-10 bg-background", children })
13428
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "relative z-10 bg-background", children })
13410
13429
  ]
13411
13430
  }
13412
13431
  );
13413
13432
  }
13414
13433
 
13415
13434
  // src/layouts/pdp/ImageEdgeBlur.tsx
13416
- var import_react61 = __toESM(require("react"), 1);
13417
- var import_jsx_runtime78 = require("react/jsx-runtime");
13435
+ var import_react62 = __toESM(require("react"), 1);
13436
+ var import_jsx_runtime79 = require("react/jsx-runtime");
13418
13437
  var BLUR_CONFIG = {
13419
13438
  blur: 24,
13420
13439
  crossfade: 68
@@ -13438,7 +13457,7 @@ var BLUR_LAYERS = [
13438
13457
  { blur: Math.round(BLUR_CONFIG.blur * 0.5), zone: 0.6 },
13439
13458
  { blur: BLUR_CONFIG.blur, zone: 1 }
13440
13459
  ];
13441
- var ImageEdgeBlur = import_react61.default.memo(
13460
+ var ImageEdgeBlur = import_react62.default.memo(
13442
13461
  function ImageEdgeBlur2({
13443
13462
  imageSrc,
13444
13463
  imageCapInfo,
@@ -13469,7 +13488,7 @@ var ImageEdgeBlur = import_react61.default.memo(
13469
13488
  viewportWidth / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO,
13470
13489
  maxWidthPx / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO
13471
13490
  );
13472
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13491
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13473
13492
  "div",
13474
13493
  {
13475
13494
  className: `absolute inset-0 pointer-events-none overflow-hidden ${className}`,
@@ -13477,7 +13496,7 @@ var ImageEdgeBlur = import_react61.default.memo(
13477
13496
  children: BLUR_LAYERS.map((layer, index) => {
13478
13497
  const layerMask = index === BLUR_LAYERS.length - 1 ? void 0 : `linear-gradient(to right, black 0%, black ${layer.zone * 100}%, transparent ${layer.zone * 100 + 10}%)`;
13479
13498
  const blurScale = 1 + layer.blur * 3 / containerHeightPx;
13480
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13499
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13481
13500
  "img",
13482
13501
  {
13483
13502
  src: imageSrc,
@@ -13524,7 +13543,7 @@ var ImageEdgeBlur = import_react61.default.memo(
13524
13543
  );
13525
13544
 
13526
13545
  // src/layouts/pdp/PDPLayout.tsx
13527
- var import_jsx_runtime79 = require("react/jsx-runtime");
13546
+ var import_jsx_runtime80 = require("react/jsx-runtime");
13528
13547
  function PDPLayout({
13529
13548
  renderHeroImage,
13530
13549
  renderContent,
@@ -13552,15 +13571,15 @@ function PDPLayout({
13552
13571
  isDesktop,
13553
13572
  isWideMonitor: isWideMonitor2
13554
13573
  };
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) })
13574
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: `pdp-layout ${className}`, children: [
13575
+ (isDesktop === false || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "md:hidden", children: [
13576
+ renderMobileCarousel && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13577
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "mobile-content p-4", children: renderContent(contentProps) })
13559
13578
  ] }),
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: [
13579
+ (isDesktop === true || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "hidden md:block relative", children: [
13580
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "desktop-hero relative", children: [
13562
13581
  renderHeroImage(heroProps),
13563
- showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13582
+ showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13564
13583
  ImageEdgeBlur,
13565
13584
  {
13566
13585
  imageSrc: blurImageSrc,
@@ -13571,7 +13590,7 @@ function PDPLayout({
13571
13590
  }
13572
13591
  )
13573
13592
  ] }),
13574
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13593
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13575
13594
  "div",
13576
13595
  {
13577
13596
  className: "desktop-sidebar",
@@ -13588,8 +13607,8 @@ function PDPLayout({
13588
13607
  }
13589
13608
 
13590
13609
  // src/layouts/pdp/SimpleImageBlur.tsx
13591
- var import_react62 = __toESM(require("react"), 1);
13592
- var import_jsx_runtime80 = require("react/jsx-runtime");
13610
+ var import_react63 = __toESM(require("react"), 1);
13611
+ var import_jsx_runtime81 = require("react/jsx-runtime");
13593
13612
  var BLUR_CONFIG2 = {
13594
13613
  blur: 24,
13595
13614
  crossfade: 60
@@ -13612,7 +13631,7 @@ function getFadeInMask(crossfadeWidth) {
13612
13631
  black ${crossfadeWidth + 10}px
13613
13632
  )`;
13614
13633
  }
13615
- var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13634
+ var SimpleImageBlur = import_react63.default.memo(function SimpleImageBlur2({
13616
13635
  imageSrc,
13617
13636
  width,
13618
13637
  height = "100%",
@@ -13622,7 +13641,7 @@ var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13622
13641
  if (!imageSrc || width <= 0) return null;
13623
13642
  const fadeInMask = getFadeInMask(BLUR_CONFIG2.crossfade);
13624
13643
  const extendedWidth = width + BLUR_CONFIG2.blur * 2;
13625
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13644
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13626
13645
  "div",
13627
13646
  {
13628
13647
  className: `relative overflow-hidden ${className}`,
@@ -13635,7 +13654,7 @@ var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13635
13654
  black 0%,
13636
13655
  black ${layer.zone * 100}%,
13637
13656
  transparent ${layer.zone * 100 + 10}%)`;
13638
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13657
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13639
13658
  "img",
13640
13659
  {
13641
13660
  src: imageSrc,
@@ -13665,8 +13684,8 @@ var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13665
13684
  });
13666
13685
 
13667
13686
  // src/layouts/pdp/EdgeBlurBox.tsx
13668
- var import_react63 = __toESM(require("react"), 1);
13669
- var import_jsx_runtime81 = require("react/jsx-runtime");
13687
+ var import_react64 = __toESM(require("react"), 1);
13688
+ var import_jsx_runtime82 = require("react/jsx-runtime");
13670
13689
  var BLUR_CONFIG3 = {
13671
13690
  blur: 24,
13672
13691
  crossfade: 60
@@ -13690,7 +13709,7 @@ function getFadeOutMask(crossfadeWidth) {
13690
13709
  transparent 100%
13691
13710
  )`;
13692
13711
  }
13693
- var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13712
+ var EdgeBlurBox = import_react64.default.memo(function EdgeBlurBox2({
13694
13713
  imageSrc,
13695
13714
  width,
13696
13715
  height = "100%",
@@ -13705,7 +13724,7 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13705
13724
  const blurExtend = BLUR_CONFIG3.blur * 2;
13706
13725
  const actualSharpWidth = sharpImageWidth ?? width + overlapLeft;
13707
13726
  const hasOverlap = overlapLeft > 0;
13708
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
13727
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
13709
13728
  "div",
13710
13729
  {
13711
13730
  className: `relative ${className}`,
@@ -13716,7 +13735,7 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13716
13735
  overflow: hasOverlap ? "visible" : "hidden"
13717
13736
  },
13718
13737
  children: [
13719
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13738
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13720
13739
  "div",
13721
13740
  {
13722
13741
  style: {
@@ -13730,7 +13749,7 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13730
13749
  transparent ${100 - (layer.zone * 100 + 10)}%,
13731
13750
  black ${100 - layer.zone * 100}%,
13732
13751
  black 100%)`;
13733
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13752
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13734
13753
  "img",
13735
13754
  {
13736
13755
  src: imageSrc,
@@ -13758,7 +13777,7 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13758
13777
  })
13759
13778
  }
13760
13779
  ),
13761
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13780
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13762
13781
  "img",
13763
13782
  {
13764
13783
  src: imageSrc,
@@ -13786,8 +13805,8 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13786
13805
  });
13787
13806
 
13788
13807
  // src/layouts/pdp/ImageBlurExtension.tsx
13789
- var import_react64 = __toESM(require("react"), 1);
13790
- var import_jsx_runtime82 = require("react/jsx-runtime");
13808
+ var import_react65 = __toESM(require("react"), 1);
13809
+ var import_jsx_runtime83 = require("react/jsx-runtime");
13791
13810
  var BLUR_CONFIG4 = {
13792
13811
  blur: 24,
13793
13812
  crossfadeWidth: 80
@@ -13810,7 +13829,7 @@ function getFadeOutMask2(crossfadeWidth) {
13810
13829
  transparent 100%
13811
13830
  )`;
13812
13831
  }
13813
- var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension2({
13832
+ var ImageBlurExtension = import_react65.default.memo(function ImageBlurExtension2({
13814
13833
  imageSrc,
13815
13834
  width,
13816
13835
  height,
@@ -13824,7 +13843,7 @@ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension
13824
13843
  const internalImageLeft = `calc(${heroImageLeft} - 100vw + ${width}px)`;
13825
13844
  const fadeOutMask = getFadeOutMask2(crossfadeWidth);
13826
13845
  const heightValue = typeof height === "number" ? `${height}px` : height;
13827
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
13846
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
13828
13847
  "div",
13829
13848
  {
13830
13849
  className: `relative overflow-hidden ${className}`,
@@ -13833,7 +13852,7 @@ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension
13833
13852
  height: heightValue
13834
13853
  },
13835
13854
  children: [
13836
- BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13855
+ BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13837
13856
  "img",
13838
13857
  {
13839
13858
  src: imageSrc,
@@ -13857,7 +13876,7 @@ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension
13857
13876
  },
13858
13877
  `blur-${index}`
13859
13878
  )),
13860
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13879
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13861
13880
  "img",
13862
13881
  {
13863
13882
  src: imageSrc,
@@ -13885,39 +13904,39 @@ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension
13885
13904
  });
13886
13905
 
13887
13906
  // src/design-system/ColorSwatch.tsx
13888
- var import_jsx_runtime83 = require("react/jsx-runtime");
13907
+ var import_jsx_runtime84 = require("react/jsx-runtime");
13889
13908
  function ColorTokenSwatch({ name, cssVar, className = "" }) {
13890
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: `flex flex-col gap-1 ${className}`, children: [
13891
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13909
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: `flex flex-col gap-1 ${className}`, children: [
13910
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
13892
13911
  "div",
13893
13912
  {
13894
13913
  className: "h-16 w-full rounded-lg border border-border shadow-sm",
13895
13914
  style: { backgroundColor: `var(${cssVar})` }
13896
13915
  }
13897
13916
  ),
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 })
13917
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13918
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: cssVar })
13900
13919
  ] });
13901
13920
  }
13902
13921
  function ColorRow({ name, cssVar, description }) {
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)(
13922
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex items-center gap-4 py-2", children: [
13923
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
13905
13924
  "div",
13906
13925
  {
13907
13926
  className: "h-10 w-10 rounded-lg border border-border shadow-sm flex-shrink-0",
13908
13927
  style: { backgroundColor: `var(${cssVar})` }
13909
13928
  }
13910
13929
  ),
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 })
13930
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex-1 min-w-0", children: [
13931
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13932
+ description && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-xs text-muted-foreground", children: description })
13914
13933
  ] }),
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 })
13934
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: cssVar })
13916
13935
  ] });
13917
13936
  }
13918
13937
 
13919
13938
  // src/design-system/ColorPalette.tsx
13920
- var import_jsx_runtime84 = require("react/jsx-runtime");
13939
+ var import_jsx_runtime85 = require("react/jsx-runtime");
13921
13940
  var COLOR_GROUPS = [
13922
13941
  {
13923
13942
  name: "Base",
@@ -13998,17 +14017,17 @@ var COLOR_GROUPS = [
13998
14017
  }
13999
14018
  ];
14000
14019
  function ColorPalette({ layout = "list", className = "" }) {
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)(
14020
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: `space-y-8 ${className}`, children: COLOR_GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("section", { children: [
14021
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
14022
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
14023
+ layout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-4", children: group.colors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
14005
14024
  ColorTokenSwatch,
14006
14025
  {
14007
14026
  name: color.name,
14008
14027
  cssVar: color.cssVar
14009
14028
  },
14010
14029
  color.cssVar
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)(
14030
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime85.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_runtime85.jsx)(
14012
14031
  ColorRow,
14013
14032
  {
14014
14033
  name: color.name,
@@ -14021,7 +14040,7 @@ function ColorPalette({ layout = "list", className = "" }) {
14021
14040
  }
14022
14041
 
14023
14042
  // src/design-system/TypographyScale.tsx
14024
- var import_jsx_runtime85 = require("react/jsx-runtime");
14043
+ var import_jsx_runtime86 = require("react/jsx-runtime");
14025
14044
  var FONT_SAMPLES = [
14026
14045
  {
14027
14046
  name: "Heading",
@@ -14055,14 +14074,14 @@ var FONT_SAMPLES = [
14055
14074
  }
14056
14075
  ];
14057
14076
  function TypographyScale({ className = "" }) {
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 })
14077
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: `space-y-8 ${className}`, children: FONT_SAMPLES.map((font) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "bg-card rounded-lg border border-border p-6", children: [
14078
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
14079
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
14080
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: font.cssVar })
14062
14081
  ] }),
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)(
14082
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "space-y-4", children: font.sizes.map((size) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex items-baseline gap-4", children: [
14083
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
14084
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
14066
14085
  "p",
14067
14086
  {
14068
14087
  className: `${size} text-foreground`,
@@ -14081,8 +14100,8 @@ var RADIUS_SAMPLES = [
14081
14100
  { name: "Full", value: "9999px" }
14082
14101
  ];
14083
14102
  function RadiusScale({ className = "" }) {
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)(
14103
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "grid grid-cols-5 gap-4", children: RADIUS_SAMPLES.map((radius) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex flex-col items-center gap-2", children: [
14104
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
14086
14105
  "div",
14087
14106
  {
14088
14107
  className: "h-16 w-16 bg-primary",
@@ -14091,13 +14110,13 @@ function RadiusScale({ className = "" }) {
14091
14110
  }
14092
14111
  }
14093
14112
  ),
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 })
14113
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
14114
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: radius.cssVar || radius.value })
14096
14115
  ] }, radius.name)) }) });
14097
14116
  }
14098
14117
 
14099
14118
  // src/design-system/ThemeSwitcher.tsx
14100
- var import_react65 = require("react");
14119
+ var import_react66 = require("react");
14101
14120
 
14102
14121
  // src/themes/types.ts
14103
14122
  var RADIUS_PRESETS = {
@@ -15265,7 +15284,7 @@ function applyTheme(config) {
15265
15284
  }
15266
15285
 
15267
15286
  // src/design-system/ThemeSwitcher.tsx
15268
- var import_jsx_runtime86 = require("react/jsx-runtime");
15287
+ var import_jsx_runtime87 = require("react/jsx-runtime");
15269
15288
  function readThemeFromDOM() {
15270
15289
  if (typeof document === "undefined") {
15271
15290
  return { themeName: "Linear", isDark: false };
@@ -15283,10 +15302,10 @@ function readThemeFromDOM() {
15283
15302
  return { themeName: "Linear", isDark: dark };
15284
15303
  }
15285
15304
  function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
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)(() => {
15305
+ const [currentTheme, setCurrentTheme] = (0, import_react66.useState)("Linear");
15306
+ const [isDark, setIsDark] = (0, import_react66.useState)(false);
15307
+ const [isOpen, setIsOpen] = (0, import_react66.useState)(false);
15308
+ (0, import_react66.useEffect)(() => {
15290
15309
  const { themeName, isDark: dark } = readThemeFromDOM();
15291
15310
  setCurrentTheme(themeName);
15292
15311
  setIsDark(dark);
@@ -15325,61 +15344,61 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
15325
15344
  applyTheme(config);
15326
15345
  };
15327
15346
  const themes = showBaseThemesOnly ? baseThemes : baseThemes;
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)(
15347
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: `flex items-center gap-3 ${className}`, children: [
15348
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "relative", children: [
15349
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
15331
15350
  "button",
15332
15351
  {
15333
15352
  onClick: () => setIsOpen(!isOpen),
15334
15353
  className: "flex items-center gap-2 px-4 py-2 bg-card border border-border rounded-lg hover:bg-muted transition-colors text-foreground",
15335
15354
  children: [
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" }) })
15355
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime87.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" }) }),
15356
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "font-medium", children: currentTheme }),
15357
+ /* @__PURE__ */ (0, import_jsx_runtime87.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_runtime87.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
15339
15358
  ]
15340
15359
  }
15341
15360
  ),
15342
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(import_jsx_runtime86.Fragment, { children: [
15343
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15361
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(import_jsx_runtime87.Fragment, { children: [
15362
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15344
15363
  "div",
15345
15364
  {
15346
15365
  className: "fixed inset-0 z-40",
15347
15366
  onClick: () => setIsOpen(false)
15348
15367
  }
15349
15368
  ),
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)(
15369
+ /* @__PURE__ */ (0, import_jsx_runtime87.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_runtime87.jsxs)(
15351
15370
  "button",
15352
15371
  {
15353
15372
  onClick: () => handleThemeSelect(theme.name),
15354
15373
  className: `w-full px-4 py-2 text-left hover:bg-muted transition-colors flex items-center gap-3 ${currentTheme === theme.name ? "bg-muted" : ""}`,
15355
15374
  children: [
15356
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15375
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15357
15376
  "div",
15358
15377
  {
15359
15378
  className: "w-4 h-4 rounded-full border border-border",
15360
15379
  style: { backgroundColor: theme.primaryColor || "#888" }
15361
15380
  }
15362
15381
  ),
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" }) })
15382
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "text-foreground", children: theme.name }),
15383
+ currentTheme === theme.name && /* @__PURE__ */ (0, import_jsx_runtime87.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_runtime87.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) })
15365
15384
  ]
15366
15385
  },
15367
15386
  theme.name
15368
15387
  )) })
15369
15388
  ] })
15370
15389
  ] }),
15371
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
15390
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
15372
15391
  "button",
15373
15392
  {
15374
15393
  onClick: handleDarkModeToggle,
15375
15394
  className: "flex items-center gap-2 px-4 py-2 bg-card border border-border rounded-lg hover:bg-muted transition-colors text-foreground",
15376
15395
  title: `Switch to ${isDark ? "light" : "dark"} mode`,
15377
15396
  children: [
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" })
15397
+ isDark ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
15398
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
15399
+ /* @__PURE__ */ (0, import_jsx_runtime87.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" })
15400
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }),
15401
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "text-sm", children: isDark ? "Light" : "Dark" })
15383
15402
  ]
15384
15403
  }
15385
15404
  )
@@ -15387,7 +15406,7 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
15387
15406
  }
15388
15407
 
15389
15408
  // src/design-system/DesignSystemPage.tsx
15390
- var import_jsx_runtime87 = require("react/jsx-runtime");
15409
+ var import_jsx_runtime88 = require("react/jsx-runtime");
15391
15410
  function DesignSystemPage({
15392
15411
  showThemeSwitcher = true,
15393
15412
  showColors = true,
@@ -15397,29 +15416,29 @@ function DesignSystemPage({
15397
15416
  colorLayout = "list",
15398
15417
  className = ""
15399
15418
  }) {
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" })
15419
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: `max-w-4xl mx-auto px-4 py-8 ${className}`, children: [
15420
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("header", { className: "mb-12", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4", children: [
15421
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { children: [
15422
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
15423
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("p", { className: "text-lg text-muted-foreground", children: "Visual reference for theme tokens and styles" })
15405
15424
  ] }),
15406
- showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ThemeSwitcher, {})
15425
+ showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ThemeSwitcher, {})
15407
15426
  ] }) }),
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 })
15427
+ showColors && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("section", { className: "mb-16", children: [
15428
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Color Palette" }),
15429
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ColorPalette, { layout: colorLayout })
15411
15430
  ] }),
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, {})
15431
+ showTypography && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("section", { className: "mb-16", children: [
15432
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
15433
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(TypographyScale, {})
15415
15434
  ] }),
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, {})
15435
+ showRadius && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("section", { className: "mb-16", children: [
15436
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Border Radius" }),
15437
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(RadiusScale, {})
15419
15438
  ] }),
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, {})
15439
+ showSpacing && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("section", { className: "mb-16", children: [
15440
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Spacing Scale" }),
15441
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(SpacingScale, {})
15423
15442
  ] })
15424
15443
  ] });
15425
15444
  }
@@ -15434,31 +15453,31 @@ function SpacingScale() {
15434
15453
  { name: "12", value: "3rem" },
15435
15454
  { name: "16", value: "4rem" }
15436
15455
  ];
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)(
15456
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "space-y-2", children: spaces.map((space) => /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex items-center gap-4", children: [
15457
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
15458
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15440
15459
  "div",
15441
15460
  {
15442
15461
  className: "h-4 bg-primary rounded",
15443
15462
  style: { width: space.value }
15444
15463
  }
15445
15464
  ),
15446
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "text-sm text-muted-foreground", children: space.value })
15465
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "text-sm text-muted-foreground", children: space.value })
15447
15466
  ] }, space.name)) });
15448
15467
  }
15449
15468
 
15450
15469
  // src/personalization/PersonalizationProvider.tsx
15451
- var import_react68 = __toESM(require("react"), 1);
15470
+ var import_react69 = __toESM(require("react"), 1);
15452
15471
 
15453
15472
  // src/personalization/PersonalizationContext.ts
15454
- var import_react66 = require("react");
15455
- var PersonalizationContext = (0, import_react66.createContext)(null);
15473
+ var import_react67 = require("react");
15474
+ var PersonalizationContext = (0, import_react67.createContext)(null);
15456
15475
  function usePersonalizationContext() {
15457
- return (0, import_react66.useContext)(PersonalizationContext);
15476
+ return (0, import_react67.useContext)(PersonalizationContext);
15458
15477
  }
15459
15478
 
15460
15479
  // src/personalization/utils.ts
15461
- var import_react67 = require("react");
15480
+ var import_react68 = require("react");
15462
15481
  function normalizeHex(color) {
15463
15482
  let hex = color.trim().toUpperCase();
15464
15483
  if (hex.length === 4 && hex.startsWith("#")) {
@@ -15479,8 +15498,8 @@ function isValidImageUrl(url) {
15479
15498
  }
15480
15499
  }
15481
15500
  function useDebouncedValue(value, delay) {
15482
- const [debounced, setDebounced] = (0, import_react67.useState)(value);
15483
- (0, import_react67.useEffect)(() => {
15501
+ const [debounced, setDebounced] = (0, import_react68.useState)(value);
15502
+ (0, import_react68.useEffect)(() => {
15484
15503
  const timer = setTimeout(() => setDebounced(value), delay);
15485
15504
  return () => clearTimeout(timer);
15486
15505
  }, [value, delay]);
@@ -15501,18 +15520,18 @@ function scrollInputAboveKeyboard(input) {
15501
15520
  }
15502
15521
 
15503
15522
  // src/personalization/PersonalizationProvider.tsx
15504
- var import_jsx_runtime88 = require("react/jsx-runtime");
15523
+ var import_jsx_runtime89 = require("react/jsx-runtime");
15505
15524
  function createBridgeFromCanvas(canvasModule) {
15506
15525
  const { useEditor, useCommands, useImageBinding } = canvasModule;
15507
15526
  function TextBinder({ name, value }) {
15508
15527
  const { elements } = useEditor();
15509
15528
  const { executeElementUpdate } = useCommands();
15510
- const elementsRef = import_react68.default.useRef(elements);
15529
+ const elementsRef = import_react69.default.useRef(elements);
15511
15530
  elementsRef.current = elements;
15512
- const executeRef = import_react68.default.useRef(executeElementUpdate);
15531
+ const executeRef = import_react69.default.useRef(executeElementUpdate);
15513
15532
  executeRef.current = executeElementUpdate;
15514
- const hasUserInput = import_react68.default.useRef(false);
15515
- import_react68.default.useEffect(() => {
15533
+ const hasUserInput = import_react69.default.useRef(false);
15534
+ import_react69.default.useEffect(() => {
15516
15535
  if (value == null) return;
15517
15536
  if (value === "" && !hasUserInput.current) return;
15518
15537
  hasUserInput.current = true;
@@ -15530,12 +15549,12 @@ function createBridgeFromCanvas(canvasModule) {
15530
15549
  function ColorBinder({ originalColor, newColor }) {
15531
15550
  const { elements } = useEditor();
15532
15551
  const { executeElementUpdate } = useCommands();
15533
- const elementsRef = import_react68.default.useRef(elements);
15552
+ const elementsRef = import_react69.default.useRef(elements);
15534
15553
  elementsRef.current = elements;
15535
- const executeRef = import_react68.default.useRef(executeElementUpdate);
15554
+ const executeRef = import_react69.default.useRef(executeElementUpdate);
15536
15555
  executeRef.current = executeElementUpdate;
15537
- const appliedColorRef = import_react68.default.useRef(normalizeHex(originalColor));
15538
- import_react68.default.useEffect(() => {
15556
+ const appliedColorRef = import_react69.default.useRef(normalizeHex(originalColor));
15557
+ import_react69.default.useEffect(() => {
15539
15558
  const normalizedNew = normalizeHex(newColor);
15540
15559
  if (normalizedNew === appliedColorRef.current) return;
15541
15560
  const matchColor = appliedColorRef.current;
@@ -15575,11 +15594,11 @@ function createBridgeFromCanvas(canvasModule) {
15575
15594
  }
15576
15595
  function ImageBinder({ name, value, fit = "cover" }) {
15577
15596
  const { setImageUrl } = useImageBinding(name, { fit });
15578
- const hasUserInput = import_react68.default.useRef(false);
15597
+ const hasUserInput = import_react69.default.useRef(false);
15579
15598
  const debouncedValue = useDebouncedValue(value, 500);
15580
- const setImageUrlRef = import_react68.default.useRef(setImageUrl);
15599
+ const setImageUrlRef = import_react69.default.useRef(setImageUrl);
15581
15600
  setImageUrlRef.current = setImageUrl;
15582
- import_react68.default.useEffect(() => {
15601
+ import_react69.default.useEffect(() => {
15583
15602
  if (debouncedValue == null) return;
15584
15603
  if (debouncedValue === "" && !hasUserInput.current) return;
15585
15604
  hasUserInput.current = true;
@@ -15589,15 +15608,15 @@ function createBridgeFromCanvas(canvasModule) {
15589
15608
  return null;
15590
15609
  }
15591
15610
  return function PersonalizationBridge({ fields = [], values = {} } = {}) {
15592
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_jsx_runtime88.Fragment, { children: fields.map((field) => {
15611
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_jsx_runtime89.Fragment, { children: fields.map((field) => {
15593
15612
  if (field.type === "text") {
15594
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
15613
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
15595
15614
  }
15596
15615
  if (field.type === "color") {
15597
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
15616
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
15598
15617
  }
15599
15618
  if (field.type === "image") {
15600
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
15619
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
15601
15620
  }
15602
15621
  return null;
15603
15622
  }) });
@@ -15619,19 +15638,19 @@ function PersonalizationProvider({
15619
15638
  children
15620
15639
  }) {
15621
15640
  const realtime = useRealtimeOptional();
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)(
15641
+ const [personValues, setPersonValues] = (0, import_react69.useState)(initialValues ?? {});
15642
+ const [isActive, setIsActive] = (0, import_react69.useState)(!!(initialValues && Object.keys(initialValues).length > 0));
15643
+ const [isExporting, setIsExporting] = (0, import_react69.useState)(false);
15644
+ const [exportedBlobUrls, setExportedBlobUrls] = (0, import_react69.useState)({});
15645
+ const [exportCount, setExportCount] = (0, import_react69.useState)(0);
15646
+ const blobUrlsRef = (0, import_react69.useRef)({});
15647
+ const [CanvasComponent, setCanvasComponent] = (0, import_react69.useState)(
15629
15648
  cachedCanvasComponent
15630
15649
  );
15631
- const [BridgeComponent, setBridgeComponent] = (0, import_react68.useState)(
15650
+ const [BridgeComponent, setBridgeComponent] = (0, import_react69.useState)(
15632
15651
  cachedBridgeComponent
15633
15652
  );
15634
- (0, import_react68.useEffect)(() => {
15653
+ (0, import_react69.useEffect)(() => {
15635
15654
  if (CanvasComponent && BridgeComponent) return;
15636
15655
  if (!canvasImport) return;
15637
15656
  if (!canvasLoadPromise) {
@@ -15649,8 +15668,8 @@ function PersonalizationProvider({
15649
15668
  }
15650
15669
  });
15651
15670
  }, [CanvasComponent, BridgeComponent, canvasImport]);
15652
- const realtimeEnabledRef = (0, import_react68.useRef)(false);
15653
- (0, import_react68.useEffect)(() => {
15671
+ const realtimeEnabledRef = (0, import_react69.useRef)(false);
15672
+ (0, import_react69.useEffect)(() => {
15654
15673
  return () => {
15655
15674
  for (const url of Object.values(blobUrlsRef.current)) {
15656
15675
  try {
@@ -15660,16 +15679,16 @@ function PersonalizationProvider({
15660
15679
  }
15661
15680
  };
15662
15681
  }, []);
15663
- const updateField = (0, import_react68.useCallback)((key, value) => {
15682
+ const updateField = (0, import_react69.useCallback)((key, value) => {
15664
15683
  setIsActive(true);
15665
15684
  setPersonValues((prev) => ({ ...prev, [key]: value }));
15666
15685
  }, []);
15667
- const reset = (0, import_react68.useCallback)(() => {
15686
+ const reset = (0, import_react69.useCallback)(() => {
15668
15687
  setPersonValues({});
15669
15688
  setIsActive(false);
15670
15689
  setIsExporting(false);
15671
15690
  }, []);
15672
- const handleExport = (0, import_react68.useCallback)(
15691
+ const handleExport = (0, import_react69.useCallback)(
15673
15692
  (exports2) => {
15674
15693
  const newUrls = {};
15675
15694
  for (const [name, data] of Object.entries(exports2)) {
@@ -15703,11 +15722,11 @@ function PersonalizationProvider({
15703
15722
  },
15704
15723
  [realtime, placementOverride]
15705
15724
  );
15706
- const handleExportScheduled = (0, import_react68.useCallback)(() => {
15725
+ const handleExportScheduled = (0, import_react69.useCallback)(() => {
15707
15726
  setIsExporting(true);
15708
15727
  }, []);
15709
15728
  const shouldMountCanvas = CanvasComponent && BridgeComponent && canvasState?.elements && canvasState.elements.length > 0 && (!lazy || isActive);
15710
- const contextValue = import_react68.default.useMemo(
15729
+ const contextValue = import_react69.default.useMemo(
15711
15730
  () => ({
15712
15731
  fields,
15713
15732
  personValues,
@@ -15720,8 +15739,8 @@ function PersonalizationProvider({
15720
15739
  }),
15721
15740
  [fields, personValues, updateField, isActive, isExporting, exportedBlobUrls, exportCount, reset]
15722
15741
  );
15723
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(PersonalizationContext.Provider, { value: contextValue, children: [
15724
- shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15742
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(PersonalizationContext.Provider, { value: contextValue, children: [
15743
+ shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15725
15744
  "div",
15726
15745
  {
15727
15746
  style: {
@@ -15734,7 +15753,7 @@ function PersonalizationProvider({
15734
15753
  pointerEvents: "none"
15735
15754
  },
15736
15755
  "aria-hidden": true,
15737
- children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15756
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15738
15757
  CanvasComponent,
15739
15758
  {
15740
15759
  initialElements: canvasState?.elements,
@@ -15754,7 +15773,7 @@ function PersonalizationProvider({
15754
15773
  exportImageQuality: exportConfig?.imageQuality ?? 0.85,
15755
15774
  onExport: handleExport,
15756
15775
  onExportScheduled: handleExportScheduled,
15757
- overlay: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(BridgeComponent, { fields, values: personValues })
15776
+ overlay: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(BridgeComponent, { fields, values: personValues })
15758
15777
  }
15759
15778
  )
15760
15779
  },
@@ -15779,7 +15798,7 @@ function usePersonalizationOptional() {
15779
15798
  }
15780
15799
 
15781
15800
  // src/personalization/PersonalizationInputs.tsx
15782
- var import_jsx_runtime89 = require("react/jsx-runtime");
15801
+ var import_jsx_runtime90 = require("react/jsx-runtime");
15783
15802
  function PersonalizationInputs({
15784
15803
  className,
15785
15804
  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",
@@ -15803,8 +15822,8 @@ function PersonalizationInputs({
15803
15822
  scrollInputAboveKeyboard(e.target);
15804
15823
  }
15805
15824
  };
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)(
15825
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: className || "flex flex-col gap-3", children: [
15826
+ textFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
15808
15827
  "input",
15809
15828
  {
15810
15829
  type: "text",
@@ -15818,8 +15837,8 @@ function PersonalizationInputs({
15818
15837
  },
15819
15838
  `text-${field.name}`
15820
15839
  )),
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)(
15840
+ colorFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "flex items-center gap-3", children: [
15841
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
15823
15842
  "input",
15824
15843
  {
15825
15844
  type: "color",
@@ -15828,9 +15847,9 @@ function PersonalizationInputs({
15828
15847
  onChange: (e) => updateField(field.color, e.target.value)
15829
15848
  }
15830
15849
  ),
15831
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "text-base text-muted-foreground", children: field.label })
15850
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "text-base text-muted-foreground", children: field.label })
15832
15851
  ] }, `color-${field.color}`)),
15833
- imageFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15852
+ imageFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
15834
15853
  "input",
15835
15854
  {
15836
15855
  type: "text",
@@ -15848,15 +15867,15 @@ function PersonalizationInputs({
15848
15867
  }
15849
15868
 
15850
15869
  // src/personalization/usePersonalizationShimmer.ts
15851
- var import_react69 = require("react");
15870
+ var import_react70 = require("react");
15852
15871
  function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15853
15872
  const personCtx = usePersonalizationContext();
15854
15873
  const realtime = useRealtimeOptional();
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)(() => {
15874
+ const [shimmerActive, setShimmerActive] = (0, import_react70.useState)(false);
15875
+ const sdkSettledRef = (0, import_react70.useRef)(false);
15876
+ const manualTriggerRef = (0, import_react70.useRef)(false);
15877
+ const safetyTimeoutRef = (0, import_react70.useRef)(void 0);
15878
+ const startShimmer = (0, import_react70.useCallback)(() => {
15860
15879
  setShimmerActive(true);
15861
15880
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
15862
15881
  safetyTimeoutRef.current = setTimeout(
@@ -15868,25 +15887,25 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15868
15887
  safetyTimeoutMs
15869
15888
  );
15870
15889
  }, [safetyTimeoutMs]);
15871
- (0, import_react69.useEffect)(() => {
15890
+ (0, import_react70.useEffect)(() => {
15872
15891
  if (!personCtx?.isActive) return;
15873
15892
  sdkSettledRef.current = false;
15874
15893
  manualTriggerRef.current = false;
15875
15894
  realtime?.resetPipelineSettled();
15876
15895
  startShimmer();
15877
15896
  }, [personCtx?.personValues, personCtx?.isActive, startShimmer]);
15878
- const triggerShimmer = (0, import_react69.useCallback)(() => {
15897
+ const triggerShimmer = (0, import_react70.useCallback)(() => {
15879
15898
  sdkSettledRef.current = false;
15880
15899
  manualTriggerRef.current = true;
15881
15900
  startShimmer();
15882
15901
  }, [startShimmer]);
15883
- (0, import_react69.useEffect)(() => {
15902
+ (0, import_react70.useEffect)(() => {
15884
15903
  if (!realtime?.subscribePipelineSettled) return;
15885
15904
  return realtime.subscribePipelineSettled(() => {
15886
15905
  sdkSettledRef.current = true;
15887
15906
  });
15888
15907
  }, [realtime]);
15889
- (0, import_react69.useEffect)(() => {
15908
+ (0, import_react70.useEffect)(() => {
15890
15909
  const container = containerRef.current;
15891
15910
  if (!container) return;
15892
15911
  const observer = new MutationObserver((mutations) => {
@@ -15929,7 +15948,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15929
15948
  });
15930
15949
  return () => observer.disconnect();
15931
15950
  }, [containerRef]);
15932
- (0, import_react69.useEffect)(() => {
15951
+ (0, import_react70.useEffect)(() => {
15933
15952
  return () => {
15934
15953
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
15935
15954
  };
@@ -16039,6 +16058,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
16039
16058
  LoadingOverlayPrismCandyInline,
16040
16059
  MasonryGrid,
16041
16060
  MobileProductCarousel,
16061
+ MockupBackground,
16042
16062
  MockupPriorityProvider,
16043
16063
  PDPLayout,
16044
16064
  PersonalizationInputs,
@@ -16164,6 +16184,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
16164
16184
  useIsolatedCanvas,
16165
16185
  useLoadingOverlay,
16166
16186
  useMediaQuery,
16187
+ useMockupBackgroundOptional,
16167
16188
  useMockupPriority,
16168
16189
  useMockupPriorityOptional,
16169
16190
  usePersonalization,