@snowcone-app/ui 0.4.6 → 0.4.8

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,
@@ -5909,16 +5911,29 @@ function useFocusTrap(isActive, onClose) {
5909
5911
  }
5910
5912
 
5911
5913
  // src/hooks/useCanvasContext.ts
5912
- var import_react26 = require("react");
5914
+ var import_react27 = require("react");
5913
5915
 
5914
5916
  // src/patterns/RealtimeProvider.tsx
5915
- var import_react24 = require("react");
5916
- var import_react25 = require("@snowcone-app/sdk/react");
5917
+ var import_react25 = require("react");
5918
+ var import_react26 = require("@snowcone-app/sdk/react");
5917
5919
  var import_sdk8 = require("@snowcone-app/sdk");
5920
+
5921
+ // src/patterns/MockupBackground.tsx
5922
+ var import_react24 = require("react");
5918
5923
  var import_jsx_runtime51 = require("react/jsx-runtime");
5924
+ var MockupBackgroundContext = (0, import_react24.createContext)(void 0);
5925
+ function MockupBackground({ bg, children }) {
5926
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(MockupBackgroundContext.Provider, { value: bg, children });
5927
+ }
5928
+ function useMockupBackgroundOptional() {
5929
+ return (0, import_react24.useContext)(MockupBackgroundContext);
5930
+ }
5931
+
5932
+ // src/patterns/RealtimeProvider.tsx
5933
+ var import_jsx_runtime52 = require("react/jsx-runtime");
5919
5934
  var DEFAULT_ARTBOARD_SIZE = 2e3;
5920
5935
  var MAX_CONCURRENT_BLOBS = 5;
