@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/CHANGELOG.md +15 -0
- package/dist/index.cjs +890 -859
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +357 -328
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/composed/HeroProductImage.tsx +10 -0
- package/src/index.ts +7 -0
- package/src/patterns/MockupBackground.tsx +43 -0
- package/src/patterns/RealtimeProvider.tsx +13 -1
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: () =>
|
|
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
|
|
5914
|
+
var import_react27 = require("react");
|
|
5913
5915
|
|
|
5914
5916
|
// src/patterns/RealtimeProvider.tsx
|
|
5915
|
-
var
|
|
5916
|
-
var
|
|
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,
|
|
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
|
|
5950
|
+
const mockupBg = useMockupBackgroundOptional();
|
|
5951
|
+
const [isEnabled, setIsEnabled] = (0, import_react25.useState)(autoEnable);
|
|
5936
5952
|
const useSessionGrant = Boolean(shop && grantUrl);
|
|
5937
|
-
const getToken = (0,
|
|
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,
|
|
5949
|
-
const colorBlobsSentRef = (0,
|
|
5950
|
-
const lastBlobSentTimeRef = (0,
|
|
5951
|
-
const isPendingMockupsRef = (0,
|
|
5952
|
-
const configSentRef = (0,
|
|
5953
|
-
const placementSettingsOverridesRef = (0,
|
|
5954
|
-
const lastSentVariantIdRef = (0,
|
|
5955
|
-
const
|
|
5956
|
-
const
|
|
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,
|
|
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,
|
|
6008
|
-
const mockupSubscribersRef = (0,
|
|
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,
|
|
6012
|
-
const pendingExportCancelledSubscribersRef = (0,
|
|
6013
|
-
const pendingBlobSubscribersRef = (0,
|
|
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,
|
|
6033
|
+
const blobReceivedSubscribersRef = (0, import_react25.useRef)(
|
|
6017
6034
|
/* @__PURE__ */ new Set()
|
|
6018
6035
|
);
|
|
6019
|
-
const blobSentSubscribersRef = (0,
|
|
6036
|
+
const blobSentSubscribersRef = (0, import_react25.useRef)(
|
|
6020
6037
|
/* @__PURE__ */ new Set()
|
|
6021
6038
|
);
|
|
6022
|
-
const pipelineSettledSubscribersRef = (0,
|
|
6023
|
-
const pipelineGenRef = (0,
|
|
6024
|
-
const blobQueuedGenRef = (0,
|
|
6025
|
-
const hasBlobInFlightRef = (0,
|
|
6026
|
-
const pipelineResetCooldownRef = (0,
|
|
6027
|
-
const mockupUrlCacheRef = (0,
|
|
6028
|
-
const registeredBlobUrlsRef = (0,
|
|
6029
|
-
const pendingPlacementsRef = (0,
|
|
6030
|
-
const pendingMockupIdsRef = (0,
|
|
6031
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
6271
|
+
const enableRealtime = (0, import_react25.useCallback)(() => {
|
|
6249
6272
|
setIsEnabled(true);
|
|
6250
6273
|
}, []);
|
|
6251
|
-
const disableRealtime = (0,
|
|
6274
|
+
const disableRealtime = (0, import_react25.useCallback)(() => {
|
|
6252
6275
|
setIsEnabled(false);
|
|
6253
6276
|
}, []);
|
|
6254
|
-
const placementDimensions = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
6449
|
+
const isMockupLoading = (0, import_react25.useCallback)((mockupId) => {
|
|
6427
6450
|
return pendingMockupIdsRef.current.has(mockupId);
|
|
6428
6451
|
}, []);
|
|
6429
|
-
const registerBlobUrl = (0,
|
|
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,
|
|
6452
|
-
const subscribeMockupResultByIdRef = (0,
|
|
6453
|
-
const subscribePendingBlobRef = (0,
|
|
6454
|
-
const subscribeBlobReceivedRef = (0,
|
|
6455
|
-
const subscribeBlobSentRef = (0,
|
|
6456
|
-
const subscribePipelineSettledRef = (0,
|
|
6457
|
-
const subscribePendingExportCancelledRef = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
6605
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(RealtimeContext.Provider, { value: contextValue, children });
|
|
6583
6606
|
}
|
|
6584
6607
|
function useRealtime() {
|
|
6585
|
-
const context = (0,
|
|
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,
|
|
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,
|
|
6600
|
-
const isRealtimeEnabledRef = (0,
|
|
6601
|
-
const isConfiguredRef = (0,
|
|
6602
|
-
const mockupCountRef = (0,
|
|
6603
|
-
const selectedPlacementRef = (0,
|
|
6604
|
-
const enableRealtimeRef = (0,
|
|
6605
|
-
const selectedArtworkRef = (0,
|
|
6606
|
-
(0,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
6707
|
-
const idleTimeoutRef = (0,
|
|
6708
|
-
const handleScroll = (0,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
6834
|
-
const preloaderRef = (0,
|
|
6835
|
-
const currentPreloadUrlRef = (0,
|
|
6836
|
-
const shimmerTimerRef = (0,
|
|
6837
|
-
const isMountedRef = (0,
|
|
6838
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
7051
|
+
const onPreloadComplete = (0, import_react30.useCallback)((_loadedUrl) => {
|
|
7029
7052
|
}, []);
|
|
7030
|
-
const onPreloadError = (0,
|
|
7053
|
+
const onPreloadError = (0, import_react30.useCallback)(() => {
|
|
7031
7054
|
}, []);
|
|
7032
|
-
const addLayerDirectly = (0,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
7247
|
-
const entriesRef = (0,
|
|
7248
|
-
const preloadingCountRef = (0,
|
|
7249
|
-
const preloadQueueRef = (0,
|
|
7250
|
-
const preloadingUrlsRef = (0,
|
|
7251
|
-
const processQueue = (0,
|
|
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,
|
|
7299
|
+
const observerOptionsRef = (0, import_react31.useRef)({
|
|
7277
7300
|
rootMargin: `${preloadMargin}px 0px`,
|
|
7278
7301
|
threshold: 0
|
|
7279
7302
|
});
|
|
7280
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
7398
|
+
var import_react32 = require("react");
|
|
7376
7399
|
function useDeviceDetection() {
|
|
7377
|
-
const [isTouchDevice, setIsTouchDevice] = (0,
|
|
7378
|
-
const [isSafari, setIsSafari] = (0,
|
|
7379
|
-
(0,
|
|
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
|
|
7421
|
+
var import_react34 = require("react");
|
|
7399
7422
|
|
|
7400
7423
|
// src/patterns/MockupPriorityProvider.tsx
|
|
7401
|
-
var
|
|
7402
|
-
var
|
|
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,
|
|
7429
|
+
var MockupPriorityContext = (0, import_react33.createContext)(
|
|
7407
7430
|
void 0
|
|
7408
7431
|
);
|
|
7409
7432
|
function MockupPriorityProvider({ children }) {
|
|
7410
|
-
(0,
|
|
7433
|
+
(0, import_react33.useEffect)(() => {
|
|
7411
7434
|
return () => {
|
|
7412
7435
|
};
|
|
7413
7436
|
}, []);
|
|
7414
|
-
const visibilityMapRef = (0,
|
|
7415
|
-
const prioritiesRef = (0,
|
|
7416
|
-
const level1MockupRef = (0,
|
|
7417
|
-
const level2MockupsRef = (0,
|
|
7418
|
-
const level3QueueRef = (0,
|
|
7419
|
-
const mobileCarouselRef = (0,
|
|
7420
|
-
const registrationOrderRef = (0,
|
|
7421
|
-
const elementRefsRef = (0,
|
|
7422
|
-
const prioritySubscribersRef = (0,
|
|
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,
|
|
7448
|
+
const level1SubscribersRef = (0, import_react33.useRef)(
|
|
7426
7449
|
/* @__PURE__ */ new Set()
|
|
7427
7450
|
);
|
|
7428
7451
|
const scrollState = useScrollDirection();
|
|
7429
|
-
const scrollDirectionRef = (0,
|
|
7452
|
+
const scrollDirectionRef = (0, import_react33.useRef)("idle");
|
|
7430
7453
|
scrollDirectionRef.current = scrollState.direction;
|
|
7431
|
-
const recalcTimeoutRef = (0,
|
|
7432
|
-
const pendingRafRef = (0,
|
|
7433
|
-
const [level1MockupId, setLevel1MockupId] = (0,
|
|
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,
|
|
7436
|
-
const pendingMockupsRef = (0,
|
|
7437
|
-
const renderedMockupsRef = (0,
|
|
7438
|
-
const lastPendingBlobTimeRef = (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,
|
|
7442
|
-
const requestMockupsForLevel = (0,
|
|
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,
|
|
7471
|
-
const handleMockupResult = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
7886
|
+
const clearMobileCarouselMode = (0, import_react33.useCallback)(() => {
|
|
7864
7887
|
mobileCarouselRef.current = null;
|
|
7865
7888
|
recalculatePriorities();
|
|
7866
7889
|
}, [recalculatePriorities]);
|
|
7867
|
-
const getPriorityLevel = (0,
|
|
7890
|
+
const getPriorityLevel = (0, import_react33.useCallback)((mockupId) => {
|
|
7868
7891
|
return prioritiesRef.current.get(mockupId) || 3;
|
|
7869
7892
|
}, []);
|
|
7870
|
-
const getQueuePriority = (0,
|
|
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,
|
|
7906
|
+
const getLevel1Mockup = (0, import_react33.useCallback)(() => {
|
|
7884
7907
|
return level1MockupRef.current;
|
|
7885
7908
|
}, []);
|
|
7886
|
-
const getLevel2Mockups = (0,
|
|
7909
|
+
const getLevel2Mockups = (0, import_react33.useCallback)(() => {
|
|
7887
7910
|
return [...level2MockupsRef.current];
|
|
7888
7911
|
}, []);
|
|
7889
|
-
const getLevel3Queue = (0,
|
|
7912
|
+
const getLevel3Queue = (0, import_react33.useCallback)(() => {
|
|
7890
7913
|
return [...level3QueueRef.current];
|
|
7891
7914
|
}, []);
|
|
7892
|
-
const getVisibility = (0,
|
|
7915
|
+
const getVisibility = (0, import_react33.useCallback)((mockupId) => {
|
|
7893
7916
|
return visibilityMapRef.current.get(mockupId) || null;
|
|
7894
7917
|
}, []);
|
|
7895
|
-
const getMockupIdsForLevel = (0,
|
|
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,
|
|
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,
|
|
7936
|
+
const isLevel1Active = (0, import_react33.useCallback)(() => {
|
|
7914
7937
|
return level1MockupRef.current !== null;
|
|
7915
7938
|
}, []);
|
|
7916
|
-
const subscribePriorityChange = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
8009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(MockupPriorityContext.Provider, { value: contextValue, children });
|
|
7987
8010
|
}
|
|
7988
8011
|
function useMockupPriority() {
|
|
7989
|
-
const context = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
8196
|
+
var import_react35 = require("react");
|
|
8174
8197
|
function useMediaQuery(query) {
|
|
8175
|
-
const [matches, setMatches] = (0,
|
|
8176
|
-
(0,
|
|
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
|
|
8210
|
+
var import_react36 = require("react");
|
|
8188
8211
|
function useViewportDimensions(isDesktop) {
|
|
8189
|
-
const [dimensions, setDimensions] = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
8725
|
-
var
|
|
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,
|
|
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,
|
|
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 =
|
|
8795
|
+
var IsolatedChildren = import_react39.default.memo(
|
|
8773
8796
|
function IsolatedChildren2({ children }) {
|
|
8774
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
8788
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
8821
|
-
var
|
|
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,
|
|
8926
|
-
(0,
|
|
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,
|
|
8932
|
-
(0,
|
|
8954
|
+
const [particles, setParticles] = (0, import_react40.useState)([]);
|
|
8955
|
+
(0, import_react40.useEffect)(() => {
|
|
8933
8956
|
setParticles(generateParticles());
|
|
8934
8957
|
}, []);
|
|
8935
|
-
const prevVisibleRef = (0,
|
|
8936
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
8965
|
-
/* @__PURE__ */ (0,
|
|
8966
|
-
/* @__PURE__ */ (0,
|
|
8967
|
-
/* @__PURE__ */ (0,
|
|
8968
|
-
/* @__PURE__ */ (0,
|
|
8969
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
8994
|
-
const timerRef = (0,
|
|
8995
|
-
(0,
|
|
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,
|
|
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
|
|
9047
|
+
var import_react41 = require("react");
|
|
9025
9048
|
var import_react_dom2 = require("react-dom");
|
|
9026
|
-
var
|
|
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,
|
|
9197
|
-
(0,
|
|
9219
|
+
const [particles, setParticles] = (0, import_react41.useState)([]);
|
|
9220
|
+
(0, import_react41.useEffect)(() => {
|
|
9198
9221
|
setParticles(generateParticles2());
|
|
9199
9222
|
}, []);
|
|
9200
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
9208
|
-
particles.map((p, i) => /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
9233
|
-
const [bounds, setBounds] = (0,
|
|
9234
|
-
const [mounted, setMounted] = (0,
|
|
9235
|
-
const measure = (0,
|
|
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,
|
|
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,
|
|
9282
|
+
(0, import_react41.useEffect)(() => {
|
|
9260
9283
|
const raf = requestAnimationFrame(() => setMounted(true));
|
|
9261
9284
|
return () => cancelAnimationFrame(raf);
|
|
9262
9285
|
}, []);
|
|
9263
|
-
const handleTransitionEnd = (0,
|
|
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,
|
|
9274
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
9314
|
-
(0,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
9386
|
+
let content = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Product, { productId, productData, children });
|
|
9364
9387
|
if (enablePriority) {
|
|
9365
|
-
content = /* @__PURE__ */ (0,
|
|
9388
|
+
content = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(MockupPriorityProvider, { children: content });
|
|
9366
9389
|
}
|
|
9367
9390
|
if (enableRealtime) {
|
|
9368
|
-
content = /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
9412
|
-
var
|
|
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
|
|
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,
|
|
9449
|
-
const imageRef = (0,
|
|
9450
|
-
const lastUserDragTimeRef = (0,
|
|
9451
|
-
const [containerSize, setContainerSize] = (0,
|
|
9452
|
-
const [position, setPosition] = (0,
|
|
9453
|
-
const [isReady, setIsReady] = (0,
|
|
9454
|
-
const [detectedAspectRatio, setDetectedAspectRatio] = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
9656
|
-
const pendingAlignmentRef = (0,
|
|
9657
|
-
const throttleTimeoutRef = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
9762
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
9788
|
-
/* @__PURE__ */ (0,
|
|
9789
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
9835
|
-
var
|
|
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,
|
|
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,
|
|
9880
|
+
(0, import_react44.useEffect)(() => {
|
|
9858
9881
|
}, [selectedPlacement]);
|
|
9859
9882
|
if (!artwork) {
|
|
9860
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
9875
|
-
placements.length > 1 && /* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
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,
|
|
9912
|
-
/* @__PURE__ */ (0,
|
|
9913
|
-
/* @__PURE__ */ (0,
|
|
9914
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
9933
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
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
|
|
9966
|
+
var import_react45 = require("react");
|
|
9944
9967
|
function useContainerWidth(containerRef, maxWidth = 3e3) {
|
|
9945
|
-
const [width, setWidth] = (0,
|
|
9946
|
-
const resizeTimeoutRef = (0,
|
|
9947
|
-
(0,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
10073
|
+
const mockupBg = useMockupBackgroundOptional();
|
|
10074
|
+
const priorityContextRef = (0, import_react46.useRef)(priorityContext);
|
|
10050
10075
|
priorityContextRef.current = priorityContext;
|
|
10051
|
-
const contextRef = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
10088
|
+
const containerRef = (0, import_react46.useRef)(null);
|
|
10064
10089
|
const measuredWidth = useContainerWidth(containerRef);
|
|
10065
10090
|
const width = widthProp ?? measuredWidth;
|
|
10066
|
-
const initialStaticUrl = (0,
|
|
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,
|
|
10133
|
-
const [isInPreloadZone, setIsInPreloadZone] = (0,
|
|
10134
|
-
const componentIdRef = (0,
|
|
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,
|
|
10138
|
-
const setContainerRef = (0,
|
|
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,
|
|
10143
|
-
const priorityRegisteredRef = (0,
|
|
10144
|
-
const onLoadCalledRef = (0,
|
|
10145
|
-
const prevArtworkSrcRef = (0,
|
|
10146
|
-
const realtimeArtworkSrcRef = (0,
|
|
10147
|
-
const hasReceivedRealtimeRef = (0,
|
|
10148
|
-
const isPendingExportRef = (0,
|
|
10149
|
-
const onUrlGeneratedRef = (0,
|
|
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,
|
|
10178
|
+
const layersLengthRef = (0, import_react46.useRef)(layers.length);
|
|
10152
10179
|
layersLengthRef.current = layers.length;
|
|
10153
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
10273
|
-
const contextOptionAttributesRef = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
10416
|
-
const [showNew, setShowNew] = (0,
|
|
10417
|
-
const [renderedUrl, setRenderedUrl] = (0,
|
|
10418
|
-
const [firstImageLoaded, setFirstImageLoaded] = (0,
|
|
10419
|
-
const [loaderMounted, setLoaderMounted] = (0,
|
|
10420
|
-
const [imgFailed, setImgFailed] = (0,
|
|
10421
|
-
const [retryNonce, setRetryNonce] = (0,
|
|
10422
|
-
const retriedUrlRef = (0,
|
|
10423
|
-
const prevDisplayUrlRef = (0,
|
|
10424
|
-
const signHintShownRef = (0,
|
|
10425
|
-
(0,
|
|
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,
|
|
10481
|
+
const handleCrossfadeEnd = (0, import_react46.useCallback)(() => {
|
|
10453
10482
|
setPrevUrl(null);
|
|
10454
10483
|
setShowNew(false);
|
|
10455
10484
|
}, []);
|
|
10456
|
-
const handleLoaderExited = (0,
|
|
10485
|
+
const handleLoaderExited = (0, import_react46.useCallback)(() => setLoaderMounted(false), []);
|
|
10457
10486
|
if (!hasArtwork) {
|
|
10458
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
10464
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
10545
|
-
realtimeContext?.renderError && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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
|
|
10584
|
-
var
|
|
10585
|
-
var SafeImg =
|
|
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,
|
|
10588
|
-
(0,
|
|
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,
|
|
10592
|
-
return /* @__PURE__ */ (0,
|
|
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
|
|
10628
|
-
var
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
10703
|
-
var
|
|
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,
|
|
10709
|
-
const [showShimmer, setShowShimmer] = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
10738
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
10748
|
-
endContent: query ? /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
10842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
10814
10843
|
Product,
|
|
10815
10844
|
{
|
|
10816
10845
|
productId,
|
|
10817
10846
|
productData: product,
|
|
10818
|
-
children: /* @__PURE__ */ (0,
|
|
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
|
|
10840
|
-
var
|
|
10868
|
+
var import_react50 = require("react");
|
|
10869
|
+
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
10841
10870
|
function ProductGridSkeletonItem() {
|
|
10842
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
10869
|
-
/* @__PURE__ */ (0,
|
|
10870
|
-
showSkeleton && /* @__PURE__ */ (0,
|
|
10871
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
10906
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
10944
|
+
var import_react51 = require("react");
|
|
10916
10945
|
var Slider2 = __toESM(require("@radix-ui/react-slider"), 1);
|
|
10917
|
-
var
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
10943
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
10961
|
-
/* @__PURE__ */ (0,
|
|
10962
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
10997
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(XIcon2, { className: "w-5 h-5" })
|
|
10969
10998
|
}
|
|
10970
10999
|
)
|
|
10971
11000
|
] }),
|
|
10972
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
10978
|
-
/* @__PURE__ */ (0,
|
|
10979
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
10996
|
-
return /* @__PURE__ */ (0,
|
|
10997
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
11006
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
11022
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
11034
|
-
showCounts && /* @__PURE__ */ (0,
|
|
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,
|
|
11040
|
-
/* @__PURE__ */ (0,
|
|
11041
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
11096
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
11105
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
11121
|
-
/* @__PURE__ */ (0,
|
|
11122
|
-
/* @__PURE__ */ (0,
|
|
11123
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
11157
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
11189
|
-
/* @__PURE__ */ (0,
|
|
11190
|
-
/* @__PURE__ */ (0,
|
|
11191
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
11210
|
-
/* @__PURE__ */ (0,
|
|
11211
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
11264
|
+
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
11236
11265
|
function Filters({ buttonClassName, buttonText }) {
|
|
11237
|
-
const [isOpen, setIsOpen] = (0,
|
|
11238
|
-
return /* @__PURE__ */ (0,
|
|
11239
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
11308
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
11361
|
+
var import_react55 = require("react");
|
|
11333
11362
|
|
|
11334
11363
|
// src/composed/zoom/ZoomOverlay.tsx
|
|
11335
|
-
var
|
|
11364
|
+
var import_react53 = require("react");
|
|
11336
11365
|
var import_lucide_react7 = require("lucide-react");
|
|
11337
|
-
var
|
|
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,
|
|
11350
|
-
const [zoomOrigin, setZoomOrigin] = (0,
|
|
11351
|
-
const [hoveredImageIndex, setHoveredImageIndex] = (0,
|
|
11352
|
-
const [cursorPos, setCursorPos] = (0,
|
|
11353
|
-
const [announcement, setAnnouncement] = (0,
|
|
11354
|
-
const [isZooming, setIsZooming] = (0,
|
|
11355
|
-
const handleZoomClick = (0,
|
|
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,
|
|
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,
|
|
11397
|
-
/* @__PURE__ */ (0,
|
|
11398
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
11494
|
-
const [isClient, setIsClient] = (0,
|
|
11495
|
-
const [scale, setScale] = (0,
|
|
11496
|
-
const [cropDimensions, setCropDimensions] = (0,
|
|
11497
|
-
const [currentZoomScale, setCurrentZoomScale] = (0,
|
|
11498
|
-
const imgRef = (0,
|
|
11499
|
-
const touchStartRef = (0,
|
|
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,
|
|
11503
|
-
const calculateScale = (0,
|
|
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,
|
|
11544
|
+
const handleImageLoad = (0, import_react54.useCallback)(() => {
|
|
11516
11545
|
calculateScale();
|
|
11517
11546
|
}, [calculateScale]);
|
|
11518
|
-
(0,
|
|
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,
|
|
11556
|
+
(0, import_react54.useEffect)(() => {
|
|
11528
11557
|
calculateScale();
|
|
11529
11558
|
}, [calculateScale]);
|
|
11530
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
11768
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
11802
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
11914
|
-
const [showEnhancedViewer, setShowEnhancedViewer] = (0,
|
|
11915
|
-
const [viewerIndex, setViewerIndex] = (0,
|
|
11916
|
-
const [currentImageUrl, setCurrentImageUrl] = (0,
|
|
11917
|
-
(0,
|
|
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,
|
|
11945
|
-
isTouchDevice ? /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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
|
|
11997
|
-
var
|
|
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,
|
|
12032
|
+
const [failed, setFailed] = (0, import_react56.useState)(false);
|
|
12004
12033
|
if (failed || !src) {
|
|
12005
|
-
return /* @__PURE__ */ (0,
|
|
12034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: `bg-muted ${className ?? ""}`, role: "img", "aria-label": alt });
|
|
12006
12035
|
}
|
|
12007
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
12037
|
-
const [touchStart, setTouchStart] = (0,
|
|
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,
|
|
12069
|
+
const [touchEnd, setTouchEnd] = (0, import_react56.useState)(
|
|
12041
12070
|
null
|
|
12042
12071
|
);
|
|
12043
|
-
const [showImageViewer, setShowImageViewer] = (0,
|
|
12044
|
-
const [viewerKey, setViewerKey] = (0,
|
|
12045
|
-
const [isDragging, setIsDragging] = (0,
|
|
12046
|
-
const [dragOffset, setDragOffset] = (0,
|
|
12047
|
-
const [isTransitioning, setIsTransitioning] = (0,
|
|
12048
|
-
const [isHorizontalSwipe, setIsHorizontalSwipe] = (0,
|
|
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,
|
|
12052
|
-
const [isPeekReturning, setIsPeekReturning] = (0,
|
|
12053
|
-
const carouselRef = (0,
|
|
12054
|
-
const indicatorRef = (0,
|
|
12055
|
-
const touchStartRef = (0,
|
|
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,
|
|
12059
|
-
const hasShownPeekRef = (0,
|
|
12060
|
-
const hasSwipedThisSessionRef = (0,
|
|
12061
|
-
const generatedUrlsRef = (0,
|
|
12062
|
-
const prevArtworkSrcRef = (0,
|
|
12063
|
-
(0,
|
|
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,
|
|
12098
|
+
const onMockupUrlGeneratedRef = (0, import_react56.useRef)(onMockupUrlGenerated);
|
|
12070
12099
|
onMockupUrlGeneratedRef.current = onMockupUrlGenerated;
|
|
12071
|
-
const handleUrlGenerated = (0,
|
|
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,
|
|
12080
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
12137
|
+
(0, import_react56.useEffect)(() => {
|
|
12109
12138
|
setActiveIndex(currentIndex);
|
|
12110
12139
|
}, [currentIndex]);
|
|
12111
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
12246
|
-
const handleImageTap = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
12426
|
+
const mouseStartRef = (0, import_react56.useRef)(
|
|
12398
12427
|
null
|
|
12399
12428
|
);
|
|
12400
|
-
const isMouseDraggingRef = (0,
|
|
12401
|
-
(0,
|
|
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,
|
|
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,
|
|
12524
|
+
(0, import_react56.useEffect)(() => {
|
|
12496
12525
|
if (stickyHeroContext?.setCarouselIndicator && images.length > 1) {
|
|
12497
|
-
const indicator = /* @__PURE__ */ (0,
|
|
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,
|
|
12504
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
12566
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
|
|
12538
12567
|
}
|
|
12539
|
-
return /* @__PURE__ */ (0,
|
|
12540
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
12576
|
-
) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
12613
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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
|
|
12698
|
-
var
|
|
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,
|
|
12709
|
-
const containerRef = (0,
|
|
12710
|
-
const touchStartRef = (0,
|
|
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,
|
|
12714
|
-
(0,
|
|
12742
|
+
const isSwipingRef = (0, import_react57.useRef)(false);
|
|
12743
|
+
(0, import_react57.useEffect)(() => {
|
|
12715
12744
|
setActiveIndex(currentIndex);
|
|
12716
12745
|
}, [currentIndex]);
|
|
12717
|
-
const goToSlide = (0,
|
|
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,
|
|
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,
|
|
12806
|
+
return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "w-full h-full bg-muted" });
|
|
12778
12807
|
}
|
|
12779
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
12857
|
-
var
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
13006
|
+
const [isHydrated, setIsHydrated] = (0, import_react59.useState)(false);
|
|
12978
13007
|
const ssrMultiplier = accountForRetina ? maxRetinaMultiplier : 2;
|
|
12979
|
-
const [scales, setScales] = (0,
|
|
13008
|
+
const [scales, setScales] = (0, import_react59.useState)(() => ({
|
|
12980
13009
|
visual: initialScale,
|
|
12981
13010
|
render: initialScale * ssrMultiplier
|
|
12982
13011
|
}));
|
|
12983
|
-
const calculateScales = (0,
|
|
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,
|
|
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
|
|
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,
|
|
13064
|
-
const headerRef = (0,
|
|
13065
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
13222
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
13271
|
-
var
|
|
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,
|
|
13292
|
-
const headerRef = (0,
|
|
13293
|
-
const [isClient, setIsClient] = (0,
|
|
13294
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
13391
|
-
/* @__PURE__ */ (0,
|
|
13392
|
-
header && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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
|
|
13417
|
-
var
|
|
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 =
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
13556
|
-
(isDesktop === false || isDesktop === null) && /* @__PURE__ */ (0,
|
|
13557
|
-
renderMobileCarousel && /* @__PURE__ */ (0,
|
|
13558
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
13561
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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
|
|
13592
|
-
var
|
|
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 =
|
|
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,
|
|
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,
|
|
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
|
|
13669
|
-
var
|
|
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 =
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
13790
|
-
var
|
|
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 =
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
13917
|
+
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
13889
13918
|
function ColorTokenSwatch({ name, cssVar, className = "" }) {
|
|
13890
|
-
return /* @__PURE__ */ (0,
|
|
13891
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
13899
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
13904
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
13912
|
-
/* @__PURE__ */ (0,
|
|
13913
|
-
description && /* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
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,
|
|
14002
|
-
/* @__PURE__ */ (0,
|
|
14003
|
-
/* @__PURE__ */ (0,
|
|
14004
|
-
layout === "grid" ? /* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
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,
|
|
14059
|
-
/* @__PURE__ */ (0,
|
|
14060
|
-
/* @__PURE__ */ (0,
|
|
14061
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
14064
|
-
/* @__PURE__ */ (0,
|
|
14065
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
14085
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
14095
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
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
|
|
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,
|
|
15287
|
-
const [isDark, setIsDark] = (0,
|
|
15288
|
-
const [isOpen, setIsOpen] = (0,
|
|
15289
|
-
(0,
|
|
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,
|
|
15329
|
-
/* @__PURE__ */ (0,
|
|
15330
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
15337
|
-
/* @__PURE__ */ (0,
|
|
15338
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
15343
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
15364
|
-
currentTheme === theme.name && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
15379
|
-
/* @__PURE__ */ (0,
|
|
15380
|
-
/* @__PURE__ */ (0,
|
|
15381
|
-
] }) : /* @__PURE__ */ (0,
|
|
15382
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
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,
|
|
15401
|
-
/* @__PURE__ */ (0,
|
|
15402
|
-
/* @__PURE__ */ (0,
|
|
15403
|
-
/* @__PURE__ */ (0,
|
|
15404
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
15435
|
+
showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(ThemeSwitcher, {})
|
|
15407
15436
|
] }) }),
|
|
15408
|
-
showColors && /* @__PURE__ */ (0,
|
|
15409
|
-
/* @__PURE__ */ (0,
|
|
15410
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
15413
|
-
/* @__PURE__ */ (0,
|
|
15414
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
15417
|
-
/* @__PURE__ */ (0,
|
|
15418
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
15421
|
-
/* @__PURE__ */ (0,
|
|
15422
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
15438
|
-
/* @__PURE__ */ (0,
|
|
15439
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
15480
|
+
var import_react69 = __toESM(require("react"), 1);
|
|
15452
15481
|
|
|
15453
15482
|
// src/personalization/PersonalizationContext.ts
|
|
15454
|
-
var
|
|
15455
|
-
var PersonalizationContext = (0,
|
|
15483
|
+
var import_react67 = require("react");
|
|
15484
|
+
var PersonalizationContext = (0, import_react67.createContext)(null);
|
|
15456
15485
|
function usePersonalizationContext() {
|
|
15457
|
-
return (0,
|
|
15486
|
+
return (0, import_react67.useContext)(PersonalizationContext);
|
|
15458
15487
|
}
|
|
15459
15488
|
|
|
15460
15489
|
// src/personalization/utils.ts
|
|
15461
|
-
var
|
|
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,
|
|
15483
|
-
(0,
|
|
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
|
|
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 =
|
|
15539
|
+
const elementsRef = import_react69.default.useRef(elements);
|
|
15511
15540
|
elementsRef.current = elements;
|
|
15512
|
-
const executeRef =
|
|
15541
|
+
const executeRef = import_react69.default.useRef(executeElementUpdate);
|
|
15513
15542
|
executeRef.current = executeElementUpdate;
|
|
15514
|
-
const hasUserInput =
|
|
15515
|
-
|
|
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 =
|
|
15562
|
+
const elementsRef = import_react69.default.useRef(elements);
|
|
15534
15563
|
elementsRef.current = elements;
|
|
15535
|
-
const executeRef =
|
|
15564
|
+
const executeRef = import_react69.default.useRef(executeElementUpdate);
|
|
15536
15565
|
executeRef.current = executeElementUpdate;
|
|
15537
|
-
const appliedColorRef =
|
|
15538
|
-
|
|
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 =
|
|
15607
|
+
const hasUserInput = import_react69.default.useRef(false);
|
|
15579
15608
|
const debouncedValue = useDebouncedValue(value, 500);
|
|
15580
|
-
const setImageUrlRef =
|
|
15609
|
+
const setImageUrlRef = import_react69.default.useRef(setImageUrl);
|
|
15581
15610
|
setImageUrlRef.current = setImageUrl;
|
|
15582
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
15623
|
-
const [isActive, setIsActive] = (0,
|
|
15624
|
-
const [isExporting, setIsExporting] = (0,
|
|
15625
|
-
const [exportedBlobUrls, setExportedBlobUrls] = (0,
|
|
15626
|
-
const [exportCount, setExportCount] = (0,
|
|
15627
|
-
const blobUrlsRef = (0,
|
|
15628
|
-
const [CanvasComponent, setCanvasComponent] = (0,
|
|
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,
|
|
15660
|
+
const [BridgeComponent, setBridgeComponent] = (0, import_react69.useState)(
|
|
15632
15661
|
cachedBridgeComponent
|
|
15633
15662
|
);
|
|
15634
|
-
(0,
|
|
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,
|
|
15653
|
-
(0,
|
|
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,
|
|
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,
|
|
15696
|
+
const reset = (0, import_react69.useCallback)(() => {
|
|
15668
15697
|
setPersonValues({});
|
|
15669
15698
|
setIsActive(false);
|
|
15670
15699
|
setIsExporting(false);
|
|
15671
15700
|
}, []);
|
|
15672
|
-
const handleExport = (0,
|
|
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,
|
|
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 =
|
|
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,
|
|
15724
|
-
shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
15807
|
-
textFields.map((field) => /* @__PURE__ */ (0,
|
|
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,
|
|
15822
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
15856
|
-
const sdkSettledRef = (0,
|
|
15857
|
-
const manualTriggerRef = (0,
|
|
15858
|
-
const safetyTimeoutRef = (0,
|
|
15859
|
-
const startShimmer = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|