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