5921
- var RealtimeContext = (0, import_react24.createContext)(
5936
+ var RealtimeContext = (0, import_react25.createContext)(
5922
5937
  void 0
5923
5938
  );
5924
5939
  function RealtimeProvider({
@@ -5932,9 +5947,10 @@ function RealtimeProvider({
5932
5947
  grantUrl
5933
5948
  }) {
5934
5949
  const productContext = useProductOptional();
5935
- const [isEnabled, setIsEnabled] = (0, import_react24.useState)(autoEnable);
5950
+ const mockupBg = useMockupBackgroundOptional();
5951
+ const [isEnabled, setIsEnabled] = (0, import_react25.useState)(autoEnable);
5936
5952
  const useSessionGrant = Boolean(shop && grantUrl);
5937
- const getToken = (0, import_react24.useCallback)(async () => {
5953
+ const getToken = (0, import_react25.useCallback)(async () => {
5938
5954
  const res = await fetch(grantUrl, {
5939
5955
  method: "POST",
5940
5956
  headers: { "Content-Type": "application/json" },
@@ -5945,15 +5961,16 @@ function RealtimeProvider({
5945
5961
  }
5946
5962
  return await res.json();
5947
5963
  }, [shop, grantUrl]);
5948
- const canvasBlobsSentRef = (0, import_react24.useRef)(0);
5949
- const colorBlobsSentRef = (0, import_react24.useRef)(0);
5950
- const lastBlobSentTimeRef = (0, import_react24.useRef)(null);
5951
- const isPendingMockupsRef = (0, import_react24.useRef)(false);
5952
- const configSentRef = (0, import_react24.useRef)(false);
5953
- const placementSettingsOverridesRef = (0, import_react24.useRef)({});
5954
- const lastSentVariantIdRef = (0, import_react24.useRef)(null);
5955
- const lastSentColorsRef = (0, import_react24.useRef)({});
5956
- const realtimeMockup = (0, import_react25.useRealtimeMockup)({
5964
+ const canvasBlobsSentRef = (0, import_react25.useRef)(0);
5965
+ const colorBlobsSentRef = (0, import_react25.useRef)(0);
5966
+ const lastBlobSentTimeRef = (0, import_react25.useRef)(null);
5967
+ const isPendingMockupsRef = (0, import_react25.useRef)(false);
5968
+ const configSentRef = (0, import_react25.useRef)(false);
5969
+ const placementSettingsOverridesRef = (0, import_react25.useRef)({});
5970
+ const lastSentVariantIdRef = (0, import_react25.useRef)(null);
5971
+ const lastSentBgRef = (0, import_react25.useRef)(void 0);
5972
+ const lastSentColorsRef = (0, import_react25.useRef)({});
5973
+ const realtimeMockup = (0, import_react26.useRealtimeMockup)({
5957
5974
  wsUrl,
5958
5975
  getToken: useSessionGrant ? getToken : void 0,
5959
5976
  onConnected: (sessionId) => {
@@ -5984,7 +6001,7 @@ function RealtimeProvider({
5984
6001
  console.error(`[RealtimeProvider] Render error [${detail.code}]:`, error);
5985
6002
  }
5986
6003
  });
5987
- const subscribeRTCTiming = (0, import_react24.useCallback)((_callback) => {
6004
+ const subscribeRTCTiming = (0, import_react25.useCallback)((_callback) => {
5988
6005
  return () => {
5989
6006
  };
5990
6007
  }, []);
@@ -6004,31 +6021,31 @@ function RealtimeProvider({
6004
6021
  flushPendingBlobs,
6005
6022
  hasPendingBlobs
6006
6023
  } = realtimeMockup;
6007
- const mockupResultsRef = (0, import_react24.useRef)([]);
6008
- const mockupSubscribersRef = (0, import_react24.useRef)(
6024
+ const mockupResultsRef = (0, import_react25.useRef)([]);
6025
+ const mockupSubscribersRef = (0, import_react25.useRef)(
6009
6026
  /* @__PURE__ */ new Set()
6010
6027
  );
6011
- const mockupSubscribersByIdRef = (0, import_react24.useRef)(/* @__PURE__ */ new Map());
6012
- const pendingExportCancelledSubscribersRef = (0, import_react24.useRef)(/* @__PURE__ */ new Set());
6013
- const pendingBlobSubscribersRef = (0, import_react24.useRef)(
6028
+ const mockupSubscribersByIdRef = (0, import_react25.useRef)(/* @__PURE__ */ new Map());
6029
+ const pendingExportCancelledSubscribersRef = (0, import_react25.useRef)(/* @__PURE__ */ new Set());
6030
+ const pendingBlobSubscribersRef = (0, import_react25.useRef)(
6014
6031
  /* @__PURE__ */ new Set()
6015
6032
  );
6016
- const blobReceivedSubscribersRef = (0, import_react24.useRef)(
6033
+ const blobReceivedSubscribersRef = (0, import_react25.useRef)(
6017
6034
  /* @__PURE__ */ new Set()
6018
6035
  );
6019
- const blobSentSubscribersRef = (0, import_react24.useRef)(
6036
+ const blobSentSubscribersRef = (0, import_react25.useRef)(
6020
6037
  /* @__PURE__ */ new Set()
6021
6038
  );
6022
- const pipelineSettledSubscribersRef = (0, import_react24.useRef)(/* @__PURE__ */ new Set());
6023
- const pipelineGenRef = (0, import_react24.useRef)(0);
6024
- const blobQueuedGenRef = (0, import_react24.useRef)(0);
6025
- const hasBlobInFlightRef = (0, import_react24.useRef)(false);
6026
- const pipelineResetCooldownRef = (0, import_react24.useRef)(false);
6027
- const mockupUrlCacheRef = (0, import_react24.useRef)(/* @__PURE__ */ new Map());
6028
- const registeredBlobUrlsRef = (0, import_react24.useRef)(/* @__PURE__ */ new Set());
6029
- const pendingPlacementsRef = (0, import_react24.useRef)(/* @__PURE__ */ new Set());
6030
- const pendingMockupIdsRef = (0, import_react24.useRef)(/* @__PURE__ */ new Set());
6031
- (0, import_react24.useEffect)(() => {
6039
+ const pipelineSettledSubscribersRef = (0, import_react25.useRef)(/* @__PURE__ */ new Set());
6040
+ const pipelineGenRef = (0, import_react25.useRef)(0);
6041
+ const blobQueuedGenRef = (0, import_react25.useRef)(0);
6042
+ const hasBlobInFlightRef = (0, import_react25.useRef)(false);
6043
+ const pipelineResetCooldownRef = (0, import_react25.useRef)(false);
6044
+ const mockupUrlCacheRef = (0, import_react25.useRef)(/* @__PURE__ */ new Map());
6045
+ const registeredBlobUrlsRef = (0, import_react25.useRef)(/* @__PURE__ */ new Set());
6046
+ const pendingPlacementsRef = (0, import_react25.useRef)(/* @__PURE__ */ new Set());
6047
+ const pendingMockupIdsRef = (0, import_react25.useRef)(/* @__PURE__ */ new Set());
6048
+ (0, import_react25.useEffect)(() => {
6032
6049
  if (rawMockupResults.length === 0) {
6033
6050
  if (mockupResultsRef.current.length > 0) {
6034
6051
  mockupResultsRef.current = [];
@@ -6080,7 +6097,7 @@ function RealtimeProvider({
6080
6097
  pipelineSettledSubscribersRef.current.forEach((cb) => cb());
6081
6098
  }
6082
6099
  }, [rawMockupResults]);
6083
- const sendCanvasBlob = (0, import_react24.useCallback)(
6100
+ const sendCanvasBlob = (0, import_react25.useCallback)(
6084
6101
  (placement, blob, mockupCount, baseThrottleMs) => {
6085
6102
  blobQueuedGenRef.current = pipelineGenRef.current;
6086
6103
  const result = sendCanvasBlobRaw(
@@ -6099,7 +6116,7 @@ function RealtimeProvider({
6099
6116
  },
6100
6117
  [sendCanvasBlobRaw]
6101
6118
  );
6102
- const sendCanvasState = (0, import_react24.useCallback)(
6119
+ const sendCanvasState = (0, import_react25.useCallback)(
6103
6120
  (placement, state, mockupCount, baseThrottleMs) => {
6104
6121
  blobQueuedGenRef.current = pipelineGenRef.current;
6105
6122
  const result = sendCanvasStateRaw(
@@ -6118,7 +6135,7 @@ function RealtimeProvider({
6118
6135
  },
6119
6136
  [sendCanvasStateRaw]
6120
6137
  );
6121
- const sendColorBlobTracked = (0, import_react24.useCallback)(
6138
+ const sendColorBlobTracked = (0, import_react25.useCallback)(
6122
6139
  (placement, color) => {
6123
6140
  const result = sendColorBlob(placement, color);
6124
6141
  if (result) {
@@ -6130,23 +6147,24 @@ function RealtimeProvider({
6130
6147
  },
6131
6148
  [sendColorBlob]
6132
6149
  );
6133
- (0, import_react24.useEffect)(() => {
6150
+ (0, import_react25.useEffect)(() => {
6134
6151
  if (isEnabled) {
6135
6152
  connect();
6136
6153
  return () => {
6137
6154
  disconnect();
6138
6155
  configSentRef.current = false;
6139
6156
  lastSentVariantIdRef.current = null;
6157
+ lastSentBgRef.current = void 0;
6140
6158
  lastSentColorsRef.current = {};
6141
6159
  };
6142
6160
  }
6143
6161
  }, [isEnabled, connect, disconnect, wsUrl]);
6144
- (0, import_react24.useEffect)(() => {
6162
+ (0, import_react25.useEffect)(() => {
6145
6163
  if (rawMockupResults.length > 0 && isPendingMockupsRef.current) {
6146
6164
  isPendingMockupsRef.current = false;
6147
6165
  }
6148
6166
  }, [rawMockupResults.length]);
6149
- (0, import_react24.useEffect)(() => {
6167
+ (0, import_react25.useEffect)(() => {
6150
6168
  if (!isEnabled || !isConnected || !productContext?.product) return;
6151
6169
  const product = productContext.product;
6152
6170
  const productId = product.id;
@@ -6158,7 +6176,8 @@ function RealtimeProvider({
6158
6176
  );
6159
6177
  const isFirstSend = !configSentRef.current;
6160
6178
  const variantChanged = lastSentVariantIdRef.current !== null && lastSentVariantIdRef.current !== variantId;
6161
- if (!isFirstSend && !variantChanged) {
6179
+ const bgChanged = configSentRef.current && lastSentBgRef.current !== mockupBg;
6180
+ if (!isFirstSend && !variantChanged && !bgChanged) {
6162
6181
  return;
6163
6182
  }
6164
6183
  const mockupIds = [];
@@ -6175,6 +6194,7 @@ function RealtimeProvider({
6175
6194
  variantId,
6176
6195
  shop,
6177
6196
  width: mockupWidth,
6197
+ ...mockupBg ? { bg: mockupBg } : {},
6178
6198
  placementSettings: { ...placementSettingsOverridesRef.current }
6179
6199
  } : {
6180
6200
  productId,
@@ -6183,6 +6203,7 @@ function RealtimeProvider({
6183
6203
  shop: "hTidnpNnNa",
6184
6204
  seal: "bypass-sig-for-k6-load-test",
6185
6205
  width: mockupWidth,
6206
+ ...mockupBg ? { bg: mockupBg } : {},
6186
6207
  placementSettings: { ...placementSettingsOverridesRef.current }
6187
6208
  };
6188
6209
  if (variantChanged) {
@@ -6194,6 +6215,7 @@ function RealtimeProvider({
6194
6215
  sendConfigRaw(configPayload);
6195
6216
  configSentRef.current = true;
6196
6217
  lastSentVariantIdRef.current = variantId;
6218
+ lastSentBgRef.current = mockupBg;
6197
6219
  setTimeout(() => {
6198
6220
  const colorPlacements = placements.filter((p) => p.type === "color");
6199
6221
  colorPlacements.forEach((p) => {
@@ -6211,9 +6233,10 @@ function RealtimeProvider({
6211
6233
  productContext?.selection,
6212
6234
  sendConfigRaw,
6213
6235
  sendColorBlobTracked,
6214
- mockupWidth
6236
+ mockupWidth,
6237
+ mockupBg
6215
6238
  ]);
6216
- (0, import_react24.useEffect)(() => {
6239
+ (0, import_react25.useEffect)(() => {
6217
6240
  if (!isEnabled || !isConnected || !isConfigured || !productContext?.product)
6218
6241
  return;
6219
6242
  const placements = productContext.product.placements || [];
@@ -6238,20 +6261,20 @@ function RealtimeProvider({
6238
6261
  productContext?.selection,
6239
6262
  sendColorBlobTracked
6240
6263
  ]);
6241
- const updatePlacementSettingsWrapped = (0, import_react24.useCallback)(
6264
+ const updatePlacementSettingsWrapped = (0, import_react25.useCallback)(
6242
6265
  (settings) => {
6243
6266
  placementSettingsOverridesRef.current = settings;
6244
6267
  return updatePlacementSettingsRaw(settings);
6245
6268
  },
6246
6269
  [updatePlacementSettingsRaw]
6247
6270
  );
6248
- const enableRealtime = (0, import_react24.useCallback)(() => {
6271
+ const enableRealtime = (0, import_react25.useCallback)(() => {
6249
6272
  setIsEnabled(true);
6250
6273
  }, []);
6251
- const disableRealtime = (0, import_react24.useCallback)(() => {
6274
+ const disableRealtime = (0, import_react25.useCallback)(() => {
6252
6275
  setIsEnabled(false);
6253
6276
  }, []);
6254
- const placementDimensions = (0, import_react24.useMemo)(() => {
6277
+ const placementDimensions = (0, import_react25.useMemo)(() => {
6255
6278
  if (!productContext?.product?.placements) return [];
6256
6279
  return productContext.product.placements.map((p) => ({
6257
6280
  label: p.label,
@@ -6260,14 +6283,14 @@ function RealtimeProvider({
6260
6283
  type: p.type || "image"
6261
6284
  }));
6262
6285
  }, [productContext?.product?.placements]);
6263
- const canvasExportSize = (0, import_react24.useMemo)(() => {
6286
+ const canvasExportSize = (0, import_react25.useMemo)(() => {
6264
6287
  const firstPlacement = productContext?.product?.placements?.[0];
6265
6288
  if (firstPlacement?.width && firstPlacement?.height) {
6266
6289
  return { width: firstPlacement.width, height: firstPlacement.height };
6267
6290
  }
6268
6291
  return { width: DEFAULT_ARTBOARD_SIZE, height: DEFAULT_ARTBOARD_SIZE };
6269
6292
  }, [productContext?.product?.placements]);
6270
- const subscribeMockupResults = (0, import_react24.useCallback)(
6293
+ const subscribeMockupResults = (0, import_react25.useCallback)(
6271
6294
  (callback) => {
6272
6295
  mockupSubscribersRef.current.add(callback);
6273
6296
  return () => {
@@ -6276,7 +6299,7 @@ function RealtimeProvider({
6276
6299
  },
6277
6300
  []
6278
6301
  );
6279
- const subscribeMockupResultById = (0, import_react24.useCallback)(
6302
+ const subscribeMockupResultById = (0, import_react25.useCallback)(
6280
6303
  (mockupId, callback) => {
6281
6304
  if (!mockupSubscribersByIdRef.current.has(mockupId)) {
6282
6305
  mockupSubscribersByIdRef.current.set(mockupId, /* @__PURE__ */ new Set());
@@ -6303,7 +6326,7 @@ function RealtimeProvider({
6303
6326
  },
6304
6327
  []
6305
6328
  );
6306
- const subscribePendingBlob = (0, import_react24.useCallback)(
6329
+ const subscribePendingBlob = (0, import_react25.useCallback)(
6307
6330
  (callback) => {
6308
6331
  pendingBlobSubscribersRef.current.add(callback);
6309
6332
  return () => {
@@ -6312,7 +6335,7 @@ function RealtimeProvider({
6312
6335
  },
6313
6336
  []
6314
6337
  );
6315
- const subscribePendingExportCancelled = (0, import_react24.useCallback)(
6338
+ const subscribePendingExportCancelled = (0, import_react25.useCallback)(
6316
6339
  (callback) => {
6317
6340
  pendingExportCancelledSubscribersRef.current.add(callback);
6318
6341
  return () => {
@@ -6321,7 +6344,7 @@ function RealtimeProvider({
6321
6344
  },
6322
6345
  []
6323
6346
  );
6324
- const subscribeBlobReceived = (0, import_react24.useCallback)(
6347
+ const subscribeBlobReceived = (0, import_react25.useCallback)(
6325
6348
  (callback) => {
6326
6349
  blobReceivedSubscribersRef.current.add(callback);
6327
6350
  return () => {
@@ -6330,7 +6353,7 @@ function RealtimeProvider({
6330
6353
  },
6331
6354
  []
6332
6355
  );
6333
- const subscribeBlobSent = (0, import_react24.useCallback)(
6356
+ const subscribeBlobSent = (0, import_react25.useCallback)(
6334
6357
  (callback) => {
6335
6358
  blobSentSubscribersRef.current.add(callback);
6336
6359
  return () => {
@@ -6339,7 +6362,7 @@ function RealtimeProvider({
6339
6362
  },
6340
6363
  []
6341
6364
  );
6342
- const subscribePipelineSettled = (0, import_react24.useCallback)(
6365
+ const subscribePipelineSettled = (0, import_react25.useCallback)(
6343
6366
  (callback) => {
6344
6367
  pipelineSettledSubscribersRef.current.add(callback);
6345
6368
  return () => {
@@ -6348,7 +6371,7 @@ function RealtimeProvider({
6348
6371
  },
6349
6372
  []
6350
6373
  );
6351
- const resetPipelineSettled = (0, import_react24.useCallback)(
6374
+ const resetPipelineSettled = (0, import_react25.useCallback)(
6352
6375
  () => {
6353
6376
  pipelineGenRef.current++;
6354
6377
  hasBlobInFlightRef.current = false;
@@ -6359,7 +6382,7 @@ function RealtimeProvider({
6359
6382
  },
6360
6383
  []
6361
6384
  );
6362
- const notifyPendingExport = (0, import_react24.useCallback)(
6385
+ const notifyPendingExport = (0, import_react25.useCallback)(
6363
6386
  (placement) => {
6364
6387
  if (pendingPlacementsRef.current.has(placement)) {
6365
6388
  return;
@@ -6379,7 +6402,7 @@ function RealtimeProvider({
6379
6402
  },
6380
6403
  [productContext?.product?.mockups]
6381
6404
  );
6382
- const notifyPendingExportCancelled = (0, import_react24.useCallback)(
6405
+ const notifyPendingExportCancelled = (0, import_react25.useCallback)(
6383
6406
  (placement) => {
6384
6407
  if (!pendingPlacementsRef.current.has(placement)) {
6385
6408
  return;
@@ -6403,7 +6426,7 @@ function RealtimeProvider({
6403
6426
  },
6404
6427
  [productContext?.product?.mockups]
6405
6428
  );
6406
- const getMockupUrl3 = (0, import_react24.useCallback)((mockupId) => {
6429
+ const getMockupUrl3 = (0, import_react25.useCallback)((mockupId) => {
6407
6430
  if (pendingMockupIdsRef.current.has(mockupId)) {
6408
6431
  console.log(`[RTP] getMockupUrl("${mockupId}") \u2192 null (pending)`);
6409
6432
  return null;
@@ -6411,7 +6434,7 @@ function RealtimeProvider({
6411
6434
  const cached = mockupUrlCacheRef.current.get(mockupId);
6412
6435
  return cached?.url ?? null;
6413
6436
  }, []);
6414
- const getMockupUrls = (0, import_react24.useCallback)((mockupIds) => {
6437
+ const getMockupUrls = (0, import_react25.useCallback)((mockupIds) => {
6415
6438
  const result = {};
6416
6439
  for (const mockupId of mockupIds) {
6417
6440
  if (pendingMockupIdsRef.current.has(mockupId)) {
@@ -6423,10 +6446,10 @@ function RealtimeProvider({
6423
6446
  }
6424
6447
  return result;
6425
6448
  }, []);
6426
- const isMockupLoading = (0, import_react24.useCallback)((mockupId) => {
6449
+ const isMockupLoading = (0, import_react25.useCallback)((mockupId) => {
6427
6450
  return pendingMockupIdsRef.current.has(mockupId);
6428
6451
  }, []);
6429
- const registerBlobUrl = (0, import_react24.useCallback)((blobOrUrl, placementName) => {
6452
+ const registerBlobUrl = (0, import_react25.useCallback)((blobOrUrl, placementName) => {
6430
6453
  let url;
6431
6454
  if (blobOrUrl instanceof Blob) {
6432
6455
  if (registeredBlobUrlsRef.current.size >= MAX_CONCURRENT_BLOBS) {
@@ -6448,13 +6471,13 @@ function RealtimeProvider({
6448
6471
  }
6449
6472
  return url;
6450
6473
  }, []);
6451
- const subscribeMockupResultsRef = (0, import_react24.useRef)(subscribeMockupResults);
6452
- const subscribeMockupResultByIdRef = (0, import_react24.useRef)(subscribeMockupResultById);
6453
- const subscribePendingBlobRef = (0, import_react24.useRef)(subscribePendingBlob);
6454
- const subscribeBlobReceivedRef = (0, import_react24.useRef)(subscribeBlobReceived);
6455
- const subscribeBlobSentRef = (0, import_react24.useRef)(subscribeBlobSent);
6456
- const subscribePipelineSettledRef = (0, import_react24.useRef)(subscribePipelineSettled);
6457
- const subscribePendingExportCancelledRef = (0, import_react24.useRef)(
6474
+ const subscribeMockupResultsRef = (0, import_react25.useRef)(subscribeMockupResults);
6475
+ const subscribeMockupResultByIdRef = (0, import_react25.useRef)(subscribeMockupResultById);
6476
+ const subscribePendingBlobRef = (0, import_react25.useRef)(subscribePendingBlob);
6477
+ const subscribeBlobReceivedRef = (0, import_react25.useRef)(subscribeBlobReceived);
6478
+ const subscribeBlobSentRef = (0, import_react25.useRef)(subscribeBlobSent);
6479
+ const subscribePipelineSettledRef = (0, import_react25.useRef)(subscribePipelineSettled);
6480
+ const subscribePendingExportCancelledRef = (0, import_react25.useRef)(
6458
6481
  subscribePendingExportCancelled
6459
6482
  );
6460
6483
  subscribeMockupResultsRef.current = subscribeMockupResults;
@@ -6464,49 +6487,49 @@ function RealtimeProvider({
6464
6487
  subscribeBlobSentRef.current = subscribeBlobSent;
6465
6488
  subscribePipelineSettledRef.current = subscribePipelineSettled;
6466
6489
  subscribePendingExportCancelledRef.current = subscribePendingExportCancelled;
6467
- const stableSubscribeMockupResults = (0, import_react24.useCallback)(
6490
+ const stableSubscribeMockupResults = (0, import_react25.useCallback)(
6468
6491
  (callback) => {
6469
6492
  return subscribeMockupResultsRef.current(callback);
6470
6493
  },
6471
6494
  []
6472
6495
  );
6473
- const stableSubscribeMockupResultById = (0, import_react24.useCallback)(
6496
+ const stableSubscribeMockupResultById = (0, import_react25.useCallback)(
6474
6497
  (mockupId, callback) => {
6475
6498
  return subscribeMockupResultByIdRef.current(mockupId, callback);
6476
6499
  },
6477
6500
  []
6478
6501
  );
6479
- const stableSubscribePendingBlob = (0, import_react24.useCallback)(
6502
+ const stableSubscribePendingBlob = (0, import_react25.useCallback)(
6480
6503
  (callback) => {
6481
6504
  return subscribePendingBlobRef.current(callback);
6482
6505
  },
6483
6506
  []
6484
6507
  );
6485
- const stableSubscribePendingExportCancelled = (0, import_react24.useCallback)(
6508
+ const stableSubscribePendingExportCancelled = (0, import_react25.useCallback)(
6486
6509
  (callback) => {
6487
6510
  return subscribePendingExportCancelledRef.current(callback);
6488
6511
  },
6489
6512
  []
6490
6513
  );
6491
- const stableSubscribeBlobReceived = (0, import_react24.useCallback)(
6514
+ const stableSubscribeBlobReceived = (0, import_react25.useCallback)(
6492
6515
  (callback) => {
6493
6516
  return subscribeBlobReceivedRef.current(callback);
6494
6517
  },
6495
6518
  []
6496
6519
  );
6497
- const stableSubscribeBlobSent = (0, import_react24.useCallback)(
6520
+ const stableSubscribeBlobSent = (0, import_react25.useCallback)(
6498
6521
  (callback) => {
6499
6522
  return subscribeBlobSentRef.current(callback);
6500
6523
  },
6501
6524
  []
6502
6525
  );
6503
- const stableSubscribePipelineSettled = (0, import_react24.useCallback)(
6526
+ const stableSubscribePipelineSettled = (0, import_react25.useCallback)(
6504
6527
  (callback) => {
6505
6528
  return subscribePipelineSettledRef.current(callback);
6506
6529
  },
6507
6530
  []
6508
6531
  );
6509
- const contextValue = (0, import_react24.useMemo)(
6532
+ const contextValue = (0, import_react25.useMemo)(
6510
6533
  () => ({
6511
6534
  isEnabled,
6512
6535
  isConnected,
@@ -6579,31 +6602,31 @@ function RealtimeProvider({
6579
6602
  registerBlobUrl
6580
6603
  ]
6581
6604
  );
6582
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RealtimeContext.Provider, { value: contextValue, children });
6605
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(RealtimeContext.Provider, { value: contextValue, children });
6583
6606
  }
6584
6607
  function useRealtime() {
6585
- const context = (0, import_react24.useContext)(RealtimeContext);
6608
+ const context = (0, import_react25.useContext)(RealtimeContext);
6586
6609
  if (!context) {
6587
6610
  throw new Error("useRealtime must be used within a RealtimeProvider");
6588
6611
  }
6589
6612
  return context;
6590
6613
  }
6591
6614
  function useRealtimeOptional() {
6592
- return (0, import_react24.useContext)(RealtimeContext);
6615
+ return (0, import_react25.useContext)(RealtimeContext);
6593
6616
  }
6594
6617
 
6595
6618
  // src/hooks/useCanvasContext.ts
6596
6619
  function useCanvasContext() {
6597
6620
  const context = useProductOptional();
6598
6621
  const realtimeContext = useRealtimeOptional();
6599
- const sendCanvasBlobRef = (0, import_react26.useRef)(realtimeContext?.sendCanvasBlob);
6600
- const isRealtimeEnabledRef = (0, import_react26.useRef)(realtimeContext?.isEnabled ?? false);
6601
- const isConfiguredRef = (0, import_react26.useRef)(realtimeContext?.isConfigured ?? false);
6602
- const mockupCountRef = (0, import_react26.useRef)(context?.product?.mockups?.length ?? 1);
6603
- const selectedPlacementRef = (0, import_react26.useRef)(context?.selectedPlacement);
6604
- const enableRealtimeRef = (0, import_react26.useRef)(realtimeContext?.enableRealtime);
6605
- const selectedArtworkRef = (0, import_react26.useRef)(context?.selectedArtwork);
6606
- (0, import_react26.useEffect)(() => {
6622
+ const sendCanvasBlobRef = (0, import_react27.useRef)(realtimeContext?.sendCanvasBlob);
6623
+ const isRealtimeEnabledRef = (0, import_react27.useRef)(realtimeContext?.isEnabled ?? false);
6624
+ const isConfiguredRef = (0, import_react27.useRef)(realtimeContext?.isConfigured ?? false);
6625
+ const mockupCountRef = (0, import_react27.useRef)(context?.product?.mockups?.length ?? 1);
6626
+ const selectedPlacementRef = (0, import_react27.useRef)(context?.selectedPlacement);
6627
+ const enableRealtimeRef = (0, import_react27.useRef)(realtimeContext?.enableRealtime);
6628
+ const selectedArtworkRef = (0, import_react27.useRef)(context?.selectedArtwork);
6629
+ (0, import_react27.useEffect)(() => {
6607
6630
  sendCanvasBlobRef.current = realtimeContext?.sendCanvasBlob;
6608
6631
  isRealtimeEnabledRef.current = realtimeContext?.isEnabled ?? false;
6609
6632
  isConfiguredRef.current = realtimeContext?.isConfigured ?? false;
@@ -6612,7 +6635,7 @@ function useCanvasContext() {
6612
6635
  enableRealtimeRef.current = realtimeContext?.enableRealtime;
6613
6636
  selectedArtworkRef.current = context?.selectedArtwork;
6614
6637
  });
6615
- return (0, import_react26.useMemo)(() => ({
6638
+ return (0, import_react27.useMemo)(() => ({
6616
6639
  /** Ref to sendCanvasBlob function - call via sendCanvasBlobRef.current?.(...) */
6617
6640
  sendCanvasBlobRef,
6618
6641
  /** Ref to isRealtimeEnabled boolean */
@@ -6645,7 +6668,7 @@ function useCanvasContext() {
6645
6668
  function useCanvasContextStatic() {
6646
6669
  const context = useProductOptional();
6647
6670
  const realtimeContext = useRealtimeOptional();
6648
- const [staticValues] = (0, import_react26.useState)(() => ({
6671
+ const [staticValues] = (0, import_react27.useState)(() => ({
6649
6672
  sendCanvasBlob: realtimeContext?.sendCanvasBlob,
6650
6673
  isRealtimeEnabled: realtimeContext?.isEnabled ?? false,
6651
6674
  isConfigured: realtimeContext?.isConfigured ?? false,
@@ -6658,14 +6681,14 @@ function useCanvasContextStatic() {
6658
6681
  }
6659
6682
 
6660
6683
  // src/hooks/useRenderGuard.ts
6661
- var import_react27 = require("react");
6684
+ var import_react28 = require("react");
6662
6685
  function useRenderGuard({
6663
6686
  name,
6664
6687
  maxRendersPerSecond = 3,
6665
6688
  enabled = process.env.NODE_ENV === "development"
6666
6689
  }) {
6667
6690
  if (!enabled) return;
6668
- const timestampsRef = (0, import_react27.useRef)([]);
6691
+ const timestampsRef = (0, import_react28.useRef)([]);
6669
6692
  const now = performance.now();
6670
6693
  timestampsRef.current = timestampsRef.current.filter((t) => t > now - 1e3);
6671
6694
  timestampsRef.current.push(now);
@@ -6682,7 +6705,7 @@ function useRenderGuard({
6682
6705
  }
6683
6706
  }
6684
6707
  function useRenderCount(componentName) {
6685
- const countRef = (0, import_react27.useRef)(0);
6708
+ const countRef = (0, import_react28.useRef)(0);
6686
6709
  countRef.current++;
6687
6710
  if (process.env.NODE_ENV === "development" && componentName && countRef.current % 5 === 0) {
6688
6711
  }
@@ -6690,22 +6713,22 @@ function useRenderCount(componentName) {
6690
6713
  }
6691
6714
 
6692
6715
  // src/hooks/useScrollDirection.ts
6693
- var import_react28 = require("react");
6716
+ var import_react29 = require("react");
6694
6717
  var IDLE_TIMEOUT_MS = 150;
6695
6718
  var MIN_DELTA_PX = 5;
6696
6719
  function useScrollDirection() {
6697
- const [state, setState] = (0, import_react28.useState)({
6720
+ const [state, setState] = (0, import_react29.useState)({
6698
6721
  direction: "idle",
6699
6722
  velocity: 0,
6700
6723
  scrollY: typeof window !== "undefined" ? window.scrollY : 0
6701
6724
  });
6702
- const lastScrollRef = (0, import_react28.useRef)({
6725
+ const lastScrollRef = (0, import_react29.useRef)({
6703
6726
  top: typeof window !== "undefined" ? window.scrollY : 0,
6704
6727
  time: Date.now()
6705
6728
  });
6706
- const rafIdRef = (0, import_react28.useRef)(null);
6707
- const idleTimeoutRef = (0, import_react28.useRef)(null);
6708
- const handleScroll = (0, import_react28.useCallback)(() => {
6729
+ const rafIdRef = (0, import_react29.useRef)(null);
6730
+ const idleTimeoutRef = (0, import_react29.useRef)(null);
6731
+ const handleScroll = (0, import_react29.useCallback)(() => {
6709
6732
  if (rafIdRef.current !== null) return;
6710
6733
  rafIdRef.current = requestAnimationFrame(() => {
6711
6734
  const currentTop = window.scrollY;
@@ -6740,7 +6763,7 @@ function useScrollDirection() {
6740
6763
  rafIdRef.current = null;
6741
6764
  });
6742
6765
  }, []);
6743
- (0, import_react28.useEffect)(() => {
6766
+ (0, import_react29.useEffect)(() => {
6744
6767
  if (typeof window === "undefined") return;
6745
6768
  lastScrollRef.current = {
6746
6769
  top: window.scrollY,
@@ -6811,7 +6834,7 @@ function createScrollDirectionTracker() {
6811
6834
  }
6812
6835
 
6813
6836
  // src/hooks/useImageTransition.ts
6814
- var import_react29 = require("react");
6837
+ var import_react30 = require("react");
6815
6838
  var layerIdCounter = 0;
6816
6839
  function useImageTransition(options = {}) {
6817
6840
  const {
@@ -6821,7 +6844,7 @@ function useImageTransition(options = {}) {
6821
6844
  darkShimmerFadeInDuration = 300,
6822
6845
  initialUrl
6823
6846
  } = options;
6824
- const [state, setState] = (0, import_react29.useState)(() => {
6847
+ const [state, setState] = (0, import_react30.useState)(() => {
6825
6848
  return {
6826
6849
  layers: initialUrl ? [{ url: initialUrl, opacity: 1, id: ++layerIdCounter, loaded: true }] : [],
6827
6850
  preloadUrl: null,
@@ -6830,12 +6853,12 @@ function useImageTransition(options = {}) {
6830
6853
  shimmerType: "light"
6831
6854
  };
6832
6855
  });
6833
- const versionRef = (0, import_react29.useRef)(0);
6834
- const preloaderRef = (0, import_react29.useRef)(null);
6835
- const currentPreloadUrlRef = (0, import_react29.useRef)(null);
6836
- const shimmerTimerRef = (0, import_react29.useRef)(null);
6837
- const isMountedRef = (0, import_react29.useRef)(true);
6838
- (0, import_react29.useEffect)(() => {
6856
+ const versionRef = (0, import_react30.useRef)(0);
6857
+ const preloaderRef = (0, import_react30.useRef)(null);
6858
+ const currentPreloadUrlRef = (0, import_react30.useRef)(null);
6859
+ const shimmerTimerRef = (0, import_react30.useRef)(null);
6860
+ const isMountedRef = (0, import_react30.useRef)(true);
6861
+ (0, import_react30.useEffect)(() => {
6839
6862
  isMountedRef.current = true;
6840
6863
  return () => {
6841
6864
  isMountedRef.current = false;
@@ -6849,7 +6872,7 @@ function useImageTransition(options = {}) {
6849
6872
  }
6850
6873
  };
6851
6874
  }, []);
6852
- const setTargetUrl = (0, import_react29.useCallback)(
6875
+ const setTargetUrl = (0, import_react30.useCallback)(
6853
6876
  (url, shimmerType = "light") => {
6854
6877
  const version = ++versionRef.current;
6855
6878
  if (shimmerTimerRef.current) {
@@ -6967,7 +6990,7 @@ function useImageTransition(options = {}) {
6967
6990
  },
6968
6991
  [shimmerDelay]
6969
6992
  );
6970
- (0, import_react29.useEffect)(() => {
6993
+ (0, import_react30.useEffect)(() => {
6971
6994
  const topLayer = state.layers[state.layers.length - 1];
6972
6995
  if (topLayer && topLayer.opacity === 0 && !topLayer.waitForLoad) {
6973
6996
  const targetId = topLayer.id;
@@ -6987,7 +7010,7 @@ function useImageTransition(options = {}) {
6987
7010
  return () => cancelAnimationFrame(raf1);
6988
7011
  }
6989
7012
  }, [state.layers]);
6990
- (0, import_react29.useEffect)(() => {
7013
+ (0, import_react30.useEffect)(() => {
6991
7014
  if (state.showShimmer && state.shimmerOpacity === 0 && state.preloadUrl) {
6992
7015
  const raf = requestAnimationFrame(() => {
6993
7016
  if (!isMountedRef.current) return;
@@ -7002,7 +7025,7 @@ function useImageTransition(options = {}) {
7002
7025
  return () => cancelAnimationFrame(raf);
7003
7026
  }
7004
7027
  }, [state.showShimmer, state.shimmerOpacity, state.preloadUrl]);
7005
- (0, import_react29.useEffect)(() => {
7028
+ (0, import_react30.useEffect)(() => {
7006
7029
  if (state.showShimmer && state.shimmerOpacity === 0 && !state.preloadUrl) {
7007
7030
  const duration = state.shimmerType === "dark" ? fadeDuration : shimmerFadeDuration;
7008
7031
  const timer = setTimeout(() => {
@@ -7011,7 +7034,7 @@ function useImageTransition(options = {}) {
7011
7034
  return () => clearTimeout(timer);
7012
7035
  }
7013
7036
  }, [state.showShimmer, state.shimmerOpacity, state.preloadUrl, state.shimmerType, fadeDuration, shimmerFadeDuration]);
7014
- const onLayerTransitionEnd = (0, import_react29.useCallback)((layerId) => {
7037
+ const onLayerTransitionEnd = (0, import_react30.useCallback)((layerId) => {
7015
7038
  setState((prev) => {
7016
7039
  const idx = prev.layers.findIndex((l) => l.id === layerId);
7017
7040
  if (idx === -1 || prev.layers[idx].opacity !== 1) return prev;
@@ -7025,11 +7048,11 @@ function useImageTransition(options = {}) {
7025
7048
  return prev;
7026
7049
  });
7027
7050
  }, []);
7028
- const onPreloadComplete = (0, import_react29.useCallback)((_loadedUrl) => {
7051
+ const onPreloadComplete = (0, import_react30.useCallback)((_loadedUrl) => {
7029
7052
  }, []);
7030
- const onPreloadError = (0, import_react29.useCallback)(() => {
7053
+ const onPreloadError = (0, import_react30.useCallback)(() => {
7031
7054
  }, []);
7032
- const addLayerDirectly = (0, import_react29.useCallback)((url, options2) => {
7055
+ const addLayerDirectly = (0, import_react30.useCallback)((url, options2) => {
7033
7056
  const shouldShowShimmer = options2?.showShimmer ?? true;
7034
7057
  const skipTransition = options2?.skipTransition ?? false;
7035
7058
  const currentVersion = ++versionRef.current;
@@ -7120,7 +7143,7 @@ function useImageTransition(options = {}) {
7120
7143
  }, 500);
7121
7144
  }
7122
7145
  }, []);
7123
- const triggerShimmer = (0, import_react29.useCallback)((type = "dark") => {
7146
+ const triggerShimmer = (0, import_react30.useCallback)((type = "dark") => {
7124
7147
  setState((prev) => {
7125
7148
  if (prev.layers.length === 0) {
7126
7149
  return prev;
@@ -7139,7 +7162,7 @@ function useImageTransition(options = {}) {
7139
7162
  };
7140
7163
  });
7141
7164
  }, []);
7142
- const onImageLoad = (0, import_react29.useCallback)((layerId) => {
7165
+ const onImageLoad = (0, import_react30.useCallback)((layerId) => {
7143
7166
  if (shimmerTimerRef.current) {
7144
7167
  clearTimeout(shimmerTimerRef.current);
7145
7168
  shimmerTimerRef.current = null;
@@ -7181,7 +7204,7 @@ function useImageTransition(options = {}) {
7181
7204
  }
7182
7205
 
7183
7206
  // src/hooks/useImagePreloader.ts
7184
- var import_react30 = require("react");
7207
+ var import_react31 = require("react");
7185
7208
 
7186
7209
  // src/hooks/visibility/observerPool.ts
7187
7210
  var observerCallbacks = /* @__PURE__ */ new WeakMap();
@@ -7243,12 +7266,12 @@ function getObservedElementCount() {
7243
7266
  // src/hooks/useImagePreloader.ts
7244
7267
  function useImagePreloader(options = {}) {
7245
7268
  const { preloadMargin = 1e3, maxConcurrent = 2 } = options;
7246
- const [preloadedUrls, setPreloadedUrls] = (0, import_react30.useState)(/* @__PURE__ */ new Set());
7247
- const entriesRef = (0, import_react30.useRef)(/* @__PURE__ */ new Map());
7248
- const preloadingCountRef = (0, import_react30.useRef)(0);
7249
- const preloadQueueRef = (0, import_react30.useRef)([]);
7250
- const preloadingUrlsRef = (0, import_react30.useRef)(/* @__PURE__ */ new Set());
7251
- const processQueue = (0, import_react30.useCallback)(() => {
7269
+ const [preloadedUrls, setPreloadedUrls] = (0, import_react31.useState)(/* @__PURE__ */ new Set());
7270
+ const entriesRef = (0, import_react31.useRef)(/* @__PURE__ */ new Map());
7271
+ const preloadingCountRef = (0, import_react31.useRef)(0);
7272
+ const preloadQueueRef = (0, import_react31.useRef)([]);
7273
+ const preloadingUrlsRef = (0, import_react31.useRef)(/* @__PURE__ */ new Set());
7274
+ const processQueue = (0, import_react31.useCallback)(() => {
7252
7275
  while (preloadingCountRef.current < maxConcurrent && preloadQueueRef.current.length > 0) {
7253
7276
  const src = preloadQueueRef.current.shift();
7254
7277
  if (preloadingUrlsRef.current.has(src) || preloadedUrls.has(src)) {
@@ -7273,17 +7296,17 @@ function useImagePreloader(options = {}) {
7273
7296
  img.onerror = handleComplete;
7274
7297
  }
7275
7298
  }, [maxConcurrent, preloadedUrls]);
7276
- const observerOptionsRef = (0, import_react30.useRef)({
7299
+ const observerOptionsRef = (0, import_react31.useRef)({
7277
7300
  rootMargin: `${preloadMargin}px 0px`,
7278
7301
  threshold: 0
7279
7302
  });
7280
- (0, import_react30.useEffect)(() => {
7303
+ (0, import_react31.useEffect)(() => {
7281
7304
  observerOptionsRef.current = {
7282
7305
  rootMargin: `${preloadMargin}px 0px`,
7283
7306
  threshold: 0
7284
7307
  };
7285
7308
  }, [preloadMargin]);
7286
- const registerElement = (0, import_react30.useCallback)(
7309
+ const registerElement = (0, import_react31.useCallback)(
7287
7310
  (key, element, src) => {
7288
7311
  const entries = entriesRef.current;
7289
7312
  const existingEntry = entries.get(key);
@@ -7347,14 +7370,14 @@ function useImagePreloader(options = {}) {
7347
7370
  },
7348
7371
  [preloadedUrls, processQueue]
7349
7372
  );
7350
- const isPreloaded = (0, import_react30.useCallback)(
7373
+ const isPreloaded = (0, import_react31.useCallback)(
7351
7374
  (src) => {
7352
7375
  if (!src) return false;
7353
7376
  return preloadedUrls.has(src);
7354
7377
  },
7355
7378
  [preloadedUrls]
7356
7379
  );
7357
- (0, import_react30.useEffect)(() => {
7380
+ (0, import_react31.useEffect)(() => {
7358
7381
  return () => {
7359
7382
  entriesRef.current.forEach((entry) => {
7360
7383
  if (entry.unobserve) {
@@ -7372,11 +7395,11 @@ function useImagePreloader(options = {}) {
7372
7395
  }
7373
7396
 
7374
7397
  // src/hooks/useDeviceDetection.ts
7375
- var import_react31 = require("react");
7398
+ var import_react32 = require("react");
7376
7399
  function useDeviceDetection() {
7377
- const [isTouchDevice, setIsTouchDevice] = (0, import_react31.useState)(false);
7378
- const [isSafari, setIsSafari] = (0, import_react31.useState)(false);
7379
- (0, import_react31.useEffect)(() => {
7400
+ const [isTouchDevice, setIsTouchDevice] = (0, import_react32.useState)(false);
7401
+ const [isSafari, setIsSafari] = (0, import_react32.useState)(false);
7402
+ (0, import_react32.useEffect)(() => {
7380
7403
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
7381
7404
  setIsTouchDevice(hasTouch);
7382
7405
  const userAgent = navigator.userAgent;
@@ -7395,51 +7418,51 @@ function useDeviceDetection() {
7395
7418
  }
7396
7419
 
7397
7420
  // src/hooks/useProductPage.ts
7398
- var import_react33 = require("react");
7421
+ var import_react34 = require("react");
7399
7422
 
7400
7423
  // src/patterns/MockupPriorityProvider.tsx
7401
- var import_react32 = require("react");
7402
- var import_jsx_runtime52 = require("react/jsx-runtime");
7424
+ var import_react33 = require("react");
7425
+ var import_jsx_runtime53 = require("react/jsx-runtime");
7403
7426
  var MAX_LEVEL3_PREFETCH = 5;
7404
7427
  var PRIORITY_RECALC_DEBOUNCE_MS = 50;
7405
7428
  var PRELOAD_MARGIN_PX = 750;
7406
- var MockupPriorityContext = (0, import_react32.createContext)(
7429
+ var MockupPriorityContext = (0, import_react33.createContext)(
7407
7430
  void 0
7408
7431
  );
7409
7432
  function MockupPriorityProvider({ children }) {
7410
- (0, import_react32.useEffect)(() => {
7433
+ (0, import_react33.useEffect)(() => {
7411
7434
  return () => {
7412
7435
  };
7413
7436
  }, []);
7414
- const visibilityMapRef = (0, import_react32.useRef)(/* @__PURE__ */ new Map());
7415
- const prioritiesRef = (0, import_react32.useRef)(/* @__PURE__ */ new Map());
7416
- const level1MockupRef = (0, import_react32.useRef)(null);
7417
- const level2MockupsRef = (0, import_react32.useRef)([]);
7418
- const level3QueueRef = (0, import_react32.useRef)([]);
7419
- const mobileCarouselRef = (0, import_react32.useRef)(null);
7420
- const registrationOrderRef = (0, import_react32.useRef)([]);
7421
- const elementRefsRef = (0, import_react32.useRef)(/* @__PURE__ */ new Map());
7422
- const prioritySubscribersRef = (0, import_react32.useRef)(
7437
+ const visibilityMapRef = (0, import_react33.useRef)(/* @__PURE__ */ new Map());
7438
+ const prioritiesRef = (0, import_react33.useRef)(/* @__PURE__ */ new Map());
7439
+ const level1MockupRef = (0, import_react33.useRef)(null);
7440
+ const level2MockupsRef = (0, import_react33.useRef)([]);
7441
+ const level3QueueRef = (0, import_react33.useRef)([]);
7442
+ const mobileCarouselRef = (0, import_react33.useRef)(null);
7443
+ const registrationOrderRef = (0, import_react33.useRef)([]);
7444
+ const elementRefsRef = (0, import_react33.useRef)(/* @__PURE__ */ new Map());
7445
+ const prioritySubscribersRef = (0, import_react33.useRef)(
7423
7446
  /* @__PURE__ */ new Map()
7424
7447
  );
7425
- const level1SubscribersRef = (0, import_react32.useRef)(
7448
+ const level1SubscribersRef = (0, import_react33.useRef)(
7426
7449
  /* @__PURE__ */ new Set()
7427
7450
  );
7428
7451
  const scrollState = useScrollDirection();
7429
- const scrollDirectionRef = (0, import_react32.useRef)("idle");
7452
+ const scrollDirectionRef = (0, import_react33.useRef)("idle");
7430
7453
  scrollDirectionRef.current = scrollState.direction;
7431
- const recalcTimeoutRef = (0, import_react32.useRef)(null);
7432
- const pendingRafRef = (0, import_react32.useRef)(null);
7433
- const [level1MockupId, setLevel1MockupId] = (0, import_react32.useState)(null);
7454
+ const recalcTimeoutRef = (0, import_react33.useRef)(null);
7455
+ const pendingRafRef = (0, import_react33.useRef)(null);
7456
+ const [level1MockupId, setLevel1MockupId] = (0, import_react33.useState)(null);
7434
7457
  const realtimeContext = useRealtimeOptional();
7435
- const currentRenderingLevelRef = (0, import_react32.useRef)(null);
7436
- const pendingMockupsRef = (0, import_react32.useRef)(/* @__PURE__ */ new Set());
7437
- const renderedMockupsRef = (0, import_react32.useRef)(/* @__PURE__ */ new Set());
7438
- const lastPendingBlobTimeRef = (0, import_react32.useRef)(0);
7458
+ const currentRenderingLevelRef = (0, import_react33.useRef)(null);
7459
+ const pendingMockupsRef = (0, import_react33.useRef)(/* @__PURE__ */ new Set());
7460
+ const renderedMockupsRef = (0, import_react33.useRef)(/* @__PURE__ */ new Set());
7461
+ const lastPendingBlobTimeRef = (0, import_react33.useRef)(0);
7439
7462
  const DRAG_STOP_DEBOUNCE_MS = 250;
7440
7463
  const BLOB_SEND_DELAY_MS = 100;
7441
- const pendingBlobRequestTimeoutRef = (0, import_react32.useRef)(null);
7442
- const requestMockupsForLevel = (0, import_react32.useCallback)((level) => {
7464
+ const pendingBlobRequestTimeoutRef = (0, import_react33.useRef)(null);
7465
+ const requestMockupsForLevel = (0, import_react33.useCallback)((level) => {
7443
7466
  if (!realtimeContext?.updateMockupIds) {
7444
7467
  return;
7445
7468
  }
@@ -7467,8 +7490,8 @@ function MockupPriorityProvider({ children }) {
7467
7490
  pendingMockupsRef.current = new Set(mockupIds);
7468
7491
  realtimeContext.updateMockupIds(mockupIds);
7469
7492
  }, [realtimeContext]);
7470
- const levelAdvanceTimeoutRef = (0, import_react32.useRef)(null);
7471
- const handleMockupResult = (0, import_react32.useCallback)((mockupId) => {
7493
+ const levelAdvanceTimeoutRef = (0, import_react33.useRef)(null);
7494
+ const handleMockupResult = (0, import_react33.useCallback)((mockupId) => {
7472
7495
  renderedMockupsRef.current.add(mockupId);
7473
7496
  pendingMockupsRef.current.delete(mockupId);
7474
7497
  const currentLevel = currentRenderingLevelRef.current;
@@ -7504,7 +7527,7 @@ function MockupPriorityProvider({ children }) {
7504
7527
  }
7505
7528
  }
7506
7529
  }, [requestMockupsForLevel]);
7507
- (0, import_react32.useEffect)(() => {
7530
+ (0, import_react33.useEffect)(() => {
7508
7531
  if (!realtimeContext?.subscribeMockupResults) return;
7509
7532
  const unsubscribe = realtimeContext.subscribeMockupResults((results) => {
7510
7533
  results.forEach((result) => {
@@ -7513,13 +7536,13 @@ function MockupPriorityProvider({ children }) {
7513
7536
  });
7514
7537
  return unsubscribe;
7515
7538
  }, [realtimeContext, handleMockupResult]);
7516
- (0, import_react32.useEffect)(() => {
7539
+ (0, import_react33.useEffect)(() => {
7517
7540
  if (realtimeContext?.isConfigured && level1MockupRef.current) {
7518
7541
  renderedMockupsRef.current.clear();
7519
7542
  requestMockupsForLevel(1);
7520
7543
  }
7521
7544
  }, [realtimeContext, requestMockupsForLevel]);
7522
- (0, import_react32.useEffect)(() => {
7545
+ (0, import_react33.useEffect)(() => {
7523
7546
  if (level1MockupId === null) {
7524
7547
  return;
7525
7548
  }
@@ -7529,7 +7552,7 @@ function MockupPriorityProvider({ children }) {
7529
7552
  renderedMockupsRef.current.clear();
7530
7553
  requestMockupsForLevel(1);
7531
7554
  }, [level1MockupId, realtimeContext?.isConfigured, requestMockupsForLevel]);
7532
- (0, import_react32.useEffect)(() => {
7555
+ (0, import_react33.useEffect)(() => {
7533
7556
  if (!realtimeContext?.subscribePendingBlob) return;
7534
7557
  const handlePendingBlob = (placement) => {
7535
7558
  lastPendingBlobTimeRef.current = Date.now();
@@ -7541,7 +7564,7 @@ function MockupPriorityProvider({ children }) {
7541
7564
  const unsubscribe = realtimeContext.subscribePendingBlob(handlePendingBlob);
7542
7565
  return unsubscribe;
7543
7566
  }, [realtimeContext]);
7544
- (0, import_react32.useEffect)(() => {
7567
+ (0, import_react33.useEffect)(() => {
7545
7568
  if (!realtimeContext?.subscribeBlobSent) return;
7546
7569
  const handleBlobSent = (placement) => {
7547
7570
  if (pendingBlobRequestTimeoutRef.current) {
@@ -7558,7 +7581,7 @@ function MockupPriorityProvider({ children }) {
7558
7581
  const unsubscribe = realtimeContext.subscribeBlobSent(handleBlobSent);
7559
7582
  return unsubscribe;
7560
7583
  }, [realtimeContext, requestMockupsForLevel]);
7561
- const recalculatePriorities = (0, import_react32.useCallback)(() => {
7584
+ const recalculatePriorities = (0, import_react33.useCallback)(() => {
7562
7585
  const mobileState = mobileCarouselRef.current;
7563
7586
  if (mobileState && mobileState.mockupIds.length > 0) {
7564
7587
  const { currentIndex, mockupIds } = mobileState;
@@ -7648,7 +7671,7 @@ function MockupPriorityProvider({ children }) {
7648
7671
  subscribers?.forEach((cb) => cb(newLevel));
7649
7672
  });
7650
7673
  }, []);
7651
- const scheduleRecalculation = (0, import_react32.useCallback)(() => {
7674
+ const scheduleRecalculation = (0, import_react33.useCallback)(() => {
7652
7675
  if (recalcTimeoutRef.current) {
7653
7676
  clearTimeout(recalcTimeoutRef.current);
7654
7677
  }
@@ -7657,7 +7680,7 @@ function MockupPriorityProvider({ children }) {
7657
7680
  recalcTimeoutRef.current = null;
7658
7681
  }, PRIORITY_RECALC_DEBOUNCE_MS);
7659
7682
  }, [recalculatePriorities]);
7660
- (0, import_react32.useEffect)(() => {
7683
+ (0, import_react33.useEffect)(() => {
7661
7684
  return () => {
7662
7685
  if (recalcTimeoutRef.current) {
7663
7686
  clearTimeout(recalcTimeoutRef.current);
@@ -7673,7 +7696,7 @@ function MockupPriorityProvider({ children }) {
7673
7696
  }
7674
7697
  };
7675
7698
  }, []);
7676
- const updateVisibilityFromRefs = (0, import_react32.useCallback)(() => {
7699
+ const updateVisibilityFromRefs = (0, import_react33.useCallback)(() => {
7677
7700
  const viewportHeight = typeof window !== "undefined" ? window.innerHeight : 800;
7678
7701
  const viewportWidth = typeof window !== "undefined" ? window.innerWidth : 1200;
7679
7702
  const viewportCenterY = viewportHeight / 2;
@@ -7714,7 +7737,7 @@ function MockupPriorityProvider({ children }) {
7714
7737
  });
7715
7738
  });
7716
7739
  }, []);
7717
- (0, import_react32.useEffect)(() => {
7740
+ (0, import_react33.useEffect)(() => {
7718
7741
  const pollVisibility = () => {
7719
7742
  updateVisibilityFromRefs();
7720
7743
  recalculatePriorities();
@@ -7727,7 +7750,7 @@ function MockupPriorityProvider({ children }) {
7727
7750
  window.removeEventListener("scroll", pollVisibility);
7728
7751
  };
7729
7752
  }, [updateVisibilityFromRefs, recalculatePriorities]);
7730
- const registerMockup = (0, import_react32.useCallback)(
7753
+ const registerMockup = (0, import_react33.useCallback)(
7731
7754
  (mockupId, placement, initialPriority, elementRef) => {
7732
7755
  if (!registrationOrderRef.current.includes(mockupId)) {
7733
7756
  registrationOrderRef.current.push(mockupId);
@@ -7776,7 +7799,7 @@ function MockupPriorityProvider({ children }) {
7776
7799
  },
7777
7800
  []
7778
7801
  );
7779
- const unregisterMockup = (0, import_react32.useCallback)((mockupId) => {
7802
+ const unregisterMockup = (0, import_react33.useCallback)((mockupId) => {
7780
7803
  visibilityMapRef.current.delete(mockupId);
7781
7804
  prioritiesRef.current.delete(mockupId);
7782
7805
  prioritySubscribersRef.current.delete(mockupId);
@@ -7791,7 +7814,7 @@ function MockupPriorityProvider({ children }) {
7791
7814
  scheduleRecalculation();
7792
7815
  }
7793
7816
  }, [scheduleRecalculation]);
7794
- const updateElementRef = (0, import_react32.useCallback)((mockupId, element) => {
7817
+ const updateElementRef = (0, import_react33.useCallback)((mockupId, element) => {
7795
7818
  if (element) {
7796
7819
  const rect = element.getBoundingClientRect();
7797
7820
  if (rect.height === 0 || rect.width === 0) {
@@ -7804,7 +7827,7 @@ function MockupPriorityProvider({ children }) {
7804
7827
  elementRefsRef.current.delete(mockupId);
7805
7828
  }
7806
7829
  }, [updateVisibilityFromRefs, scheduleRecalculation]);
7807
- const reportVisibility = (0, import_react32.useCallback)(
7830
+ const reportVisibility = (0, import_react33.useCallback)(
7808
7831
  (mockupId, ratio, boundingRect) => {
7809
7832
  const existing = visibilityMapRef.current.get(mockupId);
7810
7833
  if (!existing) {
@@ -7853,21 +7876,21 @@ function MockupPriorityProvider({ children }) {
7853
7876
  },
7854
7877
  [scheduleRecalculation, recalculatePriorities]
7855
7878
  );
7856
- const reportMobileCarouselIndex = (0, import_react32.useCallback)(
7879
+ const reportMobileCarouselIndex = (0, import_react33.useCallback)(
7857
7880
  (currentIndex, mockupIds) => {
7858
7881
  mobileCarouselRef.current = { currentIndex, mockupIds };
7859
7882
  recalculatePriorities();
7860
7883
  },
7861
7884
  [recalculatePriorities]
7862
7885
  );
7863
- const clearMobileCarouselMode = (0, import_react32.useCallback)(() => {
7886
+ const clearMobileCarouselMode = (0, import_react33.useCallback)(() => {
7864
7887
  mobileCarouselRef.current = null;
7865
7888
  recalculatePriorities();
7866
7889
  }, [recalculatePriorities]);
7867
- const getPriorityLevel = (0, import_react32.useCallback)((mockupId) => {
7890
+ const getPriorityLevel = (0, import_react33.useCallback)((mockupId) => {
7868
7891
  return prioritiesRef.current.get(mockupId) || 3;
7869
7892
  }, []);
7870
- const getQueuePriority = (0, import_react32.useCallback)((mockupId) => {
7893
+ const getQueuePriority = (0, import_react33.useCallback)((mockupId) => {
7871
7894
  const level = prioritiesRef.current.get(mockupId) || 3;
7872
7895
  switch (level) {
7873
7896
  case 1:
@@ -7880,19 +7903,19 @@ function MockupPriorityProvider({ children }) {
7880
7903
  return 10;
7881
7904
  }
7882
7905
  }, []);
7883
- const getLevel1Mockup = (0, import_react32.useCallback)(() => {
7906
+ const getLevel1Mockup = (0, import_react33.useCallback)(() => {
7884
7907
  return level1MockupRef.current;
7885
7908
  }, []);
7886
- const getLevel2Mockups = (0, import_react32.useCallback)(() => {
7909
+ const getLevel2Mockups = (0, import_react33.useCallback)(() => {
7887
7910
  return [...level2MockupsRef.current];
7888
7911
  }, []);
7889
- const getLevel3Queue = (0, import_react32.useCallback)(() => {
7912
+ const getLevel3Queue = (0, import_react33.useCallback)(() => {
7890
7913
  return [...level3QueueRef.current];
7891
7914
  }, []);
7892
- const getVisibility = (0, import_react32.useCallback)((mockupId) => {
7915
+ const getVisibility = (0, import_react33.useCallback)((mockupId) => {
7893
7916
  return visibilityMapRef.current.get(mockupId) || null;
7894
7917
  }, []);
7895
- const getMockupIdsForLevel = (0, import_react32.useCallback)((level) => {
7918
+ const getMockupIdsForLevel = (0, import_react33.useCallback)((level) => {
7896
7919
  switch (level) {
7897
7920
  case 1:
7898
7921
  return level1MockupRef.current ? [level1MockupRef.current] : [];
@@ -7904,16 +7927,16 @@ function MockupPriorityProvider({ children }) {
7904
7927
  return [];
7905
7928
  }
7906
7929
  }, []);
7907
- const shouldPauseLevel = (0, import_react32.useCallback)((level) => {
7930
+ const shouldPauseLevel = (0, import_react33.useCallback)((level) => {
7908
7931
  if (level === 2) {
7909
7932
  return level1MockupRef.current !== null;
7910
7933
  }
7911
7934
  return level1MockupRef.current !== null || level2MockupsRef.current.length > 0;
7912
7935
  }, []);
7913
- const isLevel1Active = (0, import_react32.useCallback)(() => {
7936
+ const isLevel1Active = (0, import_react33.useCallback)(() => {
7914
7937
  return level1MockupRef.current !== null;
7915
7938
  }, []);
7916
- const subscribePriorityChange = (0, import_react32.useCallback)(
7939
+ const subscribePriorityChange = (0, import_react33.useCallback)(
7917
7940
  (mockupId, callback) => {
7918
7941
  if (!prioritySubscribersRef.current.has(mockupId)) {
7919
7942
  prioritySubscribersRef.current.set(mockupId, /* @__PURE__ */ new Set());
@@ -7933,7 +7956,7 @@ function MockupPriorityProvider({ children }) {
7933
7956
  },
7934
7957
  []
7935
7958
  );
7936
- const subscribeLevel1Change = (0, import_react32.useCallback)(
7959
+ const subscribeLevel1Change = (0, import_react33.useCallback)(
7937
7960
  (callback) => {
7938
7961
  level1SubscribersRef.current.add(callback);
7939
7962
  callback(level1MockupRef.current);
@@ -7943,7 +7966,7 @@ function MockupPriorityProvider({ children }) {
7943
7966
  },
7944
7967
  []
7945
7968
  );
7946
- const contextValue = (0, import_react32.useMemo)(
7969
+ const contextValue = (0, import_react33.useMemo)(
7947
7970
  () => ({
7948
7971
  registerMockup,
7949
7972
  unregisterMockup,
@@ -7983,10 +8006,10 @@ function MockupPriorityProvider({ children }) {
7983
8006
  subscribeLevel1Change
7984
8007
  ]
7985
8008
  );
7986
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(MockupPriorityContext.Provider, { value: contextValue, children });
8009
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(MockupPriorityContext.Provider, { value: contextValue, children });
7987
8010
  }
7988
8011
  function useMockupPriority() {
7989
- const context = (0, import_react32.useContext)(MockupPriorityContext);
8012
+ const context = (0, import_react33.useContext)(MockupPriorityContext);
7990
8013
  if (!context) {
7991
8014
  throw new Error(
7992
8015
  "useMockupPriority must be used within a MockupPriorityProvider"
@@ -7995,7 +8018,7 @@ function useMockupPriority() {
7995
8018
  return context;
7996
8019
  }
7997
8020
  function useMockupPriorityOptional() {
7998
- return (0, import_react32.useContext)(MockupPriorityContext);
8021
+ return (0, import_react33.useContext)(MockupPriorityContext);
7999
8022
  }
8000
8023
 
8001
8024
  // src/hooks/useProductPage.ts
@@ -8026,7 +8049,7 @@ function useProductPage() {
8026
8049
  const realtime = useRealtimeOptional();
8027
8050
  const priority = useMockupPriorityOptional();
8028
8051
  const providers = useProviderStatus();
8029
- return (0, import_react33.useMemo)(
8052
+ return (0, import_react34.useMemo)(
8030
8053
  () => ({
8031
8054
  // Product Data
8032
8055
  product: productCtx.product,
@@ -8120,7 +8143,7 @@ function useArtworkAlignment(placement) {
8120
8143
  }
8121
8144
  function useSetArtworkAlignment() {
8122
8145
  const productCtx = useProductOptional();
8123
- return (0, import_react33.useCallback)(
8146
+ return (0, import_react34.useCallback)(
8124
8147
  (placement, alignment) => {
8125
8148
  if (productCtx) {
8126
8149
  const currentDesign = productCtx.placements[placement];
@@ -8137,7 +8160,7 @@ function useSelectedArtwork() {
8137
8160
  const productCtx = useProductOptional();
8138
8161
  const shopCtx = useShopOptional();
8139
8162
  const ctx = productCtx || shopCtx;
8140
- const setArtwork = (0, import_react33.useCallback)(
8163
+ const setArtwork = (0, import_react34.useCallback)(
8141
8164
  (artwork) => {
8142
8165
  ctx?.setSelectedArtwork(artwork);
8143
8166
  },
@@ -8147,7 +8170,7 @@ function useSelectedArtwork() {
8147
8170
  }
8148
8171
  function useProductSelection() {
8149
8172
  const productCtx = useProductOptional();
8150
- const update = (0, import_react33.useCallback)(
8173
+ const update = (0, import_react34.useCallback)(
8151
8174
  (selection) => {
8152
8175
  productCtx?.updateSelection?.(selection);
8153
8176
  },
@@ -8157,7 +8180,7 @@ function useProductSelection() {
8157
8180
  }
8158
8181
  function usePlacementClipShape(placement) {
8159
8182
  const productCtx = useProductOptional();
8160
- const setShape = (0, import_react33.useCallback)(
8183
+ const setShape = (0, import_react34.useCallback)(
8161
8184
  (shape) => {
8162
8185
  productCtx?.setPlacementClipShape(placement, shape);
8163
8186
  },
@@ -8170,10 +8193,10 @@ function usePlacementClipShape(placement) {
8170
8193
  }
8171
8194
 
8172
8195
  // src/hooks/viewport/useMediaQuery.ts
8173
- var import_react34 = require("react");
8196
+ var import_react35 = require("react");
8174
8197
  function useMediaQuery(query) {
8175
- const [matches, setMatches] = (0, import_react34.useState)(null);
8176
- (0, import_react34.useEffect)(() => {
8198
+ const [matches, setMatches] = (0, import_react35.useState)(null);
8199
+ (0, import_react35.useEffect)(() => {
8177
8200
  const media = window.matchMedia(query);
8178
8201
  setMatches(media.matches);
8179
8202
  const listener = () => setMatches(media.matches);
@@ -8184,15 +8207,15 @@ function useMediaQuery(query) {
8184
8207
  }
8185
8208
 
8186
8209
  // src/hooks/viewport/useViewportDimensions.ts
8187
- var import_react35 = require("react");
8210
+ var import_react36 = require("react");
8188
8211
  function useViewportDimensions(isDesktop) {
8189
- const [dimensions, setDimensions] = (0, import_react35.useState)({
8212
+ const [dimensions, setDimensions] = (0, import_react36.useState)({
8190
8213
  width: 0,
8191
8214
  height: 0,
8192
8215
  aspectRatio: 0,
8193
8216
  resizeVersion: 0
8194
8217
  });
8195
- (0, import_react35.useEffect)(() => {
8218
+ (0, import_react36.useEffect)(() => {
8196
8219
  const width = window.innerWidth;
8197
8220
  const height = window.innerHeight;
8198
8221
  setDimensions((prev) => ({
@@ -8203,7 +8226,7 @@ function useViewportDimensions(isDesktop) {
8203
8226
  // Keep at 0 for initial mount
8204
8227
  }));
8205
8228
  }, []);
8206
- (0, import_react35.useLayoutEffect)(() => {
8229
+ (0, import_react36.useLayoutEffect)(() => {
8207
8230
  if (isDesktop !== true) return;
8208
8231
  const width = window.innerWidth;
8209
8232
  const height = window.innerHeight;
@@ -8215,7 +8238,7 @@ function useViewportDimensions(isDesktop) {
8215
8238
  resizeVersion: prev.resizeVersion + 1
8216
8239
  }));
8217
8240
  }, [isDesktop]);
8218
- (0, import_react35.useEffect)(() => {
8241
+ (0, import_react36.useEffect)(() => {
8219
8242
  if (isDesktop !== true) return;
8220
8243
  let resizeTimeout = null;
8221
8244
  let lastWidth = window.innerWidth;
@@ -8256,7 +8279,7 @@ function useViewportDimensions(isDesktop) {
8256
8279
  }
8257
8280
 
8258
8281
  // src/hooks/viewport/useResponsiveImageCap.ts
8259
- var import_react36 = require("react");
8282
+ var import_react37 = require("react");
8260
8283
  var DEFAULT_IMAGE_CONFIG = {
8261
8284
  ASPECT_RATIO: 16 / 9,
8262
8285
  WIDTH_VW: 140,
@@ -8268,7 +8291,7 @@ var DEFAULT_IMAGE_CONFIG = {
8268
8291
  };
8269
8292
  function useResponsiveImageCap(dimensions, options = {}) {
8270
8293
  const { aspectRatio = DEFAULT_IMAGE_CONFIG.ASPECT_RATIO, sidebarWidthPx } = options;
8271
- return (0, import_react36.useMemo)(() => {
8294
+ return (0, import_react37.useMemo)(() => {
8272
8295
  const vw = dimensions.width;
8273
8296
  const vh = dimensions.height;
8274
8297
  const viewportAspectRatio = dimensions.aspectRatio;
@@ -8326,7 +8349,7 @@ function useResponsiveImageCap(dimensions, options = {}) {
8326
8349
  }
8327
8350
 
8328
8351
  // src/hooks/viewport/useWideMonitorMode.ts
8329
- var import_react37 = require("react");
8352
+ var import_react38 = require("react");
8330
8353
  var LAYOUT_CONFIG = {
8331
8354
  SIDEBAR_MAX_PX: 384,
8332
8355
  SIDEBAR_MARGIN_PX: 32,
@@ -8366,7 +8389,7 @@ function hasEdgeBlur(viewportWidth, maxWidthPx, sidebarPercent = 0.35, sidebarWi
8366
8389
  return gap > 10;
8367
8390
  }
8368
8391
  function useWideMonitorMode(imageCapInfo, sidebarPercent) {
8369
- return (0, import_react37.useMemo)(() => {
8392
+ return (0, import_react38.useMemo)(() => {
8370
8393
  const { viewportWidth, maxWidthPx } = imageCapInfo;
8371
8394
  if (viewportWidth < 768) return false;
8372
8395
  const effectiveSidebarPercent = sidebarPercent ?? (viewportWidth >= 1280 ? 0.35 : 0.3);
@@ -8721,8 +8744,8 @@ var CanvasExportService = class _CanvasExportService {
8721
8744
  var canvasExportService = new CanvasExportService();
8722
8745
 
8723
8746
  // src/components/CanvasIsolationBoundary.tsx
8724
- var import_react38 = __toESM(require("react"), 1);
8725
- var import_jsx_runtime53 = require("react/jsx-runtime");
8747
+ var import_react39 = __toESM(require("react"), 1);
8748
+ var import_jsx_runtime54 = require("react/jsx-runtime");
8726
8749
  function CanvasIsolationConfigurator({
8727
8750
  placementName: placementNameProp,
8728
8751
  onArtworkChange,
@@ -8731,7 +8754,7 @@ function CanvasIsolationConfigurator({
8731
8754
  }) {
8732
8755
  const productContext = useProductOptional();
8733
8756
  const realtimeContext = useRealtimeOptional();
8734
- (0, import_react38.useEffect)(() => {
8757
+ (0, import_react39.useEffect)(() => {
8735
8758
  canvasExportService.configure({
8736
8759
  sendCanvasBlob: realtimeContext?.sendCanvasBlob,
8737
8760
  sendCanvasState: realtimeContext?.sendCanvasState,
@@ -8762,16 +8785,16 @@ function CanvasIsolationConfigurator({
8762
8785
  onArtworkChange,
8763
8786
  clearImageBitmapCache
8764
8787
  ]);
8765
- (0, import_react38.useEffect)(() => {
8788
+ (0, import_react39.useEffect)(() => {
8766
8789
  return () => {
8767
8790
  canvasExportService.reset();
8768
8791
  };
8769
8792
  }, []);
8770
8793
  return null;
8771
8794
  }
8772
- var IsolatedChildren = import_react38.default.memo(
8795
+ var IsolatedChildren = import_react39.default.memo(
8773
8796
  function IsolatedChildren2({ children }) {
8774
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_jsx_runtime53.Fragment, { children });
8797
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_jsx_runtime54.Fragment, { children });
8775
8798
  },
8776
8799
  // Custom comparison: ALWAYS return true (never re-render due to parent changes)
8777
8800
  // This is intentional - children should use refs/services for updates that need to bypass this
@@ -8784,8 +8807,8 @@ function CanvasIsolationBoundary({
8784
8807
  clearImageBitmapCache,
8785
8808
  serializeStateForServer
8786
8809
  }) {
8787
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
8788
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
8810
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
8811
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
8789
8812
  CanvasIsolationConfigurator,
8790
8813
  {
8791
8814
  placementName,
@@ -8794,7 +8817,7 @@ function CanvasIsolationBoundary({
8794
8817
  serializeStateForServer
8795
8818
  }
8796
8819
  ),
8797
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(IsolatedChildren, { children })
8820
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(IsolatedChildren, { children })
8798
8821
  ] });
8799
8822
  }
8800
8823
  function useIsolatedCanvas() {
@@ -8817,8 +8840,8 @@ function useIsolatedCanvas() {
8817
8840
  }
8818
8841
 
8819
8842
  // src/components/LoadingOverlayPrism.tsx
8820
- var import_react39 = require("react");
8821
- var import_jsx_runtime54 = require("react/jsx-runtime");
8843
+ var import_react40 = require("react");
8844
+ var import_jsx_runtime55 = require("react/jsx-runtime");
8822
8845
  function generateParticles() {
8823
8846
  return Array.from({ length: 16 }, () => ({
8824
8847
  left: 10 + Math.random() * 80,
@@ -8922,18 +8945,18 @@ function LoadingOverlayPrism({
8922
8945
  }) {
8923
8946
  ensureStyles();
8924
8947
  console.log(`[Prism] render visible=${visible}`);
8925
- const [mounted, setMounted] = (0, import_react39.useState)(false);
8926
- (0, import_react39.useEffect)(() => {
8948
+ const [mounted, setMounted] = (0, import_react40.useState)(false);
8949
+ (0, import_react40.useEffect)(() => {
8927
8950
  console.log(`[Prism] MOUNTED \u2014 scheduling fade-in`);
8928
8951
  const raf = requestAnimationFrame(() => setMounted(true));
8929
8952
  return () => cancelAnimationFrame(raf);
8930
8953
  }, []);
8931
- const [particles, setParticles] = (0, import_react39.useState)([]);
8932
- (0, import_react39.useEffect)(() => {
8954
+ const [particles, setParticles] = (0, import_react40.useState)([]);
8955
+ (0, import_react40.useEffect)(() => {
8933
8956
  setParticles(generateParticles());
8934
8957
  }, []);
8935
- const prevVisibleRef = (0, import_react39.useRef)(visible);
8936
- (0, import_react39.useEffect)(() => {
8958
+ const prevVisibleRef = (0, import_react40.useRef)(visible);
8959
+ (0, import_react40.useEffect)(() => {
8937
8960
  if (prevVisibleRef.current && !visible) {
8938
8961
  console.log(`[Prism] visible changed true\u2192false \u2014 FADE-OUT STARTING`);
8939
8962
  } else if (!prevVisibleRef.current && visible) {
@@ -8941,7 +8964,7 @@ function LoadingOverlayPrism({
8941
8964
  }
8942
8965
  prevVisibleRef.current = visible;
8943
8966
  }, [visible]);
8944
- const handleTransitionEnd = (0, import_react39.useCallback)(() => {
8967
+ const handleTransitionEnd = (0, import_react40.useCallback)(() => {
8945
8968
  if (!visible) {
8946
8969
  console.log(`[Prism] FADE-OUT COMPLETE \u2014 calling onExited`);
8947
8970
  onExited?.();
@@ -8955,20 +8978,20 @@ function LoadingOverlayPrism({
8955
8978
  } else if (mounted) {
8956
8979
  fadeClass = " prism-fade-in";
8957
8980
  }
8958
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
8981
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
8959
8982
  "div",
8960
8983
  {
8961
8984
  className: `prism-loading-overlay absolute inset-0${fadeClass}`,
8962
8985
  onTransitionEnd: handleTransitionEnd,
8963
8986
  children: [
8964
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "prism-loading-rainbow", children: [
8965
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "prism-loading-band" }),
8966
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "prism-loading-band" }),
8967
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "prism-loading-band" }),
8968
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "prism-loading-band" }),
8969
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "prism-loading-band" })
8987
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "prism-loading-rainbow", children: [
8988
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "prism-loading-band" }),
8989
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "prism-loading-band" }),
8990
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "prism-loading-band" }),
8991
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "prism-loading-band" }),
8992
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "prism-loading-band" })
8970
8993
  ] }),
8971
- particles.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
8994
+ particles.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
8972
8995
  "div",
8973
8996
  {
8974
8997
  className: "prism-loading-particle",
@@ -8990,9 +9013,9 @@ function LoadingOverlayPrism({
8990
9013
  }
8991
9014
  var SHOW_DELAY_MS = 200;
8992
9015
  function useLoadingOverlay(isLoading) {
8993
- const [showOverlay, setShowOverlay] = (0, import_react39.useState)(false);
8994
- const timerRef = (0, import_react39.useRef)(null);
8995
- (0, import_react39.useEffect)(() => {
9016
+ const [showOverlay, setShowOverlay] = (0, import_react40.useState)(false);
9017
+ const timerRef = (0, import_react40.useRef)(null);
9018
+ (0, import_react40.useEffect)(() => {
8996
9019
  if (isLoading) {
8997
9020
  timerRef.current = setTimeout(() => {
8998
9021
  setShowOverlay(true);
@@ -9010,7 +9033,7 @@ function useLoadingOverlay(isLoading) {
9010
9033
  }
9011
9034
  };
9012
9035
  }, [isLoading]);
9013
- const handleExited = (0, import_react39.useCallback)(() => {
9036
+ const handleExited = (0, import_react40.useCallback)(() => {
9014
9037
  setShowOverlay(false);
9015
9038
  }, []);
9016
9039
  return {
@@ -9021,9 +9044,9 @@ function useLoadingOverlay(isLoading) {
9021
9044
  }
9022
9045
 
9023
9046
  // src/components/LoadingOverlayPrismCandy.tsx
9024
- var import_react40 = require("react");
9047
+ var import_react41 = require("react");
9025
9048
  var import_react_dom2 = require("react-dom");
9026
- var import_jsx_runtime55 = require("react/jsx-runtime");
9049
+ var import_jsx_runtime56 = require("react/jsx-runtime");
9027
9050
  var BANDS = [
9028
9051
  { rgb: "230, 45, 55", delay: "-0.0s" },
9029
9052
  // red
@@ -9193,19 +9216,19 @@ function CandyVisual({
9193
9216
  onTransitionEnd,
9194
9217
  variantClass = ""
9195
9218
  }) {
9196
- const [particles, setParticles] = (0, import_react40.useState)([]);
9197
- (0, import_react40.useEffect)(() => {
9219
+ const [particles, setParticles] = (0, import_react41.useState)([]);
9220
+ (0, import_react41.useEffect)(() => {
9198
9221
  setParticles(generateParticles2());
9199
9222
  }, []);
9200
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
9223
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
9201
9224
  "div",
9202
9225
  {
9203
9226
  className: `candy-loading-overlay ${variantClass} ${fadeClass}`.trim(),
9204
9227
  style,
9205
9228
  onTransitionEnd,
9206
9229
  children: [
9207
- BANDS.map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "candy-band" }, `b-${i}`)),
9208
- particles.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9230
+ BANDS.map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "candy-band" }, `b-${i}`)),
9231
+ particles.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9209
9232
  "div",
9210
9233
  {
9211
9234
  className: "candy-particle",
@@ -9224,15 +9247,15 @@ function CandyVisual({
9224
9247
  }
9225
9248
  );
9226
9249
  }
9227
- var LoadingOverlayPrismCandy = (0, import_react40.memo)(function LoadingOverlayPrismCandy2({
9250
+ var LoadingOverlayPrismCandy = (0, import_react41.memo)(function LoadingOverlayPrismCandy2({
9228
9251
  visible = true,
9229
9252
  onExited
9230
9253
  }) {
9231
9254
  ensureStyles2();
9232
- const anchorRef = (0, import_react40.useRef)(null);
9233
- const [bounds, setBounds] = (0, import_react40.useState)(null);
9234
- const [mounted, setMounted] = (0, import_react40.useState)(false);
9235
- const measure = (0, import_react40.useCallback)(() => {
9255
+ const anchorRef = (0, import_react41.useRef)(null);
9256
+ const [bounds, setBounds] = (0, import_react41.useState)(null);
9257
+ const [mounted, setMounted] = (0, import_react41.useState)(false);
9258
+ const measure = (0, import_react41.useCallback)(() => {
9236
9259
  const el = anchorRef.current;
9237
9260
  if (!el) return;
9238
9261
  const r = el.getBoundingClientRect();
@@ -9243,7 +9266,7 @@ var LoadingOverlayPrismCandy = (0, import_react40.memo)(function LoadingOverlayP
9243
9266
  height: r.height
9244
9267
  });
9245
9268
  }, []);
9246
- (0, import_react40.useLayoutEffect)(() => {
9269
+ (0, import_react41.useLayoutEffect)(() => {
9247
9270
  measure();
9248
9271
  window.addEventListener("resize", measure);
9249
9272
  let ro = null;
@@ -9256,11 +9279,11 @@ var LoadingOverlayPrismCandy = (0, import_react40.memo)(function LoadingOverlayP
9256
9279
  ro?.disconnect();
9257
9280
  };
9258
9281
  }, [measure]);
9259
- (0, import_react40.useEffect)(() => {
9282
+ (0, import_react41.useEffect)(() => {
9260
9283
  const raf = requestAnimationFrame(() => setMounted(true));
9261
9284
  return () => cancelAnimationFrame(raf);
9262
9285
  }, []);
9263
- const handleTransitionEnd = (0, import_react40.useCallback)(
9286
+ const handleTransitionEnd = (0, import_react41.useCallback)(
9264
9287
  (e) => {
9265
9288
  if (e.propertyName !== "background-color") return;
9266
9289
  if (!visible) onExited?.();
@@ -9270,8 +9293,8 @@ var LoadingOverlayPrismCandy = (0, import_react40.memo)(function LoadingOverlayP
9270
9293
  let fadeClass = "";
9271
9294
  if (!visible) fadeClass = "candy-fade-out";
9272
9295
  else if (mounted) fadeClass = "candy-fade-in";
9273
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
9274
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9296
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
9297
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9275
9298
  "div",
9276
9299
  {
9277
9300
  ref: anchorRef,
@@ -9284,7 +9307,7 @@ var LoadingOverlayPrismCandy = (0, import_react40.memo)(function LoadingOverlayP
9284
9307
  }
9285
9308
  ),
9286
9309
  bounds && typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
9287
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9310
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9288
9311
  CandyVisual,
9289
9312
  {
9290
9313
  fadeClass,
@@ -9303,19 +9326,19 @@ var LoadingOverlayPrismCandy = (0, import_react40.memo)(function LoadingOverlayP
9303
9326
  )
9304
9327
  ] });
9305
9328
  });
9306
- var LoadingOverlayPrismCandyInline = (0, import_react40.memo)(
9329
+ var LoadingOverlayPrismCandyInline = (0, import_react41.memo)(
9307
9330
  function LoadingOverlayPrismCandyInline2({
9308
9331
  visible = true,
9309
9332
  onExited,
9310
9333
  variant = "dark"
9311
9334
  }) {
9312
9335
  ensureStyles2();
9313
- const [mounted, setMounted] = (0, import_react40.useState)(false);
9314
- (0, import_react40.useEffect)(() => {
9336
+ const [mounted, setMounted] = (0, import_react41.useState)(false);
9337
+ (0, import_react41.useEffect)(() => {
9315
9338
  const raf = requestAnimationFrame(() => setMounted(true));
9316
9339
  return () => cancelAnimationFrame(raf);
9317
9340
  }, []);
9318
- const handleTransitionEnd = (0, import_react40.useCallback)(
9341
+ const handleTransitionEnd = (0, import_react41.useCallback)(
9319
9342
  (e) => {
9320
9343
  if (e.propertyName !== "background-color") return;
9321
9344
  if (!visible) onExited?.();
@@ -9325,7 +9348,7 @@ var LoadingOverlayPrismCandyInline = (0, import_react40.memo)(
9325
9348
  let fadeClass = "";
9326
9349
  if (!visible) fadeClass = "candy-fade-out";
9327
9350
  else if (mounted) fadeClass = "candy-fade-in";
9328
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9351
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9329
9352
  CandyVisual,
9330
9353
  {
9331
9354
  fadeClass,
@@ -9342,11 +9365,11 @@ var LoadingOverlayPrismCandyInline = (0, import_react40.memo)(
9342
9365
  );
9343
9366
 
9344
9367
  // src/index.ts
9345
- var import_react70 = require("@snowcone-app/sdk/react");
9368
+ var import_react71 = require("@snowcone-app/sdk/react");
9346
9369
  var import_sdk11 = require("@snowcone-app/sdk");
9347
9370
 
9348
9371
  // src/patterns/ProductPageProvider.tsx
9349
- var import_jsx_runtime56 = require("react/jsx-runtime");
9372
+ var import_jsx_runtime57 = require("react/jsx-runtime");
9350
9373
  function ProductPageProvider({
9351
9374
  children,
9352
9375
  productId,
@@ -9360,12 +9383,12 @@ function ProductPageProvider({
9360
9383
  realtimeGrantUrl,
9361
9384
  enablePriority = true
9362
9385
  }) {
9363
- let content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Product, { productId, productData, children });
9386
+ let content = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Product, { productId, productData, children });
9364
9387
  if (enablePriority) {
9365
- content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(MockupPriorityProvider, { children: content });
9388
+ content = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(MockupPriorityProvider, { children: content });
9366
9389
  }
9367
9390
  if (enableRealtime) {
9368
- content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9391
+ content = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9369
9392
  RealtimeProvider,
9370
9393
  {
9371
9394
  wsUrl: realtimeWsUrl,
@@ -9375,7 +9398,7 @@ function ProductPageProvider({
9375
9398
  }
9376
9399
  );
9377
9400
  }
9378
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9401
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9379
9402
  Shop,
9380
9403
  {
9381
9404
  endpoint,
@@ -9395,23 +9418,23 @@ function ProductPageProviderMinimal({
9395
9418
  shop,
9396
9419
  initialArtwork
9397
9420
  }) {
9398
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9421
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9399
9422
  Shop,
9400
9423
  {
9401
9424
  endpoint,
9402
9425
  mockupUrl,
9403
9426
  shop,
9404
9427
  initialArtwork,
9405
- children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Product, { productId, productData, children })
9428
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Product, { productId, productData, children })
9406
9429
  }
9407
9430
  );
9408
9431
  }
9409
9432
 
9410
9433
  // src/composed/ArtAlignment.tsx
9411
- var import_react41 = require("react");
9412
- var import_react42 = require("@use-gesture/react");
9434
+ var import_react42 = require("react");
9435
+ var import_react43 = require("@use-gesture/react");
9413
9436
  var import_sdk9 = require("@snowcone-app/sdk");
9414
- var import_jsx_runtime57 = require("react/jsx-runtime");
9437
+ var import_jsx_runtime58 = require("react/jsx-runtime");
9415
9438
  function ArtAlignment({
9416
9439
  src: propSrc,
9417
9440
  artworkAspectRatio: propAspectRatio,
@@ -9445,16 +9468,16 @@ function ArtAlignment({
9445
9468
  selection: {}
9446
9469
  };
9447
9470
  }
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)();
9471
+ const containerRef = (0, import_react42.useRef)(null);
9472
+ const imageRef = (0, import_react42.useRef)(null);
9473
+ const lastUserDragTimeRef = (0, import_react42.useRef)(0);
9474
+ const [containerSize, setContainerSize] = (0, import_react42.useState)({ width: 0, height: 0 });
9475
+ const [position, setPosition] = (0, import_react42.useState)({ x: 0, y: 0 });
9476
+ const [isReady, setIsReady] = (0, import_react42.useState)(false);
9477
+ const [detectedAspectRatio, setDetectedAspectRatio] = (0, import_react42.useState)();
9455
9478
  const effectiveAspectRatio = artworkAspectRatio || detectedAspectRatio;
9456
9479
  const alignment = placementDesign?.alignment || propAlignment || "center";
9457
- const descriptor = (0, import_react41.useMemo)(
9480
+ const descriptor = (0, import_react42.useMemo)(
9458
9481
  () => (0, import_sdk9.describeProductArtAlignment)(
9459
9482
  {
9460
9483
  src,
@@ -9476,7 +9499,7 @@ function ArtAlignment({
9476
9499
  productContext
9477
9500
  ]
9478
9501
  );
9479
- const containerStyle = (0, import_react41.useMemo)(() => {
9502
+ const containerStyle = (0, import_react42.useMemo)(() => {
9480
9503
  const style = {};
9481
9504
  if (height !== void 0) {
9482
9505
  const heightValue = typeof height === "number" ? height : parseFloat(height);
@@ -9507,7 +9530,7 @@ function ArtAlignment({
9507
9530
  }
9508
9531
  return style;
9509
9532
  }, [effectiveAspectRatio, height, maxHeight, minHeight]);
9510
- (0, import_react41.useEffect)(() => {
9533
+ (0, import_react42.useEffect)(() => {
9511
9534
  if (!containerRef.current) return;
9512
9535
  const resizeObserver = new ResizeObserver((entries) => {
9513
9536
  const entry = entries[0];
@@ -9533,7 +9556,7 @@ function ArtAlignment({
9533
9556
  }
9534
9557
  }
9535
9558
  };
9536
- (0, import_react41.useEffect)(() => {
9559
+ (0, import_react42.useEffect)(() => {
9537
9560
  if (!imageRef.current || !descriptor) return;
9538
9561
  if (imageRef.current.complete) {
9539
9562
  setIsReady(true);
@@ -9558,7 +9581,7 @@ function ArtAlignment({
9558
9581
  img.removeEventListener("load", handleLoad);
9559
9582
  };
9560
9583
  }, [descriptor?.src, artworkAspectRatio]);
9561
- const maskDimensions = (0, import_react41.useMemo)(() => {
9584
+ const maskDimensions = (0, import_react42.useMemo)(() => {
9562
9585
  if (!isReady || containerSize.width === 0 || !descriptor) {
9563
9586
  return { width: 0, height: 0 };
9564
9587
  }
@@ -9573,14 +9596,14 @@ function ArtAlignment({
9573
9596
  descriptor?.effectiveAlignment,
9574
9597
  isReady
9575
9598
  ]);
9576
- const clipPathCoords = (0, import_react41.useMemo)(() => {
9599
+ const clipPathCoords = (0, import_react42.useMemo)(() => {
9577
9600
  const halfMaskW = maskDimensions.width / 2;
9578
9601
  const halfMaskH = maskDimensions.height / 2;
9579
9602
  const halfContainerW = containerSize.width / 2;
9580
9603
  const halfContainerH = containerSize.height / 2;
9581
9604
  return { halfMaskW, halfMaskH, halfContainerW, halfContainerH };
9582
9605
  }, [maskDimensions.width, maskDimensions.height, containerSize.width, containerSize.height]);
9583
- (0, import_react41.useEffect)(() => {
9606
+ (0, import_react42.useEffect)(() => {
9584
9607
  if (Date.now() - lastUserDragTimeRef.current < 500) return;
9585
9608
  if (!isReady || maskDimensions.width === 0 || !descriptor) return;
9586
9609
  const points = (0, import_sdk9.getSnapPoints)(
@@ -9602,7 +9625,7 @@ function ArtAlignment({
9602
9625
  maskDimensions.height,
9603
9626
  isReady
9604
9627
  ]);
9605
- const overlayStyle = (0, import_react41.useMemo)(() => {
9628
+ const overlayStyle = (0, import_react42.useMemo)(() => {
9606
9629
  const { halfMaskW, halfMaskH, halfContainerW, halfContainerH } = clipPathCoords;
9607
9630
  const cx = position.x + halfContainerW;
9608
9631
  const cy = position.y + halfContainerH;
@@ -9623,7 +9646,7 @@ function ArtAlignment({
9623
9646
  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
9647
  };
9625
9648
  }, [isReady, position.x, position.y, clipPathCoords]);
9626
- const maskStyle = (0, import_react41.useMemo)(() => ({
9649
+ const maskStyle = (0, import_react42.useMemo)(() => ({
9627
9650
  width: `${maskDimensions.width}px`,
9628
9651
  height: `${maskDimensions.height}px`,
9629
9652
  boxShadow: `0 0 0 2px var(--color-background), 0 0 0 4px var(--color-primary)`,
@@ -9638,7 +9661,7 @@ function ArtAlignment({
9638
9661
  // GPU acceleration for smoother drag
9639
9662
  borderRadius: "var(--radius-image, 4px)"
9640
9663
  }), [maskDimensions.width, maskDimensions.height]);
9641
- const clearImageClipPath = (0, import_react41.useMemo)(() => {
9664
+ const clearImageClipPath = (0, import_react42.useMemo)(() => {
9642
9665
  if (!isReady) return "none";
9643
9666
  const { halfMaskW, halfMaskH, halfContainerW, halfContainerH } = clipPathCoords;
9644
9667
  const cx = position.x + halfContainerW;
@@ -9649,14 +9672,14 @@ function ArtAlignment({
9649
9672
  const top = cy - halfMaskH;
9650
9673
  return `polygon(${left}px ${top}px, ${right}px ${top}px, ${right}px ${bottom}px, ${left}px ${bottom}px)`;
9651
9674
  }, [isReady, position.x, position.y, clipPathCoords]);
9652
- const maskTransform = (0, import_react41.useMemo)(() => {
9675
+ const maskTransform = (0, import_react42.useMemo)(() => {
9653
9676
  return descriptor?.effectiveAlignment === "horizontal" ? `translate(calc(-50% + ${position.x}px), -50%)` : `translate(-50%, calc(-50% + ${position.y}px))`;
9654
9677
  }, [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);
9678
+ const lastContextUpdateTimeRef = (0, import_react42.useRef)(0);
9679
+ const pendingAlignmentRef = (0, import_react42.useRef)(null);
9680
+ const throttleTimeoutRef = (0, import_react42.useRef)(null);
9658
9681
  const THROTTLE_MS = 150;
9659
- const bind = (0, import_react42.useDrag)(
9682
+ const bind = (0, import_react43.useDrag)(
9660
9683
  ({ offset: [ox, oy], last }) => {
9661
9684
  if (maskDimensions.width === 0 || maskDimensions.height === 0 || !descriptor) {
9662
9685
  return;
@@ -9749,7 +9772,7 @@ function ArtAlignment({
9749
9772
  if (!descriptor) {
9750
9773
  return null;
9751
9774
  }
9752
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9775
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9753
9776
  "div",
9754
9777
  {
9755
9778
  className: `relative ${className || ""}`,
@@ -9758,8 +9781,8 @@ function ArtAlignment({
9758
9781
  width: "fit-content",
9759
9782
  maxWidth: "100%"
9760
9783
  },
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)(
9784
+ 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: [
9785
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9763
9786
  "img",
9764
9787
  {
9765
9788
  ref: imageRef,
@@ -9784,9 +9807,9 @@ function ArtAlignment({
9784
9807
  loading: "eager"
9785
9808
  }
9786
9809
  ),
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)(
9810
+ isReady && maskDimensions.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
9811
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { style: overlayStyle }),
9812
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9790
9813
  "img",
9791
9814
  {
9792
9815
  src: descriptor.src,
@@ -9814,7 +9837,7 @@ function ArtAlignment({
9814
9837
  loading: "eager"
9815
9838
  }
9816
9839
  ),
9817
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9840
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9818
9841
  "div",
9819
9842
  {
9820
9843
  ...bind(),
@@ -9831,8 +9854,8 @@ function ArtAlignment({
9831
9854
  }
9832
9855
 
9833
9856
  // src/composed/ArtworkCustomizer.tsx
9834
- var import_react43 = require("react");
9835
- var import_jsx_runtime58 = require("react/jsx-runtime");
9857
+ var import_react44 = require("react");
9858
+ var import_jsx_runtime59 = require("react/jsx-runtime");
9836
9859
  function ArtworkCustomizer(props) {
9837
9860
  const designContext = useDesign();
9838
9861
  const artwork = props.artwork || designContext.selectedArtwork;
@@ -9844,7 +9867,7 @@ function ArtworkCustomizer(props) {
9844
9867
  const placements = productCtx?.product?.placements || [];
9845
9868
  const selectedPlacement = productCtx?.selectedPlacement;
9846
9869
  const setSelectedPlacement = productCtx?.setSelectedPlacement;
9847
- (0, import_react43.useEffect)(() => {
9870
+ (0, import_react44.useEffect)(() => {
9848
9871
  if (placements.length > 0 && !selectedPlacement && setSelectedPlacement) {
9849
9872
  setSelectedPlacement(placements[0].label);
9850
9873
  }
@@ -9854,13 +9877,13 @@ function ArtworkCustomizer(props) {
9854
9877
  );
9855
9878
  const isColorPlacement = currentPlacement?.type === "color";
9856
9879
  const isFitMode = currentPlacement?.defaultScaleMode === "fit";
9857
- (0, import_react43.useEffect)(() => {
9880
+ (0, import_react44.useEffect)(() => {
9858
9881
  }, [selectedPlacement]);
9859
9882
  if (!artwork) {
9860
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: `text-sm text-muted-foreground ${props.className || ""}`, children: "Select artwork to customize" });
9883
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: `text-sm text-muted-foreground ${props.className || ""}`, children: "Select artwork to customize" });
9861
9884
  }
9862
9885
  if (artwork.type === "pattern") {
9863
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9886
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9864
9887
  TileCount,
9865
9888
  {
9866
9889
  artwork,
@@ -9871,8 +9894,8 @@ function ArtworkCustomizer(props) {
9871
9894
  );
9872
9895
  }
9873
9896
  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)(
9897
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex flex-col gap-4", children: [
9898
+ 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
9899
  "button",
9877
9900
  {
9878
9901
  onClick: () => setSelectedPlacement?.(p.label),
@@ -9881,7 +9904,7 @@ function ArtworkCustomizer(props) {
9881
9904
  },
9882
9905
  p.label
9883
9906
  )) }),
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)(
9907
+ 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
9908
  ArtAlignment,
9886
9909
  {
9887
9910
  artwork: { src: artwork.src },
@@ -9897,7 +9920,7 @@ function ArtworkCustomizer(props) {
9897
9920
 
9898
9921
  // src/composed/CanvasEditor.tsx
9899
9922
  var import_lucide_react2 = require("lucide-react");
9900
- var import_jsx_runtime59 = require("react/jsx-runtime");
9923
+ var import_jsx_runtime60 = require("react/jsx-runtime");
9901
9924
  var ImageIcon = import_lucide_react2.Image;
9902
9925
  var TypeIcon = import_lucide_react2.Type;
9903
9926
  var ShapesIcon = import_lucide_react2.Shapes;
@@ -9908,43 +9931,43 @@ function CanvasEditor({
9908
9931
  onOpenTypography,
9909
9932
  children
9910
9933
  }) {
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)(
9934
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "flex flex-col gap-6", children: [
9935
+ /* @__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" }) }) }),
9936
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "flex items-center justify-center gap-8 py-2", children: [
9937
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
9915
9938
  "button",
9916
9939
  {
9917
9940
  onClick: onOpenImageGallery,
9918
9941
  className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors",
9919
9942
  "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" }) })
9943
+ 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
9944
  }
9922
9945
  ),
9923
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9946
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
9924
9947
  "button",
9925
9948
  {
9926
9949
  onClick: onOpenTypography,
9927
9950
  className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors",
9928
9951
  "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" }) })
9952
+ 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
9953
  }
9931
9954
  ),
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" }) }) })
9955
+ /* @__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" }) }) }),
9956
+ /* @__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
9957
  ] })
9935
9958
  ] });
9936
9959
  }
9937
9960
 
9938
9961
  // src/composed/HeroProductImage.tsx
9939
- var import_react45 = require("react");
9962
+ var import_react46 = require("react");
9940
9963
  var import_sdk10 = require("@snowcone-app/sdk");
9941
9964
 
9942
9965
  // src/hooks/viewport/useContainerWidth.ts
9943
- var import_react44 = require("react");
9966
+ var import_react45 = require("react");
9944
9967
  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)(() => {
9968
+ const [width, setWidth] = (0, import_react45.useState)(0);
9969
+ const resizeTimeoutRef = (0, import_react45.useRef)(null);
9970
+ (0, import_react45.useLayoutEffect)(() => {
9948
9971
  const el = containerRef.current;
9949
9972
  if (!el) return;
9950
9973
  const cssWidth = el.offsetWidth;
@@ -9952,7 +9975,7 @@ function useContainerWidth(containerRef, maxWidth = 3e3) {
9952
9975
  const dpr = window.devicePixelRatio ?? 1;
9953
9976
  setWidth(Math.min(Math.round(cssWidth * dpr), maxWidth));
9954
9977
  }, [containerRef, maxWidth]);
9955
- (0, import_react44.useEffect)(() => {
9978
+ (0, import_react45.useEffect)(() => {
9956
9979
  const measure = () => {
9957
9980
  const el = containerRef.current;
9958
9981
  if (!el) return;
@@ -9975,7 +9998,7 @@ function useContainerWidth(containerRef, maxWidth = 3e3) {
9975
9998
  }
9976
9999
 
9977
10000
  // src/composed/HeroProductImage.tsx
9978
- var import_jsx_runtime60 = require("react/jsx-runtime");
10001
+ var import_jsx_runtime61 = require("react/jsx-runtime");
9979
10002
  function slugifyPlacementKey(label) {
9980
10003
  return label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
9981
10004
  }
@@ -10009,11 +10032,12 @@ function buildHeroMockupUrl(args) {
10009
10032
  width: args.width,
10010
10033
  view: args.mockupId,
10011
10034
  variant: args.variantId,
10035
+ ...args.bg ? { bg: args.bg } : {},
10012
10036
  ...snow.resolver ? { base: snow.resolver } : {}
10013
10037
  });
10014
10038
  }
10015
10039
  var EMPTY_IMAGES = [];
10016
- var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10040
+ var HeroProductImage = (0, import_react46.memo)(function HeroProductImage2({
10017
10041
  productId,
10018
10042
  mockupId,
10019
10043
  variantId,
@@ -10046,24 +10070,25 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10046
10070
  const shopContext = useShopOptional();
10047
10071
  const realtimeContext = useRealtimeOptional();
10048
10072
  const priorityContext = useMockupPriorityOptional();
10049
- const priorityContextRef = (0, import_react45.useRef)(priorityContext);
10073
+ const mockupBg = useMockupBackgroundOptional();
10074
+ const priorityContextRef = (0, import_react46.useRef)(priorityContext);
10050
10075
  priorityContextRef.current = priorityContext;
10051
- const contextRef = (0, import_react45.useRef)(context);
10076
+ const contextRef = (0, import_react46.useRef)(context);
10052
10077
  contextRef.current = context;
10053
10078
  const actualProductId = product?.id || productId || context?.product?.id;
10054
- const actualGvid = (0, import_react45.useMemo)(() => {
10079
+ const actualGvid = (0, import_react46.useMemo)(() => {
10055
10080
  return (0, import_sdk10.resolveVariantId)(context, gvid, variantId);
10056
10081
  }, [gvid, variantId, context?.selection, context?.combinations]);
10057
- const actualMockupId = (0, import_react45.useMemo)(() => {
10082
+ const actualMockupId = (0, import_react46.useMemo)(() => {
10058
10083
  return (0, import_sdk10.resolveMockupId)(context, actualGvid, mockupId);
10059
10084
  }, [mockupId, actualGvid, context]);
10060
10085
  const artworkSrc = artwork?.src;
10061
10086
  const selectedArtworkSrc = designContext?.selectedArtwork?.src;
10062
10087
  const effectiveArtworkSrc = artworkSrc || selectedArtworkSrc;
10063
- const containerRef = (0, import_react45.useRef)(null);
10088
+ const containerRef = (0, import_react46.useRef)(null);
10064
10089
  const measuredWidth = useContainerWidth(containerRef);
10065
10090
  const width = widthProp ?? measuredWidth;
10066
- const initialStaticUrl = (0, import_react45.useMemo)(() => {
10091
+ const initialStaticUrl = (0, import_react46.useMemo)(() => {
10067
10092
  if (realtimeUrl) return null;
10068
10093
  if (mode === "realtime") return null;
10069
10094
  if (typeof window !== "undefined" && window.snowcone?.signMockupUrl) {
@@ -10096,7 +10121,8 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10096
10121
  placements: allPlacements,
10097
10122
  mockupId: actualMockupId,
10098
10123
  variantId: actualGvid,
10099
- width
10124
+ width,
10125
+ bg: mockupBg
10100
10126
  });
10101
10127
  }, [
10102
10128
  realtimeUrl,
@@ -10106,6 +10132,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10106
10132
  actualProductId,
10107
10133
  actualMockupId,
10108
10134
  actualGvid,
10135
+ mockupBg,
10109
10136
  product?.placements,
10110
10137
  context?.product?.placements,
10111
10138
  images,
@@ -10129,28 +10156,28 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10129
10156
  shimmerDelay,
10130
10157
  initialUrl: realtimeUrl || initialStaticUrl
10131
10158
  });
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)(
10159
+ const [error, setError] = (0, import_react46.useState)(null);
10160
+ const [isInPreloadZone, setIsInPreloadZone] = (0, import_react46.useState)(true);
10161
+ const componentIdRef = (0, import_react46.useRef)(
10135
10162
  `hero-product-image-${Math.random().toString(36).substr(2, 9)}`
10136
10163
  );
10137
- const [containerMounted, setContainerMounted] = (0, import_react45.useState)(false);
10138
- const setContainerRef = (0, import_react45.useCallback)((node) => {
10164
+ const [containerMounted, setContainerMounted] = (0, import_react46.useState)(false);
10165
+ const setContainerRef = (0, import_react46.useCallback)((node) => {
10139
10166
  containerRef.current = node;
10140
10167
  setContainerMounted(!!node);
10141
10168
  }, []);
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);
10169
+ const lastUrlRef = (0, import_react46.useRef)(realtimeUrl ?? initialStaticUrl ?? null);
10170
+ const priorityRegisteredRef = (0, import_react46.useRef)(false);
10171
+ const onLoadCalledRef = (0, import_react46.useRef)(false);
10172
+ const prevArtworkSrcRef = (0, import_react46.useRef)(void 0);
10173
+ const realtimeArtworkSrcRef = (0, import_react46.useRef)(void 0);
10174
+ const hasReceivedRealtimeRef = (0, import_react46.useRef)(false);
10175
+ const isPendingExportRef = (0, import_react46.useRef)(false);
10176
+ const onUrlGeneratedRef = (0, import_react46.useRef)(onUrlGenerated);
10150
10177
  onUrlGeneratedRef.current = onUrlGenerated;
10151
- const layersLengthRef = (0, import_react45.useRef)(layers.length);
10178
+ const layersLengthRef = (0, import_react46.useRef)(layers.length);
10152
10179
  layersLengthRef.current = layers.length;
10153
- (0, import_react45.useEffect)(() => {
10180
+ (0, import_react46.useEffect)(() => {
10154
10181
  if (initialPriority === 1) return;
10155
10182
  if (!containerMounted || !containerRef.current) return;
10156
10183
  if (isInPreloadZone) return;
@@ -10169,7 +10196,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10169
10196
  );
10170
10197
  return unobserve;
10171
10198
  }, [containerMounted, initialPriority, isInPreloadZone]);
10172
- (0, import_react45.useEffect)(() => {
10199
+ (0, import_react46.useEffect)(() => {
10173
10200
  if (!realtimeUrl) return;
10174
10201
  if (realtimeUrl === lastUrlRef.current) return;
10175
10202
  lastUrlRef.current = realtimeUrl;
@@ -10177,7 +10204,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10177
10204
  const isInitialLoad = layersLengthRef.current === 0;
10178
10205
  addLayerDirectly(realtimeUrl, { skipTransition: isInitialLoad });
10179
10206
  }, [realtimeUrl, addLayerDirectly, actualMockupId, placement]);
10180
- (0, import_react45.useEffect)(() => {
10207
+ (0, import_react46.useEffect)(() => {
10181
10208
  if (mode === "static") {
10182
10209
  return;
10183
10210
  }
@@ -10221,7 +10248,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10221
10248
  addLayerDirectly
10222
10249
  // NOTE: layers.length removed - use layersLengthRef instead to prevent duplicate requests
10223
10250
  ]);
10224
- (0, import_react45.useEffect)(() => {
10251
+ (0, import_react46.useEffect)(() => {
10225
10252
  if (mode === "static") return;
10226
10253
  if (!realtimeContext?.subscribePendingBlob || !placement) return;
10227
10254
  const handlePendingExport = (pendingPlacement) => {
@@ -10234,7 +10261,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10234
10261
  unsubscribe?.();
10235
10262
  };
10236
10263
  }, [mode, realtimeContext?.subscribePendingBlob, placement]);
10237
- (0, import_react45.useEffect)(() => {
10264
+ (0, import_react46.useEffect)(() => {
10238
10265
  if (!priorityContext || !actualMockupId || !placement) return;
10239
10266
  priorityContext.registerMockup(actualMockupId, placement, initialPriority);
10240
10267
  priorityRegisteredRef.current = true;
@@ -10245,7 +10272,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10245
10272
  }
10246
10273
  };
10247
10274
  }, [priorityContext, actualMockupId, placement, initialPriority]);
10248
- (0, import_react45.useEffect)(() => {
10275
+ (0, import_react46.useEffect)(() => {
10249
10276
  if (!priorityContext?.updateElementRef || !actualMockupId) return;
10250
10277
  if (containerMounted && containerRef.current) {
10251
10278
  priorityContext.updateElementRef(actualMockupId, containerRef.current);
@@ -10259,7 +10286,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10259
10286
  const artworkTileCount = artwork?.type === "pattern" ? artwork?.tileCount : void 0;
10260
10287
  const selectedArtworkType = designContext?.selectedArtwork?.type;
10261
10288
  const selectedArtworkTileCount = designContext?.selectedArtwork?.type === "pattern" ? designContext?.selectedArtwork?.tileCount : void 0;
10262
- (0, import_react45.useEffect)(() => {
10289
+ (0, import_react46.useEffect)(() => {
10263
10290
  const currentSrc = artworkSrc || selectedArtworkSrc;
10264
10291
  if (currentSrc !== prevArtworkSrcRef.current) {
10265
10292
  lastUrlRef.current = null;
@@ -10269,11 +10296,11 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10269
10296
  realtimeArtworkSrcRef.current = void 0;
10270
10297
  }
10271
10298
  }, [artworkSrc, selectedArtworkSrc]);
10272
- const contextSelectionRef = (0, import_react45.useRef)(context?.selection);
10273
- const contextOptionAttributesRef = (0, import_react45.useRef)(context?.optionAttributes);
10299
+ const contextSelectionRef = (0, import_react46.useRef)(context?.selection);
10300
+ const contextOptionAttributesRef = (0, import_react46.useRef)(context?.optionAttributes);
10274
10301
  contextSelectionRef.current = context?.selection;
10275
10302
  contextOptionAttributesRef.current = context?.optionAttributes;
10276
- const createDesignForPlacementsWrapper = (0, import_react45.useCallback)(
10303
+ const createDesignForPlacementsWrapper = (0, import_react46.useCallback)(
10277
10304
  (placements, providedImages) => {
10278
10305
  const effectiveArtworkSrc2 = artworkSrc || selectedArtworkSrc;
10279
10306
  if (!effectiveArtworkSrc2 || effectiveArtworkSrc2.trim() === "" || effectiveArtworkSrc2 === "undefined" || effectiveArtworkSrc2 === "null") {
@@ -10312,7 +10339,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10312
10339
  selectedArtworkTileCount
10313
10340
  ]
10314
10341
  );
10315
- (0, import_react45.useEffect)(() => {
10342
+ (0, import_react46.useEffect)(() => {
10316
10343
  if (mode === "realtime") return;
10317
10344
  if (initialStaticUrl && lastUrlRef.current === initialStaticUrl) {
10318
10345
  return;
@@ -10341,7 +10368,8 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10341
10368
  placements: allPlacements,
10342
10369
  mockupId: actualMockupId,
10343
10370
  variantId: actualGvid,
10344
- width
10371
+ width,
10372
+ bg: mockupBg
10345
10373
  });
10346
10374
  if (!url) return;
10347
10375
  if (url === lastUrlRef.current) return;
@@ -10382,6 +10410,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10382
10410
  actualProductId,
10383
10411
  actualMockupId,
10384
10412
  actualGvid,
10413
+ mockupBg,
10385
10414
  images,
10386
10415
  width,
10387
10416
  effects,
@@ -10412,17 +10441,17 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10412
10441
  const topLayer = layers[layers.length - 1];
10413
10442
  const displayUrl = topLayer?.url || realtimeUrl || initialStaticUrl;
10414
10443
  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)(() => {
10444
+ const [prevUrl, setPrevUrl] = (0, import_react46.useState)(null);
10445
+ const [showNew, setShowNew] = (0, import_react46.useState)(false);
10446
+ const [renderedUrl, setRenderedUrl] = (0, import_react46.useState)(displayUrl);
10447
+ const [firstImageLoaded, setFirstImageLoaded] = (0, import_react46.useState)(false);
10448
+ const [loaderMounted, setLoaderMounted] = (0, import_react46.useState)(true);
10449
+ const [imgFailed, setImgFailed] = (0, import_react46.useState)(false);
10450
+ const [retryNonce, setRetryNonce] = (0, import_react46.useState)(0);
10451
+ const retriedUrlRef = (0, import_react46.useRef)(null);
10452
+ const prevDisplayUrlRef = (0, import_react46.useRef)(displayUrl);
10453
+ const signHintShownRef = (0, import_react46.useRef)(false);
10454
+ (0, import_react46.useEffect)(() => {
10426
10455
  if (!displayUrl || displayUrl === prevDisplayUrlRef.current) return;
10427
10456
  const oldUrl = prevDisplayUrlRef.current;
10428
10457
  prevDisplayUrlRef.current = displayUrl;
@@ -10449,26 +10478,26 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10449
10478
  preload.onload = null;
10450
10479
  };
10451
10480
  }, [displayUrl]);
10452
- const handleCrossfadeEnd = (0, import_react45.useCallback)(() => {
10481
+ const handleCrossfadeEnd = (0, import_react46.useCallback)(() => {
10453
10482
  setPrevUrl(null);
10454
10483
  setShowNew(false);
10455
10484
  }, []);
10456
- const handleLoaderExited = (0, import_react45.useCallback)(() => setLoaderMounted(false), []);
10485
+ const handleLoaderExited = (0, import_react46.useCallback)(() => setLoaderMounted(false), []);
10457
10486
  if (!hasArtwork) {
10458
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10487
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10459
10488
  "div",
10460
10489
  {
10461
10490
  className: `bg-gray-100 flex items-center justify-center ${className || ""}`,
10462
10491
  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)(
10492
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "text-gray-400 text-center p-4", children: [
10493
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10465
10494
  "svg",
10466
10495
  {
10467
10496
  className: "w-8 h-8 mx-auto mb-2",
10468
10497
  fill: "none",
10469
10498
  stroke: "currentColor",
10470
10499
  viewBox: "0 0 24 24",
10471
- children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10500
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10472
10501
  "path",
10473
10502
  {
10474
10503
  strokeLinecap: "round",
@@ -10479,22 +10508,22 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10479
10508
  )
10480
10509
  }
10481
10510
  ),
10482
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-xs", children: "No artwork" })
10511
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "text-xs", children: "No artwork" })
10483
10512
  ] })
10484
10513
  }
10485
10514
  );
10486
10515
  }
10487
10516
  if (error) {
10488
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10517
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10489
10518
  "div",
10490
10519
  {
10491
10520
  className: `bg-red-50 flex items-center justify-center ${className || ""}`,
10492
10521
  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" }) })
10522
+ 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
10523
  }
10495
10524
  );
10496
10525
  }
10497
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
10526
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
10498
10527
  "div",
10499
10528
  {
10500
10529
  ref: setContainerRef,
@@ -10502,7 +10531,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10502
10531
  style,
10503
10532
  "data-hero-image": "true",
10504
10533
  children: [
10505
- renderedUrl && !imgFailed && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10534
+ renderedUrl && !imgFailed && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10506
10535
  "img",
10507
10536
  {
10508
10537
  alt: `Product mockup${placement ? ` - ${placement}` : ""}`,
@@ -10541,8 +10570,8 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10541
10570
  }
10542
10571
  }
10543
10572
  ),
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)(
10573
+ 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" }) }),
10574
+ realtimeContext?.renderError && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10546
10575
  "div",
10547
10576
  {
10548
10577
  role: "alert",
@@ -10551,7 +10580,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10551
10580
  children: `Render blocked: ${realtimeContext.renderError.code} \u2014 ${realtimeContext.renderError.message}`
10552
10581
  }
10553
10582
  ),
10554
- prevUrl && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10583
+ prevUrl && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10555
10584
  "img",
10556
10585
  {
10557
10586
  alt: "",
@@ -10566,7 +10595,7 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10566
10595
  onTransitionEnd: handleCrossfadeEnd
10567
10596
  }
10568
10597
  ),
10569
- loaderMounted && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10598
+ loaderMounted && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10570
10599
  LoadingOverlayPrismCandyInline,
10571
10600
  {
10572
10601
  visible: !firstImageLoaded,
@@ -10580,16 +10609,16 @@ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
10580
10609
  });
10581
10610
 
10582
10611
  // 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(
10612
+ var import_react47 = __toESM(require("react"), 1);
10613
+ var import_jsx_runtime62 = require("react/jsx-runtime");
10614
+ var SafeImg = import_react47.default.forwardRef(
10586
10615
  function SafeImg2({ fallback = null, onError, src, ...rest }, ref) {
10587
- const [failed, setFailed] = (0, import_react46.useState)(false);
10588
- (0, import_react46.useEffect)(() => {
10616
+ const [failed, setFailed] = (0, import_react47.useState)(false);
10617
+ (0, import_react47.useEffect)(() => {
10589
10618
  setFailed(false);
10590
10619
  }, [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)(
10620
+ if (failed) return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_jsx_runtime62.Fragment, { children: fallback });
10621
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10593
10622
  "img",
10594
10623
  {
10595
10624
  ...rest,
@@ -10624,11 +10653,11 @@ var { searchClient } = (0, import_instant_meilisearch.instantMeiliSearch)(
10624
10653
  );
10625
10654
 
10626
10655
  // src/composed/search/SearchProvider.tsx
10627
- var import_react47 = require("react");
10628
- var import_jsx_runtime62 = require("react/jsx-runtime");
10656
+ var import_react48 = require("react");
10657
+ var import_jsx_runtime63 = require("react/jsx-runtime");
10629
10658
  function InitialSearchTrigger() {
10630
10659
  const { refine } = (0, import_react_instantsearch.useSearchBox)();
10631
- (0, import_react47.useEffect)(() => {
10660
+ (0, import_react48.useEffect)(() => {
10632
10661
  refine("");
10633
10662
  }, [refine]);
10634
10663
  return null;
@@ -10652,7 +10681,7 @@ function SearchProvider({
10652
10681
  ],
10653
10682
  children
10654
10683
  }) {
10655
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
10684
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
10656
10685
  import_react_instantsearch.InstantSearch,
10657
10686
  {
10658
10687
  searchClient,
@@ -10680,7 +10709,7 @@ function SearchProvider({
10680
10709
  }
10681
10710
  },
10682
10711
  children: [
10683
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10712
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10684
10713
  import_react_instantsearch.Configure,
10685
10714
  {
10686
10715
  hitsPerPage,
@@ -10689,7 +10718,7 @@ function SearchProvider({
10689
10718
  attributesToRetrieve
10690
10719
  }
10691
10720
  ),
10692
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(InitialSearchTrigger, {}),
10721
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(InitialSearchTrigger, {}),
10693
10722
  children
10694
10723
  ]
10695
10724
  }
@@ -10699,17 +10728,17 @@ function SearchProvider({
10699
10728
  // src/composed/search/SearchBox.tsx
10700
10729
  var import_react_instantsearch2 = require("react-instantsearch");
10701
10730
  var import_lucide_react3 = require("lucide-react");
10702
- var import_react48 = require("react");
10703
- var import_jsx_runtime63 = require("react/jsx-runtime");
10731
+ var import_react49 = require("react");
10732
+ var import_jsx_runtime64 = require("react/jsx-runtime");
10704
10733
  function SearchBox() {
10705
10734
  const { query, refine, clear } = (0, import_react_instantsearch2.useSearchBox)();
10706
10735
  const searchParams = useUiSearchParams();
10707
10736
  const router = useUiRouter();
10708
- const inputRef = (0, import_react48.useRef)(null);
10709
- const [showShimmer, setShowShimmer] = (0, import_react48.useState)(false);
10737
+ const inputRef = (0, import_react49.useRef)(null);
10738
+ const [showShimmer, setShowShimmer] = (0, import_react49.useState)(false);
10710
10739
  const inputId = "search-products-input";
10711
10740
  const descriptionId = "search-description";
10712
- (0, import_react48.useEffect)(() => {
10741
+ (0, import_react49.useEffect)(() => {
10713
10742
  const handleSpotlight = () => {
10714
10743
  inputRef.current?.focus();
10715
10744
  inputRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
@@ -10719,7 +10748,7 @@ function SearchBox() {
10719
10748
  window.addEventListener("search-spotlight", handleSpotlight);
10720
10749
  return () => window.removeEventListener("search-spotlight", handleSpotlight);
10721
10750
  }, []);
10722
- (0, import_react48.useEffect)(() => {
10751
+ (0, import_react49.useEffect)(() => {
10723
10752
  const shouldFocus = searchParams.get("focus") === "search";
10724
10753
  if (shouldFocus && inputRef.current) {
10725
10754
  const timer = setTimeout(() => {
@@ -10734,8 +10763,8 @@ function SearchBox() {
10734
10763
  return () => clearTimeout(timer);
10735
10764
  }
10736
10765
  }, [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)(
10766
+ 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: [
10767
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10739
10768
  Input,
10740
10769
  {
10741
10770
  ref: inputRef,
@@ -10744,15 +10773,15 @@ function SearchBox() {
10744
10773
  value: query,
10745
10774
  onChange: (e) => refine(e.target.value),
10746
10775
  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)(
10776
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(import_lucide_react3.Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10777
+ endContent: query ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10749
10778
  "button",
10750
10779
  {
10751
10780
  type: "button",
10752
10781
  onClick: clear,
10753
10782
  className: "hover:text-foreground transition-colors",
10754
10783
  "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" })
10784
+ children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(import_lucide_react3.X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10756
10785
  }
10757
10786
  ) : void 0,
10758
10787
  "aria-label": "Search products",
@@ -10762,11 +10791,11 @@ function SearchBox() {
10762
10791
  className: "[&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden"
10763
10792
  }
10764
10793
  ),
10765
- showShimmer && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10794
+ showShimmer && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10766
10795
  "div",
10767
10796
  {
10768
10797
  className: "absolute inset-0 pointer-events-none rounded-input z-20 overflow-hidden",
10769
- children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10798
+ children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10770
10799
  "div",
10771
10800
  {
10772
10801
  className: "absolute inset-0",
@@ -10779,13 +10808,13 @@ function SearchBox() {
10779
10808
  )
10780
10809
  }
10781
10810
  ),
10782
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("style", { dangerouslySetInnerHTML: { __html: `
10811
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("style", { dangerouslySetInnerHTML: { __html: `
10783
10812
  @keyframes searchShimmer {
10784
10813
  0% { transform: translateX(-100%); }
10785
10814
  100% { transform: translateX(100%); }
10786
10815
  }
10787
10816
  ` } }),
10788
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10817
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10789
10818
  ] }) });
10790
10819
  }
10791
10820
 
@@ -10793,7 +10822,7 @@ function SearchBox() {
10793
10822
  var import_react_instantsearch3 = require("react-instantsearch");
10794
10823
 
10795
10824
  // src/composed/search/ProductHit.tsx
10796
- var import_jsx_runtime64 = require("react/jsx-runtime");
10825
+ var import_jsx_runtime65 = require("react/jsx-runtime");
10797
10826
  function ProductHitComponent({
10798
10827
  hit: product,
10799
10828
  variant = "overlay"
@@ -10810,12 +10839,12 @@ function ProductHitComponent({
10810
10839
  }
10811
10840
  return "";
10812
10841
  };
10813
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10842
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10814
10843
  Product,
10815
10844
  {
10816
10845
  productId,
10817
10846
  productData: product,
10818
- children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10847
+ children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10819
10848
  ProductCard,
10820
10849
  {
10821
10850
  variant,
@@ -10836,10 +10865,10 @@ function ProductHitComponent({
10836
10865
  }
10837
10866
 
10838
10867
  // src/composed/search/ProductGrid.tsx
10839
- var import_react49 = require("react");
10840
- var import_jsx_runtime65 = require("react/jsx-runtime");
10868
+ var import_react50 = require("react");
10869
+ var import_jsx_runtime66 = require("react/jsx-runtime");
10841
10870
  function ProductGridSkeletonItem() {
10842
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "aspect-square bg-muted animate-pulse" });
10871
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "aspect-square bg-muted animate-pulse" });
10843
10872
  }
10844
10873
  function ProductGrid({
10845
10874
  className = "",
@@ -10849,26 +10878,26 @@ function ProductGrid({
10849
10878
  }) {
10850
10879
  const { nbHits } = (0, import_react_instantsearch3.useStats)();
10851
10880
  const { status, results } = (0, import_react_instantsearch3.useInstantSearch)();
10852
- const [announcement, setAnnouncement] = (0, import_react49.useState)("");
10881
+ const [announcement, setAnnouncement] = (0, import_react50.useState)("");
10853
10882
  const hitsCount = results?.hits?.length ?? 0;
10854
10883
  const showSkeleton = hitsCount === 0 && status !== "error";
10855
- (0, import_react49.useEffect)(() => {
10884
+ (0, import_react50.useEffect)(() => {
10856
10885
  const timer = setTimeout(() => {
10857
10886
  setAnnouncement(`${nbHits} ${nbHits === 1 ? "product" : "products"} found`);
10858
10887
  }, 1e3);
10859
10888
  return () => clearTimeout(timer);
10860
10889
  }, [nbHits]);
10861
- const HitComponent = (0, import_react49.useCallback)(({ hit }) => /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10890
+ const HitComponent = (0, import_react50.useCallback)(({ hit }) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10862
10891
  ProductHitComponent,
10863
10892
  {
10864
10893
  hit,
10865
10894
  variant
10866
10895
  }
10867
10896
  ), [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)(
10897
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className, children: [
10898
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10899
+ 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)) }),
10900
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: showSkeleton ? "hidden" : "", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10872
10901
  import_react_instantsearch3.Hits,
10873
10902
  {
10874
10903
  hitComponent: HitComponent,
@@ -10883,18 +10912,18 @@ function ProductGrid({
10883
10912
  }
10884
10913
 
10885
10914
  // src/composed/search/Filters.tsx
10886
- var import_react51 = require("react");
10915
+ var import_react52 = require("react");
10887
10916
 
10888
10917
  // src/composed/search/FiltersButton.tsx
10889
10918
  var import_lucide_react4 = require("lucide-react");
10890
- var import_jsx_runtime66 = require("react/jsx-runtime");
10919
+ var import_jsx_runtime67 = require("react/jsx-runtime");
10891
10920
  var SlidersHorizontalIcon = import_lucide_react4.SlidersHorizontal;
10892
10921
  function FiltersButton({
10893
10922
  onClick,
10894
10923
  className = "",
10895
10924
  children = "Filters"
10896
10925
  }) {
10897
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10926
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
10898
10927
  Button,
10899
10928
  {
10900
10929
  variant: "field",
@@ -10902,8 +10931,8 @@ function FiltersButton({
10902
10931
  className,
10903
10932
  "aria-label": "Open filters",
10904
10933
  children: [
10905
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10906
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children })
10934
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10935
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { children })
10907
10936
  ]
10908
10937
  }
10909
10938
  );
@@ -10912,15 +10941,15 @@ function FiltersButton({
10912
10941
  // src/composed/search/FiltersDrawer.tsx
10913
10942
  var import_react_instantsearch4 = require("react-instantsearch");
10914
10943
  var import_lucide_react5 = require("lucide-react");
10915
- var import_react50 = require("react");
10944
+ var import_react51 = require("react");
10916
10945
  var Slider2 = __toESM(require("@radix-ui/react-slider"), 1);
10917
- var import_jsx_runtime67 = require("react/jsx-runtime");
10946
+ var import_jsx_runtime68 = require("react/jsx-runtime");
10918
10947
  var XIcon2 = import_lucide_react5.X;
10919
10948
  function FiltersDrawer({ isOpen, onClose }) {
10920
- const [showCounts, setShowCounts] = (0, import_react50.useState)(false);
10949
+ const [showCounts, setShowCounts] = (0, import_react51.useState)(false);
10921
10950
  const { nbHits } = (0, import_react_instantsearch4.useStats)();
10922
10951
  const containerRef = useFocusTrap(isOpen, onClose);
10923
- (0, import_react50.useEffect)(() => {
10952
+ (0, import_react51.useEffect)(() => {
10924
10953
  if (isOpen) {
10925
10954
  document.body.style.overflow = "hidden";
10926
10955
  } else {
@@ -10930,7 +10959,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10930
10959
  document.body.style.overflow = "";
10931
10960
  };
10932
10961
  }, [isOpen]);
10933
- (0, import_react50.useEffect)(() => {
10962
+ (0, import_react51.useEffect)(() => {
10934
10963
  const handleEscape = (e) => {
10935
10964
  if (e.key === "Escape" && isOpen) {
10936
10965
  onClose();
@@ -10939,8 +10968,8 @@ function FiltersDrawer({ isOpen, onClose }) {
10939
10968
  document.addEventListener("keydown", handleEscape);
10940
10969
  return () => document.removeEventListener("keydown", handleEscape);
10941
10970
  }, [isOpen, onClose]);
10942
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
10943
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
10971
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
10972
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
10944
10973
  "div",
10945
10974
  {
10946
10975
  className: `fixed inset-0 bg-black/50 z-40 transition-opacity ${isOpen ? "opacity-100" : "opacity-0 pointer-events-none"}`,
@@ -10948,7 +10977,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10948
10977
  "aria-hidden": "true"
10949
10978
  }
10950
10979
  ),
10951
- /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
10980
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
10952
10981
  "div",
10953
10982
  {
10954
10983
  ref: containerRef,
@@ -10957,26 +10986,26 @@ function FiltersDrawer({ isOpen, onClose }) {
10957
10986
  "aria-modal": "true",
10958
10987
  "aria-labelledby": "filters-drawer-title",
10959
10988
  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)(
10989
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center justify-between px-4 py-4", children: [
10990
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10991
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
10963
10992
  "button",
10964
10993
  {
10965
10994
  onClick: onClose,
10966
10995
  className: "p-2 hover:bg-foreground/5 rounded-full transition-colors",
10967
10996
  "aria-label": "Close filters",
10968
- children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(XIcon2, { className: "w-5 h-5" })
10997
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(XIcon2, { className: "w-5 h-5" })
10969
10998
  }
10970
10999
  )
10971
11000
  ] }),
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: [
11001
+ /* @__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
11002
  nbHits.toLocaleString(),
10974
11003
  " ",
10975
11004
  nbHits === 1 ? "result" : "results"
10976
11005
  ] }) }),
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, {})
11006
+ /* @__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: [
11007
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(TagsSection, { showCounts, setShowCounts }),
11008
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(PriceSection, {})
10980
11009
  ] }) })
10981
11010
  ]
10982
11011
  }
@@ -10992,9 +11021,9 @@ function TagsSection({
10992
11021
  sortBy: ["count:desc", "name:asc"],
10993
11022
  limit: 100
10994
11023
  });
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)(
11024
+ const [isExpanded, setIsExpanded] = (0, import_react51.useState)(true);
11025
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
11026
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
10998
11027
  "button",
10999
11028
  {
11000
11029
  onClick: () => setIsExpanded(!isExpanded),
@@ -11002,8 +11031,8 @@ function TagsSection({
11002
11031
  "aria-expanded": isExpanded,
11003
11032
  "aria-controls": "tags-content",
11004
11033
  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)(
11034
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
11035
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11007
11036
  "svg",
11008
11037
  {
11009
11038
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -11012,14 +11041,14 @@ function TagsSection({
11012
11041
  stroke: "currentColor",
11013
11042
  strokeWidth: 2.5,
11014
11043
  "aria-hidden": "true",
11015
- children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11044
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11016
11045
  }
11017
11046
  )
11018
11047
  ]
11019
11048
  }
11020
11049
  ),
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)(
11050
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "space-y-4", id: "tags-content", children: [
11051
+ /* @__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
11052
  "button",
11024
11053
  {
11025
11054
  onClick: () => refine(item.value),
@@ -11030,15 +11059,15 @@ function TagsSection({
11030
11059
  "aria-label": `${item.isRefined ? "Remove" : "Apply"} ${item.label} filter${showCounts ? ` (${item.count} products)` : ""}`,
11031
11060
  "aria-pressed": item.isRefined,
11032
11061
  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 })
11062
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { "aria-hidden": "true", children: item.label }),
11063
+ 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
11064
  ]
11036
11065
  },
11037
11066
  item.value
11038
11067
  )) }),
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)(
11068
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center justify-between pt-2", children: [
11069
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
11070
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11042
11071
  "button",
11043
11072
  {
11044
11073
  onClick: () => setShowCounts(!showCounts),
@@ -11046,7 +11075,7 @@ function TagsSection({
11046
11075
  role: "switch",
11047
11076
  "aria-checked": showCounts,
11048
11077
  "aria-labelledby": "show-counts-label",
11049
- children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11078
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11050
11079
  "span",
11051
11080
  {
11052
11081
  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 +11092,11 @@ function PriceSection() {
11063
11092
  const { range, refine, start, canRefine } = (0, import_react_instantsearch4.useRange)({ attribute: "price" });
11064
11093
  const rangeMin = typeof range.min === "number" && isFinite(range.min) ? range.min : 0;
11065
11094
  const rangeMax = typeof range.max === "number" && isFinite(range.max) ? range.max : 15e3;
11066
- const [localRange, setLocalRange] = (0, import_react50.useState)([
11095
+ const [localRange, setLocalRange] = (0, import_react51.useState)([
11067
11096
  typeof start?.[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
11068
11097
  typeof start?.[1] === "number" && isFinite(start[1]) ? start[1] : rangeMax
11069
11098
  ]);
11070
- (0, import_react50.useEffect)(() => {
11099
+ (0, import_react51.useEffect)(() => {
11071
11100
  if (start && Array.isArray(start)) {
11072
11101
  setLocalRange([
11073
11102
  typeof start[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
@@ -11077,7 +11106,7 @@ function PriceSection() {
11077
11106
  setLocalRange([rangeMin, rangeMax]);
11078
11107
  }
11079
11108
  }, [start, rangeMin, rangeMax]);
11080
- const [isExpanded, setIsExpanded] = (0, import_react50.useState)(true);
11109
+ const [isExpanded, setIsExpanded] = (0, import_react51.useState)(true);
11081
11110
  if (!canRefine) {
11082
11111
  return null;
11083
11112
  }
@@ -11092,8 +11121,8 @@ function PriceSection() {
11092
11121
  return `$${priceInDollars.toFixed(2)}`;
11093
11122
  }
11094
11123
  };
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)(
11124
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
11125
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
11097
11126
  "button",
11098
11127
  {
11099
11128
  onClick: () => setIsExpanded(!isExpanded),
@@ -11101,8 +11130,8 @@ function PriceSection() {
11101
11130
  "aria-expanded": isExpanded,
11102
11131
  "aria-controls": "price-content",
11103
11132
  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)(
11133
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
11134
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11106
11135
  "svg",
11107
11136
  {
11108
11137
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -11111,22 +11140,22 @@ function PriceSection() {
11111
11140
  stroke: "currentColor",
11112
11141
  strokeWidth: 2.5,
11113
11142
  "aria-hidden": "true",
11114
- children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11143
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11115
11144
  }
11116
11145
  )
11117
11146
  ]
11118
11147
  }
11119
11148
  ),
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]) })
11149
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "space-y-6", id: "price-content", children: [
11150
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center justify-between text-sm font-display", children: [
11151
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: formatPrice2(localRange[0]) }),
11152
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "text-foreground/70", children: formatPrice2(localRange[1]) })
11124
11153
  ] }),
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) => {
11154
+ /* @__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
11155
  const totalBars = 19;
11127
11156
  const barPrice = rangeMin + (rangeMax - rangeMin) / totalBars * i;
11128
11157
  const isInRange = barPrice >= localRange[0] && barPrice <= localRange[1];
11129
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11158
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11130
11159
  "div",
11131
11160
  {
11132
11161
  className: `flex-1 rounded-t-sm transition-opacity ${isInRange ? "bg-foreground" : "bg-foreground/20"}`,
@@ -11135,7 +11164,7 @@ function PriceSection() {
11135
11164
  i
11136
11165
  );
11137
11166
  }) }),
11138
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
11167
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
11139
11168
  Slider2.Root,
11140
11169
  {
11141
11170
  className: "relative flex w-full touch-none select-none items-center",
@@ -11153,8 +11182,8 @@ function PriceSection() {
11153
11182
  step: 1,
11154
11183
  minStepsBetweenThumbs: 1,
11155
11184
  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)(
11185
+ /* @__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" }) }),
11186
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11158
11187
  Slider2.Thumb,
11159
11188
  {
11160
11189
  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 +11197,7 @@ function PriceSection() {
11168
11197
  "aria-valuetext": formatPrice2(localRange[0])
11169
11198
  }
11170
11199
  ),
11171
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
11200
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11172
11201
  Slider2.Thumb,
11173
11202
  {
11174
11203
  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 +11214,10 @@ function PriceSection() {
11185
11214
  ]
11186
11215
  }
11187
11216
  ) }),
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)(
11217
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "grid grid-cols-2 gap-3", children: [
11218
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { children: [
11219
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
11220
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11192
11221
  "input",
11193
11222
  {
11194
11223
  id: "price-min",
@@ -11206,9 +11235,9 @@ function PriceSection() {
11206
11235
  }
11207
11236
  )
11208
11237
  ] }),
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)(
11238
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { children: [
11239
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
11240
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11212
11241
  "input",
11213
11242
  {
11214
11243
  id: "price-max",
@@ -11232,11 +11261,11 @@ function PriceSection() {
11232
11261
  }
11233
11262
 
11234
11263
  // src/composed/search/Filters.tsx
11235
- var import_jsx_runtime68 = require("react/jsx-runtime");
11264
+ var import_jsx_runtime69 = require("react/jsx-runtime");
11236
11265
  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)(
11266
+ const [isOpen, setIsOpen] = (0, import_react52.useState)(false);
11267
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
11268
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11240
11269
  FiltersButton,
11241
11270
  {
11242
11271
  onClick: () => setIsOpen(true),
@@ -11244,14 +11273,14 @@ function Filters({ buttonClassName, buttonText }) {
11244
11273
  children: buttonText
11245
11274
  }
11246
11275
  ),
11247
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
11276
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
11248
11277
  ] });
11249
11278
  }
11250
11279
 
11251
11280
  // src/composed/search/CurrentRefinements.tsx
11252
11281
  var import_react_instantsearch5 = require("react-instantsearch");
11253
11282
  var import_lucide_react6 = require("lucide-react");
11254
- var import_jsx_runtime69 = require("react/jsx-runtime");
11283
+ var import_jsx_runtime70 = require("react/jsx-runtime");
11255
11284
  var XIcon3 = import_lucide_react6.X;
11256
11285
  function CurrentRefinements() {
11257
11286
  const { items, refine } = (0, import_react_instantsearch5.useCurrentRefinements)();
@@ -11297,15 +11326,15 @@ function CurrentRefinements() {
11297
11326
  if (allRefinements.length === 0) {
11298
11327
  return null;
11299
11328
  }
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)(
11329
+ 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
11330
  "button",
11302
11331
  {
11303
11332
  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
11333
  onClick: () => refinement.refine(),
11305
11334
  "aria-label": `Remove filter: ${refinement.displayLabel}`,
11306
11335
  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" })
11336
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "truncate", children: refinement.displayLabel }),
11337
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(XIcon3, { className: "w-3 h-3" })
11309
11338
  ]
11310
11339
  },
11311
11340
  `${refinement.attribute}-${refinement.value}-${index}`
@@ -11329,12 +11358,12 @@ var FACET_SECTIONS = [
11329
11358
  ];
11330
11359
 
11331
11360
  // src/composed/zoom/ResponsiveZoom.tsx
11332
- var import_react54 = require("react");
11361
+ var import_react55 = require("react");
11333
11362
 
11334
11363
  // src/composed/zoom/ZoomOverlay.tsx
11335
- var import_react52 = require("react");
11364
+ var import_react53 = require("react");
11336
11365
  var import_lucide_react7 = require("lucide-react");
11337
- var import_jsx_runtime70 = require("react/jsx-runtime");
11366
+ var import_jsx_runtime71 = require("react/jsx-runtime");
11338
11367
  var PlusIcon2 = import_lucide_react7.Plus;
11339
11368
  var MinusIcon2 = import_lucide_react7.Minus;
11340
11369
  function ZoomOverlay({
@@ -11346,13 +11375,13 @@ function ZoomOverlay({
11346
11375
  className,
11347
11376
  style
11348
11377
  }) {
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)(
11378
+ const [zoomedImageIndex, setZoomedImageIndex] = (0, import_react53.useState)(null);
11379
+ const [zoomOrigin, setZoomOrigin] = (0, import_react53.useState)({ x: 50, y: 50 });
11380
+ const [hoveredImageIndex, setHoveredImageIndex] = (0, import_react53.useState)(null);
11381
+ const [cursorPos, setCursorPos] = (0, import_react53.useState)({ x: 0, y: 0 });
11382
+ const [announcement, setAnnouncement] = (0, import_react53.useState)("");
11383
+ const [isZooming, setIsZooming] = (0, import_react53.useState)(false);
11384
+ const handleZoomClick = (0, import_react53.useCallback)(
11356
11385
  (e) => {
11357
11386
  e.stopPropagation();
11358
11387
  if (isLargeTouchDevice && onEnhancedViewer) {
@@ -11377,7 +11406,7 @@ function ZoomOverlay({
11377
11406
  },
11378
11407
  [zoomedImageIndex, isLargeTouchDevice, onEnhancedViewer, imageIndex]
11379
11408
  );
11380
- const handleZoomMouseMove = (0, import_react52.useCallback)(
11409
+ const handleZoomMouseMove = (0, import_react53.useCallback)(
11381
11410
  (e) => {
11382
11411
  setCursorPos({ x: e.clientX, y: e.clientY });
11383
11412
  if (zoomedImageIndex === imageIndex) {
@@ -11393,9 +11422,9 @@ function ZoomOverlay({
11393
11422
  const isZoomed = zoomedImageIndex === imageIndex;
11394
11423
  const isHovered = hoveredImageIndex === imageIndex;
11395
11424
  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)(
11425
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_jsx_runtime71.Fragment, { children: [
11426
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11427
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11399
11428
  "div",
11400
11429
  {
11401
11430
  className,
@@ -11403,7 +11432,7 @@ function ZoomOverlay({
11403
11432
  ...style,
11404
11433
  position: "relative"
11405
11434
  },
11406
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11435
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11407
11436
  "div",
11408
11437
  {
11409
11438
  style: {
@@ -11426,7 +11455,7 @@ function ZoomOverlay({
11426
11455
  handleZoomClick(e);
11427
11456
  }
11428
11457
  },
11429
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11458
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11430
11459
  "div",
11431
11460
  {
11432
11461
  style: {
@@ -11442,7 +11471,7 @@ function ZoomOverlay({
11442
11471
  )
11443
11472
  }
11444
11473
  ),
11445
- isHovered && !isTouchDevice && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11474
+ isHovered && !isTouchDevice && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11446
11475
  "div",
11447
11476
  {
11448
11477
  className: "fixed pointer-events-none z-50 hidden md:block",
@@ -11452,7 +11481,7 @@ function ZoomOverlay({
11452
11481
  transform: "translate(-50%, -50%)"
11453
11482
  },
11454
11483
  "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)(
11484
+ 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
11485
  MinusIcon2,
11457
11486
  {
11458
11487
  size: 20,
@@ -11460,7 +11489,7 @@ function ZoomOverlay({
11460
11489
  strokeWidth: 1.5,
11461
11490
  "aria-hidden": "true"
11462
11491
  }
11463
- ) : /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11492
+ ) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11464
11493
  PlusIcon2,
11465
11494
  {
11466
11495
  size: 20,
@@ -11475,11 +11504,11 @@ function ZoomOverlay({
11475
11504
  }
11476
11505
 
11477
11506
  // src/composed/zoom/EnhancedImageViewer.tsx
11478
- var import_react53 = require("react");
11507
+ var import_react54 = require("react");
11479
11508
  var import_react_dom3 = require("react-dom");
11480
11509
  var import_react_zoom_pan_pinch = require("react-zoom-pan-pinch");
11481
11510
  var import_lucide_react8 = require("lucide-react");
11482
- var import_jsx_runtime71 = require("react/jsx-runtime");
11511
+ var import_jsx_runtime72 = require("react/jsx-runtime");
11483
11512
  var TransformWrapper = import_react_zoom_pan_pinch.TransformWrapper;
11484
11513
  var TransformComponent = import_react_zoom_pan_pinch.TransformComponent;
11485
11514
  var EnhancedImageViewer = ({
@@ -11490,17 +11519,17 @@ var EnhancedImageViewer = ({
11490
11519
  onIndexChange,
11491
11520
  currentIndex: propCurrentIndex
11492
11521
  }) => {
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)(
11522
+ const [isMounted, setIsMounted] = (0, import_react54.useState)(false);
11523
+ const [isClient, setIsClient] = (0, import_react54.useState)(false);
11524
+ const [scale, setScale] = (0, import_react54.useState)({ initial: 1, min: 1, max: 8 });
11525
+ const [cropDimensions, setCropDimensions] = (0, import_react54.useState)({ width: 0, height: 0 });
11526
+ const [currentZoomScale, setCurrentZoomScale] = (0, import_react54.useState)(1);
11527
+ const imgRef = (0, import_react54.useRef)(null);
11528
+ const touchStartRef = (0, import_react54.useRef)(
11500
11529
  null
11501
11530
  );
11502
- const isSwipingRef = (0, import_react53.useRef)(false);
11503
- const calculateScale = (0, import_react53.useCallback)(() => {
11531
+ const isSwipingRef = (0, import_react54.useRef)(false);
11532
+ const calculateScale = (0, import_react54.useCallback)(() => {
11504
11533
  const viewport = {
11505
11534
  width: window.innerWidth,
11506
11535
  height: window.innerHeight
@@ -11512,10 +11541,10 @@ var EnhancedImageViewer = ({
11512
11541
  max: 8
11513
11542
  });
11514
11543
  }, []);
11515
- const handleImageLoad = (0, import_react53.useCallback)(() => {
11544
+ const handleImageLoad = (0, import_react54.useCallback)(() => {
11516
11545
  calculateScale();
11517
11546
  }, [calculateScale]);
11518
- (0, import_react53.useLayoutEffect)(() => {
11547
+ (0, import_react54.useLayoutEffect)(() => {
11519
11548
  setIsClient(true);
11520
11549
  setIsMounted(true);
11521
11550
  document.body.style.overflow = "hidden";
@@ -11524,17 +11553,17 @@ var EnhancedImageViewer = ({
11524
11553
  document.body.style.overflow = "";
11525
11554
  };
11526
11555
  }, [calculateScale]);
11527
- (0, import_react53.useEffect)(() => {
11556
+ (0, import_react54.useEffect)(() => {
11528
11557
  calculateScale();
11529
11558
  }, [calculateScale]);
11530
- (0, import_react53.useEffect)(() => {
11559
+ (0, import_react54.useEffect)(() => {
11531
11560
  const handleResize = () => {
11532
11561
  calculateScale();
11533
11562
  };
11534
11563
  window.addEventListener("resize", handleResize);
11535
11564
  return () => window.removeEventListener("resize", handleResize);
11536
11565
  }, [calculateScale]);
11537
- (0, import_react53.useEffect)(() => {
11566
+ (0, import_react54.useEffect)(() => {
11538
11567
  const handleKeyDown = (e) => {
11539
11568
  if (e.key === "Escape") {
11540
11569
  onClose();
@@ -11560,7 +11589,7 @@ var EnhancedImageViewer = ({
11560
11589
  document.addEventListener("keydown", handleKeyDown);
11561
11590
  return () => document.removeEventListener("keydown", handleKeyDown);
11562
11591
  }, [onClose, imageUrl, images, onIndexChange, propCurrentIndex]);
11563
- const handleSwipeNavigation = (0, import_react53.useCallback)(
11592
+ const handleSwipeNavigation = (0, import_react54.useCallback)(
11564
11593
  (direction) => {
11565
11594
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11566
11595
  if (currentIndex === -1) {
@@ -11581,7 +11610,7 @@ var EnhancedImageViewer = ({
11581
11610
  },
11582
11611
  [propCurrentIndex, images, imageUrl, onIndexChange]
11583
11612
  );
11584
- const handleTouchStart = (0, import_react53.useCallback)(
11613
+ const handleTouchStart = (0, import_react54.useCallback)(
11585
11614
  (e) => {
11586
11615
  const isAtInitialZoom = Math.abs(currentZoomScale - scale.initial) < 0.1;
11587
11616
  if (!isAtInitialZoom) return;
@@ -11595,7 +11624,7 @@ var EnhancedImageViewer = ({
11595
11624
  },
11596
11625
  [currentZoomScale, scale.initial]
11597
11626
  );
11598
- const handleTouchEnd = (0, import_react53.useCallback)(
11627
+ const handleTouchEnd = (0, import_react54.useCallback)(
11599
11628
  (e) => {
11600
11629
  if (!touchStartRef.current) return;
11601
11630
  const touch = e.changedTouches[0];
@@ -11619,12 +11648,12 @@ var EnhancedImageViewer = ({
11619
11648
  );
11620
11649
  if (!isMounted || !isClient) {
11621
11650
  return (0, import_react_dom3.createPortal)(
11622
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11651
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11623
11652
  "div",
11624
11653
  {
11625
11654
  className: "fixed inset-0 bg-black flex items-center justify-center",
11626
11655
  style: { zIndex: 999999 },
11627
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11656
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11628
11657
  "div",
11629
11658
  {
11630
11659
  style: {
@@ -11640,7 +11669,7 @@ var EnhancedImageViewer = ({
11640
11669
  );
11641
11670
  }
11642
11671
  return (0, import_react_dom3.createPortal)(
11643
- /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
11672
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
11644
11673
  "div",
11645
11674
  {
11646
11675
  className: "fixed inset-0 bg-black flex items-center justify-center",
@@ -11649,7 +11678,7 @@ var EnhancedImageViewer = ({
11649
11678
  "aria-modal": "true",
11650
11679
  "aria-label": "Image viewer",
11651
11680
  children: [
11652
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11681
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11653
11682
  "button",
11654
11683
  {
11655
11684
  onClick: (e) => {
@@ -11675,10 +11704,10 @@ var EnhancedImageViewer = ({
11675
11704
  touchAction: "manipulation",
11676
11705
  marginBottom: "env(safe-area-inset-bottom, 0px)"
11677
11706
  },
11678
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react8.X, { className: "w-7 h-7", strokeWidth: 2.5 })
11707
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react8.X, { className: "w-7 h-7", strokeWidth: 2.5 })
11679
11708
  }
11680
11709
  ),
11681
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11710
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11682
11711
  TransformWrapper,
11683
11712
  {
11684
11713
  initialScale: scale.initial,
@@ -11712,7 +11741,7 @@ var EnhancedImageViewer = ({
11712
11741
  onTransformed: (ref) => {
11713
11742
  setCurrentZoomScale(ref.state.scale);
11714
11743
  },
11715
- children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
11744
+ children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
11716
11745
  "div",
11717
11746
  {
11718
11747
  style: {
@@ -11725,14 +11754,14 @@ var EnhancedImageViewer = ({
11725
11754
  onTouchStart: handleTouchStart,
11726
11755
  onTouchEnd: handleTouchEnd,
11727
11756
  children: [
11728
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11757
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11729
11758
  TransformComponent,
11730
11759
  {
11731
11760
  wrapperStyle: {
11732
11761
  width: "100%",
11733
11762
  height: "100%"
11734
11763
  },
11735
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11764
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11736
11765
  "div",
11737
11766
  {
11738
11767
  style: {
@@ -11743,7 +11772,7 @@ var EnhancedImageViewer = ({
11743
11772
  alignItems: "center",
11744
11773
  justifyContent: "center"
11745
11774
  },
11746
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11775
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11747
11776
  SafeImg,
11748
11777
  {
11749
11778
  ref: imgRef,
@@ -11764,8 +11793,8 @@ var EnhancedImageViewer = ({
11764
11793
  )
11765
11794
  }
11766
11795
  ),
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: (() => {
11796
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fixed bottom-5 left-0 right-0 z-50", children: [
11797
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "flex justify-center gap-2", children: (() => {
11769
11798
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11770
11799
  if (currentIndex === -1) {
11771
11800
  currentIndex = images.findIndex(
@@ -11798,8 +11827,8 @@ var EnhancedImageViewer = ({
11798
11827
  };
11799
11828
  const nextIndex = findNextAvailableIndex(currentIndex, 1);
11800
11829
  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)(
11830
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
11831
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11803
11832
  "button",
11804
11833
  {
11805
11834
  onClick: () => {
@@ -11812,7 +11841,7 @@ var EnhancedImageViewer = ({
11812
11841
  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
11842
  style: { touchAction: "manipulation" },
11814
11843
  "aria-label": "Previous image",
11815
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11844
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11816
11845
  "svg",
11817
11846
  {
11818
11847
  className: "w-4 h-4",
@@ -11820,7 +11849,7 @@ var EnhancedImageViewer = ({
11820
11849
  stroke: "currentColor",
11821
11850
  viewBox: "0 0 24 24",
11822
11851
  "aria-hidden": "true",
11823
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11852
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11824
11853
  "path",
11825
11854
  {
11826
11855
  strokeLinecap: "round",
@@ -11833,7 +11862,7 @@ var EnhancedImageViewer = ({
11833
11862
  )
11834
11863
  }
11835
11864
  ),
11836
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11865
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11837
11866
  "button",
11838
11867
  {
11839
11868
  onClick: () => {
@@ -11846,7 +11875,7 @@ var EnhancedImageViewer = ({
11846
11875
  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
11876
  style: { touchAction: "manipulation" },
11848
11877
  "aria-label": "Next image",
11849
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11878
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11850
11879
  "svg",
11851
11880
  {
11852
11881
  className: "w-4 h-4",
@@ -11854,7 +11883,7 @@ var EnhancedImageViewer = ({
11854
11883
  stroke: "currentColor",
11855
11884
  viewBox: "0 0 24 24",
11856
11885
  "aria-hidden": "true",
11857
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11886
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11858
11887
  "path",
11859
11888
  {
11860
11889
  strokeLinecap: "round",
@@ -11869,7 +11898,7 @@ var EnhancedImageViewer = ({
11869
11898
  )
11870
11899
  ] });
11871
11900
  })() }),
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: (() => {
11901
+ /* @__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
11902
  const total = Math.max(images.length, 1);
11874
11903
  const current = propCurrentIndex !== void 0 ? Math.min(propCurrentIndex + 1, total) : 1;
11875
11904
  return `${current} / ${total}`;
@@ -11881,7 +11910,7 @@ var EnhancedImageViewer = ({
11881
11910
  },
11882
11911
  `${scale.initial}-${scale.min}-${scale.max}`
11883
11912
  ),
11884
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11913
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11885
11914
  "div",
11886
11915
  {
11887
11916
  className: "absolute inset-0 bg-black",
@@ -11900,7 +11929,7 @@ var EnhancedImageViewer = ({
11900
11929
  };
11901
11930
 
11902
11931
  // src/composed/zoom/ResponsiveZoom.tsx
11903
- var import_jsx_runtime72 = require("react/jsx-runtime");
11932
+ var import_jsx_runtime73 = require("react/jsx-runtime");
11904
11933
  function ResponsiveZoom({
11905
11934
  imageIndex,
11906
11935
  children,
@@ -11910,11 +11939,11 @@ function ResponsiveZoom({
11910
11939
  imageUrl,
11911
11940
  alt = "Product image"
11912
11941
  }) {
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)(() => {
11942
+ const [isTouchDevice, setIsTouchDevice] = (0, import_react55.useState)(false);
11943
+ const [showEnhancedViewer, setShowEnhancedViewer] = (0, import_react55.useState)(false);
11944
+ const [viewerIndex, setViewerIndex] = (0, import_react55.useState)(0);
11945
+ const [currentImageUrl, setCurrentImageUrl] = (0, import_react55.useState)(imageUrl || "");
11946
+ (0, import_react55.useEffect)(() => {
11918
11947
  const checkDeviceType = () => {
11919
11948
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
11920
11949
  setIsTouchDevice(hasTouch);
@@ -11941,8 +11970,8 @@ function ResponsiveZoom({
11941
11970
  }
11942
11971
  }
11943
11972
  };
11944
- return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
11945
- isTouchDevice ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11973
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
11974
+ isTouchDevice ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
11946
11975
  "div",
11947
11976
  {
11948
11977
  className,
@@ -11959,7 +11988,7 @@ function ResponsiveZoom({
11959
11988
  },
11960
11989
  children
11961
11990
  }
11962
- ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
11991
+ ) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
11963
11992
  ZoomOverlay,
11964
11993
  {
11965
11994
  imageIndex,
@@ -11970,7 +11999,7 @@ function ResponsiveZoom({
11970
11999
  children
11971
12000
  }
11972
12001
  ),
11973
- showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12002
+ showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
11974
12003
  EnhancedImageViewer,
11975
12004
  {
11976
12005
  imageUrl: currentImageUrl,
@@ -11993,18 +12022,18 @@ function ResponsiveZoom({
11993
12022
  }
11994
12023
 
11995
12024
  // src/composed/carousels/MobileProductCarousel.tsx
11996
- var import_react55 = require("react");
11997
- var import_jsx_runtime73 = require("react/jsx-runtime");
12025
+ var import_react56 = require("react");
12026
+ var import_jsx_runtime74 = require("react/jsx-runtime");
11998
12027
  function StaticCarouselImage({
11999
12028
  src,
12000
12029
  alt,
12001
12030
  className
12002
12031
  }) {
12003
- const [failed, setFailed] = (0, import_react55.useState)(false);
12032
+ const [failed, setFailed] = (0, import_react56.useState)(false);
12004
12033
  if (failed || !src) {
12005
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: `bg-muted ${className ?? ""}`, role: "img", "aria-label": alt });
12034
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: `bg-muted ${className ?? ""}`, role: "img", "aria-label": alt });
12006
12035
  }
12007
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12036
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12008
12037
  "img",
12009
12038
  {
12010
12039
  src,
@@ -12018,7 +12047,7 @@ function StaticCarouselImage({
12018
12047
  }
12019
12048
  );
12020
12049
  }
12021
- var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarousel2({
12050
+ var MobileProductCarousel = (0, import_react56.memo)(function MobileProductCarousel2({
12022
12051
  images,
12023
12052
  currentIndex = 0,
12024
12053
  onIndexChange,
@@ -12033,42 +12062,42 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12033
12062
  mockupWidth,
12034
12063
  onMockupUrlGenerated
12035
12064
  }) {
12036
- const [activeIndex, setActiveIndex] = (0, import_react55.useState)(currentIndex);
12037
- const [touchStart, setTouchStart] = (0, import_react55.useState)(
12065
+ const [activeIndex, setActiveIndex] = (0, import_react56.useState)(currentIndex);
12066
+ const [touchStart, setTouchStart] = (0, import_react56.useState)(
12038
12067
  null
12039
12068
  );
12040
- const [touchEnd, setTouchEnd] = (0, import_react55.useState)(
12069
+ const [touchEnd, setTouchEnd] = (0, import_react56.useState)(
12041
12070
  null
12042
12071
  );
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)(
12072
+ const [showImageViewer, setShowImageViewer] = (0, import_react56.useState)(false);
12073
+ const [viewerKey, setViewerKey] = (0, import_react56.useState)(0);
12074
+ const [isDragging, setIsDragging] = (0, import_react56.useState)(false);
12075
+ const [dragOffset, setDragOffset] = (0, import_react56.useState)(0);
12076
+ const [isTransitioning, setIsTransitioning] = (0, import_react56.useState)(false);
12077
+ const [isHorizontalSwipe, setIsHorizontalSwipe] = (0, import_react56.useState)(
12049
12078
  null
12050
12079
  );
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)(
12080
+ const [isPeeking, setIsPeeking] = (0, import_react56.useState)(false);
12081
+ const [isPeekReturning, setIsPeekReturning] = (0, import_react56.useState)(false);
12082
+ const carouselRef = (0, import_react56.useRef)(null);
12083
+ const indicatorRef = (0, import_react56.useRef)(null);
12084
+ const touchStartRef = (0, import_react56.useRef)(
12056
12085
  null
12057
12086
  );
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)(() => {
12087
+ const horizontalGestureRef = (0, import_react56.useRef)(false);
12088
+ const hasShownPeekRef = (0, import_react56.useRef)(false);
12089
+ const hasSwipedThisSessionRef = (0, import_react56.useRef)(false);
12090
+ const generatedUrlsRef = (0, import_react56.useRef)(/* @__PURE__ */ new Map());
12091
+ const prevArtworkSrcRef = (0, import_react56.useRef)(currentArtwork?.src);
12092
+ (0, import_react56.useEffect)(() => {
12064
12093
  if (currentArtwork?.src !== prevArtworkSrcRef.current) {
12065
12094
  generatedUrlsRef.current.clear();
12066
12095
  prevArtworkSrcRef.current = currentArtwork?.src;
12067
12096
  }
12068
12097
  }, [currentArtwork?.src]);
12069
- const onMockupUrlGeneratedRef = (0, import_react55.useRef)(onMockupUrlGenerated);
12098
+ const onMockupUrlGeneratedRef = (0, import_react56.useRef)(onMockupUrlGenerated);
12070
12099
  onMockupUrlGeneratedRef.current = onMockupUrlGenerated;
12071
- const handleUrlGenerated = (0, import_react55.useCallback)((mockupId, url) => {
12100
+ const handleUrlGenerated = (0, import_react56.useCallback)((mockupId, url) => {
12072
12101
  generatedUrlsRef.current.set(mockupId, url);
12073
12102
  onMockupUrlGeneratedRef.current?.(mockupId, url);
12074
12103
  }, []);
@@ -12076,24 +12105,24 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12076
12105
  const shouldHideDots = stickyHeroContext?.shouldHideDots ?? false;
12077
12106
  const priorityContext = useMockupPriorityOptional();
12078
12107
  const realtimeContext = useRealtimeOptional();
12079
- const [urlUpdateCounter, setUrlUpdateCounter] = (0, import_react55.useState)(0);
12080
- (0, import_react55.useEffect)(() => {
12108
+ const [urlUpdateCounter, setUrlUpdateCounter] = (0, import_react56.useState)(0);
12109
+ (0, import_react56.useEffect)(() => {
12081
12110
  if (!realtimeContext?.subscribeMockupResults) return;
12082
12111
  const unsubscribe = realtimeContext.subscribeMockupResults(() => {
12083
12112
  setUrlUpdateCounter((c) => c + 1);
12084
12113
  });
12085
12114
  return unsubscribe;
12086
12115
  }, [realtimeContext?.subscribeMockupResults]);
12087
- const mockupIds = (0, import_react55.useMemo)(() => {
12116
+ const mockupIds = (0, import_react56.useMemo)(() => {
12088
12117
  return images.filter((img) => img.isRealMockup && img.mockupId).map((img) => img.mockupId);
12089
12118
  }, [images]);
12090
- const realtimeMockupUrls = (0, import_react55.useMemo)(() => {
12119
+ const realtimeMockupUrls = (0, import_react56.useMemo)(() => {
12091
12120
  if (!realtimeContext?.getMockupUrls || mockupIds.length === 0) {
12092
12121
  return {};
12093
12122
  }
12094
12123
  return realtimeContext.getMockupUrls(mockupIds);
12095
12124
  }, [realtimeContext?.getMockupUrls, mockupIds, urlUpdateCounter]);
12096
- const imagesWithRealtimeUrls = (0, import_react55.useMemo)(() => {
12125
+ const imagesWithRealtimeUrls = (0, import_react56.useMemo)(() => {
12097
12126
  return images.map((img) => {
12098
12127
  if (img.isRealMockup && img.mockupId && realtimeMockupUrls[img.mockupId]) {
12099
12128
  return {
@@ -12105,10 +12134,10 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12105
12134
  });
12106
12135
  }, [images, realtimeMockupUrls]);
12107
12136
  const minSwipeDistance = 50;
12108
- (0, import_react55.useEffect)(() => {
12137
+ (0, import_react56.useEffect)(() => {
12109
12138
  setActiveIndex(currentIndex);
12110
12139
  }, [currentIndex]);
12111
- (0, import_react55.useEffect)(() => {
12140
+ (0, import_react56.useEffect)(() => {
12112
12141
  if (!priorityContext) return;
12113
12142
  const realMockups = images.map((img, idx) => ({ img, originalIdx: idx })).filter(({ img }) => img.isRealMockup && img.mockupId);
12114
12143
  const mockupIdsList = realMockups.map(({ img }) => img.mockupId);
@@ -12136,7 +12165,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12136
12165
  priorityContext.clearMobileCarouselMode?.();
12137
12166
  };
12138
12167
  }, [priorityContext, activeIndex, images]);
12139
- (0, import_react55.useEffect)(() => {
12168
+ (0, import_react56.useEffect)(() => {
12140
12169
  const indicator = indicatorRef.current;
12141
12170
  if (!indicator) return;
12142
12171
  let ticking = false;
@@ -12177,7 +12206,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12177
12206
  }, []);
12178
12207
  const SWIPE_TRACKING_KEY = "carousel-swipe-tracking";
12179
12208
  const PDP_VIEWS_BEFORE_PEEK = 10;
12180
- const getSwipeTracking = (0, import_react55.useCallback)(() => {
12209
+ const getSwipeTracking = (0, import_react56.useCallback)(() => {
12181
12210
  try {
12182
12211
  const stored = localStorage.getItem(SWIPE_TRACKING_KEY);
12183
12212
  if (stored) {
@@ -12187,7 +12216,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12187
12216
  }
12188
12217
  return { viewsWithoutSwipe: 0, hasEverSwiped: false };
12189
12218
  }, []);
12190
- const recordSwipe = (0, import_react55.useCallback)(() => {
12219
+ const recordSwipe = (0, import_react56.useCallback)(() => {
12191
12220
  if (hasSwipedThisSessionRef.current) return;
12192
12221
  hasSwipedThisSessionRef.current = true;
12193
12222
  try {
@@ -12201,7 +12230,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12201
12230
  } catch {
12202
12231
  }
12203
12232
  }, []);
12204
- (0, import_react55.useEffect)(() => {
12233
+ (0, import_react56.useEffect)(() => {
12205
12234
  if (!enablePeekAnimation || images.length <= 1) return;
12206
12235
  const tracking = getSwipeTracking();
12207
12236
  const newViewCount = tracking.viewsWithoutSwipe + 1;
@@ -12242,14 +12271,14 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12242
12271
  clearTimeout(clearTimeout_);
12243
12272
  };
12244
12273
  }, [images.length, getSwipeTracking, enablePeekAnimation]);
12245
- const wasTapRef = (0, import_react55.useRef)(false);
12246
- const handleImageTap = (0, import_react55.useCallback)(() => {
12274
+ const wasTapRef = (0, import_react56.useRef)(false);
12275
+ const handleImageTap = (0, import_react56.useCallback)(() => {
12247
12276
  if (!enableZoom) return;
12248
12277
  setViewerKey((prev) => prev + 1);
12249
12278
  setShowImageViewer(true);
12250
12279
  onZoomChange?.(true);
12251
12280
  }, [enableZoom, onZoomChange]);
12252
- const calculateDragOffset = (0, import_react55.useCallback)(
12281
+ const calculateDragOffset = (0, import_react56.useCallback)(
12253
12282
  (startX, currentX, containerWidth) => {
12254
12283
  const distance = startX - currentX;
12255
12284
  const offsetPercent = distance / containerWidth * 100;
@@ -12274,7 +12303,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12274
12303
  },
12275
12304
  [activeIndex, images.length]
12276
12305
  );
12277
- const handleSwipeEnd = (0, import_react55.useCallback)(
12306
+ const handleSwipeEnd = (0, import_react56.useCallback)(
12278
12307
  (startX, endX, containerWidth) => {
12279
12308
  const distance = startX - endX;
12280
12309
  const distancePercent = Math.abs(distance) / containerWidth * 100;
@@ -12305,7 +12334,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12305
12334
  },
12306
12335
  [activeIndex, images.length, onIndexChange, recordSwipe]
12307
12336
  );
12308
- (0, import_react55.useEffect)(() => {
12337
+ (0, import_react56.useEffect)(() => {
12309
12338
  const container = carouselRef.current;
12310
12339
  if (!container) return;
12311
12340
  const handleTouchStart = (e) => {
@@ -12394,11 +12423,11 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12394
12423
  handleSwipeEnd,
12395
12424
  handleImageTap
12396
12425
  ]);
12397
- const mouseStartRef = (0, import_react55.useRef)(
12426
+ const mouseStartRef = (0, import_react56.useRef)(
12398
12427
  null
12399
12428
  );
12400
- const isMouseDraggingRef = (0, import_react55.useRef)(false);
12401
- (0, import_react55.useEffect)(() => {
12429
+ const isMouseDraggingRef = (0, import_react56.useRef)(false);
12430
+ (0, import_react56.useEffect)(() => {
12402
12431
  const container = carouselRef.current;
12403
12432
  if (!container) return;
12404
12433
  const handleMouseDown = (e) => {
@@ -12474,7 +12503,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12474
12503
  container.removeEventListener("mouseleave", handleMouseLeave);
12475
12504
  };
12476
12505
  }, [calculateDragOffset, handleSwipeEnd, handleImageTap]);
12477
- const goToSlide = (0, import_react55.useCallback)(
12506
+ const goToSlide = (0, import_react56.useCallback)(
12478
12507
  (index, withTransition = true) => {
12479
12508
  if (withTransition) {
12480
12509
  setIsTransitioning(true);
@@ -12492,16 +12521,16 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12492
12521
  },
12493
12522
  [onIndexChange]
12494
12523
  );
12495
- (0, import_react55.useEffect)(() => {
12524
+ (0, import_react56.useEffect)(() => {
12496
12525
  if (stickyHeroContext?.setCarouselIndicator && images.length > 1) {
12497
- const indicator = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12526
+ const indicator = /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12498
12527
  "div",
12499
12528
  {
12500
12529
  className: "w-full",
12501
12530
  role: "group",
12502
12531
  "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)(
12532
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "relative h-1", children: [
12533
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "flex h-full", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12505
12534
  "button",
12506
12535
  {
12507
12536
  onClick: () => goToSlide(index),
@@ -12511,7 +12540,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12511
12540
  },
12512
12541
  index
12513
12542
  )) }),
12514
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12543
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12515
12544
  "div",
12516
12545
  {
12517
12546
  className: "absolute top-0 h-full bg-primary transition-all duration-300 ease-out",
@@ -12534,10 +12563,10 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12534
12563
  };
12535
12564
  }, [activeIndex, images.length, goToSlide, stickyHeroContext]);
12536
12565
  if (!images || images.length === 0) {
12537
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12566
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12538
12567
  }
12539
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: `relative w-full h-full ${className}`, children: [
12540
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12568
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: `relative w-full h-full ${className}`, children: [
12569
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12541
12570
  "div",
12542
12571
  {
12543
12572
  ref: carouselRef,
@@ -12555,7 +12584,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12555
12584
  role: "region",
12556
12585
  "aria-roledescription": "carousel",
12557
12586
  "aria-label": "Product images",
12558
- children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12587
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12559
12588
  "div",
12560
12589
  {
12561
12590
  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 +12594,15 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12565
12594
  children: images.map((image, index) => {
12566
12595
  const DECODE_WINDOW = 1;
12567
12596
  const isWithinDecodeWindow = Math.abs(index - activeIndex) <= DECODE_WINDOW;
12568
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12597
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12569
12598
  "div",
12570
12599
  {
12571
12600
  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 ? (
12601
+ children: !isWithinDecodeWindow ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? (
12573
12602
  // Rainbow prism loader (same as the /create route) instead of
12574
12603
  // 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)(
12604
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" })
12605
+ ) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12577
12606
  HeroProductImage,
12578
12607
  {
12579
12608
  productId,
@@ -12585,7 +12614,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12585
12614
  onUrlGenerated: image.mockupId ? (url) => handleUrlGenerated(image.mockupId, url) : void 0,
12586
12615
  className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12587
12616
  }
12588
- ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12617
+ ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(LoadingOverlayPrismCandyInline, { visible: true, variant: "light" }) : /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12589
12618
  StaticCarouselImage,
12590
12619
  {
12591
12620
  src: image.src,
@@ -12601,7 +12630,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12601
12630
  )
12602
12631
  }
12603
12632
  ),
12604
- showIndicators && images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12633
+ showIndicators && images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12605
12634
  "div",
12606
12635
  {
12607
12636
  ref: indicatorRef,
@@ -12609,8 +12638,8 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12609
12638
  className: "relative z-20 w-full",
12610
12639
  role: "group",
12611
12640
  "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)(
12641
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "relative h-1", children: [
12642
+ /* @__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
12643
  "button",
12615
12644
  {
12616
12645
  onClick: () => goToSlide(index),
@@ -12620,7 +12649,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12620
12649
  },
12621
12650
  index
12622
12651
  )) }),
12623
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12652
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12624
12653
  "div",
12625
12654
  {
12626
12655
  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 +12684,7 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12655
12684
  naturalHeight: img.naturalHeight
12656
12685
  } : null;
12657
12686
  }).filter((img) => img !== null);
12658
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12687
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12659
12688
  EnhancedImageViewer,
12660
12689
  {
12661
12690
  imageUrl,
@@ -12694,8 +12723,8 @@ var MobileProductCarousel = (0, import_react55.memo)(function MobileProductCarou
12694
12723
  });
12695
12724
 
12696
12725
  // src/composed/carousels/HeroCarousel.tsx
12697
- var import_react56 = require("react");
12698
- var import_jsx_runtime74 = require("react/jsx-runtime");
12726
+ var import_react57 = require("react");
12727
+ var import_jsx_runtime75 = require("react/jsx-runtime");
12699
12728
  function HeroCarousel({
12700
12729
  images,
12701
12730
  currentIndex = 0,
@@ -12705,16 +12734,16 @@ function HeroCarousel({
12705
12734
  productId,
12706
12735
  onImageTap
12707
12736
  }) {
12708
- const [activeIndex, setActiveIndex] = (0, import_react56.useState)(currentIndex);
12709
- const containerRef = (0, import_react56.useRef)(null);
12710
- const touchStartRef = (0, import_react56.useRef)(
12737
+ const [activeIndex, setActiveIndex] = (0, import_react57.useState)(currentIndex);
12738
+ const containerRef = (0, import_react57.useRef)(null);
12739
+ const touchStartRef = (0, import_react57.useRef)(
12711
12740
  null
12712
12741
  );
12713
- const isSwipingRef = (0, import_react56.useRef)(false);
12714
- (0, import_react56.useEffect)(() => {
12742
+ const isSwipingRef = (0, import_react57.useRef)(false);
12743
+ (0, import_react57.useEffect)(() => {
12715
12744
  setActiveIndex(currentIndex);
12716
12745
  }, [currentIndex]);
12717
- const goToSlide = (0, import_react56.useCallback)(
12746
+ const goToSlide = (0, import_react57.useCallback)(
12718
12747
  (index) => {
12719
12748
  const clampedIndex = Math.max(0, Math.min(images.length - 1, index));
12720
12749
  setActiveIndex(clampedIndex);
@@ -12722,7 +12751,7 @@ function HeroCarousel({
12722
12751
  },
12723
12752
  [images.length, onIndexChange]
12724
12753
  );
12725
- (0, import_react56.useEffect)(() => {
12754
+ (0, import_react57.useEffect)(() => {
12726
12755
  const container = containerRef.current;
12727
12756
  if (!container) return;
12728
12757
  const handleTouchStart = (e) => {
@@ -12774,9 +12803,9 @@ function HeroCarousel({
12774
12803
  };
12775
12804
  }, [activeIndex, images.length, goToSlide, onImageTap]);
12776
12805
  if (!images || images.length === 0) {
12777
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "w-full h-full bg-muted" });
12806
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "w-full h-full bg-muted" });
12778
12807
  }
12779
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
12808
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(
12780
12809
  "div",
12781
12810
  {
12782
12811
  ref: containerRef,
@@ -12787,7 +12816,7 @@ function HeroCarousel({
12787
12816
  overflow: "hidden"
12788
12817
  },
12789
12818
  children: [
12790
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12819
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12791
12820
  "div",
12792
12821
  {
12793
12822
  className: "flex h-full transition-transform duration-300 ease-out",
@@ -12798,14 +12827,14 @@ function HeroCarousel({
12798
12827
  backfaceVisibility: "hidden",
12799
12828
  WebkitBackfaceVisibility: "hidden"
12800
12829
  },
12801
- children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12830
+ children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12802
12831
  "div",
12803
12832
  {
12804
12833
  className: "w-full h-full flex-shrink-0",
12805
12834
  style: {
12806
12835
  contain: "layout paint"
12807
12836
  },
12808
- children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12837
+ children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12809
12838
  HeroProductImage,
12810
12839
  {
12811
12840
  productId,
@@ -12814,7 +12843,7 @@ function HeroCarousel({
12814
12843
  mockupId: image.mockupId,
12815
12844
  className: "w-full h-full object-cover"
12816
12845
  }
12817
- ) : /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12846
+ ) : /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12818
12847
  "img",
12819
12848
  {
12820
12849
  src: image.src,
@@ -12831,12 +12860,12 @@ function HeroCarousel({
12831
12860
  ))
12832
12861
  }
12833
12862
  ),
12834
- images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12863
+ images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12835
12864
  "div",
12836
12865
  {
12837
12866
  className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 z-10",
12838
12867
  style: { contain: "layout style" },
12839
- children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12868
+ children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12840
12869
  "button",
12841
12870
  {
12842
12871
  onClick: () => goToSlide(index),
@@ -12853,8 +12882,8 @@ function HeroCarousel({
12853
12882
  }
12854
12883
 
12855
12884
  // src/composed/grids/MasonryGrid.tsx
12856
- var import_react57 = require("react");
12857
- var import_jsx_runtime75 = require("react/jsx-runtime");
12885
+ var import_react58 = require("react");
12886
+ var import_jsx_runtime76 = require("react/jsx-runtime");
12858
12887
  var BREAKPOINTS = {
12859
12888
  sm: 640,
12860
12889
  md: 768,
@@ -12906,13 +12935,13 @@ function MasonryGrid({
12906
12935
  className = "",
12907
12936
  emptyContent
12908
12937
  }) {
12909
- const [columnCount, setColumnCount] = (0, import_react57.useState)(
12938
+ const [columnCount, setColumnCount] = (0, import_react58.useState)(
12910
12939
  () => typeof columns === "number" ? columns : getColumnCount(
12911
12940
  typeof window !== "undefined" ? window.innerWidth : 1024,
12912
12941
  columns
12913
12942
  )
12914
12943
  );
12915
- (0, import_react57.useEffect)(() => {
12944
+ (0, import_react58.useEffect)(() => {
12916
12945
  const updateColumnCount = () => {
12917
12946
  setColumnCount(getColumnCount(window.innerWidth, columns));
12918
12947
  };
@@ -12920,30 +12949,30 @@ function MasonryGrid({
12920
12949
  window.addEventListener("resize", updateColumnCount);
12921
12950
  return () => window.removeEventListener("resize", updateColumnCount);
12922
12951
  }, [columns]);
12923
- const distributedColumns = (0, import_react57.useMemo)(
12952
+ const distributedColumns = (0, import_react58.useMemo)(
12924
12953
  () => distributeItems(items, columnCount),
12925
12954
  [items, columnCount]
12926
12955
  );
12927
12956
  if (items.length === 0) {
12928
12957
  if (emptyContent) {
12929
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(import_jsx_runtime75.Fragment, { children: emptyContent });
12958
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(import_jsx_runtime76.Fragment, { children: emptyContent });
12930
12959
  }
12931
12960
  return null;
12932
12961
  }
12933
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12962
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
12934
12963
  "div",
12935
12964
  {
12936
12965
  className: `flex ${className}`,
12937
12966
  style: { gap: `${gap}px` },
12938
12967
  role: "list",
12939
- children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12968
+ children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
12940
12969
  "div",
12941
12970
  {
12942
12971
  className: "flex-1 flex flex-col",
12943
12972
  style: { gap: `${gap}px` },
12944
12973
  children: columnItems.map((item, itemIndex) => {
12945
12974
  const originalIndex = itemIndex * columnCount + columnIndex;
12946
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12975
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12947
12976
  })
12948
12977
  },
12949
12978
  columnIndex
@@ -12956,7 +12985,7 @@ function MasonryGrid({
12956
12985
  init_dev_warnings();
12957
12986
 
12958
12987
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12959
- var import_react59 = require("react");
12988
+ var import_react60 = require("react");
12960
12989
 
12961
12990
  // src/layouts/hero-zoom/types.ts
12962
12991
  var DEFAULT_HERO_ZOOM_CONFIG = {
@@ -12968,19 +12997,19 @@ var DEFAULT_HERO_ZOOM_CONFIG = {
12968
12997
  };
12969
12998
 
12970
12999
  // src/layouts/hero-zoom/useHeroZoomScales.ts
12971
- var import_react58 = require("react");
13000
+ var import_react59 = require("react");
12972
13001
  function useHeroZoomScales(config = {}) {
12973
13002
  const { initialScale, accountForRetina, maxRetinaMultiplier } = {
12974
13003
  ...DEFAULT_HERO_ZOOM_CONFIG,
12975
13004
  ...config
12976
13005
  };
12977
- const [isHydrated, setIsHydrated] = (0, import_react58.useState)(false);
13006
+ const [isHydrated, setIsHydrated] = (0, import_react59.useState)(false);
12978
13007
  const ssrMultiplier = accountForRetina ? maxRetinaMultiplier : 2;
12979
- const [scales, setScales] = (0, import_react58.useState)(() => ({
13008
+ const [scales, setScales] = (0, import_react59.useState)(() => ({
12980
13009
  visual: initialScale,
12981
13010
  render: initialScale * ssrMultiplier
12982
13011
  }));
12983
- const calculateScales = (0, import_react58.useCallback)(() => {
13012
+ const calculateScales = (0, import_react59.useCallback)(() => {
12984
13013
  const visualScale = Math.max(1, Math.min(4, initialScale));
12985
13014
  let renderScale;
12986
13015
  if (accountForRetina) {
@@ -12995,7 +13024,7 @@ function useHeroZoomScales(config = {}) {
12995
13024
  renderScale = Math.max(1, Math.min(8, renderScale));
12996
13025
  return { visual: visualScale, render: renderScale };
12997
13026
  }, [initialScale, accountForRetina, maxRetinaMultiplier]);
12998
- (0, import_react58.useEffect)(() => {
13027
+ (0, import_react59.useEffect)(() => {
12999
13028
  const supportsScrollTimeline = CSS.supports(
13000
13029
  "animation-timeline",
13001
13030
  "scroll()"
@@ -13045,7 +13074,7 @@ function useHeroZoomScales(config = {}) {
13045
13074
  }
13046
13075
 
13047
13076
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
13048
- var import_jsx_runtime76 = require("react/jsx-runtime");
13077
+ var import_jsx_runtime77 = require("react/jsx-runtime");
13049
13078
  function HeroZoomLayout({
13050
13079
  config = {},
13051
13080
  header,
@@ -13060,9 +13089,9 @@ function HeroZoomLayout({
13060
13089
  };
13061
13090
  const { aspectRatio, initialScale, headerHeight } = mergedConfig;
13062
13091
  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)(() => {
13092
+ const imageContainerRef = (0, import_react60.useRef)(null);
13093
+ const headerRef = (0, import_react60.useRef)(null);
13094
+ (0, import_react60.useEffect)(() => {
13066
13095
  if (typeof window === "undefined") return;
13067
13096
  const originalRestoration = "scrollRestoration" in history ? history.scrollRestoration : "auto";
13068
13097
  if ("scrollRestoration" in history) {
@@ -13075,7 +13104,7 @@ function HeroZoomLayout({
13075
13104
  }
13076
13105
  };
13077
13106
  }, []);
13078
- (0, import_react59.useEffect)(() => {
13107
+ (0, import_react60.useEffect)(() => {
13079
13108
  const supportsScrollTimeline = CSS.supports(
13080
13109
  "animation-timeline",
13081
13110
  "scroll()"
@@ -13204,7 +13233,7 @@ function HeroZoomLayout({
13204
13233
  The drawer covers the hero completely, so let animation run continuously. */
13205
13234
  }
13206
13235
  `;
13207
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
13236
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
13208
13237
  "div",
13209
13238
  {
13210
13239
  className: `relative min-h-screen ${className}`,
@@ -13218,8 +13247,8 @@ function HeroZoomLayout({
13218
13247
  "--hero-zoom-final-transform": 1 / activeRender
13219
13248
  },
13220
13249
  children: [
13221
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13222
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13250
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13251
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13223
13252
  "div",
13224
13253
  {
13225
13254
  style: {
@@ -13227,7 +13256,7 @@ function HeroZoomLayout({
13227
13256
  }
13228
13257
  }
13229
13258
  ),
13230
- header && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13259
+ header && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13231
13260
  "div",
13232
13261
  {
13233
13262
  ref: headerRef,
@@ -13240,7 +13269,7 @@ function HeroZoomLayout({
13240
13269
  children: header
13241
13270
  }
13242
13271
  ),
13243
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13272
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13244
13273
  "div",
13245
13274
  {
13246
13275
  ref: imageContainerRef,
@@ -13260,15 +13289,15 @@ function HeroZoomLayout({
13260
13289
  children: hero
13261
13290
  }
13262
13291
  ),
13263
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "relative z-10", children })
13292
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "relative z-10", children })
13264
13293
  ]
13265
13294
  }
13266
13295
  );
13267
13296
  }
13268
13297
 
13269
13298
  // src/layouts/hero-zoom/HeroShrinkLayout.tsx
13270
- var import_react60 = require("react");
13271
- var import_jsx_runtime77 = require("react/jsx-runtime");
13299
+ var import_react61 = require("react");
13300
+ var import_jsx_runtime78 = require("react/jsx-runtime");
13272
13301
  var DEFAULT_CONFIG = {
13273
13302
  aspectRatio: 16 / 9,
13274
13303
  initialHeightPercent: 70,
@@ -13288,13 +13317,13 @@ function HeroShrinkLayout({
13288
13317
  ...config
13289
13318
  };
13290
13319
  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)(() => {
13320
+ const heroRef = (0, import_react61.useRef)(null);
13321
+ const headerRef = (0, import_react61.useRef)(null);
13322
+ const [isClient, setIsClient] = (0, import_react61.useState)(false);
13323
+ (0, import_react61.useEffect)(() => {
13295
13324
  setIsClient(true);
13296
13325
  }, []);
13297
- (0, import_react60.useEffect)(() => {
13326
+ (0, import_react61.useEffect)(() => {
13298
13327
  if (!isClient) return;
13299
13328
  const supportsScrollTimeline = CSS.supports("animation-timeline", "scroll()");
13300
13329
  if (supportsScrollTimeline) return;
@@ -13381,15 +13410,15 @@ function HeroShrinkLayout({
13381
13410
  }
13382
13411
  `;
13383
13412
  const spacerHeight = `calc(${initialHeightPercent}svh + ${headerHeight}px)`;
13384
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
13413
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
13385
13414
  "div",
13386
13415
  {
13387
13416
  className: `relative min-h-screen ${className}`,
13388
13417
  style: { ...style, ...cssVars },
13389
13418
  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)(
13419
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13420
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { style: { height: spacerHeight } }),
13421
+ header && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13393
13422
  "div",
13394
13423
  {
13395
13424
  ref: headerRef,
@@ -13398,7 +13427,7 @@ function HeroShrinkLayout({
13398
13427
  children: header
13399
13428
  }
13400
13429
  ),
13401
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13430
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13402
13431
  "div",
13403
13432
  {
13404
13433
  ref: heroRef,
@@ -13406,15 +13435,15 @@ function HeroShrinkLayout({
13406
13435
  children: hero
13407
13436
  }
13408
13437
  ),
13409
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "relative z-10 bg-background", children })
13438
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "relative z-10 bg-background", children })
13410
13439
  ]
13411
13440
  }
13412
13441
  );
13413
13442
  }
13414
13443
 
13415
13444
  // src/layouts/pdp/ImageEdgeBlur.tsx
13416
- var import_react61 = __toESM(require("react"), 1);
13417
- var import_jsx_runtime78 = require("react/jsx-runtime");
13445
+ var import_react62 = __toESM(require("react"), 1);
13446
+ var import_jsx_runtime79 = require("react/jsx-runtime");
13418
13447
  var BLUR_CONFIG = {
13419
13448
  blur: 24,
13420
13449
  crossfade: 68
@@ -13438,7 +13467,7 @@ var BLUR_LAYERS = [
13438
13467
  { blur: Math.round(BLUR_CONFIG.blur * 0.5), zone: 0.6 },
13439
13468
  { blur: BLUR_CONFIG.blur, zone: 1 }
13440
13469
  ];
13441
- var ImageEdgeBlur = import_react61.default.memo(
13470
+ var ImageEdgeBlur = import_react62.default.memo(
13442
13471
  function ImageEdgeBlur2({
13443
13472
  imageSrc,
13444
13473
  imageCapInfo,
@@ -13469,7 +13498,7 @@ var ImageEdgeBlur = import_react61.default.memo(
13469
13498
  viewportWidth / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO,
13470
13499
  maxWidthPx / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO
13471
13500
  );
13472
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13501
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13473
13502
  "div",
13474
13503
  {
13475
13504
  className: `absolute inset-0 pointer-events-none overflow-hidden ${className}`,
@@ -13477,7 +13506,7 @@ var ImageEdgeBlur = import_react61.default.memo(
13477
13506
  children: BLUR_LAYERS.map((layer, index) => {
13478
13507
  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
13508
  const blurScale = 1 + layer.blur * 3 / containerHeightPx;
13480
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13509
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13481
13510
  "img",
13482
13511
  {
13483
13512
  src: imageSrc,
@@ -13524,7 +13553,7 @@ var ImageEdgeBlur = import_react61.default.memo(
13524
13553
  );
13525
13554
 
13526
13555
  // src/layouts/pdp/PDPLayout.tsx
13527
- var import_jsx_runtime79 = require("react/jsx-runtime");
13556
+ var import_jsx_runtime80 = require("react/jsx-runtime");
13528
13557
  function PDPLayout({
13529
13558
  renderHeroImage,
13530
13559
  renderContent,
@@ -13552,15 +13581,15 @@ function PDPLayout({
13552
13581
  isDesktop,
13553
13582
  isWideMonitor: isWideMonitor2
13554
13583
  };
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) })
13584
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: `pdp-layout ${className}`, children: [
13585
+ (isDesktop === false || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "md:hidden", children: [
13586
+ renderMobileCarousel && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13587
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "mobile-content p-4", children: renderContent(contentProps) })
13559
13588
  ] }),
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: [
13589
+ (isDesktop === true || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "hidden md:block relative", children: [
13590
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "desktop-hero relative", children: [
13562
13591
  renderHeroImage(heroProps),
13563
- showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13592
+ showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13564
13593
  ImageEdgeBlur,
13565
13594
  {
13566
13595
  imageSrc: blurImageSrc,
@@ -13571,7 +13600,7 @@ function PDPLayout({
13571
13600
  }
13572
13601
  )
13573
13602
  ] }),
13574
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13603
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13575
13604
  "div",
13576
13605
  {
13577
13606
  className: "desktop-sidebar",
@@ -13588,8 +13617,8 @@ function PDPLayout({
13588
13617
  }
13589
13618
 
13590
13619
  // src/layouts/pdp/SimpleImageBlur.tsx
13591
- var import_react62 = __toESM(require("react"), 1);
13592
- var import_jsx_runtime80 = require("react/jsx-runtime");
13620
+ var import_react63 = __toESM(require("react"), 1);
13621
+ var import_jsx_runtime81 = require("react/jsx-runtime");
13593
13622
  var BLUR_CONFIG2 = {
13594
13623
  blur: 24,
13595
13624
  crossfade: 60
@@ -13612,7 +13641,7 @@ function getFadeInMask(crossfadeWidth) {
13612
13641
  black ${crossfadeWidth + 10}px
13613
13642
  )`;
13614
13643
  }
13615
- var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13644
+ var SimpleImageBlur = import_react63.default.memo(function SimpleImageBlur2({
13616
13645
  imageSrc,
13617
13646
  width,
13618
13647
  height = "100%",
@@ -13622,7 +13651,7 @@ var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13622
13651
  if (!imageSrc || width <= 0) return null;
13623
13652
  const fadeInMask = getFadeInMask(BLUR_CONFIG2.crossfade);
13624
13653
  const extendedWidth = width + BLUR_CONFIG2.blur * 2;
13625
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13654
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13626
13655
  "div",
13627
13656
  {
13628
13657
  className: `relative overflow-hidden ${className}`,
@@ -13635,7 +13664,7 @@ var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13635
13664
  black 0%,
13636
13665
  black ${layer.zone * 100}%,
13637
13666
  transparent ${layer.zone * 100 + 10}%)`;
13638
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13667
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13639
13668
  "img",
13640
13669
  {
13641
13670
  src: imageSrc,
@@ -13665,8 +13694,8 @@ var SimpleImageBlur = import_react62.default.memo(function SimpleImageBlur2({
13665
13694
  });
13666
13695
 
13667
13696
  // src/layouts/pdp/EdgeBlurBox.tsx
13668
- var import_react63 = __toESM(require("react"), 1);
13669
- var import_jsx_runtime81 = require("react/jsx-runtime");
13697
+ var import_react64 = __toESM(require("react"), 1);
13698
+ var import_jsx_runtime82 = require("react/jsx-runtime");
13670
13699
  var BLUR_CONFIG3 = {
13671
13700
  blur: 24,
13672
13701
  crossfade: 60
@@ -13690,7 +13719,7 @@ function getFadeOutMask(crossfadeWidth) {
13690
13719
  transparent 100%
13691
13720
  )`;
13692
13721
  }
13693
- var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13722
+ var EdgeBlurBox = import_react64.default.memo(function EdgeBlurBox2({
13694
13723
  imageSrc,
13695
13724
  width,
13696
13725
  height = "100%",
@@ -13705,7 +13734,7 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13705
13734
  const blurExtend = BLUR_CONFIG3.blur * 2;
13706
13735
  const actualSharpWidth = sharpImageWidth ?? width + overlapLeft;
13707
13736
  const hasOverlap = overlapLeft > 0;
13708
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
13737
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
13709
13738
  "div",
13710
13739
  {
13711
13740
  className: `relative ${className}`,
@@ -13716,7 +13745,7 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13716
13745
  overflow: hasOverlap ? "visible" : "hidden"
13717
13746
  },
13718
13747
  children: [
13719
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13748
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13720
13749
  "div",
13721
13750
  {
13722
13751
  style: {
@@ -13730,7 +13759,7 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13730
13759
  transparent ${100 - (layer.zone * 100 + 10)}%,
13731
13760
  black ${100 - layer.zone * 100}%,
13732
13761
  black 100%)`;
13733
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13762
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13734
13763
  "img",
13735
13764
  {
13736
13765
  src: imageSrc,
@@ -13758,7 +13787,7 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13758
13787
  })
13759
13788
  }
13760
13789
  ),
13761
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13790
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13762
13791
  "img",
13763
13792
  {
13764
13793
  src: imageSrc,
@@ -13786,8 +13815,8 @@ var EdgeBlurBox = import_react63.default.memo(function EdgeBlurBox2({
13786
13815
  });
13787
13816
 
13788
13817
  // src/layouts/pdp/ImageBlurExtension.tsx
13789
- var import_react64 = __toESM(require("react"), 1);
13790
- var import_jsx_runtime82 = require("react/jsx-runtime");
13818
+ var import_react65 = __toESM(require("react"), 1);
13819
+ var import_jsx_runtime83 = require("react/jsx-runtime");
13791
13820
  var BLUR_CONFIG4 = {
13792
13821
  blur: 24,
13793
13822
  crossfadeWidth: 80
@@ -13810,7 +13839,7 @@ function getFadeOutMask2(crossfadeWidth) {
13810
13839
  transparent 100%
13811
13840
  )`;
13812
13841
  }
13813
- var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension2({
13842
+ var ImageBlurExtension = import_react65.default.memo(function ImageBlurExtension2({
13814
13843
  imageSrc,
13815
13844
  width,
13816
13845
  height,
@@ -13824,7 +13853,7 @@ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension
13824
13853
  const internalImageLeft = `calc(${heroImageLeft} - 100vw + ${width}px)`;
13825
13854
  const fadeOutMask = getFadeOutMask2(crossfadeWidth);
13826
13855
  const heightValue = typeof height === "number" ? `${height}px` : height;
13827
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
13856
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
13828
13857
  "div",
13829
13858
  {
13830
13859
  className: `relative overflow-hidden ${className}`,
@@ -13833,7 +13862,7 @@ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension
13833
13862
  height: heightValue
13834
13863
  },
13835
13864
  children: [
13836
- BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13865
+ BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13837
13866
  "img",
13838
13867
  {
13839
13868
  src: imageSrc,
@@ -13857,7 +13886,7 @@ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension
13857
13886
  },
13858
13887
  `blur-${index}`
13859
13888
  )),
13860
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13889
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13861
13890
  "img",
13862
13891
  {
13863
13892
  src: imageSrc,
@@ -13885,39 +13914,39 @@ var ImageBlurExtension = import_react64.default.memo(function ImageBlurExtension
13885
13914
  });
13886
13915
 
13887
13916
  // src/design-system/ColorSwatch.tsx
13888
- var import_jsx_runtime83 = require("react/jsx-runtime");
13917
+ var import_jsx_runtime84 = require("react/jsx-runtime");
13889
13918
  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)(
13919
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: `flex flex-col gap-1 ${className}`, children: [
13920
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
13892
13921
  "div",
13893
13922
  {
13894
13923
  className: "h-16 w-full rounded-lg border border-border shadow-sm",
13895
13924
  style: { backgroundColor: `var(${cssVar})` }
13896
13925
  }
13897
13926
  ),
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 })
13927
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13928
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: cssVar })
13900
13929
  ] });
13901
13930
  }
13902
13931
  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)(
13932
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex items-center gap-4 py-2", children: [
13933
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
13905
13934
  "div",
13906
13935
  {
13907
13936
  className: "h-10 w-10 rounded-lg border border-border shadow-sm flex-shrink-0",
13908
13937
  style: { backgroundColor: `var(${cssVar})` }
13909
13938
  }
13910
13939
  ),
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 })
13940
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex-1 min-w-0", children: [
13941
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13942
+ description && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-xs text-muted-foreground", children: description })
13914
13943
  ] }),
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 })
13944
+ /* @__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
13945
  ] });
13917
13946
  }
13918
13947
 
13919
13948
  // src/design-system/ColorPalette.tsx
13920
- var import_jsx_runtime84 = require("react/jsx-runtime");
13949
+ var import_jsx_runtime85 = require("react/jsx-runtime");
13921
13950
  var COLOR_GROUPS = [
13922
13951
  {
13923
13952
  name: "Base",
@@ -13998,17 +14027,17 @@ var COLOR_GROUPS = [
13998
14027
  }
13999
14028
  ];
14000
14029
  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)(
14030
+ 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: [
14031
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
14032
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
14033
+ 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
14034
  ColorTokenSwatch,
14006
14035
  {
14007
14036
  name: color.name,
14008
14037
  cssVar: color.cssVar
14009
14038
  },
14010
14039
  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)(
14040
+ )) }) : /* @__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
14041
  ColorRow,
14013
14042
  {
14014
14043
  name: color.name,
@@ -14021,7 +14050,7 @@ function ColorPalette({ layout = "list", className = "" }) {
14021
14050
  }
14022
14051
 
14023
14052
  // src/design-system/TypographyScale.tsx
14024
- var import_jsx_runtime85 = require("react/jsx-runtime");
14053
+ var import_jsx_runtime86 = require("react/jsx-runtime");
14025
14054
  var FONT_SAMPLES = [
14026
14055
  {
14027
14056
  name: "Heading",
@@ -14055,14 +14084,14 @@ var FONT_SAMPLES = [
14055
14084
  }
14056
14085
  ];
14057
14086
  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 })
14087
+ 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: [
14088
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
14089
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
14090
+ /* @__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
14091
  ] }),
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)(
14092
+ /* @__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: [
14093
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
14094
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
14066
14095
  "p",
14067
14096
  {
14068
14097
  className: `${size} text-foreground`,
@@ -14081,8 +14110,8 @@ var RADIUS_SAMPLES = [
14081
14110
  { name: "Full", value: "9999px" }
14082
14111
  ];
14083
14112
  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)(
14113
+ 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: [
14114
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
14086
14115
  "div",
14087
14116
  {
14088
14117
  className: "h-16 w-16 bg-primary",
@@ -14091,13 +14120,13 @@ function RadiusScale({ className = "" }) {
14091
14120
  }
14092
14121
  }
14093
14122
  ),
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 })
14123
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
14124
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: radius.cssVar || radius.value })
14096
14125
  ] }, radius.name)) }) });
14097
14126
  }
14098
14127
 
14099
14128
  // src/design-system/ThemeSwitcher.tsx
14100
- var import_react65 = require("react");
14129
+ var import_react66 = require("react");
14101
14130
 
14102
14131
  // src/themes/types.ts
14103
14132
  var RADIUS_PRESETS = {
@@ -15265,7 +15294,7 @@ function applyTheme(config) {
15265
15294
  }
15266
15295
 
15267
15296
  // src/design-system/ThemeSwitcher.tsx
15268
- var import_jsx_runtime86 = require("react/jsx-runtime");
15297
+ var import_jsx_runtime87 = require("react/jsx-runtime");
15269
15298
  function readThemeFromDOM() {
15270
15299
  if (typeof document === "undefined") {
15271
15300
  return { themeName: "Linear", isDark: false };
@@ -15283,10 +15312,10 @@ function readThemeFromDOM() {
15283
15312
  return { themeName: "Linear", isDark: dark };
15284
15313
  }
15285
15314
  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)(() => {
15315
+ const [currentTheme, setCurrentTheme] = (0, import_react66.useState)("Linear");
15316
+ const [isDark, setIsDark] = (0, import_react66.useState)(false);
15317
+ const [isOpen, setIsOpen] = (0, import_react66.useState)(false);
15318
+ (0, import_react66.useEffect)(() => {
15290
15319
  const { themeName, isDark: dark } = readThemeFromDOM();
15291
15320
  setCurrentTheme(themeName);
15292
15321
  setIsDark(dark);
@@ -15325,61 +15354,61 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
15325
15354
  applyTheme(config);
15326
15355
  };
15327
15356
  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)(
15357
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: `flex items-center gap-3 ${className}`, children: [
15358
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "relative", children: [
15359
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
15331
15360
  "button",
15332
15361
  {
15333
15362
  onClick: () => setIsOpen(!isOpen),
15334
15363
  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
15364
  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" }) })
15365
+ /* @__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" }) }),
15366
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "font-medium", children: currentTheme }),
15367
+ /* @__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
15368
  ]
15340
15369
  }
15341
15370
  ),
15342
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(import_jsx_runtime86.Fragment, { children: [
15343
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15371
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(import_jsx_runtime87.Fragment, { children: [
15372
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15344
15373
  "div",
15345
15374
  {
15346
15375
  className: "fixed inset-0 z-40",
15347
15376
  onClick: () => setIsOpen(false)
15348
15377
  }
15349
15378
  ),
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)(
15379
+ /* @__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
15380
  "button",
15352
15381
  {
15353
15382
  onClick: () => handleThemeSelect(theme.name),
15354
15383
  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
15384
  children: [
15356
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15385
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15357
15386
  "div",
15358
15387
  {
15359
15388
  className: "w-4 h-4 rounded-full border border-border",
15360
15389
  style: { backgroundColor: theme.primaryColor || "#888" }
15361
15390
  }
15362
15391
  ),
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" }) })
15392
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "text-foreground", children: theme.name }),
15393
+ 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
15394
  ]
15366
15395
  },
15367
15396
  theme.name
15368
15397
  )) })
15369
15398
  ] })
15370
15399
  ] }),
15371
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
15400
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
15372
15401
  "button",
15373
15402
  {
15374
15403
  onClick: handleDarkModeToggle,
15375
15404
  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
15405
  title: `Switch to ${isDark ? "light" : "dark"} mode`,
15377
15406
  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" })
15407
+ 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: [
15408
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
15409
+ /* @__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" })
15410
+ ] }) : /* @__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" }) }),
15411
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "text-sm", children: isDark ? "Light" : "Dark" })
15383
15412
  ]
15384
15413
  }
15385
15414
  )
@@ -15387,7 +15416,7 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
15387
15416
  }
15388
15417
 
15389
15418
  // src/design-system/DesignSystemPage.tsx
15390
- var import_jsx_runtime87 = require("react/jsx-runtime");
15419
+ var import_jsx_runtime88 = require("react/jsx-runtime");
15391
15420
  function DesignSystemPage({
15392
15421
  showThemeSwitcher = true,
15393
15422
  showColors = true,
@@ -15397,29 +15426,29 @@ function DesignSystemPage({
15397
15426
  colorLayout = "list",
15398
15427
  className = ""
15399
15428
  }) {
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" })
15429
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: `max-w-4xl mx-auto px-4 py-8 ${className}`, children: [
15430
+ /* @__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: [
15431
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { children: [
15432
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
15433
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("p", { className: "text-lg text-muted-foreground", children: "Visual reference for theme tokens and styles" })
15405
15434
  ] }),
15406
- showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ThemeSwitcher, {})
15435
+ showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ThemeSwitcher, {})
15407
15436
  ] }) }),
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 })
15437
+ showColors && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("section", { className: "mb-16", children: [
15438
+ /* @__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" }),
15439
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ColorPalette, { layout: colorLayout })
15411
15440
  ] }),
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, {})
15441
+ showTypography && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("section", { className: "mb-16", children: [
15442
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
15443
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(TypographyScale, {})
15415
15444
  ] }),
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, {})
15445
+ showRadius && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("section", { className: "mb-16", children: [
15446
+ /* @__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" }),
15447
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(RadiusScale, {})
15419
15448
  ] }),
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, {})
15449
+ showSpacing && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("section", { className: "mb-16", children: [
15450
+ /* @__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" }),
15451
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(SpacingScale, {})
15423
15452
  ] })
15424
15453
  ] });
15425
15454
  }
@@ -15434,31 +15463,31 @@ function SpacingScale() {
15434
15463
  { name: "12", value: "3rem" },
15435
15464
  { name: "16", value: "4rem" }
15436
15465
  ];
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)(
15466
+ 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: [
15467
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
15468
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15440
15469
  "div",
15441
15470
  {
15442
15471
  className: "h-4 bg-primary rounded",
15443
15472
  style: { width: space.value }
15444
15473
  }
15445
15474
  ),
15446
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "text-sm text-muted-foreground", children: space.value })
15475
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "text-sm text-muted-foreground", children: space.value })
15447
15476
  ] }, space.name)) });
15448
15477
  }
15449
15478
 
15450
15479
  // src/personalization/PersonalizationProvider.tsx
15451
- var import_react68 = __toESM(require("react"), 1);
15480
+ var import_react69 = __toESM(require("react"), 1);
15452
15481
 
15453
15482
  // src/personalization/PersonalizationContext.ts
15454
- var import_react66 = require("react");
15455
- var PersonalizationContext = (0, import_react66.createContext)(null);
15483
+ var import_react67 = require("react");
15484
+ var PersonalizationContext = (0, import_react67.createContext)(null);
15456
15485
  function usePersonalizationContext() {
15457
- return (0, import_react66.useContext)(PersonalizationContext);
15486
+ return (0, import_react67.useContext)(PersonalizationContext);
15458
15487
  }
15459
15488
 
15460
15489
  // src/personalization/utils.ts
15461
- var import_react67 = require("react");
15490
+ var import_react68 = require("react");
15462
15491
  function normalizeHex(color) {
15463
15492
  let hex = color.trim().toUpperCase();
15464
15493
  if (hex.length === 4 && hex.startsWith("#")) {
@@ -15479,8 +15508,8 @@ function isValidImageUrl(url) {
15479
15508
  }
15480
15509
  }
15481
15510
  function useDebouncedValue(value, delay) {
15482
- const [debounced, setDebounced] = (0, import_react67.useState)(value);
15483
- (0, import_react67.useEffect)(() => {
15511
+ const [debounced, setDebounced] = (0, import_react68.useState)(value);
15512
+ (0, import_react68.useEffect)(() => {
15484
15513
  const timer = setTimeout(() => setDebounced(value), delay);
15485
15514
  return () => clearTimeout(timer);
15486
15515
  }, [value, delay]);
@@ -15501,18 +15530,18 @@ function scrollInputAboveKeyboard(input) {
15501
15530
  }
15502
15531
 
15503
15532
  // src/personalization/PersonalizationProvider.tsx
15504
- var import_jsx_runtime88 = require("react/jsx-runtime");
15533
+ var import_jsx_runtime89 = require("react/jsx-runtime");
15505
15534
  function createBridgeFromCanvas(canvasModule) {
15506
15535
  const { useEditor, useCommands, useImageBinding } = canvasModule;
15507
15536
  function TextBinder({ name, value }) {
15508
15537
  const { elements } = useEditor();
15509
15538
  const { executeElementUpdate } = useCommands();
15510
- const elementsRef = import_react68.default.useRef(elements);
15539
+ const elementsRef = import_react69.default.useRef(elements);
15511
15540
  elementsRef.current = elements;
15512
- const executeRef = import_react68.default.useRef(executeElementUpdate);
15541
+ const executeRef = import_react69.default.useRef(executeElementUpdate);
15513
15542
  executeRef.current = executeElementUpdate;
15514
- const hasUserInput = import_react68.default.useRef(false);
15515
- import_react68.default.useEffect(() => {
15543
+ const hasUserInput = import_react69.default.useRef(false);
15544
+ import_react69.default.useEffect(() => {
15516
15545
  if (value == null) return;
15517
15546
  if (value === "" && !hasUserInput.current) return;
15518
15547
  hasUserInput.current = true;
@@ -15530,12 +15559,12 @@ function createBridgeFromCanvas(canvasModule) {
15530
15559
  function ColorBinder({ originalColor, newColor }) {
15531
15560
  const { elements } = useEditor();
15532
15561
  const { executeElementUpdate } = useCommands();
15533
- const elementsRef = import_react68.default.useRef(elements);
15562
+ const elementsRef = import_react69.default.useRef(elements);
15534
15563
  elementsRef.current = elements;
15535
- const executeRef = import_react68.default.useRef(executeElementUpdate);
15564
+ const executeRef = import_react69.default.useRef(executeElementUpdate);
15536
15565
  executeRef.current = executeElementUpdate;
15537
- const appliedColorRef = import_react68.default.useRef(normalizeHex(originalColor));
15538
- import_react68.default.useEffect(() => {
15566
+ const appliedColorRef = import_react69.default.useRef(normalizeHex(originalColor));
15567
+ import_react69.default.useEffect(() => {
15539
15568
  const normalizedNew = normalizeHex(newColor);
15540
15569
  if (normalizedNew === appliedColorRef.current) return;
15541
15570
  const matchColor = appliedColorRef.current;
@@ -15575,11 +15604,11 @@ function createBridgeFromCanvas(canvasModule) {
15575
15604
  }
15576
15605
  function ImageBinder({ name, value, fit = "cover" }) {
15577
15606
  const { setImageUrl } = useImageBinding(name, { fit });
15578
- const hasUserInput = import_react68.default.useRef(false);
15607
+ const hasUserInput = import_react69.default.useRef(false);
15579
15608
  const debouncedValue = useDebouncedValue(value, 500);
15580
- const setImageUrlRef = import_react68.default.useRef(setImageUrl);
15609
+ const setImageUrlRef = import_react69.default.useRef(setImageUrl);
15581
15610
  setImageUrlRef.current = setImageUrl;
15582
- import_react68.default.useEffect(() => {
15611
+ import_react69.default.useEffect(() => {
15583
15612
  if (debouncedValue == null) return;
15584
15613
  if (debouncedValue === "" && !hasUserInput.current) return;
15585
15614
  hasUserInput.current = true;
@@ -15589,15 +15618,15 @@ function createBridgeFromCanvas(canvasModule) {
15589
15618
  return null;
15590
15619
  }
15591
15620
  return function PersonalizationBridge({ fields = [], values = {} } = {}) {
15592
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_jsx_runtime88.Fragment, { children: fields.map((field) => {
15621
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_jsx_runtime89.Fragment, { children: fields.map((field) => {
15593
15622
  if (field.type === "text") {
15594
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
15623
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
15595
15624
  }
15596
15625
  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}`);
15626
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
15598
15627
  }
15599
15628
  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}`);
15629
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
15601
15630
  }
15602
15631
  return null;
15603
15632
  }) });
@@ -15619,19 +15648,19 @@ function PersonalizationProvider({
15619
15648
  children
15620
15649
  }) {
15621
15650
  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)(
15651
+ const [personValues, setPersonValues] = (0, import_react69.useState)(initialValues ?? {});
15652
+ const [isActive, setIsActive] = (0, import_react69.useState)(!!(initialValues && Object.keys(initialValues).length > 0));
15653
+ const [isExporting, setIsExporting] = (0, import_react69.useState)(false);
15654
+ const [exportedBlobUrls, setExportedBlobUrls] = (0, import_react69.useState)({});
15655
+ const [exportCount, setExportCount] = (0, import_react69.useState)(0);
15656
+ const blobUrlsRef = (0, import_react69.useRef)({});
15657
+ const [CanvasComponent, setCanvasComponent] = (0, import_react69.useState)(
15629
15658
  cachedCanvasComponent
15630
15659
  );
15631
- const [BridgeComponent, setBridgeComponent] = (0, import_react68.useState)(
15660
+ const [BridgeComponent, setBridgeComponent] = (0, import_react69.useState)(
15632
15661
  cachedBridgeComponent
15633
15662
  );
15634
- (0, import_react68.useEffect)(() => {
15663
+ (0, import_react69.useEffect)(() => {
15635
15664
  if (CanvasComponent && BridgeComponent) return;
15636
15665
  if (!canvasImport) return;
15637
15666
  if (!canvasLoadPromise) {
@@ -15649,8 +15678,8 @@ function PersonalizationProvider({
15649
15678
  }
15650
15679
  });
15651
15680
  }, [CanvasComponent, BridgeComponent, canvasImport]);
15652
- const realtimeEnabledRef = (0, import_react68.useRef)(false);
15653
- (0, import_react68.useEffect)(() => {
15681
+ const realtimeEnabledRef = (0, import_react69.useRef)(false);
15682
+ (0, import_react69.useEffect)(() => {
15654
15683
  return () => {
15655
15684
  for (const url of Object.values(blobUrlsRef.current)) {
15656
15685
  try {
@@ -15660,16 +15689,16 @@ function PersonalizationProvider({
15660
15689
  }
15661
15690
  };
15662
15691
  }, []);
15663
- const updateField = (0, import_react68.useCallback)((key, value) => {
15692
+ const updateField = (0, import_react69.useCallback)((key, value) => {
15664
15693
  setIsActive(true);
15665
15694
  setPersonValues((prev) => ({ ...prev, [key]: value }));
15666
15695
  }, []);
15667
- const reset = (0, import_react68.useCallback)(() => {
15696
+ const reset = (0, import_react69.useCallback)(() => {
15668
15697
  setPersonValues({});
15669
15698
  setIsActive(false);
15670
15699
  setIsExporting(false);
15671
15700
  }, []);
15672
- const handleExport = (0, import_react68.useCallback)(
15701
+ const handleExport = (0, import_react69.useCallback)(
15673
15702
  (exports2) => {
15674
15703
  const newUrls = {};
15675
15704
  for (const [name, data] of Object.entries(exports2)) {
@@ -15703,11 +15732,11 @@ function PersonalizationProvider({
15703
15732
  },
15704
15733
  [realtime, placementOverride]
15705
15734
  );
15706
- const handleExportScheduled = (0, import_react68.useCallback)(() => {
15735
+ const handleExportScheduled = (0, import_react69.useCallback)(() => {
15707
15736
  setIsExporting(true);
15708
15737
  }, []);
15709
15738
  const shouldMountCanvas = CanvasComponent && BridgeComponent && canvasState?.elements && canvasState.elements.length > 0 && (!lazy || isActive);
15710
- const contextValue = import_react68.default.useMemo(
15739
+ const contextValue = import_react69.default.useMemo(
15711
15740
  () => ({
15712
15741
  fields,
15713
15742
  personValues,
@@ -15720,8 +15749,8 @@ function PersonalizationProvider({
15720
15749
  }),
15721
15750
  [fields, personValues, updateField, isActive, isExporting, exportedBlobUrls, exportCount, reset]
15722
15751
  );
15723
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(PersonalizationContext.Provider, { value: contextValue, children: [
15724
- shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15752
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(PersonalizationContext.Provider, { value: contextValue, children: [
15753
+ shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15725
15754
  "div",
15726
15755
  {
15727
15756
  style: {
@@ -15734,7 +15763,7 @@ function PersonalizationProvider({
15734
15763
  pointerEvents: "none"
15735
15764
  },
15736
15765
  "aria-hidden": true,
15737
- children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15766
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15738
15767
  CanvasComponent,
15739
15768
  {
15740
15769
  initialElements: canvasState?.elements,
@@ -15754,7 +15783,7 @@ function PersonalizationProvider({
15754
15783
  exportImageQuality: exportConfig?.imageQuality ?? 0.85,
15755
15784
  onExport: handleExport,
15756
15785
  onExportScheduled: handleExportScheduled,
15757
- overlay: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(BridgeComponent, { fields, values: personValues })
15786
+ overlay: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(BridgeComponent, { fields, values: personValues })
15758
15787
  }
15759
15788
  )
15760
15789
  },
@@ -15779,7 +15808,7 @@ function usePersonalizationOptional() {
15779
15808
  }
15780
15809
 
15781
15810
  // src/personalization/PersonalizationInputs.tsx
15782
- var import_jsx_runtime89 = require("react/jsx-runtime");
15811
+ var import_jsx_runtime90 = require("react/jsx-runtime");
15783
15812
  function PersonalizationInputs({
15784
15813
  className,
15785
15814
  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 +15832,8 @@ function PersonalizationInputs({
15803
15832
  scrollInputAboveKeyboard(e.target);
15804
15833
  }
15805
15834
  };
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)(
15835
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: className || "flex flex-col gap-3", children: [
15836
+ textFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
15808
15837
  "input",
15809
15838
  {
15810
15839
  type: "text",
@@ -15818,8 +15847,8 @@ function PersonalizationInputs({
15818
15847
  },
15819
15848
  `text-${field.name}`
15820
15849
  )),
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)(
15850
+ colorFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "flex items-center gap-3", children: [
15851
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
15823
15852
  "input",
15824
15853
  {
15825
15854
  type: "color",
@@ -15828,9 +15857,9 @@ function PersonalizationInputs({
15828
15857
  onChange: (e) => updateField(field.color, e.target.value)
15829
15858
  }
15830
15859
  ),
15831
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "text-base text-muted-foreground", children: field.label })
15860
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "text-base text-muted-foreground", children: field.label })
15832
15861
  ] }, `color-${field.color}`)),
15833
- imageFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
15862
+ imageFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
15834
15863
  "input",
15835
15864
  {
15836
15865
  type: "text",
@@ -15848,15 +15877,15 @@ function PersonalizationInputs({
15848
15877
  }
15849
15878
 
15850
15879
  // src/personalization/usePersonalizationShimmer.ts
15851
- var import_react69 = require("react");
15880
+ var import_react70 = require("react");
15852
15881
  function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15853
15882
  const personCtx = usePersonalizationContext();
15854
15883
  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)(() => {
15884
+ const [shimmerActive, setShimmerActive] = (0, import_react70.useState)(false);
15885
+ const sdkSettledRef = (0, import_react70.useRef)(false);
15886
+ const manualTriggerRef = (0, import_react70.useRef)(false);
15887
+ const safetyTimeoutRef = (0, import_react70.useRef)(void 0);
15888
+ const startShimmer = (0, import_react70.useCallback)(() => {
15860
15889
  setShimmerActive(true);
15861
15890
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
15862
15891
  safetyTimeoutRef.current = setTimeout(
@@ -15868,25 +15897,25 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15868
15897
  safetyTimeoutMs
15869
15898
  );
15870
15899
  }, [safetyTimeoutMs]);
15871
- (0, import_react69.useEffect)(() => {
15900
+ (0, import_react70.useEffect)(() => {
15872
15901
  if (!personCtx?.isActive) return;
15873
15902
  sdkSettledRef.current = false;
15874
15903
  manualTriggerRef.current = false;
15875
15904
  realtime?.resetPipelineSettled();
15876
15905
  startShimmer();
15877
15906
  }, [personCtx?.personValues, personCtx?.isActive, startShimmer]);
15878
- const triggerShimmer = (0, import_react69.useCallback)(() => {
15907
+ const triggerShimmer = (0, import_react70.useCallback)(() => {
15879
15908
  sdkSettledRef.current = false;
15880
15909
  manualTriggerRef.current = true;
15881
15910
  startShimmer();
15882
15911
  }, [startShimmer]);
15883
- (0, import_react69.useEffect)(() => {
15912
+ (0, import_react70.useEffect)(() => {
15884
15913
  if (!realtime?.subscribePipelineSettled) return;
15885
15914
  return realtime.subscribePipelineSettled(() => {
15886
15915
  sdkSettledRef.current = true;
15887
15916
  });
15888
15917
  }, [realtime]);
15889
- (0, import_react69.useEffect)(() => {
15918
+ (0, import_react70.useEffect)(() => {
15890
15919
  const container = containerRef.current;
15891
15920
  if (!container) return;
15892
15921
  const observer = new MutationObserver((mutations) => {
@@ -15929,7 +15958,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15929
15958
  });
15930
15959
  return () => observer.disconnect();
15931
15960
  }, [containerRef]);
15932
- (0, import_react69.useEffect)(() => {
15961
+ (0, import_react70.useEffect)(() => {
15933
15962
  return () => {
15934
15963
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
15935
15964
  };
@@ -16039,6 +16068,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
16039
16068
  LoadingOverlayPrismCandyInline,
16040
16069
  MasonryGrid,
16041
16070
  MobileProductCarousel,
16071
+ MockupBackground,
16042
16072
  MockupPriorityProvider,
16043
16073
  PDPLayout,
16044
16074
  PersonalizationInputs,
@@ -16164,6 +16194,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
16164
16194
  useIsolatedCanvas,
16165
16195
  useLoadingOverlay,
16166
16196
  useMediaQuery,
16197
+ useMockupBackgroundOptional,
16167
16198
  useMockupPriority,
16168
16199
  useMockupPriorityOptional,
16169
16200
  usePersonalization,