@snowcone-app/ui 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -235,6 +235,8 @@ __export(src_exports, {
235
235
  Link: () => Link,
236
236
  LinkIcon: () => LinkIcon,
237
237
  LoadingOverlayPrism: () => LoadingOverlayPrism,
238
+ LoadingOverlayPrismCandy: () => LoadingOverlayPrismCandy,
239
+ LoadingOverlayPrismCandyInline: () => LoadingOverlayPrismCandyInline,
238
240
  MasonryGrid: () => MasonryGrid,
239
241
  MobileProductCarousel: () => MobileProductCarousel,
240
242
  MockupPriorityProvider: () => MockupPriorityProvider,
@@ -376,7 +378,7 @@ __export(src_exports, {
376
378
  useProductSelection: () => useProductSelection,
377
379
  useProviderStatus: () => useProviderStatus,
378
380
  useRealtime: () => useRealtime,
379
- useRealtimeMockup: () => import_react68.useRealtimeMockup,
381
+ useRealtimeMockup: () => import_react69.useRealtimeMockup,
380
382
  useRealtimeOptional: () => useRealtimeOptional,
381
383
  useRenderCount: () => useRenderCount,
382
384
  useRenderGuard: () => useRenderGuard,
@@ -9014,12 +9016,333 @@ function useLoadingOverlay(isLoading) {
9014
9016
  };
9015
9017
  }
9016
9018
 
9019
+ // src/components/LoadingOverlayPrismCandy.tsx
9020
+ var import_react40 = require("react");
9021
+ var import_react_dom2 = require("react-dom");
9022
+ var import_jsx_runtime55 = require("react/jsx-runtime");
9023
+ var BANDS = [
9024
+ { rgb: "230, 45, 55", delay: "-0.0s" },
9025
+ // red
9026
+ { rgb: "250, 125, 30", delay: "-0.3s" },
9027
+ // orange
9028
+ { rgb: "244, 215, 60", delay: "-0.6s" },
9029
+ // yellow
9030
+ { rgb: "110, 200, 70", delay: "-0.9s" },
9031
+ // green
9032
+ { rgb: "65, 145, 205", delay: "-1.2s" },
9033
+ // blue
9034
+ { rgb: "140, 90, 175", delay: "-1.5s" }
9035
+ // purple
9036
+ ];
9037
+ function generateParticles2() {
9038
+ return Array.from({ length: 10 }, () => ({
9039
+ left: 2 + Math.random() * 96,
9040
+ top: 2 + Math.random() * 96,
9041
+ delay: (Math.random() * 3.5).toFixed(1),
9042
+ duration: (3 + Math.random() * 2).toFixed(1),
9043
+ size: 3 + Math.random() * 5
9044
+ }));
9045
+ }
9046
+ var PLATE_ALPHA = 0.1;
9047
+ var BAND_ALPHA = 0.55;
9048
+ var FADE_IN_MS2 = 600;
9049
+ var FADE_OUT_MS2 = 400;
9050
+ var STYLES2 = `
9051
+ /* Registered custom properties \u2014 required for the browser to interpolate
9052
+ them across a CSS transition / animation. Without @property, value
9053
+ changes snap rather than animate. */
9054
+ @property --candy-mount {
9055
+ syntax: "<number>";
9056
+ initial-value: 0;
9057
+ inherits: true;
9058
+ }
9059
+ /* Per-band sweep-fade. Animated by the keyframes below to scale the band
9060
+ rgba alpha 0 \u2192 1 \u2192 1 \u2192 0 across a sweep cycle. Lives on .candy-band
9061
+ only (not inherited), so each band has its own animated value. */
9062
+ @property --band-alpha {
9063
+ syntax: "<number>";
9064
+ initial-value: 0;
9065
+ inherits: false;
9066
+ }
9067
+
9068
+ .candy-loading-overlay {
9069
+ --candy-mount: 0;
9070
+ overflow: hidden;
9071
+ background-color: rgba(255, 255, 255, calc(${PLATE_ALPHA} * var(--candy-mount)));
9072
+ transition: --candy-mount ${FADE_IN_MS2}ms ease-in,
9073
+ background-color ${FADE_IN_MS2}ms ease-in;
9074
+ }
9075
+ .candy-loading-overlay.candy-fade-in { --candy-mount: 1; }
9076
+ .candy-loading-overlay.candy-fade-out {
9077
+ --candy-mount: 0;
9078
+ transition: --candy-mount ${FADE_OUT_MS2}ms ease-out,
9079
+ background-color ${FADE_OUT_MS2}ms ease-out;
9080
+ }
9081
+
9082
+ .candy-band {
9083
+ --band-alpha: 0;
9084
+ position: absolute;
9085
+ width: 220%; height: 30%;
9086
+ left: -60%;
9087
+ mix-blend-mode: screen;
9088
+ -webkit-mask-image: linear-gradient(180deg, transparent 0%, black 35%, black 65%, transparent 100%);
9089
+ mask-image: linear-gradient(180deg, transparent 0%, black 35%, black 65%, transparent 100%);
9090
+ animation-timing-function: ease-in-out;
9091
+ animation-iteration-count: infinite;
9092
+ animation-duration: 6s;
9093
+ }
9094
+ ${BANDS.map((b, i) => {
9095
+ const top = -5 + i * 16;
9096
+ const direction = i % 2 === 0 ? "ltr" : "rtl";
9097
+ return `.candy-band:nth-child(${i + 1}) { top: ${top}%; background: linear-gradient(90deg, transparent 0%, rgba(${b.rgb}, calc(${BAND_ALPHA} * var(--candy-mount) * var(--band-alpha) * var(--band-strength, 1))) 30%, rgba(${b.rgb}, calc(${BAND_ALPHA} * var(--candy-mount) * var(--band-alpha) * var(--band-strength, 1))) 70%, transparent 100%); animation-name: candy-sweep-${direction}; animation-delay: ${b.delay}; }`;
9098
+ }).join("\n")}
9099
+ @keyframes candy-sweep-ltr {
9100
+ 0% { transform: translateX(-45%) rotate(-6deg); --band-alpha: 0; }
9101
+ 25% { --band-alpha: 1; }
9102
+ 50% { transform: translateX(0%) rotate(-6deg); }
9103
+ 75% { --band-alpha: 1; }
9104
+ 100% { transform: translateX(45%) rotate(-6deg); --band-alpha: 0; }
9105
+ }
9106
+ @keyframes candy-sweep-rtl {
9107
+ 0% { transform: translateX(45%) rotate(-6deg); --band-alpha: 0; }
9108
+ 25% { --band-alpha: 1; }
9109
+ 50% { transform: translateX(0%) rotate(-6deg); }
9110
+ 75% { --band-alpha: 1; }
9111
+ 100% { transform: translateX(-45%) rotate(-6deg); --band-alpha: 0; }
9112
+ }
9113
+
9114
+ .candy-particle {
9115
+ position: absolute; border-radius: 50%;
9116
+ /* Particle background and glow alphas also scale with --candy-mount so
9117
+ the sparkles fade with the rest of the overlay. */
9118
+ background: rgba(255, 255, 255, calc(1 * var(--candy-mount)));
9119
+ box-shadow: 0 0 8px rgba(255, 255, 255, calc(0.85 * var(--candy-mount)));
9120
+ opacity: 0;
9121
+ animation: candy-sparkle infinite ease-in-out;
9122
+ }
9123
+ @keyframes candy-sparkle {
9124
+ 0% { opacity: 0; transform: scale(0); }
9125
+ 15% { opacity: 0.7; transform: scale(1.4); }
9126
+ 30% { opacity: 0.4; transform: scale(0.6); }
9127
+ 55% { opacity: 1; transform: scale(2); }
9128
+ 75% { opacity: 0.5; transform: scale(0.9); }
9129
+ 100% { opacity: 0; transform: scale(0); }
9130
+ }
9131
+
9132
+ /* Light-backdrop variant. The default bands screen-blend \u2014 vivid on a dark
9133
+ stage, but they wash out to nothing over white (screen over white = white).
9134
+ On a light card we multiply-blend instead, so each band tints the backdrop
9135
+ toward its hue (jewel/pastel rainbow rather than neon). The sparkle particles
9136
+ stay white in both variants \u2014 they read as snow, and the white glow keeps
9137
+ them legible over the multiply rainbow bands. */
9138
+ .candy-on-light .candy-band { mix-blend-mode: multiply; }
9139
+ /* Opaque light stage baked into the overlay so it fades in/out as one unit
9140
+ with the bands \u2014 matching the PDP hero's smooth crossfade \u2014 instead of a
9141
+ hard backdrop on the parent that snaps on/off. The alpha scales with
9142
+ --candy-mount (overriding the default 0.1 white plate), so it rides the
9143
+ same candy-fade-in / candy-fade-out transition the bands do. The bands
9144
+ multiply-blend against this opaque stage to read as the candy rainbow.
9145
+ #f5f5f5 = the site page background (defaults.css --color-background), kept
9146
+ as a fixed hex (not the token, which would flip dark in dark mode and break
9147
+ the multiply blend) so the loader sits flush with the surrounding page. */
9148
+ .candy-on-light {
9149
+ background-color: rgba(245, 245, 245, calc(1 * var(--candy-mount)));
9150
+ /* Half the band opacity on the light stage \u2014 multiply-blended bands read
9151
+ stronger on light gray than the screen-blended ones do on the dark PDP
9152
+ stage, so dial them back to ~50%. Inherits down to .candy-band; the dark
9153
+ default leaves --band-strength at its 1 fallback, untouched. */
9154
+ --band-strength: 0.5;
9155
+ }
9156
+
9157
+ `;
9158
+ var stylesInjected2 = false;
9159
+ function ensureStyles2() {
9160
+ if (stylesInjected2 || typeof document === "undefined") return;
9161
+ if (typeof CSS !== "undefined" && typeof CSS.registerProperty === "function") {
9162
+ try {
9163
+ CSS.registerProperty({
9164
+ name: "--candy-mount",
9165
+ syntax: "<number>",
9166
+ initialValue: "0",
9167
+ inherits: true
9168
+ });
9169
+ } catch {
9170
+ }
9171
+ try {
9172
+ CSS.registerProperty({
9173
+ name: "--band-alpha",
9174
+ syntax: "<number>",
9175
+ initialValue: "0",
9176
+ inherits: false
9177
+ });
9178
+ } catch {
9179
+ }
9180
+ }
9181
+ const s = document.createElement("style");
9182
+ s.textContent = STYLES2;
9183
+ document.head.appendChild(s);
9184
+ stylesInjected2 = true;
9185
+ }
9186
+ function CandyVisual({
9187
+ fadeClass,
9188
+ style,
9189
+ onTransitionEnd,
9190
+ variantClass = ""
9191
+ }) {
9192
+ const [particles, setParticles] = (0, import_react40.useState)([]);
9193
+ (0, import_react40.useEffect)(() => {
9194
+ setParticles(generateParticles2());
9195
+ }, []);
9196
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
9197
+ "div",
9198
+ {
9199
+ className: `candy-loading-overlay ${variantClass} ${fadeClass}`.trim(),
9200
+ style,
9201
+ onTransitionEnd,
9202
+ children: [
9203
+ BANDS.map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "candy-band" }, `b-${i}`)),
9204
+ particles.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9205
+ "div",
9206
+ {
9207
+ className: "candy-particle",
9208
+ style: {
9209
+ left: `${p.left}%`,
9210
+ top: `${p.top}%`,
9211
+ animationDelay: `${p.delay}s`,
9212
+ animationDuration: `${p.duration}s`,
9213
+ width: `${p.size}px`,
9214
+ height: `${p.size}px`
9215
+ }
9216
+ },
9217
+ `p-${i}`
9218
+ ))
9219
+ ]
9220
+ }
9221
+ );
9222
+ }
9223
+ var LoadingOverlayPrismCandy = (0, import_react40.memo)(function LoadingOverlayPrismCandy2({
9224
+ visible = true,
9225
+ onExited
9226
+ }) {
9227
+ ensureStyles2();
9228
+ const anchorRef = (0, import_react40.useRef)(null);
9229
+ const [bounds, setBounds] = (0, import_react40.useState)(null);
9230
+ const [mounted, setMounted] = (0, import_react40.useState)(false);
9231
+ const measure = (0, import_react40.useCallback)(() => {
9232
+ const el = anchorRef.current;
9233
+ if (!el) return;
9234
+ const r = el.getBoundingClientRect();
9235
+ setBounds({
9236
+ top: r.top + window.scrollY,
9237
+ left: r.left + window.scrollX,
9238
+ width: r.width,
9239
+ height: r.height
9240
+ });
9241
+ }, []);
9242
+ (0, import_react40.useLayoutEffect)(() => {
9243
+ measure();
9244
+ window.addEventListener("resize", measure);
9245
+ let ro = null;
9246
+ if (typeof ResizeObserver !== "undefined" && anchorRef.current) {
9247
+ ro = new ResizeObserver(measure);
9248
+ ro.observe(anchorRef.current);
9249
+ }
9250
+ return () => {
9251
+ window.removeEventListener("resize", measure);
9252
+ ro?.disconnect();
9253
+ };
9254
+ }, [measure]);
9255
+ (0, import_react40.useEffect)(() => {
9256
+ const raf = requestAnimationFrame(() => setMounted(true));
9257
+ return () => cancelAnimationFrame(raf);
9258
+ }, []);
9259
+ const handleTransitionEnd = (0, import_react40.useCallback)(
9260
+ (e) => {
9261
+ if (e.propertyName !== "background-color") return;
9262
+ if (!visible) onExited?.();
9263
+ },
9264
+ [visible, onExited]
9265
+ );
9266
+ let fadeClass = "";
9267
+ if (!visible) fadeClass = "candy-fade-out";
9268
+ else if (mounted) fadeClass = "candy-fade-in";
9269
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
9270
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9271
+ "div",
9272
+ {
9273
+ ref: anchorRef,
9274
+ style: {
9275
+ position: "absolute",
9276
+ inset: 0,
9277
+ pointerEvents: "none"
9278
+ },
9279
+ "aria-hidden": "true"
9280
+ }
9281
+ ),
9282
+ bounds && typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
9283
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9284
+ CandyVisual,
9285
+ {
9286
+ fadeClass,
9287
+ style: {
9288
+ position: "absolute",
9289
+ top: bounds.top,
9290
+ left: bounds.left,
9291
+ width: bounds.width,
9292
+ height: bounds.height,
9293
+ pointerEvents: "none"
9294
+ },
9295
+ onTransitionEnd: handleTransitionEnd
9296
+ }
9297
+ ),
9298
+ document.body
9299
+ )
9300
+ ] });
9301
+ });
9302
+ var LoadingOverlayPrismCandyInline = (0, import_react40.memo)(
9303
+ function LoadingOverlayPrismCandyInline2({
9304
+ visible = true,
9305
+ onExited,
9306
+ variant = "dark"
9307
+ }) {
9308
+ ensureStyles2();
9309
+ const [mounted, setMounted] = (0, import_react40.useState)(false);
9310
+ (0, import_react40.useEffect)(() => {
9311
+ const raf = requestAnimationFrame(() => setMounted(true));
9312
+ return () => cancelAnimationFrame(raf);
9313
+ }, []);
9314
+ const handleTransitionEnd = (0, import_react40.useCallback)(
9315
+ (e) => {
9316
+ if (e.propertyName !== "background-color") return;
9317
+ if (!visible) onExited?.();
9318
+ },
9319
+ [visible, onExited]
9320
+ );
9321
+ let fadeClass = "";
9322
+ if (!visible) fadeClass = "candy-fade-out";
9323
+ else if (mounted) fadeClass = "candy-fade-in";
9324
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9325
+ CandyVisual,
9326
+ {
9327
+ fadeClass,
9328
+ variantClass: variant === "light" ? "candy-on-light" : "",
9329
+ style: {
9330
+ position: "absolute",
9331
+ inset: 0,
9332
+ pointerEvents: "none"
9333
+ },
9334
+ onTransitionEnd: handleTransitionEnd
9335
+ }
9336
+ );
9337
+ }
9338
+ );
9339
+
9017
9340
  // src/index.ts
9018
- var import_react68 = require("@snowcone-app/sdk/react");
9341
+ var import_react69 = require("@snowcone-app/sdk/react");
9019
9342
  var import_sdk11 = require("@snowcone-app/sdk");
9020
9343
 
9021
9344
  // src/patterns/ProductPageProvider.tsx
9022
- var import_jsx_runtime55 = require("react/jsx-runtime");
9345
+ var import_jsx_runtime56 = require("react/jsx-runtime");
9023
9346
  function ProductPageProvider({
9024
9347
  children,
9025
9348
  productId,
@@ -9033,12 +9356,12 @@ function ProductPageProvider({
9033
9356
  realtimeGrantUrl,
9034
9357
  enablePriority = true
9035
9358
  }) {
9036
- let content = /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Product, { productId, productData, children });
9359
+ let content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Product, { productId, productData, children });
9037
9360
  if (enablePriority) {
9038
- content = /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(MockupPriorityProvider, { children: content });
9361
+ content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(MockupPriorityProvider, { children: content });
9039
9362
  }
9040
9363
  if (enableRealtime) {
9041
- content = /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9364
+ content = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9042
9365
  RealtimeProvider,
9043
9366
  {
9044
9367
  wsUrl: realtimeWsUrl,
@@ -9048,7 +9371,7 @@ function ProductPageProvider({
9048
9371
  }
9049
9372
  );
9050
9373
  }
9051
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9374
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9052
9375
  Shop,
9053
9376
  {
9054
9377
  endpoint,
@@ -9068,23 +9391,23 @@ function ProductPageProviderMinimal({
9068
9391
  shop,
9069
9392
  initialArtwork
9070
9393
  }) {
9071
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9394
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9072
9395
  Shop,
9073
9396
  {
9074
9397
  endpoint,
9075
9398
  mockupUrl,
9076
9399
  shop,
9077
9400
  initialArtwork,
9078
- children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Product, { productId, productData, children })
9401
+ children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Product, { productId, productData, children })
9079
9402
  }
9080
9403
  );
9081
9404
  }
9082
9405
 
9083
9406
  // src/composed/ArtAlignment.tsx
9084
- var import_react40 = require("react");
9085
- var import_react41 = require("@use-gesture/react");
9407
+ var import_react41 = require("react");
9408
+ var import_react42 = require("@use-gesture/react");
9086
9409
  var import_sdk9 = require("@snowcone-app/sdk");
9087
- var import_jsx_runtime56 = require("react/jsx-runtime");
9410
+ var import_jsx_runtime57 = require("react/jsx-runtime");
9088
9411
  function ArtAlignment({
9089
9412
  src: propSrc,
9090
9413
  artworkAspectRatio: propAspectRatio,
@@ -9118,16 +9441,16 @@ function ArtAlignment({
9118
9441
  selection: {}
9119
9442
  };
9120
9443
  }
9121
- const containerRef = (0, import_react40.useRef)(null);
9122
- const imageRef = (0, import_react40.useRef)(null);
9123
- const lastUserDragTimeRef = (0, import_react40.useRef)(0);
9124
- const [containerSize, setContainerSize] = (0, import_react40.useState)({ width: 0, height: 0 });
9125
- const [position, setPosition] = (0, import_react40.useState)({ x: 0, y: 0 });
9126
- const [isReady, setIsReady] = (0, import_react40.useState)(false);
9127
- const [detectedAspectRatio, setDetectedAspectRatio] = (0, import_react40.useState)();
9444
+ const containerRef = (0, import_react41.useRef)(null);
9445
+ const imageRef = (0, import_react41.useRef)(null);
9446
+ const lastUserDragTimeRef = (0, import_react41.useRef)(0);
9447
+ const [containerSize, setContainerSize] = (0, import_react41.useState)({ width: 0, height: 0 });
9448
+ const [position, setPosition] = (0, import_react41.useState)({ x: 0, y: 0 });
9449
+ const [isReady, setIsReady] = (0, import_react41.useState)(false);
9450
+ const [detectedAspectRatio, setDetectedAspectRatio] = (0, import_react41.useState)();
9128
9451
  const effectiveAspectRatio = artworkAspectRatio || detectedAspectRatio;
9129
9452
  const alignment = placementDesign?.alignment || propAlignment || "center";
9130
- const descriptor = (0, import_react40.useMemo)(
9453
+ const descriptor = (0, import_react41.useMemo)(
9131
9454
  () => (0, import_sdk9.describeProductArtAlignment)(
9132
9455
  {
9133
9456
  src,
@@ -9149,7 +9472,7 @@ function ArtAlignment({
9149
9472
  productContext
9150
9473
  ]
9151
9474
  );
9152
- const containerStyle = (0, import_react40.useMemo)(() => {
9475
+ const containerStyle = (0, import_react41.useMemo)(() => {
9153
9476
  const style = {};
9154
9477
  if (height !== void 0) {
9155
9478
  const heightValue = typeof height === "number" ? height : parseFloat(height);
@@ -9180,7 +9503,7 @@ function ArtAlignment({
9180
9503
  }
9181
9504
  return style;
9182
9505
  }, [effectiveAspectRatio, height, maxHeight, minHeight]);
9183
- (0, import_react40.useEffect)(() => {
9506
+ (0, import_react41.useEffect)(() => {
9184
9507
  if (!containerRef.current) return;
9185
9508
  const resizeObserver = new ResizeObserver((entries) => {
9186
9509
  const entry = entries[0];
@@ -9206,7 +9529,7 @@ function ArtAlignment({
9206
9529
  }
9207
9530
  }
9208
9531
  };
9209
- (0, import_react40.useEffect)(() => {
9532
+ (0, import_react41.useEffect)(() => {
9210
9533
  if (!imageRef.current || !descriptor) return;
9211
9534
  if (imageRef.current.complete) {
9212
9535
  setIsReady(true);
@@ -9231,7 +9554,7 @@ function ArtAlignment({
9231
9554
  img.removeEventListener("load", handleLoad);
9232
9555
  };
9233
9556
  }, [descriptor?.src, artworkAspectRatio]);
9234
- const maskDimensions = (0, import_react40.useMemo)(() => {
9557
+ const maskDimensions = (0, import_react41.useMemo)(() => {
9235
9558
  if (!isReady || containerSize.width === 0 || !descriptor) {
9236
9559
  return { width: 0, height: 0 };
9237
9560
  }
@@ -9246,14 +9569,14 @@ function ArtAlignment({
9246
9569
  descriptor?.effectiveAlignment,
9247
9570
  isReady
9248
9571
  ]);
9249
- const clipPathCoords = (0, import_react40.useMemo)(() => {
9572
+ const clipPathCoords = (0, import_react41.useMemo)(() => {
9250
9573
  const halfMaskW = maskDimensions.width / 2;
9251
9574
  const halfMaskH = maskDimensions.height / 2;
9252
9575
  const halfContainerW = containerSize.width / 2;
9253
9576
  const halfContainerH = containerSize.height / 2;
9254
9577
  return { halfMaskW, halfMaskH, halfContainerW, halfContainerH };
9255
9578
  }, [maskDimensions.width, maskDimensions.height, containerSize.width, containerSize.height]);
9256
- (0, import_react40.useEffect)(() => {
9579
+ (0, import_react41.useEffect)(() => {
9257
9580
  if (Date.now() - lastUserDragTimeRef.current < 500) return;
9258
9581
  if (!isReady || maskDimensions.width === 0 || !descriptor) return;
9259
9582
  const points = (0, import_sdk9.getSnapPoints)(
@@ -9275,7 +9598,7 @@ function ArtAlignment({
9275
9598
  maskDimensions.height,
9276
9599
  isReady
9277
9600
  ]);
9278
- const overlayStyle = (0, import_react40.useMemo)(() => {
9601
+ const overlayStyle = (0, import_react41.useMemo)(() => {
9279
9602
  const { halfMaskW, halfMaskH, halfContainerW, halfContainerH } = clipPathCoords;
9280
9603
  const cx = position.x + halfContainerW;
9281
9604
  const cy = position.y + halfContainerH;
@@ -9296,7 +9619,7 @@ function ArtAlignment({
9296
9619
  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"
9297
9620
  };
9298
9621
  }, [isReady, position.x, position.y, clipPathCoords]);
9299
- const maskStyle = (0, import_react40.useMemo)(() => ({
9622
+ const maskStyle = (0, import_react41.useMemo)(() => ({
9300
9623
  width: `${maskDimensions.width}px`,
9301
9624
  height: `${maskDimensions.height}px`,
9302
9625
  boxShadow: `0 0 0 2px var(--color-background), 0 0 0 4px var(--color-primary)`,
@@ -9311,7 +9634,7 @@ function ArtAlignment({
9311
9634
  // GPU acceleration for smoother drag
9312
9635
  borderRadius: "var(--radius-image, 4px)"
9313
9636
  }), [maskDimensions.width, maskDimensions.height]);
9314
- const clearImageClipPath = (0, import_react40.useMemo)(() => {
9637
+ const clearImageClipPath = (0, import_react41.useMemo)(() => {
9315
9638
  if (!isReady) return "none";
9316
9639
  const { halfMaskW, halfMaskH, halfContainerW, halfContainerH } = clipPathCoords;
9317
9640
  const cx = position.x + halfContainerW;
@@ -9322,14 +9645,14 @@ function ArtAlignment({
9322
9645
  const top = cy - halfMaskH;
9323
9646
  return `polygon(${left}px ${top}px, ${right}px ${top}px, ${right}px ${bottom}px, ${left}px ${bottom}px)`;
9324
9647
  }, [isReady, position.x, position.y, clipPathCoords]);
9325
- const maskTransform = (0, import_react40.useMemo)(() => {
9648
+ const maskTransform = (0, import_react41.useMemo)(() => {
9326
9649
  return descriptor?.effectiveAlignment === "horizontal" ? `translate(calc(-50% + ${position.x}px), -50%)` : `translate(-50%, calc(-50% + ${position.y}px))`;
9327
9650
  }, [descriptor?.effectiveAlignment, position.x, position.y]);
9328
- const lastContextUpdateTimeRef = (0, import_react40.useRef)(0);
9329
- const pendingAlignmentRef = (0, import_react40.useRef)(null);
9330
- const throttleTimeoutRef = (0, import_react40.useRef)(null);
9651
+ const lastContextUpdateTimeRef = (0, import_react41.useRef)(0);
9652
+ const pendingAlignmentRef = (0, import_react41.useRef)(null);
9653
+ const throttleTimeoutRef = (0, import_react41.useRef)(null);
9331
9654
  const THROTTLE_MS = 150;
9332
- const bind = (0, import_react41.useDrag)(
9655
+ const bind = (0, import_react42.useDrag)(
9333
9656
  ({ offset: [ox, oy], last }) => {
9334
9657
  if (maskDimensions.width === 0 || maskDimensions.height === 0 || !descriptor) {
9335
9658
  return;
@@ -9422,7 +9745,7 @@ function ArtAlignment({
9422
9745
  if (!descriptor) {
9423
9746
  return null;
9424
9747
  }
9425
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9748
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9426
9749
  "div",
9427
9750
  {
9428
9751
  className: `relative ${className || ""}`,
@@ -9431,8 +9754,8 @@ function ArtAlignment({
9431
9754
  width: "fit-content",
9432
9755
  maxWidth: "100%"
9433
9756
  },
9434
- children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "overflow-hidden p-1", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { ref: containerRef, className: "relative", style: containerStyle, children: [
9435
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9757
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "overflow-hidden p-1", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { ref: containerRef, className: "relative", style: containerStyle, children: [
9758
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9436
9759
  "img",
9437
9760
  {
9438
9761
  ref: imageRef,
@@ -9457,9 +9780,9 @@ function ArtAlignment({
9457
9780
  loading: "eager"
9458
9781
  }
9459
9782
  ),
9460
- isReady && maskDimensions.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
9461
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { style: overlayStyle }),
9462
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9783
+ isReady && maskDimensions.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
9784
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { style: overlayStyle }),
9785
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9463
9786
  "img",
9464
9787
  {
9465
9788
  src: descriptor.src,
@@ -9487,7 +9810,7 @@ function ArtAlignment({
9487
9810
  loading: "eager"
9488
9811
  }
9489
9812
  ),
9490
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
9813
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9491
9814
  "div",
9492
9815
  {
9493
9816
  ...bind(),
@@ -9504,8 +9827,8 @@ function ArtAlignment({
9504
9827
  }
9505
9828
 
9506
9829
  // src/composed/ArtworkCustomizer.tsx
9507
- var import_react42 = require("react");
9508
- var import_jsx_runtime57 = require("react/jsx-runtime");
9830
+ var import_react43 = require("react");
9831
+ var import_jsx_runtime58 = require("react/jsx-runtime");
9509
9832
  function ArtworkCustomizer(props) {
9510
9833
  const designContext = useDesign();
9511
9834
  const artwork = props.artwork || designContext.selectedArtwork;
@@ -9517,7 +9840,7 @@ function ArtworkCustomizer(props) {
9517
9840
  const placements = productCtx?.product?.placements || [];
9518
9841
  const selectedPlacement = productCtx?.selectedPlacement;
9519
9842
  const setSelectedPlacement = productCtx?.setSelectedPlacement;
9520
- (0, import_react42.useEffect)(() => {
9843
+ (0, import_react43.useEffect)(() => {
9521
9844
  if (placements.length > 0 && !selectedPlacement && setSelectedPlacement) {
9522
9845
  setSelectedPlacement(placements[0].label);
9523
9846
  }
@@ -9527,13 +9850,13 @@ function ArtworkCustomizer(props) {
9527
9850
  );
9528
9851
  const isColorPlacement = currentPlacement?.type === "color";
9529
9852
  const isFitMode = currentPlacement?.defaultScaleMode === "fit";
9530
- (0, import_react42.useEffect)(() => {
9853
+ (0, import_react43.useEffect)(() => {
9531
9854
  }, [selectedPlacement]);
9532
9855
  if (!artwork) {
9533
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: `text-sm text-muted-foreground ${props.className || ""}`, children: "Select artwork to customize" });
9856
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: `text-sm text-muted-foreground ${props.className || ""}`, children: "Select artwork to customize" });
9534
9857
  }
9535
9858
  if (artwork.type === "pattern") {
9536
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9859
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9537
9860
  TileCount,
9538
9861
  {
9539
9862
  artwork,
@@ -9544,8 +9867,8 @@ function ArtworkCustomizer(props) {
9544
9867
  );
9545
9868
  }
9546
9869
  const isCanvasEditorMode = props.mode === "canvas" || !!props.children && props.mode !== "alignment";
9547
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex flex-col gap-4", children: [
9548
- placements.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "text-sm leading-relaxed", children: placements.map((p) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9870
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex flex-col gap-4", children: [
9871
+ placements.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "text-sm leading-relaxed", children: placements.map((p) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9549
9872
  "button",
9550
9873
  {
9551
9874
  onClick: () => setSelectedPlacement?.(p.label),
@@ -9554,7 +9877,7 @@ function ArtworkCustomizer(props) {
9554
9877
  },
9555
9878
  p.label
9556
9879
  )) }),
9557
- isColorPlacement ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ColorPicker2, { placement: selectedPlacement }) : isFitMode ? null : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "relative", children: props.children || /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
9880
+ isColorPlacement ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ColorPicker2, { placement: selectedPlacement }) : isFitMode ? null : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "relative", children: props.children || /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9558
9881
  ArtAlignment,
9559
9882
  {
9560
9883
  artwork: { src: artwork.src },
@@ -9570,7 +9893,7 @@ function ArtworkCustomizer(props) {
9570
9893
 
9571
9894
  // src/composed/CanvasEditor.tsx
9572
9895
  var import_lucide_react2 = require("lucide-react");
9573
- var import_jsx_runtime58 = require("react/jsx-runtime");
9896
+ var import_jsx_runtime59 = require("react/jsx-runtime");
9574
9897
  var ImageIcon = import_lucide_react2.Image;
9575
9898
  var TypeIcon = import_lucide_react2.Type;
9576
9899
  var ShapesIcon = import_lucide_react2.Shapes;
@@ -9581,43 +9904,43 @@ function CanvasEditor({
9581
9904
  onOpenTypography,
9582
9905
  children
9583
9906
  }) {
9584
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex flex-col gap-6", children: [
9585
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "bg-background border-2 border-border rounded-lg aspect-square overflow-hidden relative", children: children || /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "text-muted-foreground text-sm", children: "No editor provided" }) }) }),
9586
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex items-center justify-center gap-8 py-2", children: [
9587
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9907
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex flex-col gap-6", children: [
9908
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "bg-background border-2 border-border rounded-lg aspect-square overflow-hidden relative", children: children || /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "text-muted-foreground text-sm", children: "No editor provided" }) }) }),
9909
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex items-center justify-center gap-8 py-2", children: [
9910
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9588
9911
  "button",
9589
9912
  {
9590
9913
  onClick: onOpenImageGallery,
9591
9914
  className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors",
9592
9915
  "aria-label": "Open image gallery",
9593
- children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ImageIcon, { className: "w-6 h-6" }) })
9916
+ children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(ImageIcon, { className: "w-6 h-6" }) })
9594
9917
  }
9595
9918
  ),
9596
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9919
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
9597
9920
  "button",
9598
9921
  {
9599
9922
  onClick: onOpenTypography,
9600
9923
  className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors",
9601
9924
  "aria-label": "Add text",
9602
- children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TypeIcon, { className: "w-6 h-6" }) })
9925
+ children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TypeIcon, { className: "w-6 h-6" }) })
9603
9926
  }
9604
9927
  ),
9605
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ShapesIcon, { className: "w-6 h-6" }) }) }),
9606
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(UploadIcon, { className: "w-6 h-6" }) }) })
9928
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(ShapesIcon, { className: "w-6 h-6" }) }) }),
9929
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { className: "flex flex-col items-center gap-2 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(UploadIcon, { className: "w-6 h-6" }) }) })
9607
9930
  ] })
9608
9931
  ] });
9609
9932
  }
9610
9933
 
9611
9934
  // src/composed/HeroProductImage.tsx
9612
- var import_react44 = require("react");
9935
+ var import_react45 = require("react");
9613
9936
  var import_sdk10 = require("@snowcone-app/sdk");
9614
9937
 
9615
9938
  // src/hooks/viewport/useContainerWidth.ts
9616
- var import_react43 = require("react");
9939
+ var import_react44 = require("react");
9617
9940
  function useContainerWidth(containerRef, maxWidth = 3e3) {
9618
- const [width, setWidth] = (0, import_react43.useState)(0);
9619
- const resizeTimeoutRef = (0, import_react43.useRef)(null);
9620
- (0, import_react43.useLayoutEffect)(() => {
9941
+ const [width, setWidth] = (0, import_react44.useState)(0);
9942
+ const resizeTimeoutRef = (0, import_react44.useRef)(null);
9943
+ (0, import_react44.useLayoutEffect)(() => {
9621
9944
  const el = containerRef.current;
9622
9945
  if (!el) return;
9623
9946
  const cssWidth = el.offsetWidth;
@@ -9625,7 +9948,7 @@ function useContainerWidth(containerRef, maxWidth = 3e3) {
9625
9948
  const dpr = window.devicePixelRatio ?? 1;
9626
9949
  setWidth(Math.min(Math.round(cssWidth * dpr), maxWidth));
9627
9950
  }, [containerRef, maxWidth]);
9628
- (0, import_react43.useEffect)(() => {
9951
+ (0, import_react44.useEffect)(() => {
9629
9952
  const measure = () => {
9630
9953
  const el = containerRef.current;
9631
9954
  if (!el) return;
@@ -9648,7 +9971,7 @@ function useContainerWidth(containerRef, maxWidth = 3e3) {
9648
9971
  }
9649
9972
 
9650
9973
  // src/composed/HeroProductImage.tsx
9651
- var import_jsx_runtime59 = require("react/jsx-runtime");
9974
+ var import_jsx_runtime60 = require("react/jsx-runtime");
9652
9975
  function slugifyPlacementKey(label) {
9653
9976
  return label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
9654
9977
  }
@@ -9686,7 +10009,7 @@ function buildHeroMockupUrl(args) {
9686
10009
  });
9687
10010
  }
9688
10011
  var EMPTY_IMAGES = [];
9689
- var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
10012
+ var HeroProductImage = (0, import_react45.memo)(function HeroProductImage2({
9690
10013
  productId,
9691
10014
  mockupId,
9692
10015
  variantId,
@@ -9719,24 +10042,24 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9719
10042
  const shopContext = useShopOptional();
9720
10043
  const realtimeContext = useRealtimeOptional();
9721
10044
  const priorityContext = useMockupPriorityOptional();
9722
- const priorityContextRef = (0, import_react44.useRef)(priorityContext);
10045
+ const priorityContextRef = (0, import_react45.useRef)(priorityContext);
9723
10046
  priorityContextRef.current = priorityContext;
9724
- const contextRef = (0, import_react44.useRef)(context);
10047
+ const contextRef = (0, import_react45.useRef)(context);
9725
10048
  contextRef.current = context;
9726
10049
  const actualProductId = product?.id || productId || context?.product?.id;
9727
- const actualGvid = (0, import_react44.useMemo)(() => {
10050
+ const actualGvid = (0, import_react45.useMemo)(() => {
9728
10051
  return (0, import_sdk10.resolveVariantId)(context, gvid, variantId);
9729
10052
  }, [gvid, variantId, context?.selection, context?.combinations]);
9730
- const actualMockupId = (0, import_react44.useMemo)(() => {
10053
+ const actualMockupId = (0, import_react45.useMemo)(() => {
9731
10054
  return (0, import_sdk10.resolveMockupId)(context, actualGvid, mockupId);
9732
10055
  }, [mockupId, actualGvid, context]);
9733
10056
  const artworkSrc = artwork?.src;
9734
10057
  const selectedArtworkSrc = designContext?.selectedArtwork?.src;
9735
10058
  const effectiveArtworkSrc = artworkSrc || selectedArtworkSrc;
9736
- const containerRef = (0, import_react44.useRef)(null);
10059
+ const containerRef = (0, import_react45.useRef)(null);
9737
10060
  const measuredWidth = useContainerWidth(containerRef);
9738
10061
  const width = widthProp ?? measuredWidth;
9739
- const initialStaticUrl = (0, import_react44.useMemo)(() => {
10062
+ const initialStaticUrl = (0, import_react45.useMemo)(() => {
9740
10063
  if (realtimeUrl) return null;
9741
10064
  if (mode === "realtime") return null;
9742
10065
  if (typeof window !== "undefined" && window.snowcone?.signMockupUrl) {
@@ -9802,28 +10125,28 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9802
10125
  shimmerDelay,
9803
10126
  initialUrl: realtimeUrl || initialStaticUrl
9804
10127
  });
9805
- const [error, setError] = (0, import_react44.useState)(null);
9806
- const [isInPreloadZone, setIsInPreloadZone] = (0, import_react44.useState)(true);
9807
- const componentIdRef = (0, import_react44.useRef)(
10128
+ const [error, setError] = (0, import_react45.useState)(null);
10129
+ const [isInPreloadZone, setIsInPreloadZone] = (0, import_react45.useState)(true);
10130
+ const componentIdRef = (0, import_react45.useRef)(
9808
10131
  `hero-product-image-${Math.random().toString(36).substr(2, 9)}`
9809
10132
  );
9810
- const [containerMounted, setContainerMounted] = (0, import_react44.useState)(false);
9811
- const setContainerRef = (0, import_react44.useCallback)((node) => {
10133
+ const [containerMounted, setContainerMounted] = (0, import_react45.useState)(false);
10134
+ const setContainerRef = (0, import_react45.useCallback)((node) => {
9812
10135
  containerRef.current = node;
9813
10136
  setContainerMounted(!!node);
9814
10137
  }, []);
9815
- const lastUrlRef = (0, import_react44.useRef)(realtimeUrl ?? initialStaticUrl ?? null);
9816
- const priorityRegisteredRef = (0, import_react44.useRef)(false);
9817
- const onLoadCalledRef = (0, import_react44.useRef)(false);
9818
- const prevArtworkSrcRef = (0, import_react44.useRef)(void 0);
9819
- const realtimeArtworkSrcRef = (0, import_react44.useRef)(void 0);
9820
- const hasReceivedRealtimeRef = (0, import_react44.useRef)(false);
9821
- const isPendingExportRef = (0, import_react44.useRef)(false);
9822
- const onUrlGeneratedRef = (0, import_react44.useRef)(onUrlGenerated);
10138
+ const lastUrlRef = (0, import_react45.useRef)(realtimeUrl ?? initialStaticUrl ?? null);
10139
+ const priorityRegisteredRef = (0, import_react45.useRef)(false);
10140
+ const onLoadCalledRef = (0, import_react45.useRef)(false);
10141
+ const prevArtworkSrcRef = (0, import_react45.useRef)(void 0);
10142
+ const realtimeArtworkSrcRef = (0, import_react45.useRef)(void 0);
10143
+ const hasReceivedRealtimeRef = (0, import_react45.useRef)(false);
10144
+ const isPendingExportRef = (0, import_react45.useRef)(false);
10145
+ const onUrlGeneratedRef = (0, import_react45.useRef)(onUrlGenerated);
9823
10146
  onUrlGeneratedRef.current = onUrlGenerated;
9824
- const layersLengthRef = (0, import_react44.useRef)(layers.length);
10147
+ const layersLengthRef = (0, import_react45.useRef)(layers.length);
9825
10148
  layersLengthRef.current = layers.length;
9826
- (0, import_react44.useEffect)(() => {
10149
+ (0, import_react45.useEffect)(() => {
9827
10150
  if (initialPriority === 1) return;
9828
10151
  if (!containerMounted || !containerRef.current) return;
9829
10152
  if (isInPreloadZone) return;
@@ -9842,7 +10165,7 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9842
10165
  );
9843
10166
  return unobserve;
9844
10167
  }, [containerMounted, initialPriority, isInPreloadZone]);
9845
- (0, import_react44.useEffect)(() => {
10168
+ (0, import_react45.useEffect)(() => {
9846
10169
  if (!realtimeUrl) return;
9847
10170
  if (realtimeUrl === lastUrlRef.current) return;
9848
10171
  lastUrlRef.current = realtimeUrl;
@@ -9850,7 +10173,7 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9850
10173
  const isInitialLoad = layersLengthRef.current === 0;
9851
10174
  addLayerDirectly(realtimeUrl, { skipTransition: isInitialLoad });
9852
10175
  }, [realtimeUrl, addLayerDirectly, actualMockupId, placement]);
9853
- (0, import_react44.useEffect)(() => {
10176
+ (0, import_react45.useEffect)(() => {
9854
10177
  if (mode === "static") {
9855
10178
  return;
9856
10179
  }
@@ -9894,7 +10217,7 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9894
10217
  addLayerDirectly
9895
10218
  // NOTE: layers.length removed - use layersLengthRef instead to prevent duplicate requests
9896
10219
  ]);
9897
- (0, import_react44.useEffect)(() => {
10220
+ (0, import_react45.useEffect)(() => {
9898
10221
  if (mode === "static") return;
9899
10222
  if (!realtimeContext?.subscribePendingBlob || !placement) return;
9900
10223
  const handlePendingExport = (pendingPlacement) => {
@@ -9907,7 +10230,7 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9907
10230
  unsubscribe?.();
9908
10231
  };
9909
10232
  }, [mode, realtimeContext?.subscribePendingBlob, placement]);
9910
- (0, import_react44.useEffect)(() => {
10233
+ (0, import_react45.useEffect)(() => {
9911
10234
  if (!priorityContext || !actualMockupId || !placement) return;
9912
10235
  priorityContext.registerMockup(actualMockupId, placement, initialPriority);
9913
10236
  priorityRegisteredRef.current = true;
@@ -9918,7 +10241,7 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9918
10241
  }
9919
10242
  };
9920
10243
  }, [priorityContext, actualMockupId, placement, initialPriority]);
9921
- (0, import_react44.useEffect)(() => {
10244
+ (0, import_react45.useEffect)(() => {
9922
10245
  if (!priorityContext?.updateElementRef || !actualMockupId) return;
9923
10246
  if (containerMounted && containerRef.current) {
9924
10247
  priorityContext.updateElementRef(actualMockupId, containerRef.current);
@@ -9932,7 +10255,7 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9932
10255
  const artworkTileCount = artwork?.type === "pattern" ? artwork?.tileCount : void 0;
9933
10256
  const selectedArtworkType = designContext?.selectedArtwork?.type;
9934
10257
  const selectedArtworkTileCount = designContext?.selectedArtwork?.type === "pattern" ? designContext?.selectedArtwork?.tileCount : void 0;
9935
- (0, import_react44.useEffect)(() => {
10258
+ (0, import_react45.useEffect)(() => {
9936
10259
  const currentSrc = artworkSrc || selectedArtworkSrc;
9937
10260
  if (currentSrc !== prevArtworkSrcRef.current) {
9938
10261
  lastUrlRef.current = null;
@@ -9942,11 +10265,11 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9942
10265
  realtimeArtworkSrcRef.current = void 0;
9943
10266
  }
9944
10267
  }, [artworkSrc, selectedArtworkSrc]);
9945
- const contextSelectionRef = (0, import_react44.useRef)(context?.selection);
9946
- const contextOptionAttributesRef = (0, import_react44.useRef)(context?.optionAttributes);
10268
+ const contextSelectionRef = (0, import_react45.useRef)(context?.selection);
10269
+ const contextOptionAttributesRef = (0, import_react45.useRef)(context?.optionAttributes);
9947
10270
  contextSelectionRef.current = context?.selection;
9948
10271
  contextOptionAttributesRef.current = context?.optionAttributes;
9949
- const createDesignForPlacementsWrapper = (0, import_react44.useCallback)(
10272
+ const createDesignForPlacementsWrapper = (0, import_react45.useCallback)(
9950
10273
  (placements, providedImages) => {
9951
10274
  const effectiveArtworkSrc2 = artworkSrc || selectedArtworkSrc;
9952
10275
  if (!effectiveArtworkSrc2 || effectiveArtworkSrc2.trim() === "" || effectiveArtworkSrc2 === "undefined" || effectiveArtworkSrc2 === "null") {
@@ -9985,7 +10308,7 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
9985
10308
  selectedArtworkTileCount
9986
10309
  ]
9987
10310
  );
9988
- (0, import_react44.useEffect)(() => {
10311
+ (0, import_react45.useEffect)(() => {
9989
10312
  if (mode === "realtime") return;
9990
10313
  if (initialStaticUrl && lastUrlRef.current === initialStaticUrl) {
9991
10314
  return;
@@ -10085,13 +10408,13 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
10085
10408
  const topLayer = layers[layers.length - 1];
10086
10409
  const displayUrl = topLayer?.url || realtimeUrl || initialStaticUrl;
10087
10410
  const CROSSFADE_MS = 400;
10088
- const [prevUrl, setPrevUrl] = (0, import_react44.useState)(null);
10089
- const [showNew, setShowNew] = (0, import_react44.useState)(false);
10090
- const [renderedUrl, setRenderedUrl] = (0, import_react44.useState)(displayUrl);
10091
- const [firstImageLoaded, setFirstImageLoaded] = (0, import_react44.useState)(false);
10092
- const prevDisplayUrlRef = (0, import_react44.useRef)(displayUrl);
10093
- const signHintShownRef = (0, import_react44.useRef)(false);
10094
- (0, import_react44.useEffect)(() => {
10411
+ const [prevUrl, setPrevUrl] = (0, import_react45.useState)(null);
10412
+ const [showNew, setShowNew] = (0, import_react45.useState)(false);
10413
+ const [renderedUrl, setRenderedUrl] = (0, import_react45.useState)(displayUrl);
10414
+ const [firstImageLoaded, setFirstImageLoaded] = (0, import_react45.useState)(false);
10415
+ const prevDisplayUrlRef = (0, import_react45.useRef)(displayUrl);
10416
+ const signHintShownRef = (0, import_react45.useRef)(false);
10417
+ (0, import_react45.useEffect)(() => {
10095
10418
  if (!displayUrl || displayUrl === prevDisplayUrlRef.current) return;
10096
10419
  const oldUrl = prevDisplayUrlRef.current;
10097
10420
  prevDisplayUrlRef.current = displayUrl;
@@ -10116,25 +10439,25 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
10116
10439
  preload.onload = null;
10117
10440
  };
10118
10441
  }, [displayUrl]);
10119
- const handleCrossfadeEnd = (0, import_react44.useCallback)(() => {
10442
+ const handleCrossfadeEnd = (0, import_react45.useCallback)(() => {
10120
10443
  setPrevUrl(null);
10121
10444
  setShowNew(false);
10122
10445
  }, []);
10123
10446
  if (!hasArtwork) {
10124
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
10447
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10125
10448
  "div",
10126
10449
  {
10127
10450
  className: `bg-gray-100 flex items-center justify-center ${className || ""}`,
10128
10451
  style,
10129
- children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "text-gray-400 text-center p-4", children: [
10130
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
10452
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "text-gray-400 text-center p-4", children: [
10453
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10131
10454
  "svg",
10132
10455
  {
10133
10456
  className: "w-8 h-8 mx-auto mb-2",
10134
10457
  fill: "none",
10135
10458
  stroke: "currentColor",
10136
10459
  viewBox: "0 0 24 24",
10137
- children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
10460
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10138
10461
  "path",
10139
10462
  {
10140
10463
  strokeLinecap: "round",
@@ -10145,22 +10468,22 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
10145
10468
  )
10146
10469
  }
10147
10470
  ),
10148
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "text-xs", children: "No artwork" })
10471
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-xs", children: "No artwork" })
10149
10472
  ] })
10150
10473
  }
10151
10474
  );
10152
10475
  }
10153
10476
  if (error) {
10154
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
10477
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10155
10478
  "div",
10156
10479
  {
10157
10480
  className: `bg-red-50 flex items-center justify-center ${className || ""}`,
10158
10481
  style,
10159
- children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "text-red-600 text-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "text-xs", children: "Error loading" }) })
10482
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "text-red-600 text-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-xs", children: "Error loading" }) })
10160
10483
  }
10161
10484
  );
10162
10485
  }
10163
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
10486
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
10164
10487
  "div",
10165
10488
  {
10166
10489
  ref: setContainerRef,
@@ -10168,8 +10491,8 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
10168
10491
  style,
10169
10492
  "data-hero-image": "true",
10170
10493
  children: [
10171
- !firstImageLoaded && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "absolute inset-0 bg-muted-foreground/20 animate-pulse" }),
10172
- renderedUrl && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
10494
+ !firstImageLoaded && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "absolute inset-0 bg-muted-foreground/20 animate-pulse" }),
10495
+ renderedUrl && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10173
10496
  "img",
10174
10497
  {
10175
10498
  alt: `Product mockup${placement ? ` - ${placement}` : ""}`,
@@ -10201,7 +10524,7 @@ var HeroProductImage = (0, import_react44.memo)(function HeroProductImage2({
10201
10524
  }
10202
10525
  }
10203
10526
  ),
10204
- prevUrl && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
10527
+ prevUrl && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10205
10528
  "img",
10206
10529
  {
10207
10530
  alt: "",
@@ -10241,11 +10564,11 @@ var { searchClient } = (0, import_instant_meilisearch.instantMeiliSearch)(
10241
10564
  );
10242
10565
 
10243
10566
  // src/composed/search/SearchProvider.tsx
10244
- var import_react45 = require("react");
10245
- var import_jsx_runtime60 = require("react/jsx-runtime");
10567
+ var import_react46 = require("react");
10568
+ var import_jsx_runtime61 = require("react/jsx-runtime");
10246
10569
  function InitialSearchTrigger() {
10247
10570
  const { refine } = (0, import_react_instantsearch.useSearchBox)();
10248
- (0, import_react45.useEffect)(() => {
10571
+ (0, import_react46.useEffect)(() => {
10249
10572
  refine("");
10250
10573
  }, [refine]);
10251
10574
  return null;
@@ -10269,7 +10592,7 @@ function SearchProvider({
10269
10592
  ],
10270
10593
  children
10271
10594
  }) {
10272
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
10595
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
10273
10596
  import_react_instantsearch.InstantSearch,
10274
10597
  {
10275
10598
  searchClient,
@@ -10297,7 +10620,7 @@ function SearchProvider({
10297
10620
  }
10298
10621
  },
10299
10622
  children: [
10300
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
10623
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10301
10624
  import_react_instantsearch.Configure,
10302
10625
  {
10303
10626
  hitsPerPage,
@@ -10306,7 +10629,7 @@ function SearchProvider({
10306
10629
  attributesToRetrieve
10307
10630
  }
10308
10631
  ),
10309
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InitialSearchTrigger, {}),
10632
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(InitialSearchTrigger, {}),
10310
10633
  children
10311
10634
  ]
10312
10635
  }
@@ -10316,17 +10639,17 @@ function SearchProvider({
10316
10639
  // src/composed/search/SearchBox.tsx
10317
10640
  var import_react_instantsearch2 = require("react-instantsearch");
10318
10641
  var import_lucide_react3 = require("lucide-react");
10319
- var import_react46 = require("react");
10320
- var import_jsx_runtime61 = require("react/jsx-runtime");
10642
+ var import_react47 = require("react");
10643
+ var import_jsx_runtime62 = require("react/jsx-runtime");
10321
10644
  function SearchBox() {
10322
10645
  const { query, refine, clear } = (0, import_react_instantsearch2.useSearchBox)();
10323
10646
  const searchParams = useUiSearchParams();
10324
10647
  const router = useUiRouter();
10325
- const inputRef = (0, import_react46.useRef)(null);
10326
- const [showShimmer, setShowShimmer] = (0, import_react46.useState)(false);
10648
+ const inputRef = (0, import_react47.useRef)(null);
10649
+ const [showShimmer, setShowShimmer] = (0, import_react47.useState)(false);
10327
10650
  const inputId = "search-products-input";
10328
10651
  const descriptionId = "search-description";
10329
- (0, import_react46.useEffect)(() => {
10652
+ (0, import_react47.useEffect)(() => {
10330
10653
  const handleSpotlight = () => {
10331
10654
  inputRef.current?.focus();
10332
10655
  inputRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
@@ -10336,7 +10659,7 @@ function SearchBox() {
10336
10659
  window.addEventListener("search-spotlight", handleSpotlight);
10337
10660
  return () => window.removeEventListener("search-spotlight", handleSpotlight);
10338
10661
  }, []);
10339
- (0, import_react46.useEffect)(() => {
10662
+ (0, import_react47.useEffect)(() => {
10340
10663
  const shouldFocus = searchParams.get("focus") === "search";
10341
10664
  if (shouldFocus && inputRef.current) {
10342
10665
  const timer = setTimeout(() => {
@@ -10351,8 +10674,8 @@ function SearchBox() {
10351
10674
  return () => clearTimeout(timer);
10352
10675
  }
10353
10676
  }, [searchParams, router]);
10354
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "relative", children: [
10355
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10677
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("form", { role: "search", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "relative", children: [
10678
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10356
10679
  Input,
10357
10680
  {
10358
10681
  ref: inputRef,
@@ -10361,15 +10684,15 @@ function SearchBox() {
10361
10684
  value: query,
10362
10685
  onChange: (e) => refine(e.target.value),
10363
10686
  placeholder: "Search products...",
10364
- startContent: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_lucide_react3.Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10365
- endContent: query ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10687
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react3.Search, { className: "w-5 h-5", strokeWidth: 1.5, "aria-hidden": "true" }),
10688
+ endContent: query ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10366
10689
  "button",
10367
10690
  {
10368
10691
  type: "button",
10369
10692
  onClick: clear,
10370
10693
  className: "hover:text-foreground transition-colors",
10371
10694
  "aria-label": "Clear search",
10372
- children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_lucide_react3.X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10695
+ children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react3.X, { className: "w-4 h-4", strokeWidth: 2, "aria-hidden": "true" })
10373
10696
  }
10374
10697
  ) : void 0,
10375
10698
  "aria-label": "Search products",
@@ -10379,11 +10702,11 @@ function SearchBox() {
10379
10702
  className: "[&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden"
10380
10703
  }
10381
10704
  ),
10382
- showShimmer && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10705
+ showShimmer && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10383
10706
  "div",
10384
10707
  {
10385
10708
  className: "absolute inset-0 pointer-events-none rounded-input z-20 overflow-hidden",
10386
- children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
10709
+ children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10387
10710
  "div",
10388
10711
  {
10389
10712
  className: "absolute inset-0",
@@ -10396,13 +10719,13 @@ function SearchBox() {
10396
10719
  )
10397
10720
  }
10398
10721
  ),
10399
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("style", { dangerouslySetInnerHTML: { __html: `
10722
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("style", { dangerouslySetInnerHTML: { __html: `
10400
10723
  @keyframes searchShimmer {
10401
10724
  0% { transform: translateX(-100%); }
10402
10725
  100% { transform: translateX(100%); }
10403
10726
  }
10404
10727
  ` } }),
10405
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10728
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { id: descriptionId, className: "sr-only", children: "Search results will update as you type" })
10406
10729
  ] }) });
10407
10730
  }
10408
10731
 
@@ -10410,7 +10733,7 @@ function SearchBox() {
10410
10733
  var import_react_instantsearch3 = require("react-instantsearch");
10411
10734
 
10412
10735
  // src/composed/search/ProductHit.tsx
10413
- var import_jsx_runtime62 = require("react/jsx-runtime");
10736
+ var import_jsx_runtime63 = require("react/jsx-runtime");
10414
10737
  function ProductHitComponent({
10415
10738
  hit: product,
10416
10739
  variant = "overlay"
@@ -10427,12 +10750,12 @@ function ProductHitComponent({
10427
10750
  }
10428
10751
  return "";
10429
10752
  };
10430
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10753
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10431
10754
  Product,
10432
10755
  {
10433
10756
  productId,
10434
10757
  productData: product,
10435
- children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10758
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10436
10759
  ProductCard,
10437
10760
  {
10438
10761
  variant,
@@ -10453,10 +10776,10 @@ function ProductHitComponent({
10453
10776
  }
10454
10777
 
10455
10778
  // src/composed/search/ProductGrid.tsx
10456
- var import_react47 = require("react");
10457
- var import_jsx_runtime63 = require("react/jsx-runtime");
10779
+ var import_react48 = require("react");
10780
+ var import_jsx_runtime64 = require("react/jsx-runtime");
10458
10781
  function ProductGridSkeletonItem() {
10459
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "aspect-square bg-muted animate-pulse" });
10782
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "aspect-square bg-muted animate-pulse" });
10460
10783
  }
10461
10784
  function ProductGrid({
10462
10785
  className = "",
@@ -10466,26 +10789,26 @@ function ProductGrid({
10466
10789
  }) {
10467
10790
  const { nbHits } = (0, import_react_instantsearch3.useStats)();
10468
10791
  const { status, results } = (0, import_react_instantsearch3.useInstantSearch)();
10469
- const [announcement, setAnnouncement] = (0, import_react47.useState)("");
10792
+ const [announcement, setAnnouncement] = (0, import_react48.useState)("");
10470
10793
  const hitsCount = results?.hits?.length ?? 0;
10471
10794
  const showSkeleton = hitsCount === 0 && status !== "error";
10472
- (0, import_react47.useEffect)(() => {
10795
+ (0, import_react48.useEffect)(() => {
10473
10796
  const timer = setTimeout(() => {
10474
10797
  setAnnouncement(`${nbHits} ${nbHits === 1 ? "product" : "products"} found`);
10475
10798
  }, 1e3);
10476
10799
  return () => clearTimeout(timer);
10477
10800
  }, [nbHits]);
10478
- const HitComponent = (0, import_react47.useCallback)(({ hit }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10801
+ const HitComponent = (0, import_react48.useCallback)(({ hit }) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10479
10802
  ProductHitComponent,
10480
10803
  {
10481
10804
  hit,
10482
10805
  variant
10483
10806
  }
10484
10807
  ), [variant]);
10485
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className, children: [
10486
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10487
- showSkeleton && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: `grid ${gridClassName}`, children: Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(ProductGridSkeletonItem, {}, i)) }),
10488
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: showSkeleton ? "hidden" : "", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10808
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className, children: [
10809
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
10810
+ showSkeleton && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: `grid ${gridClassName}`, children: Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(ProductGridSkeletonItem, {}, i)) }),
10811
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: showSkeleton ? "hidden" : "", children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
10489
10812
  import_react_instantsearch3.Hits,
10490
10813
  {
10491
10814
  hitComponent: HitComponent,
@@ -10500,18 +10823,18 @@ function ProductGrid({
10500
10823
  }
10501
10824
 
10502
10825
  // src/composed/search/Filters.tsx
10503
- var import_react49 = require("react");
10826
+ var import_react50 = require("react");
10504
10827
 
10505
10828
  // src/composed/search/FiltersButton.tsx
10506
10829
  var import_lucide_react4 = require("lucide-react");
10507
- var import_jsx_runtime64 = require("react/jsx-runtime");
10830
+ var import_jsx_runtime65 = require("react/jsx-runtime");
10508
10831
  var SlidersHorizontalIcon = import_lucide_react4.SlidersHorizontal;
10509
10832
  function FiltersButton({
10510
10833
  onClick,
10511
10834
  className = "",
10512
10835
  children = "Filters"
10513
10836
  }) {
10514
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
10837
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
10515
10838
  Button,
10516
10839
  {
10517
10840
  variant: "field",
@@ -10519,8 +10842,8 @@ function FiltersButton({
10519
10842
  className,
10520
10843
  "aria-label": "Open filters",
10521
10844
  children: [
10522
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10523
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { children })
10845
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(SlidersHorizontalIcon, { className: "w-4 h-4" }),
10846
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { children })
10524
10847
  ]
10525
10848
  }
10526
10849
  );
@@ -10529,15 +10852,15 @@ function FiltersButton({
10529
10852
  // src/composed/search/FiltersDrawer.tsx
10530
10853
  var import_react_instantsearch4 = require("react-instantsearch");
10531
10854
  var import_lucide_react5 = require("lucide-react");
10532
- var import_react48 = require("react");
10855
+ var import_react49 = require("react");
10533
10856
  var Slider2 = __toESM(require("@radix-ui/react-slider"), 1);
10534
- var import_jsx_runtime65 = require("react/jsx-runtime");
10857
+ var import_jsx_runtime66 = require("react/jsx-runtime");
10535
10858
  var XIcon2 = import_lucide_react5.X;
10536
10859
  function FiltersDrawer({ isOpen, onClose }) {
10537
- const [showCounts, setShowCounts] = (0, import_react48.useState)(false);
10860
+ const [showCounts, setShowCounts] = (0, import_react49.useState)(false);
10538
10861
  const { nbHits } = (0, import_react_instantsearch4.useStats)();
10539
10862
  const containerRef = useFocusTrap(isOpen, onClose);
10540
- (0, import_react48.useEffect)(() => {
10863
+ (0, import_react49.useEffect)(() => {
10541
10864
  if (isOpen) {
10542
10865
  document.body.style.overflow = "hidden";
10543
10866
  } else {
@@ -10547,7 +10870,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10547
10870
  document.body.style.overflow = "";
10548
10871
  };
10549
10872
  }, [isOpen]);
10550
- (0, import_react48.useEffect)(() => {
10873
+ (0, import_react49.useEffect)(() => {
10551
10874
  const handleEscape = (e) => {
10552
10875
  if (e.key === "Escape" && isOpen) {
10553
10876
  onClose();
@@ -10556,8 +10879,8 @@ function FiltersDrawer({ isOpen, onClose }) {
10556
10879
  document.addEventListener("keydown", handleEscape);
10557
10880
  return () => document.removeEventListener("keydown", handleEscape);
10558
10881
  }, [isOpen, onClose]);
10559
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(import_jsx_runtime65.Fragment, { children: [
10560
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10882
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(import_jsx_runtime66.Fragment, { children: [
10883
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10561
10884
  "div",
10562
10885
  {
10563
10886
  className: `fixed inset-0 bg-black/50 z-40 transition-opacity ${isOpen ? "opacity-100" : "opacity-0 pointer-events-none"}`,
@@ -10565,7 +10888,7 @@ function FiltersDrawer({ isOpen, onClose }) {
10565
10888
  "aria-hidden": "true"
10566
10889
  }
10567
10890
  ),
10568
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
10891
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10569
10892
  "div",
10570
10893
  {
10571
10894
  ref: containerRef,
@@ -10574,26 +10897,26 @@ function FiltersDrawer({ isOpen, onClose }) {
10574
10897
  "aria-modal": "true",
10575
10898
  "aria-labelledby": "filters-drawer-title",
10576
10899
  children: [
10577
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "flex items-center justify-between px-4 py-4", children: [
10578
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10579
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10900
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center justify-between px-4 py-4", children: [
10901
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("h2", { id: "filters-drawer-title", className: "text-xl font-bold", children: "Filters" }),
10902
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10580
10903
  "button",
10581
10904
  {
10582
10905
  onClick: onClose,
10583
10906
  className: "p-2 hover:bg-foreground/5 rounded-full transition-colors",
10584
10907
  "aria-label": "Close filters",
10585
- children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(XIcon2, { className: "w-5 h-5" })
10908
+ children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(XIcon2, { className: "w-5 h-5" })
10586
10909
  }
10587
10910
  )
10588
10911
  ] }),
10589
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("p", { className: "text-sm font-caption text-foreground/60", role: "status", "aria-live": "polite", children: [
10912
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("p", { className: "text-sm font-caption text-foreground/60", role: "status", "aria-live": "polite", children: [
10590
10913
  nbHits.toLocaleString(),
10591
10914
  " ",
10592
10915
  nbHits === 1 ? "result" : "results"
10593
10916
  ] }) }),
10594
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "flex flex-col gap-8", children: [
10595
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(TagsSection, { showCounts, setShowCounts }),
10596
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(PriceSection, {})
10917
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "flex flex-col gap-8", children: [
10918
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(TagsSection, { showCounts, setShowCounts }),
10919
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(PriceSection, {})
10597
10920
  ] }) })
10598
10921
  ]
10599
10922
  }
@@ -10609,9 +10932,9 @@ function TagsSection({
10609
10932
  sortBy: ["count:desc", "name:asc"],
10610
10933
  limit: 100
10611
10934
  });
10612
- const [isExpanded, setIsExpanded] = (0, import_react48.useState)(true);
10613
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
10614
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
10935
+ const [isExpanded, setIsExpanded] = (0, import_react49.useState)(true);
10936
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
10937
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10615
10938
  "button",
10616
10939
  {
10617
10940
  onClick: () => setIsExpanded(!isExpanded),
@@ -10619,8 +10942,8 @@ function TagsSection({
10619
10942
  "aria-expanded": isExpanded,
10620
10943
  "aria-controls": "tags-content",
10621
10944
  children: [
10622
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
10623
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10945
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Tags" }),
10946
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10624
10947
  "svg",
10625
10948
  {
10626
10949
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -10629,14 +10952,14 @@ function TagsSection({
10629
10952
  stroke: "currentColor",
10630
10953
  strokeWidth: 2.5,
10631
10954
  "aria-hidden": "true",
10632
- children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
10955
+ children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
10633
10956
  }
10634
10957
  )
10635
10958
  ]
10636
10959
  }
10637
10960
  ),
10638
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "space-y-4", id: "tags-content", children: [
10639
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "flex flex-wrap gap-2", role: "group", "aria-label": "Product tags filter", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
10961
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "space-y-4", id: "tags-content", children: [
10962
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "flex flex-wrap gap-2", role: "group", "aria-label": "Product tags filter", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10640
10963
  "button",
10641
10964
  {
10642
10965
  onClick: () => refine(item.value),
@@ -10647,15 +10970,15 @@ function TagsSection({
10647
10970
  "aria-label": `${item.isRefined ? "Remove" : "Apply"} ${item.label} filter${showCounts ? ` (${item.count} products)` : ""}`,
10648
10971
  "aria-pressed": item.isRefined,
10649
10972
  children: [
10650
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { "aria-hidden": "true", children: item.label }),
10651
- showCounts && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: `text-xs font-caption ${item.isRefined ? "opacity-80" : "opacity-60"}`, "aria-hidden": "true", children: item.count })
10973
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { "aria-hidden": "true", children: item.label }),
10974
+ showCounts && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: `text-xs font-caption ${item.isRefined ? "opacity-80" : "opacity-60"}`, "aria-hidden": "true", children: item.count })
10652
10975
  ]
10653
10976
  },
10654
10977
  item.value
10655
10978
  )) }),
10656
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "flex items-center justify-between pt-2", children: [
10657
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
10658
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10979
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center justify-between pt-2", children: [
10980
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "text-sm font-label text-foreground/60", id: "show-counts-label", children: "Show counts" }),
10981
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10659
10982
  "button",
10660
10983
  {
10661
10984
  onClick: () => setShowCounts(!showCounts),
@@ -10663,7 +10986,7 @@ function TagsSection({
10663
10986
  role: "switch",
10664
10987
  "aria-checked": showCounts,
10665
10988
  "aria-labelledby": "show-counts-label",
10666
- children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
10989
+ children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10667
10990
  "span",
10668
10991
  {
10669
10992
  className: `inline-block h-4 w-4 transform rounded-full bg-background shadow-sm transition-transform ${showCounts ? "translate-x-6" : "translate-x-1"}`,
@@ -10680,11 +11003,11 @@ function PriceSection() {
10680
11003
  const { range, refine, start, canRefine } = (0, import_react_instantsearch4.useRange)({ attribute: "price" });
10681
11004
  const rangeMin = typeof range.min === "number" && isFinite(range.min) ? range.min : 0;
10682
11005
  const rangeMax = typeof range.max === "number" && isFinite(range.max) ? range.max : 15e3;
10683
- const [localRange, setLocalRange] = (0, import_react48.useState)([
11006
+ const [localRange, setLocalRange] = (0, import_react49.useState)([
10684
11007
  typeof start?.[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
10685
11008
  typeof start?.[1] === "number" && isFinite(start[1]) ? start[1] : rangeMax
10686
11009
  ]);
10687
- (0, import_react48.useEffect)(() => {
11010
+ (0, import_react49.useEffect)(() => {
10688
11011
  if (start && Array.isArray(start)) {
10689
11012
  setLocalRange([
10690
11013
  typeof start[0] === "number" && isFinite(start[0]) ? start[0] : rangeMin,
@@ -10694,7 +11017,7 @@ function PriceSection() {
10694
11017
  setLocalRange([rangeMin, rangeMax]);
10695
11018
  }
10696
11019
  }, [start, rangeMin, rangeMax]);
10697
- const [isExpanded, setIsExpanded] = (0, import_react48.useState)(true);
11020
+ const [isExpanded, setIsExpanded] = (0, import_react49.useState)(true);
10698
11021
  if (!canRefine) {
10699
11022
  return null;
10700
11023
  }
@@ -10709,8 +11032,8 @@ function PriceSection() {
10709
11032
  return `$${priceInDollars.toFixed(2)}`;
10710
11033
  }
10711
11034
  };
10712
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
10713
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
11035
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "bg-foreground/5 rounded-lg p-4", children: [
11036
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10714
11037
  "button",
10715
11038
  {
10716
11039
  onClick: () => setIsExpanded(!isExpanded),
@@ -10718,8 +11041,8 @@ function PriceSection() {
10718
11041
  "aria-expanded": isExpanded,
10719
11042
  "aria-controls": "price-content",
10720
11043
  children: [
10721
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
10722
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
11044
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("h3", { className: "text-base font-semibold text-primary", children: "Price" }),
11045
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10723
11046
  "svg",
10724
11047
  {
10725
11048
  className: `w-5 h-5 transition-transform text-foreground/40 group-hover:text-foreground/60 ${isExpanded ? "rotate-180" : ""}`,
@@ -10728,22 +11051,22 @@ function PriceSection() {
10728
11051
  stroke: "currentColor",
10729
11052
  strokeWidth: 2.5,
10730
11053
  "aria-hidden": "true",
10731
- children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
11054
+ children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
10732
11055
  }
10733
11056
  )
10734
11057
  ]
10735
11058
  }
10736
11059
  ),
10737
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "space-y-6", id: "price-content", children: [
10738
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "flex items-center justify-between text-sm font-display", children: [
10739
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { children: formatPrice2(localRange[0]) }),
10740
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "text-foreground/70", children: formatPrice2(localRange[1]) })
11060
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "space-y-6", id: "price-content", children: [
11061
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center justify-between text-sm font-display", children: [
11062
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: formatPrice2(localRange[0]) }),
11063
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "text-foreground/70", children: formatPrice2(localRange[1]) })
10741
11064
  ] }),
10742
- /* @__PURE__ */ (0, import_jsx_runtime65.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) => {
11065
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "relative h-24 flex items-end justify-between gap-0.5 px-1", "aria-hidden": "true", role: "presentation", children: [60, 40, 80, 50, 60, 30, 20, 15, 10, 5, 30, 20, 15, 10, 5, 3, 3, 60, 40].map((height, i) => {
10743
11066
  const totalBars = 19;
10744
11067
  const barPrice = rangeMin + (rangeMax - rangeMin) / totalBars * i;
10745
11068
  const isInRange = barPrice >= localRange[0] && barPrice <= localRange[1];
10746
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
11069
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10747
11070
  "div",
10748
11071
  {
10749
11072
  className: `flex-1 rounded-t-sm transition-opacity ${isInRange ? "bg-foreground" : "bg-foreground/20"}`,
@@ -10752,7 +11075,7 @@ function PriceSection() {
10752
11075
  i
10753
11076
  );
10754
11077
  }) }),
10755
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
11078
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { style: { touchAction: "none" }, className: "my-6", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
10756
11079
  Slider2.Root,
10757
11080
  {
10758
11081
  className: "relative flex w-full touch-none select-none items-center",
@@ -10770,8 +11093,8 @@ function PriceSection() {
10770
11093
  step: 1,
10771
11094
  minStepsBetweenThumbs: 1,
10772
11095
  children: [
10773
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Slider2.Track, { className: "relative h-3 w-full grow overflow-hidden rounded-full bg-foreground/20", children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Slider2.Range, { className: "absolute h-full bg-foreground" }) }),
10774
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
11096
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Slider2.Track, { className: "relative h-3 w-full grow overflow-hidden rounded-full bg-foreground/20", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Slider2.Range, { className: "absolute h-full bg-foreground" }) }),
11097
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10775
11098
  Slider2.Thumb,
10776
11099
  {
10777
11100
  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",
@@ -10785,7 +11108,7 @@ function PriceSection() {
10785
11108
  "aria-valuetext": formatPrice2(localRange[0])
10786
11109
  }
10787
11110
  ),
10788
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
11111
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10789
11112
  Slider2.Thumb,
10790
11113
  {
10791
11114
  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",
@@ -10802,10 +11125,10 @@ function PriceSection() {
10802
11125
  ]
10803
11126
  }
10804
11127
  ) }),
10805
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "grid grid-cols-2 gap-3", children: [
10806
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { children: [
10807
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
10808
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
11128
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "grid grid-cols-2 gap-3", children: [
11129
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { children: [
11130
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("label", { htmlFor: "price-min", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Min" }),
11131
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10809
11132
  "input",
10810
11133
  {
10811
11134
  id: "price-min",
@@ -10823,9 +11146,9 @@ function PriceSection() {
10823
11146
  }
10824
11147
  )
10825
11148
  ] }),
10826
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { children: [
10827
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
10828
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
11149
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { children: [
11150
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("label", { htmlFor: "price-max", className: "text-xs font-label text-foreground/60 mb-1.5 block", children: "Max" }),
11151
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
10829
11152
  "input",
10830
11153
  {
10831
11154
  id: "price-max",
@@ -10849,11 +11172,11 @@ function PriceSection() {
10849
11172
  }
10850
11173
 
10851
11174
  // src/composed/search/Filters.tsx
10852
- var import_jsx_runtime66 = require("react/jsx-runtime");
11175
+ var import_jsx_runtime67 = require("react/jsx-runtime");
10853
11176
  function Filters({ buttonClassName, buttonText }) {
10854
- const [isOpen, setIsOpen] = (0, import_react49.useState)(false);
10855
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(import_jsx_runtime66.Fragment, { children: [
10856
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
11177
+ const [isOpen, setIsOpen] = (0, import_react50.useState)(false);
11178
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
11179
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
10857
11180
  FiltersButton,
10858
11181
  {
10859
11182
  onClick: () => setIsOpen(true),
@@ -10861,14 +11184,14 @@ function Filters({ buttonClassName, buttonText }) {
10861
11184
  children: buttonText
10862
11185
  }
10863
11186
  ),
10864
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
11187
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FiltersDrawer, { isOpen, onClose: () => setIsOpen(false) })
10865
11188
  ] });
10866
11189
  }
10867
11190
 
10868
11191
  // src/composed/search/CurrentRefinements.tsx
10869
11192
  var import_react_instantsearch5 = require("react-instantsearch");
10870
11193
  var import_lucide_react6 = require("lucide-react");
10871
- var import_jsx_runtime67 = require("react/jsx-runtime");
11194
+ var import_jsx_runtime68 = require("react/jsx-runtime");
10872
11195
  var XIcon3 = import_lucide_react6.X;
10873
11196
  function CurrentRefinements() {
10874
11197
  const { items, refine } = (0, import_react_instantsearch5.useCurrentRefinements)();
@@ -10914,15 +11237,15 @@ function CurrentRefinements() {
10914
11237
  if (allRefinements.length === 0) {
10915
11238
  return null;
10916
11239
  }
10917
- return /* @__PURE__ */ (0, import_jsx_runtime67.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_runtime67.jsxs)(
11240
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "flex flex-wrap items-center gap-2 mb-4 -mt-1", role: "group", "aria-label": "Active filters", children: allRefinements.map((refinement, index) => /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
10918
11241
  "button",
10919
11242
  {
10920
11243
  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",
10921
11244
  onClick: () => refinement.refine(),
10922
11245
  "aria-label": `Remove filter: ${refinement.displayLabel}`,
10923
11246
  children: [
10924
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "truncate", children: refinement.displayLabel }),
10925
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(XIcon3, { className: "w-3 h-3" })
11247
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "truncate", children: refinement.displayLabel }),
11248
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(XIcon3, { className: "w-3 h-3" })
10926
11249
  ]
10927
11250
  },
10928
11251
  `${refinement.attribute}-${refinement.value}-${index}`
@@ -10946,12 +11269,12 @@ var FACET_SECTIONS = [
10946
11269
  ];
10947
11270
 
10948
11271
  // src/composed/zoom/ResponsiveZoom.tsx
10949
- var import_react52 = require("react");
11272
+ var import_react53 = require("react");
10950
11273
 
10951
11274
  // src/composed/zoom/ZoomOverlay.tsx
10952
- var import_react50 = require("react");
11275
+ var import_react51 = require("react");
10953
11276
  var import_lucide_react7 = require("lucide-react");
10954
- var import_jsx_runtime68 = require("react/jsx-runtime");
11277
+ var import_jsx_runtime69 = require("react/jsx-runtime");
10955
11278
  var PlusIcon2 = import_lucide_react7.Plus;
10956
11279
  var MinusIcon2 = import_lucide_react7.Minus;
10957
11280
  function ZoomOverlay({
@@ -10963,13 +11286,13 @@ function ZoomOverlay({
10963
11286
  className,
10964
11287
  style
10965
11288
  }) {
10966
- const [zoomedImageIndex, setZoomedImageIndex] = (0, import_react50.useState)(null);
10967
- const [zoomOrigin, setZoomOrigin] = (0, import_react50.useState)({ x: 50, y: 50 });
10968
- const [hoveredImageIndex, setHoveredImageIndex] = (0, import_react50.useState)(null);
10969
- const [cursorPos, setCursorPos] = (0, import_react50.useState)({ x: 0, y: 0 });
10970
- const [announcement, setAnnouncement] = (0, import_react50.useState)("");
10971
- const [isZooming, setIsZooming] = (0, import_react50.useState)(false);
10972
- const handleZoomClick = (0, import_react50.useCallback)(
11289
+ const [zoomedImageIndex, setZoomedImageIndex] = (0, import_react51.useState)(null);
11290
+ const [zoomOrigin, setZoomOrigin] = (0, import_react51.useState)({ x: 50, y: 50 });
11291
+ const [hoveredImageIndex, setHoveredImageIndex] = (0, import_react51.useState)(null);
11292
+ const [cursorPos, setCursorPos] = (0, import_react51.useState)({ x: 0, y: 0 });
11293
+ const [announcement, setAnnouncement] = (0, import_react51.useState)("");
11294
+ const [isZooming, setIsZooming] = (0, import_react51.useState)(false);
11295
+ const handleZoomClick = (0, import_react51.useCallback)(
10973
11296
  (e) => {
10974
11297
  e.stopPropagation();
10975
11298
  if (isLargeTouchDevice && onEnhancedViewer) {
@@ -10994,7 +11317,7 @@ function ZoomOverlay({
10994
11317
  },
10995
11318
  [zoomedImageIndex, isLargeTouchDevice, onEnhancedViewer, imageIndex]
10996
11319
  );
10997
- const handleZoomMouseMove = (0, import_react50.useCallback)(
11320
+ const handleZoomMouseMove = (0, import_react51.useCallback)(
10998
11321
  (e) => {
10999
11322
  setCursorPos({ x: e.clientX, y: e.clientY });
11000
11323
  if (zoomedImageIndex === imageIndex) {
@@ -11010,9 +11333,9 @@ function ZoomOverlay({
11010
11333
  const isZoomed = zoomedImageIndex === imageIndex;
11011
11334
  const isHovered = hoveredImageIndex === imageIndex;
11012
11335
  const cursorStyle = isLargeTouchDevice ? "pointer" : isTouchDevice ? "default" : "none";
11013
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
11014
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11015
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11336
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
11337
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }),
11338
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11016
11339
  "div",
11017
11340
  {
11018
11341
  className,
@@ -11020,7 +11343,7 @@ function ZoomOverlay({
11020
11343
  ...style,
11021
11344
  position: "relative"
11022
11345
  },
11023
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11346
+ children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11024
11347
  "div",
11025
11348
  {
11026
11349
  style: {
@@ -11043,7 +11366,7 @@ function ZoomOverlay({
11043
11366
  handleZoomClick(e);
11044
11367
  }
11045
11368
  },
11046
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11369
+ children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11047
11370
  "div",
11048
11371
  {
11049
11372
  style: {
@@ -11059,7 +11382,7 @@ function ZoomOverlay({
11059
11382
  )
11060
11383
  }
11061
11384
  ),
11062
- isHovered && !isTouchDevice && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11385
+ isHovered && !isTouchDevice && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11063
11386
  "div",
11064
11387
  {
11065
11388
  className: "fixed pointer-events-none z-50 hidden md:block",
@@ -11069,7 +11392,7 @@ function ZoomOverlay({
11069
11392
  transform: "translate(-50%, -50%)"
11070
11393
  },
11071
11394
  "aria-hidden": "true",
11072
- children: /* @__PURE__ */ (0, import_jsx_runtime68.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_runtime68.jsx)(
11395
+ children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "bg-white dark:bg-gray-800 rounded-full p-2 shadow-sm dark:shadow-gray-950/50", children: isZoomed ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11073
11396
  MinusIcon2,
11074
11397
  {
11075
11398
  size: 20,
@@ -11077,7 +11400,7 @@ function ZoomOverlay({
11077
11400
  strokeWidth: 1.5,
11078
11401
  "aria-hidden": "true"
11079
11402
  }
11080
- ) : /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
11403
+ ) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11081
11404
  PlusIcon2,
11082
11405
  {
11083
11406
  size: 20,
@@ -11092,11 +11415,11 @@ function ZoomOverlay({
11092
11415
  }
11093
11416
 
11094
11417
  // src/composed/zoom/EnhancedImageViewer.tsx
11095
- var import_react51 = require("react");
11096
- var import_react_dom2 = require("react-dom");
11418
+ var import_react52 = require("react");
11419
+ var import_react_dom3 = require("react-dom");
11097
11420
  var import_react_zoom_pan_pinch = require("react-zoom-pan-pinch");
11098
11421
  var import_lucide_react8 = require("lucide-react");
11099
- var import_jsx_runtime69 = require("react/jsx-runtime");
11422
+ var import_jsx_runtime70 = require("react/jsx-runtime");
11100
11423
  var TransformWrapper = import_react_zoom_pan_pinch.TransformWrapper;
11101
11424
  var TransformComponent = import_react_zoom_pan_pinch.TransformComponent;
11102
11425
  var EnhancedImageViewer = ({
@@ -11107,17 +11430,17 @@ var EnhancedImageViewer = ({
11107
11430
  onIndexChange,
11108
11431
  currentIndex: propCurrentIndex
11109
11432
  }) => {
11110
- const [isMounted, setIsMounted] = (0, import_react51.useState)(false);
11111
- const [isClient, setIsClient] = (0, import_react51.useState)(false);
11112
- const [scale, setScale] = (0, import_react51.useState)({ initial: 1, min: 1, max: 8 });
11113
- const [cropDimensions, setCropDimensions] = (0, import_react51.useState)({ width: 0, height: 0 });
11114
- const [currentZoomScale, setCurrentZoomScale] = (0, import_react51.useState)(1);
11115
- const imgRef = (0, import_react51.useRef)(null);
11116
- const touchStartRef = (0, import_react51.useRef)(
11433
+ const [isMounted, setIsMounted] = (0, import_react52.useState)(false);
11434
+ const [isClient, setIsClient] = (0, import_react52.useState)(false);
11435
+ const [scale, setScale] = (0, import_react52.useState)({ initial: 1, min: 1, max: 8 });
11436
+ const [cropDimensions, setCropDimensions] = (0, import_react52.useState)({ width: 0, height: 0 });
11437
+ const [currentZoomScale, setCurrentZoomScale] = (0, import_react52.useState)(1);
11438
+ const imgRef = (0, import_react52.useRef)(null);
11439
+ const touchStartRef = (0, import_react52.useRef)(
11117
11440
  null
11118
11441
  );
11119
- const isSwipingRef = (0, import_react51.useRef)(false);
11120
- const calculateScale = (0, import_react51.useCallback)(() => {
11442
+ const isSwipingRef = (0, import_react52.useRef)(false);
11443
+ const calculateScale = (0, import_react52.useCallback)(() => {
11121
11444
  const viewport = {
11122
11445
  width: window.innerWidth,
11123
11446
  height: window.innerHeight
@@ -11129,10 +11452,10 @@ var EnhancedImageViewer = ({
11129
11452
  max: 8
11130
11453
  });
11131
11454
  }, []);
11132
- const handleImageLoad = (0, import_react51.useCallback)(() => {
11455
+ const handleImageLoad = (0, import_react52.useCallback)(() => {
11133
11456
  calculateScale();
11134
11457
  }, [calculateScale]);
11135
- (0, import_react51.useLayoutEffect)(() => {
11458
+ (0, import_react52.useLayoutEffect)(() => {
11136
11459
  setIsClient(true);
11137
11460
  setIsMounted(true);
11138
11461
  document.body.style.overflow = "hidden";
@@ -11141,17 +11464,17 @@ var EnhancedImageViewer = ({
11141
11464
  document.body.style.overflow = "";
11142
11465
  };
11143
11466
  }, [calculateScale]);
11144
- (0, import_react51.useEffect)(() => {
11467
+ (0, import_react52.useEffect)(() => {
11145
11468
  calculateScale();
11146
11469
  }, [calculateScale]);
11147
- (0, import_react51.useEffect)(() => {
11470
+ (0, import_react52.useEffect)(() => {
11148
11471
  const handleResize = () => {
11149
11472
  calculateScale();
11150
11473
  };
11151
11474
  window.addEventListener("resize", handleResize);
11152
11475
  return () => window.removeEventListener("resize", handleResize);
11153
11476
  }, [calculateScale]);
11154
- (0, import_react51.useEffect)(() => {
11477
+ (0, import_react52.useEffect)(() => {
11155
11478
  const handleKeyDown = (e) => {
11156
11479
  if (e.key === "Escape") {
11157
11480
  onClose();
@@ -11177,7 +11500,7 @@ var EnhancedImageViewer = ({
11177
11500
  document.addEventListener("keydown", handleKeyDown);
11178
11501
  return () => document.removeEventListener("keydown", handleKeyDown);
11179
11502
  }, [onClose, imageUrl, images, onIndexChange, propCurrentIndex]);
11180
- const handleSwipeNavigation = (0, import_react51.useCallback)(
11503
+ const handleSwipeNavigation = (0, import_react52.useCallback)(
11181
11504
  (direction) => {
11182
11505
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11183
11506
  if (currentIndex === -1) {
@@ -11198,7 +11521,7 @@ var EnhancedImageViewer = ({
11198
11521
  },
11199
11522
  [propCurrentIndex, images, imageUrl, onIndexChange]
11200
11523
  );
11201
- const handleTouchStart = (0, import_react51.useCallback)(
11524
+ const handleTouchStart = (0, import_react52.useCallback)(
11202
11525
  (e) => {
11203
11526
  const isAtInitialZoom = Math.abs(currentZoomScale - scale.initial) < 0.1;
11204
11527
  if (!isAtInitialZoom) return;
@@ -11212,7 +11535,7 @@ var EnhancedImageViewer = ({
11212
11535
  },
11213
11536
  [currentZoomScale, scale.initial]
11214
11537
  );
11215
- const handleTouchEnd = (0, import_react51.useCallback)(
11538
+ const handleTouchEnd = (0, import_react52.useCallback)(
11216
11539
  (e) => {
11217
11540
  if (!touchStartRef.current) return;
11218
11541
  const touch = e.changedTouches[0];
@@ -11235,13 +11558,13 @@ var EnhancedImageViewer = ({
11235
11558
  [handleSwipeNavigation]
11236
11559
  );
11237
11560
  if (!isMounted || !isClient) {
11238
- return (0, import_react_dom2.createPortal)(
11239
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11561
+ return (0, import_react_dom3.createPortal)(
11562
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11240
11563
  "div",
11241
11564
  {
11242
11565
  className: "fixed inset-0 bg-black flex items-center justify-center",
11243
11566
  style: { zIndex: 999999 },
11244
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11567
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11245
11568
  "div",
11246
11569
  {
11247
11570
  style: {
@@ -11256,8 +11579,8 @@ var EnhancedImageViewer = ({
11256
11579
  document.body
11257
11580
  );
11258
11581
  }
11259
- return (0, import_react_dom2.createPortal)(
11260
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
11582
+ return (0, import_react_dom3.createPortal)(
11583
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
11261
11584
  "div",
11262
11585
  {
11263
11586
  className: "fixed inset-0 bg-black flex items-center justify-center",
@@ -11266,7 +11589,7 @@ var EnhancedImageViewer = ({
11266
11589
  "aria-modal": "true",
11267
11590
  "aria-label": "Image viewer",
11268
11591
  children: [
11269
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11592
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11270
11593
  "button",
11271
11594
  {
11272
11595
  onClick: (e) => {
@@ -11292,10 +11615,10 @@ var EnhancedImageViewer = ({
11292
11615
  touchAction: "manipulation",
11293
11616
  marginBottom: "env(safe-area-inset-bottom, 0px)"
11294
11617
  },
11295
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react8.X, { className: "w-7 h-7", strokeWidth: 2.5 })
11618
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(import_lucide_react8.X, { className: "w-7 h-7", strokeWidth: 2.5 })
11296
11619
  }
11297
11620
  ),
11298
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11621
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11299
11622
  TransformWrapper,
11300
11623
  {
11301
11624
  initialScale: scale.initial,
@@ -11329,7 +11652,7 @@ var EnhancedImageViewer = ({
11329
11652
  onTransformed: (ref) => {
11330
11653
  setCurrentZoomScale(ref.state.scale);
11331
11654
  },
11332
- children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
11655
+ children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
11333
11656
  "div",
11334
11657
  {
11335
11658
  style: {
@@ -11342,14 +11665,14 @@ var EnhancedImageViewer = ({
11342
11665
  onTouchStart: handleTouchStart,
11343
11666
  onTouchEnd: handleTouchEnd,
11344
11667
  children: [
11345
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11668
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11346
11669
  TransformComponent,
11347
11670
  {
11348
11671
  wrapperStyle: {
11349
11672
  width: "100%",
11350
11673
  height: "100%"
11351
11674
  },
11352
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11675
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11353
11676
  "div",
11354
11677
  {
11355
11678
  style: {
@@ -11360,7 +11683,7 @@ var EnhancedImageViewer = ({
11360
11683
  alignItems: "center",
11361
11684
  justifyContent: "center"
11362
11685
  },
11363
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11686
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11364
11687
  "img",
11365
11688
  {
11366
11689
  ref: imgRef,
@@ -11381,8 +11704,8 @@ var EnhancedImageViewer = ({
11381
11704
  )
11382
11705
  }
11383
11706
  ),
11384
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fixed bottom-5 left-0 right-0 z-50", children: [
11385
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "flex justify-center gap-2", children: (() => {
11707
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fixed bottom-5 left-0 right-0 z-50", children: [
11708
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "flex justify-center gap-2", children: (() => {
11386
11709
  let currentIndex = propCurrentIndex !== void 0 ? propCurrentIndex : -1;
11387
11710
  if (currentIndex === -1) {
11388
11711
  currentIndex = images.findIndex(
@@ -11415,8 +11738,8 @@ var EnhancedImageViewer = ({
11415
11738
  };
11416
11739
  const nextIndex = findNextAvailableIndex(currentIndex, 1);
11417
11740
  const prevIndex = findNextAvailableIndex(currentIndex, -1);
11418
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
11419
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11741
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(import_jsx_runtime70.Fragment, { children: [
11742
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11420
11743
  "button",
11421
11744
  {
11422
11745
  onClick: () => {
@@ -11429,7 +11752,7 @@ var EnhancedImageViewer = ({
11429
11752
  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"}`,
11430
11753
  style: { touchAction: "manipulation" },
11431
11754
  "aria-label": "Previous image",
11432
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11755
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11433
11756
  "svg",
11434
11757
  {
11435
11758
  className: "w-4 h-4",
@@ -11437,7 +11760,7 @@ var EnhancedImageViewer = ({
11437
11760
  stroke: "currentColor",
11438
11761
  viewBox: "0 0 24 24",
11439
11762
  "aria-hidden": "true",
11440
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11763
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11441
11764
  "path",
11442
11765
  {
11443
11766
  strokeLinecap: "round",
@@ -11450,7 +11773,7 @@ var EnhancedImageViewer = ({
11450
11773
  )
11451
11774
  }
11452
11775
  ),
11453
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11776
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11454
11777
  "button",
11455
11778
  {
11456
11779
  onClick: () => {
@@ -11463,7 +11786,7 @@ var EnhancedImageViewer = ({
11463
11786
  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"}`,
11464
11787
  style: { touchAction: "manipulation" },
11465
11788
  "aria-label": "Next image",
11466
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11789
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11467
11790
  "svg",
11468
11791
  {
11469
11792
  className: "w-4 h-4",
@@ -11471,7 +11794,7 @@ var EnhancedImageViewer = ({
11471
11794
  stroke: "currentColor",
11472
11795
  viewBox: "0 0 24 24",
11473
11796
  "aria-hidden": "true",
11474
- children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11797
+ children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11475
11798
  "path",
11476
11799
  {
11477
11800
  strokeLinecap: "round",
@@ -11486,7 +11809,7 @@ var EnhancedImageViewer = ({
11486
11809
  )
11487
11810
  ] });
11488
11811
  })() }),
11489
- /* @__PURE__ */ (0, import_jsx_runtime69.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: (() => {
11812
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { style: { position: "fixed", bottom: 20, left: 24, zIndex: 10, marginBottom: "env(safe-area-inset-bottom, 0px)" }, className: "h-10 px-3 rounded-full bg-white/90 text-black text-sm font-medium flex items-center justify-center shadow-lg", children: (() => {
11490
11813
  const total = Math.max(images.length, 1);
11491
11814
  const current = propCurrentIndex !== void 0 ? Math.min(propCurrentIndex + 1, total) : 1;
11492
11815
  return `${current} / ${total}`;
@@ -11498,7 +11821,7 @@ var EnhancedImageViewer = ({
11498
11821
  },
11499
11822
  `${scale.initial}-${scale.min}-${scale.max}`
11500
11823
  ),
11501
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
11824
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11502
11825
  "div",
11503
11826
  {
11504
11827
  className: "absolute inset-0 bg-black",
@@ -11517,7 +11840,7 @@ var EnhancedImageViewer = ({
11517
11840
  };
11518
11841
 
11519
11842
  // src/composed/zoom/ResponsiveZoom.tsx
11520
- var import_jsx_runtime70 = require("react/jsx-runtime");
11843
+ var import_jsx_runtime71 = require("react/jsx-runtime");
11521
11844
  function ResponsiveZoom({
11522
11845
  imageIndex,
11523
11846
  children,
@@ -11527,11 +11850,11 @@ function ResponsiveZoom({
11527
11850
  imageUrl,
11528
11851
  alt = "Product image"
11529
11852
  }) {
11530
- const [isTouchDevice, setIsTouchDevice] = (0, import_react52.useState)(false);
11531
- const [showEnhancedViewer, setShowEnhancedViewer] = (0, import_react52.useState)(false);
11532
- const [viewerIndex, setViewerIndex] = (0, import_react52.useState)(0);
11533
- const [currentImageUrl, setCurrentImageUrl] = (0, import_react52.useState)(imageUrl || "");
11534
- (0, import_react52.useEffect)(() => {
11853
+ const [isTouchDevice, setIsTouchDevice] = (0, import_react53.useState)(false);
11854
+ const [showEnhancedViewer, setShowEnhancedViewer] = (0, import_react53.useState)(false);
11855
+ const [viewerIndex, setViewerIndex] = (0, import_react53.useState)(0);
11856
+ const [currentImageUrl, setCurrentImageUrl] = (0, import_react53.useState)(imageUrl || "");
11857
+ (0, import_react53.useEffect)(() => {
11535
11858
  const checkDeviceType = () => {
11536
11859
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
11537
11860
  setIsTouchDevice(hasTouch);
@@ -11558,8 +11881,8 @@ function ResponsiveZoom({
11558
11881
  }
11559
11882
  }
11560
11883
  };
11561
- return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(import_jsx_runtime70.Fragment, { children: [
11562
- isTouchDevice ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11884
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_jsx_runtime71.Fragment, { children: [
11885
+ isTouchDevice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11563
11886
  "div",
11564
11887
  {
11565
11888
  className,
@@ -11576,7 +11899,7 @@ function ResponsiveZoom({
11576
11899
  },
11577
11900
  children
11578
11901
  }
11579
- ) : /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11902
+ ) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11580
11903
  ZoomOverlay,
11581
11904
  {
11582
11905
  imageIndex,
@@ -11587,7 +11910,7 @@ function ResponsiveZoom({
11587
11910
  children
11588
11911
  }
11589
11912
  ),
11590
- showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
11913
+ showEnhancedViewer && isTouchDevice && currentImageUrl && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
11591
11914
  EnhancedImageViewer,
11592
11915
  {
11593
11916
  imageUrl: currentImageUrl,
@@ -11610,9 +11933,9 @@ function ResponsiveZoom({
11610
11933
  }
11611
11934
 
11612
11935
  // src/composed/carousels/MobileProductCarousel.tsx
11613
- var import_react53 = require("react");
11614
- var import_jsx_runtime71 = require("react/jsx-runtime");
11615
- var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarousel2({
11936
+ var import_react54 = require("react");
11937
+ var import_jsx_runtime72 = require("react/jsx-runtime");
11938
+ var MobileProductCarousel = (0, import_react54.memo)(function MobileProductCarousel2({
11616
11939
  images,
11617
11940
  currentIndex = 0,
11618
11941
  onIndexChange,
@@ -11627,42 +11950,42 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11627
11950
  mockupWidth,
11628
11951
  onMockupUrlGenerated
11629
11952
  }) {
11630
- const [activeIndex, setActiveIndex] = (0, import_react53.useState)(currentIndex);
11631
- const [touchStart, setTouchStart] = (0, import_react53.useState)(
11953
+ const [activeIndex, setActiveIndex] = (0, import_react54.useState)(currentIndex);
11954
+ const [touchStart, setTouchStart] = (0, import_react54.useState)(
11632
11955
  null
11633
11956
  );
11634
- const [touchEnd, setTouchEnd] = (0, import_react53.useState)(
11957
+ const [touchEnd, setTouchEnd] = (0, import_react54.useState)(
11635
11958
  null
11636
11959
  );
11637
- const [showImageViewer, setShowImageViewer] = (0, import_react53.useState)(false);
11638
- const [viewerKey, setViewerKey] = (0, import_react53.useState)(0);
11639
- const [isDragging, setIsDragging] = (0, import_react53.useState)(false);
11640
- const [dragOffset, setDragOffset] = (0, import_react53.useState)(0);
11641
- const [isTransitioning, setIsTransitioning] = (0, import_react53.useState)(false);
11642
- const [isHorizontalSwipe, setIsHorizontalSwipe] = (0, import_react53.useState)(
11960
+ const [showImageViewer, setShowImageViewer] = (0, import_react54.useState)(false);
11961
+ const [viewerKey, setViewerKey] = (0, import_react54.useState)(0);
11962
+ const [isDragging, setIsDragging] = (0, import_react54.useState)(false);
11963
+ const [dragOffset, setDragOffset] = (0, import_react54.useState)(0);
11964
+ const [isTransitioning, setIsTransitioning] = (0, import_react54.useState)(false);
11965
+ const [isHorizontalSwipe, setIsHorizontalSwipe] = (0, import_react54.useState)(
11643
11966
  null
11644
11967
  );
11645
- const [isPeeking, setIsPeeking] = (0, import_react53.useState)(false);
11646
- const [isPeekReturning, setIsPeekReturning] = (0, import_react53.useState)(false);
11647
- const carouselRef = (0, import_react53.useRef)(null);
11648
- const indicatorRef = (0, import_react53.useRef)(null);
11649
- const touchStartRef = (0, import_react53.useRef)(
11968
+ const [isPeeking, setIsPeeking] = (0, import_react54.useState)(false);
11969
+ const [isPeekReturning, setIsPeekReturning] = (0, import_react54.useState)(false);
11970
+ const carouselRef = (0, import_react54.useRef)(null);
11971
+ const indicatorRef = (0, import_react54.useRef)(null);
11972
+ const touchStartRef = (0, import_react54.useRef)(
11650
11973
  null
11651
11974
  );
11652
- const horizontalGestureRef = (0, import_react53.useRef)(false);
11653
- const hasShownPeekRef = (0, import_react53.useRef)(false);
11654
- const hasSwipedThisSessionRef = (0, import_react53.useRef)(false);
11655
- const generatedUrlsRef = (0, import_react53.useRef)(/* @__PURE__ */ new Map());
11656
- const prevArtworkSrcRef = (0, import_react53.useRef)(currentArtwork?.src);
11657
- (0, import_react53.useEffect)(() => {
11975
+ const horizontalGestureRef = (0, import_react54.useRef)(false);
11976
+ const hasShownPeekRef = (0, import_react54.useRef)(false);
11977
+ const hasSwipedThisSessionRef = (0, import_react54.useRef)(false);
11978
+ const generatedUrlsRef = (0, import_react54.useRef)(/* @__PURE__ */ new Map());
11979
+ const prevArtworkSrcRef = (0, import_react54.useRef)(currentArtwork?.src);
11980
+ (0, import_react54.useEffect)(() => {
11658
11981
  if (currentArtwork?.src !== prevArtworkSrcRef.current) {
11659
11982
  generatedUrlsRef.current.clear();
11660
11983
  prevArtworkSrcRef.current = currentArtwork?.src;
11661
11984
  }
11662
11985
  }, [currentArtwork?.src]);
11663
- const onMockupUrlGeneratedRef = (0, import_react53.useRef)(onMockupUrlGenerated);
11986
+ const onMockupUrlGeneratedRef = (0, import_react54.useRef)(onMockupUrlGenerated);
11664
11987
  onMockupUrlGeneratedRef.current = onMockupUrlGenerated;
11665
- const handleUrlGenerated = (0, import_react53.useCallback)((mockupId, url) => {
11988
+ const handleUrlGenerated = (0, import_react54.useCallback)((mockupId, url) => {
11666
11989
  generatedUrlsRef.current.set(mockupId, url);
11667
11990
  onMockupUrlGeneratedRef.current?.(mockupId, url);
11668
11991
  }, []);
@@ -11670,24 +11993,24 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11670
11993
  const shouldHideDots = stickyHeroContext?.shouldHideDots ?? false;
11671
11994
  const priorityContext = useMockupPriorityOptional();
11672
11995
  const realtimeContext = useRealtimeOptional();
11673
- const [urlUpdateCounter, setUrlUpdateCounter] = (0, import_react53.useState)(0);
11674
- (0, import_react53.useEffect)(() => {
11996
+ const [urlUpdateCounter, setUrlUpdateCounter] = (0, import_react54.useState)(0);
11997
+ (0, import_react54.useEffect)(() => {
11675
11998
  if (!realtimeContext?.subscribeMockupResults) return;
11676
11999
  const unsubscribe = realtimeContext.subscribeMockupResults(() => {
11677
12000
  setUrlUpdateCounter((c) => c + 1);
11678
12001
  });
11679
12002
  return unsubscribe;
11680
12003
  }, [realtimeContext?.subscribeMockupResults]);
11681
- const mockupIds = (0, import_react53.useMemo)(() => {
12004
+ const mockupIds = (0, import_react54.useMemo)(() => {
11682
12005
  return images.filter((img) => img.isRealMockup && img.mockupId).map((img) => img.mockupId);
11683
12006
  }, [images]);
11684
- const realtimeMockupUrls = (0, import_react53.useMemo)(() => {
12007
+ const realtimeMockupUrls = (0, import_react54.useMemo)(() => {
11685
12008
  if (!realtimeContext?.getMockupUrls || mockupIds.length === 0) {
11686
12009
  return {};
11687
12010
  }
11688
12011
  return realtimeContext.getMockupUrls(mockupIds);
11689
12012
  }, [realtimeContext?.getMockupUrls, mockupIds, urlUpdateCounter]);
11690
- const imagesWithRealtimeUrls = (0, import_react53.useMemo)(() => {
12013
+ const imagesWithRealtimeUrls = (0, import_react54.useMemo)(() => {
11691
12014
  return images.map((img) => {
11692
12015
  if (img.isRealMockup && img.mockupId && realtimeMockupUrls[img.mockupId]) {
11693
12016
  return {
@@ -11699,10 +12022,10 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11699
12022
  });
11700
12023
  }, [images, realtimeMockupUrls]);
11701
12024
  const minSwipeDistance = 50;
11702
- (0, import_react53.useEffect)(() => {
12025
+ (0, import_react54.useEffect)(() => {
11703
12026
  setActiveIndex(currentIndex);
11704
12027
  }, [currentIndex]);
11705
- (0, import_react53.useEffect)(() => {
12028
+ (0, import_react54.useEffect)(() => {
11706
12029
  if (!priorityContext) return;
11707
12030
  const realMockups = images.map((img, idx) => ({ img, originalIdx: idx })).filter(({ img }) => img.isRealMockup && img.mockupId);
11708
12031
  const mockupIdsList = realMockups.map(({ img }) => img.mockupId);
@@ -11730,7 +12053,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11730
12053
  priorityContext.clearMobileCarouselMode?.();
11731
12054
  };
11732
12055
  }, [priorityContext, activeIndex, images]);
11733
- (0, import_react53.useEffect)(() => {
12056
+ (0, import_react54.useEffect)(() => {
11734
12057
  const indicator = indicatorRef.current;
11735
12058
  if (!indicator) return;
11736
12059
  let ticking = false;
@@ -11771,7 +12094,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11771
12094
  }, []);
11772
12095
  const SWIPE_TRACKING_KEY = "carousel-swipe-tracking";
11773
12096
  const PDP_VIEWS_BEFORE_PEEK = 10;
11774
- const getSwipeTracking = (0, import_react53.useCallback)(() => {
12097
+ const getSwipeTracking = (0, import_react54.useCallback)(() => {
11775
12098
  try {
11776
12099
  const stored = localStorage.getItem(SWIPE_TRACKING_KEY);
11777
12100
  if (stored) {
@@ -11781,7 +12104,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11781
12104
  }
11782
12105
  return { viewsWithoutSwipe: 0, hasEverSwiped: false };
11783
12106
  }, []);
11784
- const recordSwipe = (0, import_react53.useCallback)(() => {
12107
+ const recordSwipe = (0, import_react54.useCallback)(() => {
11785
12108
  if (hasSwipedThisSessionRef.current) return;
11786
12109
  hasSwipedThisSessionRef.current = true;
11787
12110
  try {
@@ -11795,7 +12118,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11795
12118
  } catch {
11796
12119
  }
11797
12120
  }, []);
11798
- (0, import_react53.useEffect)(() => {
12121
+ (0, import_react54.useEffect)(() => {
11799
12122
  if (!enablePeekAnimation || images.length <= 1) return;
11800
12123
  const tracking = getSwipeTracking();
11801
12124
  const newViewCount = tracking.viewsWithoutSwipe + 1;
@@ -11836,14 +12159,14 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11836
12159
  clearTimeout(clearTimeout_);
11837
12160
  };
11838
12161
  }, [images.length, getSwipeTracking, enablePeekAnimation]);
11839
- const wasTapRef = (0, import_react53.useRef)(false);
11840
- const handleImageTap = (0, import_react53.useCallback)(() => {
12162
+ const wasTapRef = (0, import_react54.useRef)(false);
12163
+ const handleImageTap = (0, import_react54.useCallback)(() => {
11841
12164
  if (!enableZoom) return;
11842
12165
  setViewerKey((prev) => prev + 1);
11843
12166
  setShowImageViewer(true);
11844
12167
  onZoomChange?.(true);
11845
12168
  }, [enableZoom, onZoomChange]);
11846
- const calculateDragOffset = (0, import_react53.useCallback)(
12169
+ const calculateDragOffset = (0, import_react54.useCallback)(
11847
12170
  (startX, currentX, containerWidth) => {
11848
12171
  const distance = startX - currentX;
11849
12172
  const offsetPercent = distance / containerWidth * 100;
@@ -11868,7 +12191,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11868
12191
  },
11869
12192
  [activeIndex, images.length]
11870
12193
  );
11871
- const handleSwipeEnd = (0, import_react53.useCallback)(
12194
+ const handleSwipeEnd = (0, import_react54.useCallback)(
11872
12195
  (startX, endX, containerWidth) => {
11873
12196
  const distance = startX - endX;
11874
12197
  const distancePercent = Math.abs(distance) / containerWidth * 100;
@@ -11899,7 +12222,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11899
12222
  },
11900
12223
  [activeIndex, images.length, onIndexChange, recordSwipe]
11901
12224
  );
11902
- (0, import_react53.useEffect)(() => {
12225
+ (0, import_react54.useEffect)(() => {
11903
12226
  const container = carouselRef.current;
11904
12227
  if (!container) return;
11905
12228
  const handleTouchStart = (e) => {
@@ -11988,11 +12311,11 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
11988
12311
  handleSwipeEnd,
11989
12312
  handleImageTap
11990
12313
  ]);
11991
- const mouseStartRef = (0, import_react53.useRef)(
12314
+ const mouseStartRef = (0, import_react54.useRef)(
11992
12315
  null
11993
12316
  );
11994
- const isMouseDraggingRef = (0, import_react53.useRef)(false);
11995
- (0, import_react53.useEffect)(() => {
12317
+ const isMouseDraggingRef = (0, import_react54.useRef)(false);
12318
+ (0, import_react54.useEffect)(() => {
11996
12319
  const container = carouselRef.current;
11997
12320
  if (!container) return;
11998
12321
  const handleMouseDown = (e) => {
@@ -12068,7 +12391,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12068
12391
  container.removeEventListener("mouseleave", handleMouseLeave);
12069
12392
  };
12070
12393
  }, [calculateDragOffset, handleSwipeEnd, handleImageTap]);
12071
- const goToSlide = (0, import_react53.useCallback)(
12394
+ const goToSlide = (0, import_react54.useCallback)(
12072
12395
  (index, withTransition = true) => {
12073
12396
  if (withTransition) {
12074
12397
  setIsTransitioning(true);
@@ -12086,16 +12409,16 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12086
12409
  },
12087
12410
  [onIndexChange]
12088
12411
  );
12089
- (0, import_react53.useEffect)(() => {
12412
+ (0, import_react54.useEffect)(() => {
12090
12413
  if (stickyHeroContext?.setCarouselIndicator && images.length > 1) {
12091
- const indicator = /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12414
+ const indicator = /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12092
12415
  "div",
12093
12416
  {
12094
12417
  className: "w-full",
12095
12418
  role: "group",
12096
12419
  "aria-label": "Product image navigation",
12097
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "relative h-1", children: [
12098
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "flex h-full", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12420
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "relative h-1", children: [
12421
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "flex h-full", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12099
12422
  "button",
12100
12423
  {
12101
12424
  onClick: () => goToSlide(index),
@@ -12105,7 +12428,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12105
12428
  },
12106
12429
  index
12107
12430
  )) }),
12108
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12431
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12109
12432
  "div",
12110
12433
  {
12111
12434
  className: "absolute top-0 h-full bg-primary transition-all duration-300 ease-out",
@@ -12128,10 +12451,10 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12128
12451
  };
12129
12452
  }, [activeIndex, images.length, goToSlide, stickyHeroContext]);
12130
12453
  if (!images || images.length === 0) {
12131
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12454
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full aspect-video bg-muted rounded-lg" });
12132
12455
  }
12133
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: `relative w-full h-full ${className}`, children: [
12134
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12456
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: `relative w-full h-full ${className}`, children: [
12457
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12135
12458
  "div",
12136
12459
  {
12137
12460
  ref: carouselRef,
@@ -12149,7 +12472,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12149
12472
  role: "region",
12150
12473
  "aria-roledescription": "carousel",
12151
12474
  "aria-label": "Product images",
12152
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12475
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12153
12476
  "div",
12154
12477
  {
12155
12478
  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)]" : ""}`,
@@ -12159,11 +12482,11 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12159
12482
  children: images.map((image, index) => {
12160
12483
  const DECODE_WINDOW = 1;
12161
12484
  const isWithinDecodeWindow = Math.abs(index - activeIndex) <= DECODE_WINDOW;
12162
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12485
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12163
12486
  "div",
12164
12487
  {
12165
12488
  className: "w-full h-full flex-shrink-0 relative select-none",
12166
- children: !isWithinDecodeWindow ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "w-full h-full bg-muted-foreground/20 animate-pulse" }) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12489
+ children: !isWithinDecodeWindow ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full h-full bg-muted" }) : image.isPlaceholder ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full h-full bg-muted-foreground/20 animate-pulse" }) : image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12167
12490
  HeroProductImage,
12168
12491
  {
12169
12492
  productId,
@@ -12175,7 +12498,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12175
12498
  onUrlGenerated: image.mockupId ? (url) => handleUrlGenerated(image.mockupId, url) : void 0,
12176
12499
  className: "w-full h-full object-cover cursor-pointer pointer-events-none"
12177
12500
  }
12178
- ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "w-full h-full bg-muted animate-pulse" }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12501
+ ) : image.isRealMockup && !currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full h-full bg-muted animate-pulse" }) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12179
12502
  "img",
12180
12503
  {
12181
12504
  src: image.src,
@@ -12195,7 +12518,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12195
12518
  )
12196
12519
  }
12197
12520
  ),
12198
- showIndicators && images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12521
+ showIndicators && images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12199
12522
  "div",
12200
12523
  {
12201
12524
  ref: indicatorRef,
@@ -12203,8 +12526,8 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12203
12526
  className: "relative z-20 w-full",
12204
12527
  role: "group",
12205
12528
  "aria-label": "Product image navigation",
12206
- children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "relative h-1", children: [
12207
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "flex h-full absolute inset-0", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12529
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "relative h-1", children: [
12530
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "flex h-full absolute inset-0", children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12208
12531
  "button",
12209
12532
  {
12210
12533
  onClick: () => goToSlide(index),
@@ -12214,7 +12537,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12214
12537
  },
12215
12538
  index
12216
12539
  )) }),
12217
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12540
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12218
12541
  "div",
12219
12542
  {
12220
12543
  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"}`,
@@ -12249,7 +12572,7 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12249
12572
  naturalHeight: img.naturalHeight
12250
12573
  } : null;
12251
12574
  }).filter((img) => img !== null);
12252
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
12575
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12253
12576
  EnhancedImageViewer,
12254
12577
  {
12255
12578
  imageUrl,
@@ -12288,8 +12611,8 @@ var MobileProductCarousel = (0, import_react53.memo)(function MobileProductCarou
12288
12611
  });
12289
12612
 
12290
12613
  // src/composed/carousels/HeroCarousel.tsx
12291
- var import_react54 = require("react");
12292
- var import_jsx_runtime72 = require("react/jsx-runtime");
12614
+ var import_react55 = require("react");
12615
+ var import_jsx_runtime73 = require("react/jsx-runtime");
12293
12616
  function HeroCarousel({
12294
12617
  images,
12295
12618
  currentIndex = 0,
@@ -12299,16 +12622,16 @@ function HeroCarousel({
12299
12622
  productId,
12300
12623
  onImageTap
12301
12624
  }) {
12302
- const [activeIndex, setActiveIndex] = (0, import_react54.useState)(currentIndex);
12303
- const containerRef = (0, import_react54.useRef)(null);
12304
- const touchStartRef = (0, import_react54.useRef)(
12625
+ const [activeIndex, setActiveIndex] = (0, import_react55.useState)(currentIndex);
12626
+ const containerRef = (0, import_react55.useRef)(null);
12627
+ const touchStartRef = (0, import_react55.useRef)(
12305
12628
  null
12306
12629
  );
12307
- const isSwipingRef = (0, import_react54.useRef)(false);
12308
- (0, import_react54.useEffect)(() => {
12630
+ const isSwipingRef = (0, import_react55.useRef)(false);
12631
+ (0, import_react55.useEffect)(() => {
12309
12632
  setActiveIndex(currentIndex);
12310
12633
  }, [currentIndex]);
12311
- const goToSlide = (0, import_react54.useCallback)(
12634
+ const goToSlide = (0, import_react55.useCallback)(
12312
12635
  (index) => {
12313
12636
  const clampedIndex = Math.max(0, Math.min(images.length - 1, index));
12314
12637
  setActiveIndex(clampedIndex);
@@ -12316,7 +12639,7 @@ function HeroCarousel({
12316
12639
  },
12317
12640
  [images.length, onIndexChange]
12318
12641
  );
12319
- (0, import_react54.useEffect)(() => {
12642
+ (0, import_react55.useEffect)(() => {
12320
12643
  const container = containerRef.current;
12321
12644
  if (!container) return;
12322
12645
  const handleTouchStart = (e) => {
@@ -12368,9 +12691,9 @@ function HeroCarousel({
12368
12691
  };
12369
12692
  }, [activeIndex, images.length, goToSlide, onImageTap]);
12370
12693
  if (!images || images.length === 0) {
12371
- return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full h-full bg-muted" });
12694
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "w-full h-full bg-muted" });
12372
12695
  }
12373
- return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
12696
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
12374
12697
  "div",
12375
12698
  {
12376
12699
  ref: containerRef,
@@ -12381,7 +12704,7 @@ function HeroCarousel({
12381
12704
  overflow: "hidden"
12382
12705
  },
12383
12706
  children: [
12384
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12707
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12385
12708
  "div",
12386
12709
  {
12387
12710
  className: "flex h-full transition-transform duration-300 ease-out",
@@ -12392,14 +12715,14 @@ function HeroCarousel({
12392
12715
  backfaceVisibility: "hidden",
12393
12716
  WebkitBackfaceVisibility: "hidden"
12394
12717
  },
12395
- children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12718
+ children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12396
12719
  "div",
12397
12720
  {
12398
12721
  className: "w-full h-full flex-shrink-0",
12399
12722
  style: {
12400
12723
  contain: "layout paint"
12401
12724
  },
12402
- children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12725
+ children: image.isRealMockup && currentArtwork ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12403
12726
  HeroProductImage,
12404
12727
  {
12405
12728
  productId,
@@ -12408,7 +12731,7 @@ function HeroCarousel({
12408
12731
  mockupId: image.mockupId,
12409
12732
  className: "w-full h-full object-cover"
12410
12733
  }
12411
- ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12734
+ ) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12412
12735
  "img",
12413
12736
  {
12414
12737
  src: image.src,
@@ -12425,12 +12748,12 @@ function HeroCarousel({
12425
12748
  ))
12426
12749
  }
12427
12750
  ),
12428
- images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12751
+ images.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12429
12752
  "div",
12430
12753
  {
12431
12754
  className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 z-10",
12432
12755
  style: { contain: "layout style" },
12433
- children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
12756
+ children: images.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12434
12757
  "button",
12435
12758
  {
12436
12759
  onClick: () => goToSlide(index),
@@ -12447,8 +12770,8 @@ function HeroCarousel({
12447
12770
  }
12448
12771
 
12449
12772
  // src/composed/grids/MasonryGrid.tsx
12450
- var import_react55 = require("react");
12451
- var import_jsx_runtime73 = require("react/jsx-runtime");
12773
+ var import_react56 = require("react");
12774
+ var import_jsx_runtime74 = require("react/jsx-runtime");
12452
12775
  var BREAKPOINTS = {
12453
12776
  sm: 640,
12454
12777
  md: 768,
@@ -12500,13 +12823,13 @@ function MasonryGrid({
12500
12823
  className = "",
12501
12824
  emptyContent
12502
12825
  }) {
12503
- const [columnCount, setColumnCount] = (0, import_react55.useState)(
12826
+ const [columnCount, setColumnCount] = (0, import_react56.useState)(
12504
12827
  () => typeof columns === "number" ? columns : getColumnCount(
12505
12828
  typeof window !== "undefined" ? window.innerWidth : 1024,
12506
12829
  columns
12507
12830
  )
12508
12831
  );
12509
- (0, import_react55.useEffect)(() => {
12832
+ (0, import_react56.useEffect)(() => {
12510
12833
  const updateColumnCount = () => {
12511
12834
  setColumnCount(getColumnCount(window.innerWidth, columns));
12512
12835
  };
@@ -12514,30 +12837,30 @@ function MasonryGrid({
12514
12837
  window.addEventListener("resize", updateColumnCount);
12515
12838
  return () => window.removeEventListener("resize", updateColumnCount);
12516
12839
  }, [columns]);
12517
- const distributedColumns = (0, import_react55.useMemo)(
12840
+ const distributedColumns = (0, import_react56.useMemo)(
12518
12841
  () => distributeItems(items, columnCount),
12519
12842
  [items, columnCount]
12520
12843
  );
12521
12844
  if (items.length === 0) {
12522
12845
  if (emptyContent) {
12523
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_jsx_runtime73.Fragment, { children: emptyContent });
12846
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(import_jsx_runtime74.Fragment, { children: emptyContent });
12524
12847
  }
12525
12848
  return null;
12526
12849
  }
12527
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12850
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12528
12851
  "div",
12529
12852
  {
12530
12853
  className: `flex ${className}`,
12531
12854
  style: { gap: `${gap}px` },
12532
12855
  role: "list",
12533
- children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
12856
+ children: distributedColumns.map((columnItems, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
12534
12857
  "div",
12535
12858
  {
12536
12859
  className: "flex-1 flex flex-col",
12537
12860
  style: { gap: `${gap}px` },
12538
12861
  children: columnItems.map((item, itemIndex) => {
12539
12862
  const originalIndex = itemIndex * columnCount + columnIndex;
12540
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12863
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { role: "listitem", children: renderItem(item, originalIndex) }, originalIndex);
12541
12864
  })
12542
12865
  },
12543
12866
  columnIndex
@@ -12550,7 +12873,7 @@ function MasonryGrid({
12550
12873
  init_dev_warnings();
12551
12874
 
12552
12875
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12553
- var import_react57 = require("react");
12876
+ var import_react58 = require("react");
12554
12877
 
12555
12878
  // src/layouts/hero-zoom/types.ts
12556
12879
  var DEFAULT_HERO_ZOOM_CONFIG = {
@@ -12562,19 +12885,19 @@ var DEFAULT_HERO_ZOOM_CONFIG = {
12562
12885
  };
12563
12886
 
12564
12887
  // src/layouts/hero-zoom/useHeroZoomScales.ts
12565
- var import_react56 = require("react");
12888
+ var import_react57 = require("react");
12566
12889
  function useHeroZoomScales(config = {}) {
12567
12890
  const { initialScale, accountForRetina, maxRetinaMultiplier } = {
12568
12891
  ...DEFAULT_HERO_ZOOM_CONFIG,
12569
12892
  ...config
12570
12893
  };
12571
- const [isHydrated, setIsHydrated] = (0, import_react56.useState)(false);
12894
+ const [isHydrated, setIsHydrated] = (0, import_react57.useState)(false);
12572
12895
  const ssrMultiplier = accountForRetina ? maxRetinaMultiplier : 2;
12573
- const [scales, setScales] = (0, import_react56.useState)(() => ({
12896
+ const [scales, setScales] = (0, import_react57.useState)(() => ({
12574
12897
  visual: initialScale,
12575
12898
  render: initialScale * ssrMultiplier
12576
12899
  }));
12577
- const calculateScales = (0, import_react56.useCallback)(() => {
12900
+ const calculateScales = (0, import_react57.useCallback)(() => {
12578
12901
  const visualScale = Math.max(1, Math.min(4, initialScale));
12579
12902
  let renderScale;
12580
12903
  if (accountForRetina) {
@@ -12589,7 +12912,7 @@ function useHeroZoomScales(config = {}) {
12589
12912
  renderScale = Math.max(1, Math.min(8, renderScale));
12590
12913
  return { visual: visualScale, render: renderScale };
12591
12914
  }, [initialScale, accountForRetina, maxRetinaMultiplier]);
12592
- (0, import_react56.useEffect)(() => {
12915
+ (0, import_react57.useEffect)(() => {
12593
12916
  const supportsScrollTimeline = CSS.supports(
12594
12917
  "animation-timeline",
12595
12918
  "scroll()"
@@ -12639,7 +12962,7 @@ function useHeroZoomScales(config = {}) {
12639
12962
  }
12640
12963
 
12641
12964
  // src/layouts/hero-zoom/HeroZoomLayout.tsx
12642
- var import_jsx_runtime74 = require("react/jsx-runtime");
12965
+ var import_jsx_runtime75 = require("react/jsx-runtime");
12643
12966
  function HeroZoomLayout({
12644
12967
  config = {},
12645
12968
  header,
@@ -12654,9 +12977,9 @@ function HeroZoomLayout({
12654
12977
  };
12655
12978
  const { aspectRatio, initialScale, headerHeight } = mergedConfig;
12656
12979
  const { visual, render, isHydrated } = useHeroZoomScales(mergedConfig);
12657
- const imageContainerRef = (0, import_react57.useRef)(null);
12658
- const headerRef = (0, import_react57.useRef)(null);
12659
- (0, import_react57.useEffect)(() => {
12980
+ const imageContainerRef = (0, import_react58.useRef)(null);
12981
+ const headerRef = (0, import_react58.useRef)(null);
12982
+ (0, import_react58.useEffect)(() => {
12660
12983
  if (typeof window === "undefined") return;
12661
12984
  const originalRestoration = "scrollRestoration" in history ? history.scrollRestoration : "auto";
12662
12985
  if ("scrollRestoration" in history) {
@@ -12669,7 +12992,7 @@ function HeroZoomLayout({
12669
12992
  }
12670
12993
  };
12671
12994
  }, []);
12672
- (0, import_react57.useEffect)(() => {
12995
+ (0, import_react58.useEffect)(() => {
12673
12996
  const supportsScrollTimeline = CSS.supports(
12674
12997
  "animation-timeline",
12675
12998
  "scroll()"
@@ -12798,7 +13121,7 @@ function HeroZoomLayout({
12798
13121
  The drawer covers the hero completely, so let animation run continuously. */
12799
13122
  }
12800
13123
  `;
12801
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
13124
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(
12802
13125
  "div",
12803
13126
  {
12804
13127
  className: `relative min-h-screen ${className}`,
@@ -12812,8 +13135,8 @@ function HeroZoomLayout({
12812
13135
  "--hero-zoom-final-transform": 1 / activeRender
12813
13136
  },
12814
13137
  children: [
12815
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
12816
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
13138
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13139
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12817
13140
  "div",
12818
13141
  {
12819
13142
  style: {
@@ -12821,7 +13144,7 @@ function HeroZoomLayout({
12821
13144
  }
12822
13145
  }
12823
13146
  ),
12824
- header && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
13147
+ header && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12825
13148
  "div",
12826
13149
  {
12827
13150
  ref: headerRef,
@@ -12834,7 +13157,7 @@ function HeroZoomLayout({
12834
13157
  children: header
12835
13158
  }
12836
13159
  ),
12837
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
13160
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
12838
13161
  "div",
12839
13162
  {
12840
13163
  ref: imageContainerRef,
@@ -12854,15 +13177,15 @@ function HeroZoomLayout({
12854
13177
  children: hero
12855
13178
  }
12856
13179
  ),
12857
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "relative z-10", children })
13180
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "relative z-10", children })
12858
13181
  ]
12859
13182
  }
12860
13183
  );
12861
13184
  }
12862
13185
 
12863
13186
  // src/layouts/hero-zoom/HeroShrinkLayout.tsx
12864
- var import_react58 = require("react");
12865
- var import_jsx_runtime75 = require("react/jsx-runtime");
13187
+ var import_react59 = require("react");
13188
+ var import_jsx_runtime76 = require("react/jsx-runtime");
12866
13189
  var DEFAULT_CONFIG = {
12867
13190
  aspectRatio: 16 / 9,
12868
13191
  initialHeightPercent: 70,
@@ -12882,13 +13205,13 @@ function HeroShrinkLayout({
12882
13205
  ...config
12883
13206
  };
12884
13207
  const { aspectRatio, initialHeightPercent, minHeightPercent, headerHeight } = mergedConfig;
12885
- const heroRef = (0, import_react58.useRef)(null);
12886
- const headerRef = (0, import_react58.useRef)(null);
12887
- const [isClient, setIsClient] = (0, import_react58.useState)(false);
12888
- (0, import_react58.useEffect)(() => {
13208
+ const heroRef = (0, import_react59.useRef)(null);
13209
+ const headerRef = (0, import_react59.useRef)(null);
13210
+ const [isClient, setIsClient] = (0, import_react59.useState)(false);
13211
+ (0, import_react59.useEffect)(() => {
12889
13212
  setIsClient(true);
12890
13213
  }, []);
12891
- (0, import_react58.useEffect)(() => {
13214
+ (0, import_react59.useEffect)(() => {
12892
13215
  if (!isClient) return;
12893
13216
  const supportsScrollTimeline = CSS.supports("animation-timeline", "scroll()");
12894
13217
  if (supportsScrollTimeline) return;
@@ -12975,15 +13298,15 @@ function HeroShrinkLayout({
12975
13298
  }
12976
13299
  `;
12977
13300
  const spacerHeight = `calc(${initialHeightPercent}svh + ${headerHeight}px)`;
12978
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(
13301
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
12979
13302
  "div",
12980
13303
  {
12981
13304
  className: `relative min-h-screen ${className}`,
12982
13305
  style: { ...style, ...cssVars },
12983
13306
  children: [
12984
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
12985
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { style: { height: spacerHeight } }),
12986
- header && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
13307
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("style", { dangerouslySetInnerHTML: { __html: scopedStyles } }),
13308
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { style: { height: spacerHeight } }),
13309
+ header && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
12987
13310
  "div",
12988
13311
  {
12989
13312
  ref: headerRef,
@@ -12992,7 +13315,7 @@ function HeroShrinkLayout({
12992
13315
  children: header
12993
13316
  }
12994
13317
  ),
12995
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
13318
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
12996
13319
  "div",
12997
13320
  {
12998
13321
  ref: heroRef,
@@ -13000,15 +13323,15 @@ function HeroShrinkLayout({
13000
13323
  children: hero
13001
13324
  }
13002
13325
  ),
13003
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "relative z-10 bg-background", children })
13326
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "relative z-10 bg-background", children })
13004
13327
  ]
13005
13328
  }
13006
13329
  );
13007
13330
  }
13008
13331
 
13009
13332
  // src/layouts/pdp/ImageEdgeBlur.tsx
13010
- var import_react59 = __toESM(require("react"), 1);
13011
- var import_jsx_runtime76 = require("react/jsx-runtime");
13333
+ var import_react60 = __toESM(require("react"), 1);
13334
+ var import_jsx_runtime77 = require("react/jsx-runtime");
13012
13335
  var BLUR_CONFIG = {
13013
13336
  blur: 24,
13014
13337
  crossfade: 68
@@ -13032,7 +13355,7 @@ var BLUR_LAYERS = [
13032
13355
  { blur: Math.round(BLUR_CONFIG.blur * 0.5), zone: 0.6 },
13033
13356
  { blur: BLUR_CONFIG.blur, zone: 1 }
13034
13357
  ];
13035
- var ImageEdgeBlur = import_react59.default.memo(
13358
+ var ImageEdgeBlur = import_react60.default.memo(
13036
13359
  function ImageEdgeBlur2({
13037
13360
  imageSrc,
13038
13361
  imageCapInfo,
@@ -13063,7 +13386,7 @@ var ImageEdgeBlur = import_react59.default.memo(
13063
13386
  viewportWidth / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO,
13064
13387
  maxWidthPx / LAYOUT_CONFIG2.IMAGE.ASPECT_RATIO
13065
13388
  );
13066
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13389
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13067
13390
  "div",
13068
13391
  {
13069
13392
  className: `absolute inset-0 pointer-events-none overflow-hidden ${className}`,
@@ -13071,7 +13394,7 @@ var ImageEdgeBlur = import_react59.default.memo(
13071
13394
  children: BLUR_LAYERS.map((layer, index) => {
13072
13395
  const layerMask = index === BLUR_LAYERS.length - 1 ? void 0 : `linear-gradient(to right, black 0%, black ${layer.zone * 100}%, transparent ${layer.zone * 100 + 10}%)`;
13073
13396
  const blurScale = 1 + layer.blur * 3 / containerHeightPx;
13074
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
13397
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13075
13398
  "img",
13076
13399
  {
13077
13400
  src: imageSrc,
@@ -13118,7 +13441,7 @@ var ImageEdgeBlur = import_react59.default.memo(
13118
13441
  );
13119
13442
 
13120
13443
  // src/layouts/pdp/PDPLayout.tsx
13121
- var import_jsx_runtime77 = require("react/jsx-runtime");
13444
+ var import_jsx_runtime78 = require("react/jsx-runtime");
13122
13445
  function PDPLayout({
13123
13446
  renderHeroImage,
13124
13447
  renderContent,
@@ -13146,15 +13469,15 @@ function PDPLayout({
13146
13469
  isDesktop,
13147
13470
  isWideMonitor: isWideMonitor2
13148
13471
  };
13149
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: `pdp-layout ${className}`, children: [
13150
- (isDesktop === false || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "md:hidden", children: [
13151
- renderMobileCarousel && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13152
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "mobile-content p-4", children: renderContent(contentProps) })
13472
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: `pdp-layout ${className}`, children: [
13473
+ (isDesktop === false || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "md:hidden", children: [
13474
+ renderMobileCarousel && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "mobile-carousel-container", children: renderMobileCarousel({ images: carouselImages }) }),
13475
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "mobile-content p-4", children: renderContent(contentProps) })
13153
13476
  ] }),
13154
- (isDesktop === true || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "hidden md:block relative", children: [
13155
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "desktop-hero relative", children: [
13477
+ (isDesktop === true || isDesktop === null) && /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "hidden md:block relative", children: [
13478
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "desktop-hero relative", children: [
13156
13479
  renderHeroImage(heroProps),
13157
- showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13480
+ showEdgeBlur && blurImageSrc && isWideMonitor2 && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13158
13481
  ImageEdgeBlur,
13159
13482
  {
13160
13483
  imageSrc: blurImageSrc,
@@ -13165,7 +13488,7 @@ function PDPLayout({
13165
13488
  }
13166
13489
  )
13167
13490
  ] }),
13168
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
13491
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13169
13492
  "div",
13170
13493
  {
13171
13494
  className: "desktop-sidebar",
@@ -13182,8 +13505,8 @@ function PDPLayout({
13182
13505
  }
13183
13506
 
13184
13507
  // src/layouts/pdp/SimpleImageBlur.tsx
13185
- var import_react60 = __toESM(require("react"), 1);
13186
- var import_jsx_runtime78 = require("react/jsx-runtime");
13508
+ var import_react61 = __toESM(require("react"), 1);
13509
+ var import_jsx_runtime79 = require("react/jsx-runtime");
13187
13510
  var BLUR_CONFIG2 = {
13188
13511
  blur: 24,
13189
13512
  crossfade: 60
@@ -13206,7 +13529,7 @@ function getFadeInMask(crossfadeWidth) {
13206
13529
  black ${crossfadeWidth + 10}px
13207
13530
  )`;
13208
13531
  }
13209
- var SimpleImageBlur = import_react60.default.memo(function SimpleImageBlur2({
13532
+ var SimpleImageBlur = import_react61.default.memo(function SimpleImageBlur2({
13210
13533
  imageSrc,
13211
13534
  width,
13212
13535
  height = "100%",
@@ -13216,7 +13539,7 @@ var SimpleImageBlur = import_react60.default.memo(function SimpleImageBlur2({
13216
13539
  if (!imageSrc || width <= 0) return null;
13217
13540
  const fadeInMask = getFadeInMask(BLUR_CONFIG2.crossfade);
13218
13541
  const extendedWidth = width + BLUR_CONFIG2.blur * 2;
13219
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13542
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13220
13543
  "div",
13221
13544
  {
13222
13545
  className: `relative overflow-hidden ${className}`,
@@ -13229,7 +13552,7 @@ var SimpleImageBlur = import_react60.default.memo(function SimpleImageBlur2({
13229
13552
  black 0%,
13230
13553
  black ${layer.zone * 100}%,
13231
13554
  transparent ${layer.zone * 100 + 10}%)`;
13232
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
13555
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13233
13556
  "img",
13234
13557
  {
13235
13558
  src: imageSrc,
@@ -13259,8 +13582,8 @@ var SimpleImageBlur = import_react60.default.memo(function SimpleImageBlur2({
13259
13582
  });
13260
13583
 
13261
13584
  // src/layouts/pdp/EdgeBlurBox.tsx
13262
- var import_react61 = __toESM(require("react"), 1);
13263
- var import_jsx_runtime79 = require("react/jsx-runtime");
13585
+ var import_react62 = __toESM(require("react"), 1);
13586
+ var import_jsx_runtime80 = require("react/jsx-runtime");
13264
13587
  var BLUR_CONFIG3 = {
13265
13588
  blur: 24,
13266
13589
  crossfade: 60
@@ -13284,7 +13607,7 @@ function getFadeOutMask(crossfadeWidth) {
13284
13607
  transparent 100%
13285
13608
  )`;
13286
13609
  }
13287
- var EdgeBlurBox = import_react61.default.memo(function EdgeBlurBox2({
13610
+ var EdgeBlurBox = import_react62.default.memo(function EdgeBlurBox2({
13288
13611
  imageSrc,
13289
13612
  width,
13290
13613
  height = "100%",
@@ -13299,7 +13622,7 @@ var EdgeBlurBox = import_react61.default.memo(function EdgeBlurBox2({
13299
13622
  const blurExtend = BLUR_CONFIG3.blur * 2;
13300
13623
  const actualSharpWidth = sharpImageWidth ?? width + overlapLeft;
13301
13624
  const hasOverlap = overlapLeft > 0;
13302
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
13625
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
13303
13626
  "div",
13304
13627
  {
13305
13628
  className: `relative ${className}`,
@@ -13310,7 +13633,7 @@ var EdgeBlurBox = import_react61.default.memo(function EdgeBlurBox2({
13310
13633
  overflow: hasOverlap ? "visible" : "hidden"
13311
13634
  },
13312
13635
  children: [
13313
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13636
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13314
13637
  "div",
13315
13638
  {
13316
13639
  style: {
@@ -13324,7 +13647,7 @@ var EdgeBlurBox = import_react61.default.memo(function EdgeBlurBox2({
13324
13647
  transparent ${100 - (layer.zone * 100 + 10)}%,
13325
13648
  black ${100 - layer.zone * 100}%,
13326
13649
  black 100%)`;
13327
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13650
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13328
13651
  "img",
13329
13652
  {
13330
13653
  src: imageSrc,
@@ -13352,7 +13675,7 @@ var EdgeBlurBox = import_react61.default.memo(function EdgeBlurBox2({
13352
13675
  })
13353
13676
  }
13354
13677
  ),
13355
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
13678
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13356
13679
  "img",
13357
13680
  {
13358
13681
  src: imageSrc,
@@ -13380,8 +13703,8 @@ var EdgeBlurBox = import_react61.default.memo(function EdgeBlurBox2({
13380
13703
  });
13381
13704
 
13382
13705
  // src/layouts/pdp/ImageBlurExtension.tsx
13383
- var import_react62 = __toESM(require("react"), 1);
13384
- var import_jsx_runtime80 = require("react/jsx-runtime");
13706
+ var import_react63 = __toESM(require("react"), 1);
13707
+ var import_jsx_runtime81 = require("react/jsx-runtime");
13385
13708
  var BLUR_CONFIG4 = {
13386
13709
  blur: 24,
13387
13710
  crossfadeWidth: 80
@@ -13404,7 +13727,7 @@ function getFadeOutMask2(crossfadeWidth) {
13404
13727
  transparent 100%
13405
13728
  )`;
13406
13729
  }
13407
- var ImageBlurExtension = import_react62.default.memo(function ImageBlurExtension2({
13730
+ var ImageBlurExtension = import_react63.default.memo(function ImageBlurExtension2({
13408
13731
  imageSrc,
13409
13732
  width,
13410
13733
  height,
@@ -13418,7 +13741,7 @@ var ImageBlurExtension = import_react62.default.memo(function ImageBlurExtension
13418
13741
  const internalImageLeft = `calc(${heroImageLeft} - 100vw + ${width}px)`;
13419
13742
  const fadeOutMask = getFadeOutMask2(crossfadeWidth);
13420
13743
  const heightValue = typeof height === "number" ? `${height}px` : height;
13421
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
13744
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
13422
13745
  "div",
13423
13746
  {
13424
13747
  className: `relative overflow-hidden ${className}`,
@@ -13427,7 +13750,7 @@ var ImageBlurExtension = import_react62.default.memo(function ImageBlurExtension
13427
13750
  height: heightValue
13428
13751
  },
13429
13752
  children: [
13430
- BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13753
+ BLUR_LAYERS4.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13431
13754
  "img",
13432
13755
  {
13433
13756
  src: imageSrc,
@@ -13451,7 +13774,7 @@ var ImageBlurExtension = import_react62.default.memo(function ImageBlurExtension
13451
13774
  },
13452
13775
  `blur-${index}`
13453
13776
  )),
13454
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
13777
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13455
13778
  "img",
13456
13779
  {
13457
13780
  src: imageSrc,
@@ -13479,39 +13802,39 @@ var ImageBlurExtension = import_react62.default.memo(function ImageBlurExtension
13479
13802
  });
13480
13803
 
13481
13804
  // src/design-system/ColorSwatch.tsx
13482
- var import_jsx_runtime81 = require("react/jsx-runtime");
13805
+ var import_jsx_runtime82 = require("react/jsx-runtime");
13483
13806
  function ColorTokenSwatch({ name, cssVar, className = "" }) {
13484
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: `flex flex-col gap-1 ${className}`, children: [
13485
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13807
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: `flex flex-col gap-1 ${className}`, children: [
13808
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13486
13809
  "div",
13487
13810
  {
13488
13811
  className: "h-16 w-full rounded-lg border border-border shadow-sm",
13489
13812
  style: { backgroundColor: `var(${cssVar})` }
13490
13813
  }
13491
13814
  ),
13492
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13493
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: cssVar })
13815
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13816
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: cssVar })
13494
13817
  ] });
13495
13818
  }
13496
13819
  function ColorRow({ name, cssVar, description }) {
13497
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "flex items-center gap-4 py-2", children: [
13498
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
13820
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex items-center gap-4 py-2", children: [
13821
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13499
13822
  "div",
13500
13823
  {
13501
13824
  className: "h-10 w-10 rounded-lg border border-border shadow-sm flex-shrink-0",
13502
13825
  style: { backgroundColor: `var(${cssVar})` }
13503
13826
  }
13504
13827
  ),
13505
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "flex-1 min-w-0", children: [
13506
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13507
- description && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "text-xs text-muted-foreground", children: description })
13828
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex-1 min-w-0", children: [
13829
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-sm font-medium text-foreground", children: name }),
13830
+ description && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-xs text-muted-foreground", children: description })
13508
13831
  ] }),
13509
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: cssVar })
13832
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: cssVar })
13510
13833
  ] });
13511
13834
  }
13512
13835
 
13513
13836
  // src/design-system/ColorPalette.tsx
13514
- var import_jsx_runtime82 = require("react/jsx-runtime");
13837
+ var import_jsx_runtime83 = require("react/jsx-runtime");
13515
13838
  var COLOR_GROUPS = [
13516
13839
  {
13517
13840
  name: "Base",
@@ -13592,17 +13915,17 @@ var COLOR_GROUPS = [
13592
13915
  }
13593
13916
  ];
13594
13917
  function ColorPalette({ layout = "list", className = "" }) {
13595
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: `space-y-8 ${className}`, children: COLOR_GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("section", { children: [
13596
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
13597
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
13598
- layout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-4", children: group.colors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
13918
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: `space-y-8 ${className}`, children: COLOR_GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("section", { children: [
13919
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("h3", { className: "text-lg font-semibold text-foreground mb-1", children: group.name }),
13920
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: group.description }),
13921
+ layout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-4", children: group.colors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13599
13922
  ColorTokenSwatch,
13600
13923
  {
13601
13924
  name: color.name,
13602
13925
  cssVar: color.cssVar
13603
13926
  },
13604
13927
  color.cssVar
13605
- )) }) : /* @__PURE__ */ (0, import_jsx_runtime82.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_runtime82.jsx)(
13928
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "bg-card rounded-lg border border-border p-4 divide-y divide-border", children: group.colors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13606
13929
  ColorRow,
13607
13930
  {
13608
13931
  name: color.name,
@@ -13615,7 +13938,7 @@ function ColorPalette({ layout = "list", className = "" }) {
13615
13938
  }
13616
13939
 
13617
13940
  // src/design-system/TypographyScale.tsx
13618
- var import_jsx_runtime83 = require("react/jsx-runtime");
13941
+ var import_jsx_runtime84 = require("react/jsx-runtime");
13619
13942
  var FONT_SAMPLES = [
13620
13943
  {
13621
13944
  name: "Heading",
@@ -13649,14 +13972,14 @@ var FONT_SAMPLES = [
13649
13972
  }
13650
13973
  ];
13651
13974
  function TypographyScale({ className = "" }) {
13652
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: `space-y-8 ${className}`, children: FONT_SAMPLES.map((font) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("section", { className: "bg-card rounded-lg border border-border p-6", children: [
13653
- /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
13654
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
13655
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: font.cssVar })
13975
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: `space-y-8 ${className}`, children: FONT_SAMPLES.map((font) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("section", { className: "bg-card rounded-lg border border-border p-6", children: [
13976
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
13977
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: font.name }),
13978
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("code", { className: "text-xs text-muted-foreground font-mono bg-muted px-2 py-1 rounded", children: font.cssVar })
13656
13979
  ] }),
13657
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "space-y-4", children: font.sizes.map((size) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex items-baseline gap-4", children: [
13658
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
13659
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
13980
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "space-y-4", children: font.sizes.map((size) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex items-baseline gap-4", children: [
13981
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "text-xs text-muted-foreground w-20 flex-shrink-0", children: size }),
13982
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
13660
13983
  "p",
13661
13984
  {
13662
13985
  className: `${size} text-foreground`,
@@ -13675,8 +13998,8 @@ var RADIUS_SAMPLES = [
13675
13998
  { name: "Full", value: "9999px" }
13676
13999
  ];
13677
14000
  function RadiusScale({ className = "" }) {
13678
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "grid grid-cols-5 gap-4", children: RADIUS_SAMPLES.map((radius) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex flex-col items-center gap-2", children: [
13679
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
14001
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "grid grid-cols-5 gap-4", children: RADIUS_SAMPLES.map((radius) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex flex-col items-center gap-2", children: [
14002
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
13680
14003
  "div",
13681
14004
  {
13682
14005
  className: "h-16 w-16 bg-primary",
@@ -13685,13 +14008,13 @@ function RadiusScale({ className = "" }) {
13685
14008
  }
13686
14009
  }
13687
14010
  ),
13688
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
13689
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: radius.cssVar || radius.value })
14011
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "text-sm font-medium text-foreground", children: radius.name }),
14012
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("code", { className: "text-xs text-muted-foreground font-mono", children: radius.cssVar || radius.value })
13690
14013
  ] }, radius.name)) }) });
13691
14014
  }
13692
14015
 
13693
14016
  // src/design-system/ThemeSwitcher.tsx
13694
- var import_react63 = require("react");
14017
+ var import_react64 = require("react");
13695
14018
 
13696
14019
  // src/themes/types.ts
13697
14020
  var RADIUS_PRESETS = {
@@ -14859,7 +15182,7 @@ function applyTheme(config) {
14859
15182
  }
14860
15183
 
14861
15184
  // src/design-system/ThemeSwitcher.tsx
14862
- var import_jsx_runtime84 = require("react/jsx-runtime");
15185
+ var import_jsx_runtime85 = require("react/jsx-runtime");
14863
15186
  function readThemeFromDOM() {
14864
15187
  if (typeof document === "undefined") {
14865
15188
  return { themeName: "Linear", isDark: false };
@@ -14877,10 +15200,10 @@ function readThemeFromDOM() {
14877
15200
  return { themeName: "Linear", isDark: dark };
14878
15201
  }
14879
15202
  function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
14880
- const [currentTheme, setCurrentTheme] = (0, import_react63.useState)("Linear");
14881
- const [isDark, setIsDark] = (0, import_react63.useState)(false);
14882
- const [isOpen, setIsOpen] = (0, import_react63.useState)(false);
14883
- (0, import_react63.useEffect)(() => {
15203
+ const [currentTheme, setCurrentTheme] = (0, import_react64.useState)("Linear");
15204
+ const [isDark, setIsDark] = (0, import_react64.useState)(false);
15205
+ const [isOpen, setIsOpen] = (0, import_react64.useState)(false);
15206
+ (0, import_react64.useEffect)(() => {
14884
15207
  const { themeName, isDark: dark } = readThemeFromDOM();
14885
15208
  setCurrentTheme(themeName);
14886
15209
  setIsDark(dark);
@@ -14919,61 +15242,61 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
14919
15242
  applyTheme(config);
14920
15243
  };
14921
15244
  const themes = showBaseThemesOnly ? baseThemes : baseThemes;
14922
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: `flex items-center gap-3 ${className}`, children: [
14923
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "relative", children: [
14924
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
15245
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: `flex items-center gap-3 ${className}`, children: [
15246
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "relative", children: [
15247
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
14925
15248
  "button",
14926
15249
  {
14927
15250
  onClick: () => setIsOpen(!isOpen),
14928
15251
  className: "flex items-center gap-2 px-4 py-2 bg-card border border-border rounded-lg hover:bg-muted transition-colors text-foreground",
14929
15252
  children: [
14930
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime84.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" }) }),
14931
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "font-medium", children: currentTheme }),
14932
- /* @__PURE__ */ (0, import_jsx_runtime84.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_runtime84.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
15253
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" }) }),
15254
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "font-medium", children: currentTheme }),
15255
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("svg", { className: `w-4 h-4 transition-transform ${isOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
14933
15256
  ]
14934
15257
  }
14935
15258
  ),
14936
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(import_jsx_runtime84.Fragment, { children: [
14937
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
15259
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(import_jsx_runtime85.Fragment, { children: [
15260
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
14938
15261
  "div",
14939
15262
  {
14940
15263
  className: "fixed inset-0 z-40",
14941
15264
  onClick: () => setIsOpen(false)
14942
15265
  }
14943
15266
  ),
14944
- /* @__PURE__ */ (0, import_jsx_runtime84.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_runtime84.jsxs)(
15267
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "absolute top-full left-0 mt-2 w-56 max-h-80 overflow-auto bg-card border border-border rounded-lg shadow-lg z-50", children: themes.map((theme) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
14945
15268
  "button",
14946
15269
  {
14947
15270
  onClick: () => handleThemeSelect(theme.name),
14948
15271
  className: `w-full px-4 py-2 text-left hover:bg-muted transition-colors flex items-center gap-3 ${currentTheme === theme.name ? "bg-muted" : ""}`,
14949
15272
  children: [
14950
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
15273
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
14951
15274
  "div",
14952
15275
  {
14953
15276
  className: "w-4 h-4 rounded-full border border-border",
14954
15277
  style: { backgroundColor: theme.primaryColor || "#888" }
14955
15278
  }
14956
15279
  ),
14957
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "text-foreground", children: theme.name }),
14958
- currentTheme === theme.name && /* @__PURE__ */ (0, import_jsx_runtime84.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_runtime84.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) })
15280
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "text-foreground", children: theme.name }),
15281
+ currentTheme === theme.name && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("svg", { className: "w-4 h-4 ml-auto text-primary", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) })
14959
15282
  ]
14960
15283
  },
14961
15284
  theme.name
14962
15285
  )) })
14963
15286
  ] })
14964
15287
  ] }),
14965
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
15288
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
14966
15289
  "button",
14967
15290
  {
14968
15291
  onClick: handleDarkModeToggle,
14969
15292
  className: "flex items-center gap-2 px-4 py-2 bg-card border border-border rounded-lg hover:bg-muted transition-colors text-foreground",
14970
15293
  title: `Switch to ${isDark ? "light" : "dark"} mode`,
14971
15294
  children: [
14972
- isDark ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
14973
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
14974
- /* @__PURE__ */ (0, import_jsx_runtime84.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" })
14975
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }),
14976
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "text-sm", children: isDark ? "Light" : "Dark" })
15295
+ isDark ? /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
15296
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
15297
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })
15298
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }),
15299
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "text-sm", children: isDark ? "Light" : "Dark" })
14977
15300
  ]
14978
15301
  }
14979
15302
  )
@@ -14981,7 +15304,7 @@ function ThemeSwitcher({ className = "", showBaseThemesOnly = true }) {
14981
15304
  }
14982
15305
 
14983
15306
  // src/design-system/DesignSystemPage.tsx
14984
- var import_jsx_runtime85 = require("react/jsx-runtime");
15307
+ var import_jsx_runtime86 = require("react/jsx-runtime");
14985
15308
  function DesignSystemPage({
14986
15309
  showThemeSwitcher = true,
14987
15310
  showColors = true,
@@ -14991,29 +15314,29 @@ function DesignSystemPage({
14991
15314
  colorLayout = "list",
14992
15315
  className = ""
14993
15316
  }) {
14994
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: `max-w-4xl mx-auto px-4 py-8 ${className}`, children: [
14995
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("header", { className: "mb-12", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4", children: [
14996
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { children: [
14997
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
14998
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("p", { className: "text-lg text-muted-foreground", children: "Visual reference for theme tokens and styles" })
15317
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: `max-w-4xl mx-auto px-4 py-8 ${className}`, children: [
15318
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("header", { className: "mb-12", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4", children: [
15319
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { children: [
15320
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h1", { className: "text-4xl font-bold text-foreground mb-2", children: "Design System" }),
15321
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "text-lg text-muted-foreground", children: "Visual reference for theme tokens and styles" })
14999
15322
  ] }),
15000
- showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ThemeSwitcher, {})
15323
+ showThemeSwitcher && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ThemeSwitcher, {})
15001
15324
  ] }) }),
15002
- showColors && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("section", { className: "mb-16", children: [
15003
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Color Palette" }),
15004
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ColorPalette, { layout: colorLayout })
15325
+ showColors && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "mb-16", children: [
15326
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Color Palette" }),
15327
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ColorPalette, { layout: colorLayout })
15005
15328
  ] }),
15006
- showTypography && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("section", { className: "mb-16", children: [
15007
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
15008
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(TypographyScale, {})
15329
+ showTypography && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "mb-16", children: [
15330
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Typography" }),
15331
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(TypographyScale, {})
15009
15332
  ] }),
15010
- showRadius && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("section", { className: "mb-16", children: [
15011
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Border Radius" }),
15012
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(RadiusScale, {})
15333
+ showRadius && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "mb-16", children: [
15334
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Border Radius" }),
15335
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(RadiusScale, {})
15013
15336
  ] }),
15014
- showSpacing && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("section", { className: "mb-16", children: [
15015
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Spacing Scale" }),
15016
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(SpacingScale, {})
15337
+ showSpacing && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("section", { className: "mb-16", children: [
15338
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-6 pb-2 border-b border-border", children: "Spacing Scale" }),
15339
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(SpacingScale, {})
15017
15340
  ] })
15018
15341
  ] });
15019
15342
  }
@@ -15028,31 +15351,31 @@ function SpacingScale() {
15028
15351
  { name: "12", value: "3rem" },
15029
15352
  { name: "16", value: "4rem" }
15030
15353
  ];
15031
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "space-y-2", children: spaces.map((space) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex items-center gap-4", children: [
15032
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
15033
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
15354
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "space-y-2", children: spaces.map((space) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex items-center gap-4", children: [
15355
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("code", { className: "text-xs text-muted-foreground font-mono w-8", children: space.name }),
15356
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15034
15357
  "div",
15035
15358
  {
15036
15359
  className: "h-4 bg-primary rounded",
15037
15360
  style: { width: space.value }
15038
15361
  }
15039
15362
  ),
15040
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "text-sm text-muted-foreground", children: space.value })
15363
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-sm text-muted-foreground", children: space.value })
15041
15364
  ] }, space.name)) });
15042
15365
  }
15043
15366
 
15044
15367
  // src/personalization/PersonalizationProvider.tsx
15045
- var import_react66 = __toESM(require("react"), 1);
15368
+ var import_react67 = __toESM(require("react"), 1);
15046
15369
 
15047
15370
  // src/personalization/PersonalizationContext.ts
15048
- var import_react64 = require("react");
15049
- var PersonalizationContext = (0, import_react64.createContext)(null);
15371
+ var import_react65 = require("react");
15372
+ var PersonalizationContext = (0, import_react65.createContext)(null);
15050
15373
  function usePersonalizationContext() {
15051
- return (0, import_react64.useContext)(PersonalizationContext);
15374
+ return (0, import_react65.useContext)(PersonalizationContext);
15052
15375
  }
15053
15376
 
15054
15377
  // src/personalization/utils.ts
15055
- var import_react65 = require("react");
15378
+ var import_react66 = require("react");
15056
15379
  function normalizeHex(color) {
15057
15380
  let hex = color.trim().toUpperCase();
15058
15381
  if (hex.length === 4 && hex.startsWith("#")) {
@@ -15073,8 +15396,8 @@ function isValidImageUrl(url) {
15073
15396
  }
15074
15397
  }
15075
15398
  function useDebouncedValue(value, delay) {
15076
- const [debounced, setDebounced] = (0, import_react65.useState)(value);
15077
- (0, import_react65.useEffect)(() => {
15399
+ const [debounced, setDebounced] = (0, import_react66.useState)(value);
15400
+ (0, import_react66.useEffect)(() => {
15078
15401
  const timer = setTimeout(() => setDebounced(value), delay);
15079
15402
  return () => clearTimeout(timer);
15080
15403
  }, [value, delay]);
@@ -15095,18 +15418,18 @@ function scrollInputAboveKeyboard(input) {
15095
15418
  }
15096
15419
 
15097
15420
  // src/personalization/PersonalizationProvider.tsx
15098
- var import_jsx_runtime86 = require("react/jsx-runtime");
15421
+ var import_jsx_runtime87 = require("react/jsx-runtime");
15099
15422
  function createBridgeFromCanvas(canvasModule) {
15100
15423
  const { useEditor, useCommands, useImageBinding } = canvasModule;
15101
15424
  function TextBinder({ name, value }) {
15102
15425
  const { elements } = useEditor();
15103
15426
  const { executeElementUpdate } = useCommands();
15104
- const elementsRef = import_react66.default.useRef(elements);
15427
+ const elementsRef = import_react67.default.useRef(elements);
15105
15428
  elementsRef.current = elements;
15106
- const executeRef = import_react66.default.useRef(executeElementUpdate);
15429
+ const executeRef = import_react67.default.useRef(executeElementUpdate);
15107
15430
  executeRef.current = executeElementUpdate;
15108
- const hasUserInput = import_react66.default.useRef(false);
15109
- import_react66.default.useEffect(() => {
15431
+ const hasUserInput = import_react67.default.useRef(false);
15432
+ import_react67.default.useEffect(() => {
15110
15433
  if (value == null) return;
15111
15434
  if (value === "" && !hasUserInput.current) return;
15112
15435
  hasUserInput.current = true;
@@ -15124,12 +15447,12 @@ function createBridgeFromCanvas(canvasModule) {
15124
15447
  function ColorBinder({ originalColor, newColor }) {
15125
15448
  const { elements } = useEditor();
15126
15449
  const { executeElementUpdate } = useCommands();
15127
- const elementsRef = import_react66.default.useRef(elements);
15450
+ const elementsRef = import_react67.default.useRef(elements);
15128
15451
  elementsRef.current = elements;
15129
- const executeRef = import_react66.default.useRef(executeElementUpdate);
15452
+ const executeRef = import_react67.default.useRef(executeElementUpdate);
15130
15453
  executeRef.current = executeElementUpdate;
15131
- const appliedColorRef = import_react66.default.useRef(normalizeHex(originalColor));
15132
- import_react66.default.useEffect(() => {
15454
+ const appliedColorRef = import_react67.default.useRef(normalizeHex(originalColor));
15455
+ import_react67.default.useEffect(() => {
15133
15456
  const normalizedNew = normalizeHex(newColor);
15134
15457
  if (normalizedNew === appliedColorRef.current) return;
15135
15458
  const matchColor = appliedColorRef.current;
@@ -15169,11 +15492,11 @@ function createBridgeFromCanvas(canvasModule) {
15169
15492
  }
15170
15493
  function ImageBinder({ name, value, fit = "cover" }) {
15171
15494
  const { setImageUrl } = useImageBinding(name, { fit });
15172
- const hasUserInput = import_react66.default.useRef(false);
15495
+ const hasUserInput = import_react67.default.useRef(false);
15173
15496
  const debouncedValue = useDebouncedValue(value, 500);
15174
- const setImageUrlRef = import_react66.default.useRef(setImageUrl);
15497
+ const setImageUrlRef = import_react67.default.useRef(setImageUrl);
15175
15498
  setImageUrlRef.current = setImageUrl;
15176
- import_react66.default.useEffect(() => {
15499
+ import_react67.default.useEffect(() => {
15177
15500
  if (debouncedValue == null) return;
15178
15501
  if (debouncedValue === "" && !hasUserInput.current) return;
15179
15502
  hasUserInput.current = true;
@@ -15183,15 +15506,15 @@ function createBridgeFromCanvas(canvasModule) {
15183
15506
  return null;
15184
15507
  }
15185
15508
  return function PersonalizationBridge({ fields = [], values = {} } = {}) {
15186
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_jsx_runtime86.Fragment, { children: fields.map((field) => {
15509
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_jsx_runtime87.Fragment, { children: fields.map((field) => {
15187
15510
  if (field.type === "text") {
15188
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
15511
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(TextBinder, { name: field.name, value: values[field.name] ?? "" }, `text-${field.name}`);
15189
15512
  }
15190
15513
  if (field.type === "color") {
15191
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
15514
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ColorBinder, { originalColor: field.color, newColor: values[field.color] ?? field.color }, `color-${field.color}`);
15192
15515
  }
15193
15516
  if (field.type === "image") {
15194
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
15517
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ImageBinder, { name: field.name, value: values[field.name] ?? "", fit: field.fit ?? "cover" }, `image-${field.name}`);
15195
15518
  }
15196
15519
  return null;
15197
15520
  }) });
@@ -15213,19 +15536,19 @@ function PersonalizationProvider({
15213
15536
  children
15214
15537
  }) {
15215
15538
  const realtime = useRealtimeOptional();
15216
- const [personValues, setPersonValues] = (0, import_react66.useState)(initialValues ?? {});
15217
- const [isActive, setIsActive] = (0, import_react66.useState)(!!(initialValues && Object.keys(initialValues).length > 0));
15218
- const [isExporting, setIsExporting] = (0, import_react66.useState)(false);
15219
- const [exportedBlobUrls, setExportedBlobUrls] = (0, import_react66.useState)({});
15220
- const [exportCount, setExportCount] = (0, import_react66.useState)(0);
15221
- const blobUrlsRef = (0, import_react66.useRef)({});
15222
- const [CanvasComponent, setCanvasComponent] = (0, import_react66.useState)(
15539
+ const [personValues, setPersonValues] = (0, import_react67.useState)(initialValues ?? {});
15540
+ const [isActive, setIsActive] = (0, import_react67.useState)(!!(initialValues && Object.keys(initialValues).length > 0));
15541
+ const [isExporting, setIsExporting] = (0, import_react67.useState)(false);
15542
+ const [exportedBlobUrls, setExportedBlobUrls] = (0, import_react67.useState)({});
15543
+ const [exportCount, setExportCount] = (0, import_react67.useState)(0);
15544
+ const blobUrlsRef = (0, import_react67.useRef)({});
15545
+ const [CanvasComponent, setCanvasComponent] = (0, import_react67.useState)(
15223
15546
  cachedCanvasComponent
15224
15547
  );
15225
- const [BridgeComponent, setBridgeComponent] = (0, import_react66.useState)(
15548
+ const [BridgeComponent, setBridgeComponent] = (0, import_react67.useState)(
15226
15549
  cachedBridgeComponent
15227
15550
  );
15228
- (0, import_react66.useEffect)(() => {
15551
+ (0, import_react67.useEffect)(() => {
15229
15552
  if (CanvasComponent && BridgeComponent) return;
15230
15553
  if (!canvasImport) return;
15231
15554
  if (!canvasLoadPromise) {
@@ -15243,8 +15566,8 @@ function PersonalizationProvider({
15243
15566
  }
15244
15567
  });
15245
15568
  }, [CanvasComponent, BridgeComponent, canvasImport]);
15246
- const realtimeEnabledRef = (0, import_react66.useRef)(false);
15247
- (0, import_react66.useEffect)(() => {
15569
+ const realtimeEnabledRef = (0, import_react67.useRef)(false);
15570
+ (0, import_react67.useEffect)(() => {
15248
15571
  return () => {
15249
15572
  for (const url of Object.values(blobUrlsRef.current)) {
15250
15573
  try {
@@ -15254,16 +15577,16 @@ function PersonalizationProvider({
15254
15577
  }
15255
15578
  };
15256
15579
  }, []);
15257
- const updateField = (0, import_react66.useCallback)((key, value) => {
15580
+ const updateField = (0, import_react67.useCallback)((key, value) => {
15258
15581
  setIsActive(true);
15259
15582
  setPersonValues((prev) => ({ ...prev, [key]: value }));
15260
15583
  }, []);
15261
- const reset = (0, import_react66.useCallback)(() => {
15584
+ const reset = (0, import_react67.useCallback)(() => {
15262
15585
  setPersonValues({});
15263
15586
  setIsActive(false);
15264
15587
  setIsExporting(false);
15265
15588
  }, []);
15266
- const handleExport = (0, import_react66.useCallback)(
15589
+ const handleExport = (0, import_react67.useCallback)(
15267
15590
  (exports2) => {
15268
15591
  const newUrls = {};
15269
15592
  for (const [name, data] of Object.entries(exports2)) {
@@ -15297,11 +15620,11 @@ function PersonalizationProvider({
15297
15620
  },
15298
15621
  [realtime, placementOverride]
15299
15622
  );
15300
- const handleExportScheduled = (0, import_react66.useCallback)(() => {
15623
+ const handleExportScheduled = (0, import_react67.useCallback)(() => {
15301
15624
  setIsExporting(true);
15302
15625
  }, []);
15303
15626
  const shouldMountCanvas = CanvasComponent && BridgeComponent && canvasState?.elements && canvasState.elements.length > 0 && (!lazy || isActive);
15304
- const contextValue = import_react66.default.useMemo(
15627
+ const contextValue = import_react67.default.useMemo(
15305
15628
  () => ({
15306
15629
  fields,
15307
15630
  personValues,
@@ -15314,8 +15637,8 @@ function PersonalizationProvider({
15314
15637
  }),
15315
15638
  [fields, personValues, updateField, isActive, isExporting, exportedBlobUrls, exportCount, reset]
15316
15639
  );
15317
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(PersonalizationContext.Provider, { value: contextValue, children: [
15318
- shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15640
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(PersonalizationContext.Provider, { value: contextValue, children: [
15641
+ shouldMountCanvas && CanvasComponent && BridgeComponent && /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15319
15642
  "div",
15320
15643
  {
15321
15644
  style: {
@@ -15328,7 +15651,7 @@ function PersonalizationProvider({
15328
15651
  pointerEvents: "none"
15329
15652
  },
15330
15653
  "aria-hidden": true,
15331
- children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
15654
+ children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15332
15655
  CanvasComponent,
15333
15656
  {
15334
15657
  initialElements: canvasState?.elements,
@@ -15348,7 +15671,7 @@ function PersonalizationProvider({
15348
15671
  exportImageQuality: exportConfig?.imageQuality ?? 0.85,
15349
15672
  onExport: handleExport,
15350
15673
  onExportScheduled: handleExportScheduled,
15351
- overlay: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(BridgeComponent, { fields, values: personValues })
15674
+ overlay: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(BridgeComponent, { fields, values: personValues })
15352
15675
  }
15353
15676
  )
15354
15677
  },
@@ -15373,7 +15696,7 @@ function usePersonalizationOptional() {
15373
15696
  }
15374
15697
 
15375
15698
  // src/personalization/PersonalizationInputs.tsx
15376
- var import_jsx_runtime87 = require("react/jsx-runtime");
15699
+ var import_jsx_runtime88 = require("react/jsx-runtime");
15377
15700
  function PersonalizationInputs({
15378
15701
  className,
15379
15702
  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",
@@ -15397,8 +15720,8 @@ function PersonalizationInputs({
15397
15720
  scrollInputAboveKeyboard(e.target);
15398
15721
  }
15399
15722
  };
15400
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: className || "flex flex-col gap-3", children: [
15401
- textFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15723
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: className || "flex flex-col gap-3", children: [
15724
+ textFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15402
15725
  "input",
15403
15726
  {
15404
15727
  type: "text",
@@ -15412,8 +15735,8 @@ function PersonalizationInputs({
15412
15735
  },
15413
15736
  `text-${field.name}`
15414
15737
  )),
15415
- colorFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex items-center gap-3", children: [
15416
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15738
+ colorFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex items-center gap-3", children: [
15739
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15417
15740
  "input",
15418
15741
  {
15419
15742
  type: "color",
@@ -15422,9 +15745,9 @@ function PersonalizationInputs({
15422
15745
  onChange: (e) => updateField(field.color, e.target.value)
15423
15746
  }
15424
15747
  ),
15425
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "text-base text-muted-foreground", children: field.label })
15748
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "text-base text-muted-foreground", children: field.label })
15426
15749
  ] }, `color-${field.color}`)),
15427
- imageFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
15750
+ imageFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
15428
15751
  "input",
15429
15752
  {
15430
15753
  type: "text",
@@ -15442,15 +15765,15 @@ function PersonalizationInputs({
15442
15765
  }
15443
15766
 
15444
15767
  // src/personalization/usePersonalizationShimmer.ts
15445
- var import_react67 = require("react");
15768
+ var import_react68 = require("react");
15446
15769
  function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15447
15770
  const personCtx = usePersonalizationContext();
15448
15771
  const realtime = useRealtimeOptional();
15449
- const [shimmerActive, setShimmerActive] = (0, import_react67.useState)(false);
15450
- const sdkSettledRef = (0, import_react67.useRef)(false);
15451
- const manualTriggerRef = (0, import_react67.useRef)(false);
15452
- const safetyTimeoutRef = (0, import_react67.useRef)(void 0);
15453
- const startShimmer = (0, import_react67.useCallback)(() => {
15772
+ const [shimmerActive, setShimmerActive] = (0, import_react68.useState)(false);
15773
+ const sdkSettledRef = (0, import_react68.useRef)(false);
15774
+ const manualTriggerRef = (0, import_react68.useRef)(false);
15775
+ const safetyTimeoutRef = (0, import_react68.useRef)(void 0);
15776
+ const startShimmer = (0, import_react68.useCallback)(() => {
15454
15777
  setShimmerActive(true);
15455
15778
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
15456
15779
  safetyTimeoutRef.current = setTimeout(
@@ -15462,25 +15785,25 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15462
15785
  safetyTimeoutMs
15463
15786
  );
15464
15787
  }, [safetyTimeoutMs]);
15465
- (0, import_react67.useEffect)(() => {
15788
+ (0, import_react68.useEffect)(() => {
15466
15789
  if (!personCtx?.isActive) return;
15467
15790
  sdkSettledRef.current = false;
15468
15791
  manualTriggerRef.current = false;
15469
15792
  realtime?.resetPipelineSettled();
15470
15793
  startShimmer();
15471
15794
  }, [personCtx?.personValues, personCtx?.isActive, startShimmer]);
15472
- const triggerShimmer = (0, import_react67.useCallback)(() => {
15795
+ const triggerShimmer = (0, import_react68.useCallback)(() => {
15473
15796
  sdkSettledRef.current = false;
15474
15797
  manualTriggerRef.current = true;
15475
15798
  startShimmer();
15476
15799
  }, [startShimmer]);
15477
- (0, import_react67.useEffect)(() => {
15800
+ (0, import_react68.useEffect)(() => {
15478
15801
  if (!realtime?.subscribePipelineSettled) return;
15479
15802
  return realtime.subscribePipelineSettled(() => {
15480
15803
  sdkSettledRef.current = true;
15481
15804
  });
15482
15805
  }, [realtime]);
15483
- (0, import_react67.useEffect)(() => {
15806
+ (0, import_react68.useEffect)(() => {
15484
15807
  const container = containerRef.current;
15485
15808
  if (!container) return;
15486
15809
  const observer = new MutationObserver((mutations) => {
@@ -15523,7 +15846,7 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15523
15846
  });
15524
15847
  return () => observer.disconnect();
15525
15848
  }, [containerRef]);
15526
- (0, import_react67.useEffect)(() => {
15849
+ (0, import_react68.useEffect)(() => {
15527
15850
  return () => {
15528
15851
  if (safetyTimeoutRef.current) clearTimeout(safetyTimeoutRef.current);
15529
15852
  };
@@ -15629,6 +15952,8 @@ function usePersonalizationShimmer(containerRef, safetyTimeoutMs = 1e4) {
15629
15952
  Link,
15630
15953
  LinkIcon,
15631
15954
  LoadingOverlayPrism,
15955
+ LoadingOverlayPrismCandy,
15956
+ LoadingOverlayPrismCandyInline,
15632
15957
  MasonryGrid,
15633
15958
  MobileProductCarousel,
15634
15959
  MockupPriorityProvider,