@patternmode/aperto 0.2.2 → 2.0.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/README.md CHANGED
@@ -69,6 +69,72 @@ const leadSrc = media[0]?.src;
69
69
  </Aperto.Group>;
70
70
  ```
71
71
 
72
+ ## Panel shape and aspect ratio
73
+
74
+ The expanded panel takes its shape from the active item's `width`/`height`.
75
+ Set them to the aspect ratio you want the panel to hold — they are a ratio,
76
+ not pixel dimensions, so `width: 1, height: 1` and `width: 1200, height: 1200`
77
+ both produce a square panel:
78
+
79
+ ```tsx
80
+ const media: ApertoMediaItem[] = [
81
+ {
82
+ type: "image",
83
+ src: "/images/swatch-1600.jpg",
84
+ thumbnailSrc: "/images/swatch-400.jpg",
85
+ alt: "Herringbone weave",
86
+ // Square panel — matches a square-cropped (object-cover) thumbnail, so
87
+ // the shared-element morph never re-frames the image.
88
+ width: 1,
89
+ height: 1,
90
+ },
91
+ ];
92
+ ```
93
+
94
+ Omitting `width`/`height` falls back to a 3:2 panel.
95
+
96
+ The declared ratio is honoured under every viewport constraint: the media box
97
+ refuses to flex-shrink inside the panel and derives its size budget from the
98
+ panel's own height cap, minus room for the caption stack. Three CSS custom
99
+ properties tune this without forking the stylesheet:
100
+
101
+ - `--aperto-panel-max-h` — the panel's height cap (default `min(90vh, 920px)`)
102
+ - `--aperto-caption-allowance` — vertical room reserved for title /
103
+ description / counter (default `6rem`)
104
+ - `--aperto-expanded-width` — the media's preferred width (default `76vw`)
105
+
106
+ Set them via `classNames.content` or any ancestor.
107
+
108
+ ## Seamless expansion
109
+
110
+ The in-flight transition clone always renders `thumbnailSrc` (falling back to
111
+ `src`) — those pixels are already decoded and on screen, so the morph is
112
+ seamless even when the full-size `src` hasn't loaded yet.
113
+
114
+ For the beat _after_ the morph, while the full-size asset is still loading,
115
+ layer the thumbnail underneath it in `renderImage` so there is never a blank
116
+ frame. Keep both variants on the same crop (`object-fit: cover` with matching
117
+ aspect) so nothing re-frames.
118
+
119
+ With `next/image`, also pin one **fixed** `sizes` value for every
120
+ thumbnail-sourced render — the grid tile, the clone (`variant: "thumbnail"`),
121
+ and the expanded underlay. `sizes` decides the srcset candidate, so any
122
+ divergence produces a different URL and defeats the cache reuse that makes the
123
+ morph seamless:
124
+
125
+ ```tsx
126
+ renderImage={({ alt, item, src, variant }) =>
127
+ variant === "expanded" ? (
128
+ <>
129
+ <Image alt="" aria-hidden className="object-cover" fill sizes={THUMB_SIZES} src={item.thumbnailSrc ?? String(src)} />
130
+ <Image alt={alt ?? item.alt} className="object-cover" fill loading="eager" sizes="1600px" src={String(src)} />
131
+ </>
132
+ ) : (
133
+ <Image alt={alt ?? item.alt} className="object-cover" fill sizes={THUMB_SIZES} src={String(src)} />
134
+ )
135
+ }
136
+ ```
137
+
72
138
  ## Install
73
139
 
74
140
  ```bash
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import * as react from 'react';
2
- import { ImgHTMLAttributes, ReactNode, VideoHTMLAttributes, ComponentPropsWithRef, Ref, CSSProperties, ComponentPropsWithoutRef } from 'react';
3
- import * as Dialog from '@radix-ui/react-dialog';
2
+ import { ImgHTMLAttributes, ReactNode, VideoHTMLAttributes, ComponentPropsWithRef, CSSProperties, Ref, ComponentPropsWithoutRef } from 'react';
3
+ import * as _base_ui_react from '@base-ui/react';
4
4
  import { Transition } from 'motion/react';
5
+ import { Dialog } from '@base-ui/react/dialog';
5
6
 
6
7
  /**
7
8
  * Package: @patternmode/aperto
@@ -187,7 +188,10 @@ declare const ApertoClose: {
187
188
  displayName: string;
188
189
  };
189
190
 
190
- interface ApertoContentProps extends Omit<ComponentPropsWithRef<typeof Dialog.Content>, "asChild" | "forceMount"> {
191
+ interface ApertoContentProps extends Omit<ComponentPropsWithRef<typeof Dialog.Popup>, "render" | "hidden" | "className" | "style"> {
192
+ /** Constrained to a plain string/object (Base UI's function forms aren't used). */
193
+ className?: string;
194
+ style?: CSSProperties;
191
195
  /** Motion preset override for this content panel, independent of the root preset. */
192
196
  motion?: MotionPresetName;
193
197
  /** Built-in positioning strategy. Use "none" for custom primitive compositions. */
@@ -281,7 +285,7 @@ declare const resolvePreset: (componentType: ComponentType, componentMotion: Mot
281
285
  /** Lower-level compound component namespace for advanced composition. */
282
286
  declare const ApertoPrimitive: {
283
287
  Close: {
284
- ({ children, ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogCloseProps & react.RefAttributes<HTMLButtonElement>>>): react.JSX.Element;
288
+ ({ children, ref, ...props }: react.ComponentPropsWithRef<typeof _base_ui_react.DialogClose>): react.JSX.Element;
285
289
  displayName: string;
286
290
  };
287
291
  Content: {
@@ -289,7 +293,7 @@ declare const ApertoPrimitive: {
289
293
  displayName: string;
290
294
  };
291
295
  Description: {
292
- ({ ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogDescriptionProps & react.RefAttributes<HTMLParagraphElement>>>): react.JSX.Element;
296
+ ({ ref, ...props }: react.ComponentPropsWithRef<typeof _base_ui_react.DialogDescription>): react.JSX.Element;
293
297
  displayName: string;
294
298
  };
295
299
  Overlay: {
@@ -299,7 +303,7 @@ declare const ApertoPrimitive: {
299
303
  Portal: ({ children, container }: ApertoPortalProps) => react.JSX.Element;
300
304
  Root: ({ children, defaultOpen, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react.JSX.Element;
301
305
  Title: {
302
- ({ ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogTitleProps & react.RefAttributes<HTMLHeadingElement>>>): react.JSX.Element;
306
+ ({ ref, ...props }: react.ComponentPropsWithRef<typeof _base_ui_react.DialogTitle>): react.JSX.Element;
303
307
  displayName: string;
304
308
  };
305
309
  Trigger: {
@@ -312,7 +316,7 @@ declare const Aperto: (({ classNames, dismissible, media, renderImage, renderVid
312
316
  Group: ({ children, classNames, dismissible, index, initialIndex, media, motion: motionProp, navigationMotion, onIndexChange, renderImage, renderVideo, }: ApertoGroupProps) => react.JSX.Element;
313
317
  Primitive: {
314
318
  Close: {
315
- ({ children, ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogCloseProps & react.RefAttributes<HTMLButtonElement>>>): react.JSX.Element;
319
+ ({ children, ref, ...props }: react.ComponentPropsWithRef<typeof _base_ui_react.DialogClose>): react.JSX.Element;
316
320
  displayName: string;
317
321
  };
318
322
  Content: {
@@ -320,7 +324,7 @@ declare const Aperto: (({ classNames, dismissible, media, renderImage, renderVid
320
324
  displayName: string;
321
325
  };
322
326
  Description: {
323
- ({ ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogDescriptionProps & react.RefAttributes<HTMLParagraphElement>>>): react.JSX.Element;
327
+ ({ ref, ...props }: react.ComponentPropsWithRef<typeof _base_ui_react.DialogDescription>): react.JSX.Element;
324
328
  displayName: string;
325
329
  };
326
330
  Overlay: {
@@ -330,7 +334,7 @@ declare const Aperto: (({ classNames, dismissible, media, renderImage, renderVid
330
334
  Portal: ({ children, container }: ApertoPortalProps) => react.JSX.Element;
331
335
  Root: ({ children, defaultOpen, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react.JSX.Element;
332
336
  Title: {
333
- ({ ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogTitleProps & react.RefAttributes<HTMLHeadingElement>>>): react.JSX.Element;
337
+ ({ ref, ...props }: react.ComponentPropsWithRef<typeof _base_ui_react.DialogTitle>): react.JSX.Element;
334
338
  displayName: string;
335
339
  };
336
340
  Trigger: {
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { ChevronLeft, ChevronRight, X } from "lucide-react";
5
5
  import { useId as useId2, useLayoutEffect, useReducer, useRef as useRef2 } from "react";
6
6
 
7
7
  // src/aperto-content.tsx
8
- import * as Dialog from "@radix-ui/react-dialog";
8
+ import { Dialog } from "@base-ui/react/dialog";
9
9
  import { m, useMotionValue, useSpring, useTransform } from "motion/react";
10
10
  import { useState } from "react";
11
11
 
@@ -158,31 +158,44 @@ var ApertoContent = ({
158
158
  ...placementStyle,
159
159
  ...style
160
160
  };
161
- return /* @__PURE__ */ jsx(Dialog.Content, { asChild: true, forceMount: true, ...props, children: /* @__PURE__ */ jsx(
162
- m.div,
163
- {
164
- className,
165
- "data-slot": "aperto-content",
166
- drag: isDismissible,
167
- dragConstraints: { bottom: 0, left: 0, right: 0, top: 0 },
168
- dragElastic: 0,
169
- dragMomentum: false,
170
- dragSnapToOrigin: true,
171
- layout: contentLayoutId === void 0 || contentLayoutId === "" ? void 0 : true,
172
- layoutId: contentLayoutId,
173
- onDrag: isDismissible ? handleDrag : void 0,
174
- onDragEnd: isDismissible ? handleDragEnd : void 0,
175
- ref,
176
- style: motionStyle,
177
- transition: resolved.transition,
178
- children
179
- }
180
- ) });
161
+ return (
162
+ // `hidden={false}` neutralises Base UI's `hidden: !mounted` so the content
163
+ // stays visible while Motion plays the drag-dismiss / shared-layout exit on
164
+ // close (Motion animations are invisible to Base UI's `getAnimations()`
165
+ // unmount detection); `AnimatePresence` in the portal owns the real unmount.
166
+ /* @__PURE__ */ jsx(
167
+ Dialog.Popup,
168
+ {
169
+ className,
170
+ hidden: false,
171
+ ref,
172
+ render: /* @__PURE__ */ jsx(
173
+ m.div,
174
+ {
175
+ "data-slot": "aperto-content",
176
+ drag: isDismissible,
177
+ dragConstraints: { bottom: 0, left: 0, right: 0, top: 0 },
178
+ dragElastic: 0,
179
+ dragMomentum: false,
180
+ dragSnapToOrigin: true,
181
+ layout: contentLayoutId === void 0 || contentLayoutId === "" ? void 0 : true,
182
+ layoutId: contentLayoutId,
183
+ onDrag: isDismissible ? handleDrag : void 0,
184
+ onDragEnd: isDismissible ? handleDragEnd : void 0,
185
+ style: motionStyle,
186
+ transition: resolved.transition,
187
+ children
188
+ }
189
+ ),
190
+ ...props
191
+ }
192
+ )
193
+ );
181
194
  };
182
195
  ApertoContent.displayName = "ApertoContent";
183
196
 
184
197
  // src/aperto-description.tsx
185
- import * as Dialog2 from "@radix-ui/react-dialog";
198
+ import { Dialog as Dialog2 } from "@base-ui/react/dialog";
186
199
  import { jsx as jsx2 } from "react/jsx-runtime";
187
200
  var ApertoDescription = ({ ref, ...props }) => /* @__PURE__ */ jsx2(Dialog2.Description, { "data-slot": "aperto-description", ref, ...props });
188
201
  ApertoDescription.displayName = "ApertoDescription";
@@ -199,7 +212,7 @@ var useApertoGroup = () => {
199
212
  };
200
213
 
201
214
  // src/aperto-overlay.tsx
202
- import * as Dialog3 from "@radix-ui/react-dialog";
215
+ import { Dialog as Dialog3 } from "@base-ui/react/dialog";
203
216
  import { m as m2 } from "motion/react";
204
217
  import { easings as easings2 } from "@howells/motion";
205
218
  import { jsx as jsx3 } from "react/jsx-runtime";
@@ -214,33 +227,44 @@ var OVERLAY_TRANSITION_REDUCED = {
214
227
  var ApertoOverlay = ({ className, fadeOut, ref, style }) => {
215
228
  const ctx = useApertoContext();
216
229
  const transition = ctx.reduceMotion ? OVERLAY_TRANSITION_REDUCED : OVERLAY_TRANSITION;
217
- return /* @__PURE__ */ jsx3(Dialog3.Overlay, { asChild: true, forceMount: true, children: /* @__PURE__ */ jsx3(
218
- m2.div,
219
- {
220
- animate: { opacity: fadeOut === true ? 0 : 1 },
221
- className,
222
- "data-slot": "aperto-overlay",
223
- exit: { opacity: 0 },
224
- initial: { opacity: 0 },
225
- ref,
226
- style,
227
- transition
228
- }
229
- ) });
230
+ return (
231
+ // `hidden={false}` neutralises Base UI's `hidden: !mounted` so the backdrop
232
+ // stays visible while Motion fades it out on close (Motion animations are
233
+ // invisible to Base UI's `getAnimations()`-based unmount detection).
234
+ /* @__PURE__ */ jsx3(
235
+ Dialog3.Backdrop,
236
+ {
237
+ hidden: false,
238
+ render: /* @__PURE__ */ jsx3(
239
+ m2.div,
240
+ {
241
+ animate: { opacity: fadeOut === true ? 0 : 1 },
242
+ className,
243
+ "data-slot": "aperto-overlay",
244
+ exit: { opacity: 0 },
245
+ initial: { opacity: 0 },
246
+ ref,
247
+ style,
248
+ transition
249
+ }
250
+ )
251
+ }
252
+ )
253
+ );
230
254
  };
231
255
  ApertoOverlay.displayName = "ApertoOverlay";
232
256
 
233
257
  // src/aperto-portal.tsx
234
- import * as Dialog4 from "@radix-ui/react-dialog";
258
+ import { Dialog as Dialog4 } from "@base-ui/react/dialog";
235
259
  import { AnimatePresence } from "motion/react";
236
260
  import { jsx as jsx4 } from "react/jsx-runtime";
237
261
  var ApertoPortal = ({ children, container }) => {
238
262
  const { open } = useApertoContext();
239
- return /* @__PURE__ */ jsx4(AnimatePresence, { children: open && /* @__PURE__ */ jsx4(Dialog4.Portal, { container, forceMount: true, children }) });
263
+ return /* @__PURE__ */ jsx4(AnimatePresence, { children: open && /* @__PURE__ */ jsx4(Dialog4.Portal, { container, keepMounted: true, children }) });
240
264
  };
241
265
 
242
266
  // src/aperto-root.tsx
243
- import * as Dialog5 from "@radix-ui/react-dialog";
267
+ import { Dialog as Dialog5 } from "@base-ui/react/dialog";
244
268
  import { domMax, LayoutGroup, LazyMotion, useReducedMotion } from "motion/react";
245
269
  import { useId, useState as useState2 } from "react";
246
270
  import { jsx as jsx5 } from "react/jsx-runtime";
@@ -286,7 +310,7 @@ var ApertoRoot = ({
286
310
  };
287
311
 
288
312
  // src/aperto-title.tsx
289
- import * as Dialog6 from "@radix-ui/react-dialog";
313
+ import { Dialog as Dialog6 } from "@base-ui/react/dialog";
290
314
  import { jsx as jsx6 } from "react/jsx-runtime";
291
315
  var ApertoTitle = ({ ref, ...props }) => /* @__PURE__ */ jsx6(Dialog6.Title, { "data-slot": "aperto-title", ref, ...props });
292
316
  ApertoTitle.displayName = "ApertoTitle";
@@ -376,8 +400,16 @@ var ApertoTransitionMedia = ({
376
400
  alt: item.alt,
377
401
  height: item.height,
378
402
  item,
379
- src: item.src,
380
- variant: "expanded",
403
+ // The clone flies with the thumbnail's pixels — they are already decoded
404
+ // and on screen, so the shared element stays seamless in flight. Using
405
+ // the full-size `src` here makes the morph pop to a blank/half-loaded
406
+ // frame whenever the expanded asset differs from the thumbnail and has
407
+ // not finished loading yet. `variant: "thumbnail"` matters for the same
408
+ // reason: consumers key srcset/sizes off the variant, and only the
409
+ // thumbnail variant reproduces the exact URL the browser already has in
410
+ // cache.
411
+ src: item.thumbnailSrc ?? item.src,
412
+ variant: "thumbnail",
381
413
  width: item.width
382
414
  };
383
415
  return (renderImage ?? renderDefaultImage)(imageProps);
@@ -517,6 +549,13 @@ var rectFromElement = (element) => {
517
549
  width: rect.width
518
550
  };
519
551
  };
552
+ var rectFromTrigger = (trigger) => {
553
+ if (!trigger) {
554
+ return null;
555
+ }
556
+ const media = trigger.querySelector("[data-aperto-media-source], img, video");
557
+ return rectFromElement(media ?? trigger);
558
+ };
520
559
  var rectTarget = (rect) => ({
521
560
  height: rect.height,
522
561
  left: rect.left,
@@ -719,7 +758,7 @@ var ApertoGroupPortal = ({
719
758
  activeMedia,
720
759
  classNames,
721
760
  expandedMediaStyle,
722
- handleCloseAutoFocus,
761
+ finalFocus,
723
762
  handleContentKeyDown,
724
763
  handleMediaTransitionComplete,
725
764
  hasNavigation,
@@ -745,7 +784,7 @@ var ApertoGroupPortal = ({
745
784
  {
746
785
  className: classNames?.content,
747
786
  "data-aperto-transition": transition?.phase,
748
- onCloseAutoFocus: handleCloseAutoFocus,
787
+ finalFocus,
749
788
  onKeyDown: handleContentKeyDown,
750
789
  sharedLayoutId: false,
751
790
  ...getDescriptionProps(activeMedia),
@@ -841,7 +880,7 @@ var useApertoMediaLifecycle = ({
841
880
  }
842
881
  }, [dispatch, state.mediaTransition]);
843
882
  const openAtIndex = (thumbIndex) => {
844
- const sourceRect = rectFromElement(thumbnailMap.get(thumbIndex) ?? null);
883
+ const sourceRect = rectFromTrigger(thumbnailMap.get(thumbIndex) ?? null);
845
884
  const item = media[thumbIndex] ?? null;
846
885
  const transition = sourceRect === null || item === null ? null : { from: sourceRect, item, phase: "opening" };
847
886
  dispatch({ index: thumbIndex, transition, type: "open-at-index" });
@@ -852,7 +891,7 @@ var useApertoMediaLifecycle = ({
852
891
  return;
853
892
  }
854
893
  const sourceRect = rectFromElement(expandedMediaRef.current);
855
- const targetRect = rectFromElement(thumbnailMap.get(index) ?? null);
894
+ const targetRect = rectFromTrigger(thumbnailMap.get(index) ?? null);
856
895
  if (activeMedia === void 0 || sourceRect === null || targetRect === null) {
857
896
  dispatch({ type: "close-without-transition" });
858
897
  return;
@@ -862,13 +901,11 @@ var useApertoMediaLifecycle = ({
862
901
  type: "start-close"
863
902
  });
864
903
  };
865
- const handleCloseAutoFocus = (event) => {
866
- event.preventDefault();
904
+ const finalFocus = () => {
867
905
  const openerThumbnail = state.openerIndex === null ? void 0 : thumbnailMap.get(state.openerIndex);
868
- const target = openerThumbnail ?? thumbnailMap.get(index);
869
- target?.focus({ preventScroll: true });
906
+ return openerThumbnail ?? thumbnailMap.get(index) ?? null;
870
907
  };
871
- return { handleCloseAutoFocus, openAtIndex, registerThumbnail, setExpandedMediaNode, startClose };
908
+ return { finalFocus, openAtIndex, registerThumbnail, setExpandedMediaNode, startClose };
872
909
  };
873
910
  var useApertoGroupController = ({
874
911
  classNames,
@@ -951,9 +988,9 @@ var useApertoGroupController = ({
951
988
  return {
952
989
  activeMedia,
953
990
  expandedMediaStyle,
991
+ finalFocus: lifecycle.finalFocus,
954
992
  goToNext,
955
993
  goToPrevious,
956
- handleCloseAutoFocus: lifecycle.handleCloseAutoFocus,
957
994
  handleContentKeyDown,
958
995
  handleMediaTransitionComplete,
959
996
  handleOpenChange,
@@ -1002,9 +1039,9 @@ var ApertoGroup = ({
1002
1039
  activeMedia: controller.activeMedia,
1003
1040
  classNames,
1004
1041
  expandedMediaStyle: controller.expandedMediaStyle,
1042
+ finalFocus: controller.finalFocus,
1005
1043
  goToNext: controller.goToNext,
1006
1044
  goToPrevious: controller.goToPrevious,
1007
- handleCloseAutoFocus: controller.handleCloseAutoFocus,
1008
1045
  handleContentKeyDown: controller.hasNavigation ? controller.handleContentKeyDown : void 0,
1009
1046
  handleMediaTransitionComplete: controller.handleMediaTransitionComplete,
1010
1047
  hasNavigation: controller.hasNavigation,
@@ -1025,14 +1062,14 @@ var ApertoGroup = ({
1025
1062
  };
1026
1063
 
1027
1064
  // src/aperto-close.tsx
1028
- import * as Dialog7 from "@radix-ui/react-dialog";
1065
+ import { Dialog as Dialog7 } from "@base-ui/react/dialog";
1029
1066
  import { X as X2 } from "lucide-react";
1030
1067
  import { jsx as jsx11 } from "react/jsx-runtime";
1031
1068
  var ApertoClose = ({ children, ref, ...props }) => /* @__PURE__ */ jsx11(Dialog7.Close, { "data-slot": "aperto-close", ref, ...props, children: children ?? /* @__PURE__ */ jsx11(X2, { "aria-hidden": "true", size: 17, strokeWidth: 2 }) });
1032
1069
  ApertoClose.displayName = "ApertoClose";
1033
1070
 
1034
1071
  // src/aperto-trigger.tsx
1035
- import * as Dialog8 from "@radix-ui/react-dialog";
1072
+ import { Dialog as Dialog8 } from "@base-ui/react/dialog";
1036
1073
  import { m as m5 } from "motion/react";
1037
1074
  import { jsx as jsx12 } from "react/jsx-runtime";
1038
1075
  var TRIGGER_OPEN_Z_INDEX = 1e3;
@@ -1055,21 +1092,33 @@ var ApertoTrigger = ({
1055
1092
  ctx.reduceMotion
1056
1093
  );
1057
1094
  const layoutId = sharedLayoutId === false ? void 0 : sharedLayoutId ?? `${ctx.layoutId}-shared`;
1058
- return /* @__PURE__ */ jsx12(Dialog8.Trigger, { asChild: true, ref, ...props, children: /* @__PURE__ */ jsx12(
1059
- m5.button,
1060
- {
1061
- "data-aperto-active": shouldRaise ? "" : void 0,
1062
- "data-slot": "aperto-trigger",
1063
- layout: true,
1064
- layoutCrossfade: false,
1065
- layoutId,
1066
- style: { zIndex },
1067
- transition: resolved.transition,
1068
- type: "button",
1069
- children
1070
- },
1071
- layoutId ?? "unshared"
1072
- ) });
1095
+ return (
1096
+ // `key` sits on the Trigger (not the render element, which Base UI re-clones)
1097
+ // so a changing shared `layoutId` still remounts the Motion button and
1098
+ // resets its layout animation.
1099
+ /* @__PURE__ */ jsx12(
1100
+ Dialog8.Trigger,
1101
+ {
1102
+ ref,
1103
+ render: /* @__PURE__ */ jsx12(
1104
+ m5.button,
1105
+ {
1106
+ "data-aperto-active": shouldRaise ? "" : void 0,
1107
+ "data-slot": "aperto-trigger",
1108
+ layout: true,
1109
+ layoutCrossfade: false,
1110
+ layoutId,
1111
+ style: { zIndex },
1112
+ transition: resolved.transition,
1113
+ type: "button",
1114
+ children
1115
+ }
1116
+ ),
1117
+ ...props
1118
+ },
1119
+ layoutId ?? "unshared"
1120
+ )
1121
+ );
1073
1122
  };
1074
1123
  ApertoTrigger.displayName = "ApertoTrigger";
1075
1124
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/Aperto/aperto-group.tsx","../src/aperto-content.tsx","../src/context.ts","../src/physics.ts","../src/presets.ts","../src/aperto-description.tsx","../src/aperto-group-context.ts","../src/aperto-overlay.tsx","../src/aperto-portal.tsx","../src/aperto-root.tsx","../src/aperto-title.tsx","../src/expanded-media-stage.tsx","../src/media-rendering.tsx","../src/media-utils.ts","../src/media-transition.tsx","../src/media-transition-utils.ts","../src/Aperto/aperto-group-state.ts","../src/Aperto/aperto-keyboard.ts","../src/aperto-close.tsx","../src/aperto-trigger.tsx","../src/Aperto/aperto-single.tsx","../src/Aperto/aperto-thumbnail.tsx","../src/index.ts"],"sourcesContent":["\"use client\";\n\nimport { ChevronLeft, ChevronRight, X } from \"lucide-react\";\nimport { useId, useLayoutEffect, useReducer, useRef } from \"react\";\nimport type { CSSProperties, Dispatch, KeyboardEvent } from \"react\";\n\nimport { ApertoContent } from \"../aperto-content\";\nimport { ApertoDescription } from \"../aperto-description\";\nimport { ApertoGroupContext } from \"../aperto-group-context\";\nimport { ApertoOverlay } from \"../aperto-overlay\";\nimport { ApertoPortal } from \"../aperto-portal\";\nimport { ApertoRoot } from \"../aperto-root\";\nimport { ApertoTitle } from \"../aperto-title\";\nimport { ApertoExpandedMediaStage } from \"../expanded-media-stage\";\nimport type { NavigationDirection } from \"../expanded-media-stage\";\nimport { ApertoMediaTransitionClone } from \"../media-transition\";\nimport { rectFromElement } from \"../media-transition-utils\";\nimport type { ApertoMediaTransition } from \"../media-transition-utils\";\nimport { getDescriptionProps, getMediaLabel } from \"../media-utils\";\nimport type {\n ApertoClassNames,\n ApertoMediaItem,\n NavigationMotionPresetName,\n RenderImage,\n RenderVideo,\n} from \"../types\";\nimport { apertoGroupReducer, getInitialGroupState } from \"./aperto-group-state\";\nimport type { ApertoGroupAction, ApertoGroupState } from \"./aperto-group-state\";\nimport { shouldIgnoreKeyboardNavigationTarget } from \"./aperto-keyboard\";\nimport type { ApertoGroupProps } from \"./aperto-types\";\n\ntype ApertoExpandedMediaStyle = CSSProperties & {\n \"--aperto-expanded-aspect-ratio\"?: string;\n \"--aperto-expanded-aspect-ratio-height\"?: number;\n \"--aperto-expanded-aspect-ratio-width\"?: number;\n};\ntype ApertoGroupDispatch = Dispatch<ApertoGroupAction>;\n\nconst ApertoMediaNavigationButtons = ({\n classNames,\n enabled,\n onNext,\n onPrevious,\n}: {\n classNames: ApertoClassNames | undefined;\n enabled: boolean;\n onNext: () => void;\n onPrevious: () => void;\n}) => {\n if (!enabled) {\n return null;\n }\n\n return (\n <>\n <button\n aria-label=\"Previous media\"\n className={classNames?.previousButton}\n data-slot=\"aperto-previous-button\"\n onClick={onPrevious}\n type=\"button\"\n >\n <ChevronLeft aria-hidden=\"true\" size={18} strokeWidth={2} />\n </button>\n <button\n aria-label=\"Next media\"\n className={classNames?.nextButton}\n data-slot=\"aperto-next-button\"\n onClick={onNext}\n type=\"button\"\n >\n <ChevronRight aria-hidden=\"true\" size={18} strokeWidth={2} />\n </button>\n </>\n );\n};\n\nconst useThumbnailMap = () => {\n const thumbnailRefs = useRef<Map<number, HTMLButtonElement> | null>(null);\n thumbnailRefs.current ??= new Map();\n return thumbnailRefs.current;\n};\n\nconst getExpandedMediaStyle = (\n activeMedia: ApertoMediaItem | undefined,\n): ApertoExpandedMediaStyle | undefined => {\n if (\n activeMedia === undefined ||\n activeMedia.width === undefined ||\n activeMedia.height === undefined\n ) {\n return undefined;\n }\n\n return {\n \"--aperto-expanded-aspect-ratio\": `${activeMedia.width} / ${activeMedia.height}`,\n \"--aperto-expanded-aspect-ratio-height\": activeMedia.height,\n \"--aperto-expanded-aspect-ratio-width\": activeMedia.width,\n };\n};\n\nconst ApertoGroupPortal = ({\n activeMedia,\n classNames,\n expandedMediaStyle,\n handleCloseAutoFocus,\n handleContentKeyDown,\n handleMediaTransitionComplete,\n hasNavigation,\n index,\n mediaLength,\n navigationDirection,\n navigationMotion,\n renderImage,\n renderVideo,\n setExpandedMediaNode,\n startClose,\n transition,\n goToNext,\n goToPrevious,\n}: {\n activeMedia: ApertoMediaItem | undefined;\n classNames: ApertoClassNames | undefined;\n expandedMediaStyle: ApertoExpandedMediaStyle | undefined;\n goToNext: () => void;\n goToPrevious: () => void;\n handleCloseAutoFocus: (event: Event) => void;\n handleContentKeyDown: ((event: KeyboardEvent<HTMLDivElement>) => void) | undefined;\n handleMediaTransitionComplete: () => void;\n hasNavigation: boolean;\n index: number;\n mediaLength: number;\n navigationDirection: NavigationDirection;\n navigationMotion: NavigationMotionPresetName;\n renderImage: RenderImage | undefined;\n renderVideo: RenderVideo | undefined;\n setExpandedMediaNode: (node: HTMLDivElement | null) => void;\n startClose: () => void;\n transition: ApertoMediaTransition | null;\n}) => {\n if (activeMedia === undefined) {\n return null;\n }\n\n return (\n <ApertoPortal>\n <ApertoOverlay className={classNames?.overlay} fadeOut={transition?.phase === \"closing\"} />\n <ApertoContent\n className={classNames?.content}\n data-aperto-transition={transition?.phase}\n onCloseAutoFocus={handleCloseAutoFocus}\n onKeyDown={handleContentKeyDown}\n sharedLayoutId={false}\n {...getDescriptionProps(activeMedia)}\n >\n <div data-slot=\"aperto-media\" ref={setExpandedMediaNode} style={expandedMediaStyle}>\n <ApertoExpandedMediaStage\n direction={navigationDirection}\n index={index}\n item={activeMedia}\n navigationMotion={navigationMotion}\n renderImage={renderImage}\n renderVideo={renderVideo}\n />\n <ApertoMediaNavigationButtons\n classNames={classNames}\n enabled={hasNavigation}\n onNext={goToNext}\n onPrevious={goToPrevious}\n />\n </div>\n <ApertoTitle>{activeMedia.title ?? getMediaLabel(activeMedia)}</ApertoTitle>\n {activeMedia.description === undefined || activeMedia.description === \"\" ? null : (\n <ApertoDescription>{activeMedia.description}</ApertoDescription>\n )}\n {hasNavigation ? (\n <div className={classNames?.counter} data-slot=\"aperto-counter\">\n {index + 1} / {mediaLength}\n </div>\n ) : null}\n <button\n aria-label=\"Close\"\n className={classNames?.closeButton}\n data-slot=\"aperto-close\"\n onClick={startClose}\n type=\"button\"\n >\n <X aria-hidden=\"true\" size={17} strokeWidth={2} />\n </button>\n </ApertoContent>\n <ApertoMediaTransitionClone\n onComplete={handleMediaTransitionComplete}\n renderImage={renderImage}\n renderVideo={renderVideo}\n transition={transition}\n />\n </ApertoPortal>\n );\n};\n\nconst useApertoMediaLifecycle = ({\n activeMedia,\n dispatch,\n index,\n media,\n onIndexChange,\n state,\n}: {\n activeMedia: ApertoMediaItem | undefined;\n dispatch: ApertoGroupDispatch;\n index: number;\n media: ApertoMediaItem[];\n onIndexChange: ApertoGroupProps[\"onIndexChange\"];\n state: ApertoGroupState;\n}) => {\n const expandedMediaRef = useRef<HTMLDivElement | null>(null);\n const thumbnailMap = useThumbnailMap();\n\n const setExpandedMediaNode = (node: HTMLDivElement | null) => {\n expandedMediaRef.current = node;\n if (node === null) {\n return;\n }\n const targetRect = rectFromElement(node);\n if (targetRect !== null) {\n dispatch({ rect: targetRect, type: \"complete-opening-target\" });\n }\n };\n\n const registerThumbnail = (thumbIndex: number, node: HTMLButtonElement | null) => {\n if (node !== null) {\n thumbnailMap.set(thumbIndex, node);\n return;\n }\n thumbnailMap.delete(thumbIndex);\n };\n\n useLayoutEffect(() => {\n if (\n state.mediaTransition?.phase !== \"opening\" ||\n state.mediaTransition.to !== undefined ||\n expandedMediaRef.current === null\n ) {\n return;\n }\n\n const targetRect = rectFromElement(expandedMediaRef.current);\n if (targetRect !== null) {\n dispatch({ rect: targetRect, type: \"complete-opening-target\" });\n }\n }, [dispatch, state.mediaTransition]);\n\n const openAtIndex = (thumbIndex: number) => {\n const sourceRect = rectFromElement(thumbnailMap.get(thumbIndex) ?? null);\n const item = media[thumbIndex] ?? null;\n const transition =\n sourceRect === null || item === null\n ? null\n : { from: sourceRect, item, phase: \"opening\" as const };\n\n dispatch({ index: thumbIndex, transition, type: \"open-at-index\" });\n onIndexChange?.(thumbIndex);\n };\n\n const startClose = () => {\n if (!state.open || state.closing) {\n return;\n }\n\n const sourceRect = rectFromElement(expandedMediaRef.current);\n const targetRect = rectFromElement(thumbnailMap.get(index) ?? null);\n if (activeMedia === undefined || sourceRect === null || targetRect === null) {\n dispatch({ type: \"close-without-transition\" });\n return;\n }\n\n dispatch({\n transition: { from: sourceRect, item: activeMedia, phase: \"closing\", to: targetRect },\n type: \"start-close\",\n });\n };\n\n const handleCloseAutoFocus = (event: Event) => {\n event.preventDefault();\n // Focus Return: restore focus to the Thumbnail that opened the Media\n // Transition, falling back to the active thumbnail if it unmounted.\n const openerThumbnail =\n state.openerIndex === null ? undefined : thumbnailMap.get(state.openerIndex);\n const target = openerThumbnail ?? thumbnailMap.get(index);\n target?.focus({ preventScroll: true });\n };\n\n return { handleCloseAutoFocus, openAtIndex, registerThumbnail, setExpandedMediaNode, startClose };\n};\n\nconst useApertoGroupController = ({\n classNames,\n index: controlledIndex,\n initialIndex = 0,\n media,\n onIndexChange,\n renderImage,\n renderVideo,\n}: Omit<ApertoGroupProps, \"children\" | \"dismissible\" | \"motion\" | \"navigationMotion\">) => {\n const generatedId = useId();\n const [state, dispatch] = useReducer(apertoGroupReducer, initialIndex, getInitialGroupState);\n const isControlled = controlledIndex !== undefined;\n const index = isControlled ? controlledIndex : state.internalIndex;\n const activeMedia = media[index] ?? media[0];\n const lifecycle = useApertoMediaLifecycle({\n activeMedia,\n dispatch,\n index,\n media,\n onIndexChange,\n state,\n });\n const sharedLayoutIdForIndex = (nextIndex: number) =>\n `aperto-group-${generatedId}-${nextIndex}-shared`;\n const sharedLayoutId = sharedLayoutIdForIndex(state.layoutSourceIndex);\n\n const setIndex = (nextIndex: number) => {\n if (!isControlled) {\n dispatch({ index: nextIndex, type: \"set-index\" });\n }\n onIndexChange?.(nextIndex);\n };\n\n const handleMediaTransitionComplete = () => {\n dispatch({ type: \"finish-transition\" });\n };\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (nextOpen) {\n dispatch({ open: true, type: \"set-open\" });\n return;\n }\n\n lifecycle.startClose();\n };\n\n const value = {\n classNames,\n index,\n media,\n open: state.open,\n openAtIndex: lifecycle.openAtIndex,\n registerThumbnail: lifecycle.registerThumbnail,\n renderImage,\n renderVideo,\n setIndex,\n sharedLayoutId,\n sharedLayoutIdForIndex,\n };\n const hasNavigation = media.length > 1;\n const navigateToIndex = (nextIndex: number, direction: NavigationDirection) => {\n dispatch({ direction, index: nextIndex, type: \"navigate\" });\n onIndexChange?.(nextIndex);\n };\n const goToPrevious = () => {\n navigateToIndex((index - 1 + media.length) % media.length, -1);\n };\n const goToNext = () => {\n navigateToIndex((index + 1) % media.length, 1);\n };\n const handleContentKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (\n event.defaultPrevented ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n shouldIgnoreKeyboardNavigationTarget(event.target)\n ) {\n return;\n }\n\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n goToPrevious();\n }\n\n if (event.key === \"ArrowRight\") {\n event.preventDefault();\n goToNext();\n }\n };\n const expandedMediaStyle = getExpandedMediaStyle(activeMedia);\n\n return {\n activeMedia,\n expandedMediaStyle,\n goToNext,\n goToPrevious,\n handleCloseAutoFocus: lifecycle.handleCloseAutoFocus,\n handleContentKeyDown,\n handleMediaTransitionComplete,\n handleOpenChange,\n hasNavigation,\n index,\n setExpandedMediaNode: lifecycle.setExpandedMediaNode,\n startClose: lifecycle.startClose,\n state,\n value,\n };\n};\n\nexport const ApertoGroup = ({\n children,\n classNames,\n dismissible,\n index,\n initialIndex,\n media,\n motion: motionProp,\n navigationMotion = \"glide\",\n onIndexChange,\n renderImage,\n renderVideo,\n}: ApertoGroupProps) => {\n const controller = useApertoGroupController({\n classNames,\n index,\n initialIndex,\n media,\n onIndexChange,\n renderImage,\n renderVideo,\n });\n\n return (\n <ApertoGroupContext.Provider value={controller.value}>\n <ApertoRoot\n dismissible={dismissible}\n motion={motionProp}\n onOpenChange={controller.handleOpenChange}\n open={controller.state.open}\n >\n {children}\n <ApertoGroupPortal\n activeMedia={controller.activeMedia}\n classNames={classNames}\n expandedMediaStyle={controller.expandedMediaStyle}\n goToNext={controller.goToNext}\n goToPrevious={controller.goToPrevious}\n handleCloseAutoFocus={controller.handleCloseAutoFocus}\n handleContentKeyDown={\n controller.hasNavigation ? controller.handleContentKeyDown : undefined\n }\n handleMediaTransitionComplete={controller.handleMediaTransitionComplete}\n hasNavigation={controller.hasNavigation}\n index={controller.index}\n mediaLength={media.length}\n navigationDirection={controller.state.navigationDirection}\n navigationMotion={navigationMotion}\n renderImage={renderImage}\n renderVideo={renderVideo}\n setExpandedMediaNode={controller.setExpandedMediaNode}\n startClose={controller.startClose}\n transition={controller.state.mediaTransition}\n />\n </ApertoRoot>\n </ApertoGroupContext.Provider>\n );\n};\n","\"use client\";\n\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { m, useMotionValue, useSpring, useTransform } from \"motion/react\";\nimport type { MotionStyle, PanInfo } from \"motion/react\";\nimport { useState } from \"react\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nimport { useApertoContext } from \"./context\";\nimport {\n calculateResistance,\n DEFAULT_DISTANCE_THRESHOLD,\n DEFAULT_VELOCITY_THRESHOLD,\n OPACITY_INPUT,\n OPACITY_OUTPUT,\n SCALE_INPUT,\n SCALE_OUTPUT,\n} from \"./physics\";\nimport { getDragSpring, resolvePreset } from \"./presets\";\nimport type { DismissibleConfig, MotionPresetName } from \"./types\";\n\nexport interface ApertoContentProps extends Omit<\n ComponentPropsWithRef<typeof Dialog.Content>,\n \"asChild\" | \"forceMount\"\n> {\n /** Motion preset override for this content panel, independent of the root preset. */\n motion?: MotionPresetName;\n /** Built-in positioning strategy. Use \"none\" for custom primitive compositions. */\n placement?: \"center\" | \"none\";\n /** Internal shared layout ID override for grouped media. */\n sharedLayoutId?: string | false;\n}\n\nconst ApertoContent = ({\n children,\n className,\n motion: motionOverride,\n placement = \"center\",\n ref,\n sharedLayoutId,\n style,\n ...props\n}: ApertoContentProps) => {\n const ctx = useApertoContext();\n const [isDragging, setIsDragging] = useState(false);\n const resolved = resolvePreset(\n \"content\",\n motionOverride,\n ctx.presetName,\n ctx.variants,\n ctx.reduceMotion,\n );\n\n const contentLayoutId =\n sharedLayoutId === false ? undefined : (sharedLayoutId ?? `${ctx.layoutId}-shared`);\n\n const dragSpring = getDragSpring(resolved);\n const isDismissible = ctx.dismissible !== false;\n\n const dismissConfig: DismissibleConfig =\n typeof ctx.dismissible === \"object\" ? ctx.dismissible : {};\n const distanceThreshold = dismissConfig.threshold ?? DEFAULT_DISTANCE_THRESHOLD;\n const velocityThreshold = dismissConfig.velocity ?? DEFAULT_VELOCITY_THRESHOLD;\n\n const dragX = useMotionValue(0);\n const dragY = useMotionValue(0);\n const springX = useSpring(dragX, dragSpring);\n const springY = useSpring(dragY, dragSpring);\n\n const distance = useTransform(() => Math.hypot(springX.get(), springY.get()));\n const scaleMotion = useTransform(distance, SCALE_INPUT, SCALE_OUTPUT);\n const opacityMotion = useTransform(distance, OPACITY_INPUT, OPACITY_OUTPUT);\n const resistance = useTransform(distance, calculateResistance);\n const { onOpenChange } = ctx;\n\n const handleDrag = (_event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {\n if (!isDragging) {\n setIsDragging(true);\n }\n const r = resistance.get();\n dragX.set(info.offset.x * r);\n dragY.set(info.offset.y * r);\n };\n\n const handleDragEnd = (_event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {\n setIsDragging(false);\n const speed = Math.hypot(info.velocity.x, info.velocity.y);\n const dist = Math.hypot(info.offset.x, info.offset.y);\n\n if (speed > velocityThreshold || dist > distanceThreshold) {\n onOpenChange(false);\n return;\n }\n\n dragX.set(0);\n dragY.set(0);\n };\n\n const placementStyle =\n placement === \"center\"\n ? {\n left: \"50%\",\n top: \"50%\",\n translate: \"-50% -50%\",\n }\n : {};\n let cursor: MotionStyle[\"cursor\"];\n\n if (isDragging) {\n cursor = \"grabbing\";\n } else if (isDismissible) {\n cursor = \"grab\";\n }\n\n const motionStyle: MotionStyle = {\n cursor,\n opacity: opacityMotion,\n scale: scaleMotion,\n x: springX,\n y: springY,\n ...placementStyle,\n ...style,\n };\n\n return (\n <Dialog.Content asChild forceMount {...props}>\n <m.div\n className={className}\n data-slot=\"aperto-content\"\n drag={isDismissible}\n dragConstraints={{ bottom: 0, left: 0, right: 0, top: 0 }}\n dragElastic={0}\n dragMomentum={false}\n dragSnapToOrigin\n layout={contentLayoutId === undefined || contentLayoutId === \"\" ? undefined : true}\n layoutId={contentLayoutId}\n onDrag={isDismissible ? handleDrag : undefined}\n onDragEnd={isDismissible ? handleDragEnd : undefined}\n ref={ref}\n style={motionStyle}\n transition={resolved.transition}\n >\n {children}\n </m.div>\n </Dialog.Content>\n );\n};\n\nApertoContent.displayName = \"ApertoContent\";\n\nexport { ApertoContent };\n","\"use client\";\n\nimport { createContext, use } from \"react\";\n\nimport type { ApertoContextValue } from \"./types\";\n\nexport const ApertoContext = createContext<ApertoContextValue | null>(null);\n\nexport const useApertoContext = (): ApertoContextValue => {\n const ctx = use(ApertoContext);\n if (!ctx) {\n throw new Error(\"Aperto components must be used within <Aperto.Root>\");\n }\n return ctx;\n};\n","/**\n * Drag physics utilities.\n *\n * The logarithmic resistance function creates a rubber-band feel:\n * initial movement is free, but gets progressively harder the further\n * you drag. Combined with spring-smoothed motion values, this produces\n * a natural, elastic gesture.\n */\n\nconst RESISTANCE_DIVISOR = 20;\nconst RESISTANCE_SCALE = 4;\nconst RESISTANCE_MIN = 0.1;\n\n/**\n * Logarithmic resistance — decelerates drag progressively.\n * Returns a multiplier between RESISTANCE_MIN and 1.0.\n *\n * At distance 0: returns 1.0 (full movement)\n * At distance 50: returns ~0.77\n * At distance 100: returns ~0.58\n * At distance 200: returns ~0.42\n */\nexport const calculateResistance = (distance: number): number =>\n Math.max(RESISTANCE_MIN, 1 - Math.log(distance / RESISTANCE_DIVISOR + 1) / RESISTANCE_SCALE);\n\n/** Scale mapping: distance → visual scale (1.0 → 0.95) */\nexport const SCALE_INPUT = [0, 50, 100];\nexport const SCALE_OUTPUT = [1, 0.98, 0.95];\n\n/** Opacity mapping: distance → visual opacity (1.0 → 0.96) */\nexport const OPACITY_INPUT = [0, 80];\nexport const OPACITY_OUTPUT = [1, 0.96];\n\n/** Default dismissal thresholds */\nexport const DEFAULT_DISTANCE_THRESHOLD = 100;\nexport const DEFAULT_VELOCITY_THRESHOLD = 500;\n","import { durations, easings, springs } from \"@howells/motion\";\nimport type { DragSpringConfig, MotionPreset, MotionPresetName, MotionVariants } from \"./types\";\n\n/**\n * Motion presets — each bundles transition timing AND drag physics\n * so \"snappy\" feels snappy everywhere: open, close, and drag.\n *\n * Curves and springs come from the shared @howells/motion tokens so motion\n * feel stays consistent across the catalog.\n */\nexport const PRESETS: Record<MotionPresetName, MotionPreset> = {\n bouncy: {\n drag: {\n damping: springs.snappy.damping,\n restDelta: 0.01,\n stiffness: springs.snappy.stiffness,\n },\n transition: {\n damping: springs.bouncy.damping,\n mass: springs.bouncy.mass,\n stiffness: springs.bouncy.stiffness,\n type: \"spring\",\n },\n },\n reduced: {\n drag: { damping: 50, restDelta: 0.1, stiffness: 1000 },\n transition: { duration: 0.01, ease: \"linear\" },\n },\n smooth: {\n drag: {\n damping: springs.natural.damping,\n restDelta: 0.01,\n stiffness: springs.natural.stiffness,\n },\n transition: { duration: durations.moderate, ease: easings.customGentle },\n },\n snappy: {\n drag: {\n damping: springs.stiff.damping,\n restDelta: 0.01,\n stiffness: springs.stiff.stiffness,\n },\n transition: { duration: durations.snappy, ease: easings.snappy },\n },\n};\n\ntype ComponentType = \"trigger\" | \"content\" | \"backdrop\";\n\n/**\n * Three-level motion resolution:\n * 1. Component-level override (highest)\n * 2. Per-component variant from Root\n * 3. Global preset from Root (lowest)\n *\n * If `prefers-reduced-motion` is active, always returns \"reduced\".\n */\nexport const resolvePreset = (\n componentType: ComponentType,\n componentMotion: MotionPresetName | undefined,\n globalPreset: MotionPresetName,\n variants: MotionVariants | undefined,\n reduceMotion: boolean,\n): MotionPreset => {\n if (reduceMotion) {\n return PRESETS.reduced;\n }\n\n // 1. Component-level override\n if (componentMotion) {\n return PRESETS[componentMotion];\n }\n\n // 2. Per-component variant\n if (variants?.[componentType]) {\n return PRESETS[variants[componentType]];\n }\n\n // 3. Global preset\n return PRESETS[globalPreset];\n};\n\n/** Extract the drag spring config from a preset */\nexport const getDragSpring = (preset: MotionPreset): DragSpringConfig => preset.drag;\n","\"use client\";\n\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst ApertoDescription = ({ ref, ...props }: ComponentPropsWithRef<typeof Dialog.Description>) => (\n <Dialog.Description data-slot=\"aperto-description\" ref={ref} {...props} />\n);\n\nApertoDescription.displayName = \"ApertoDescription\";\n\nexport { ApertoDescription };\n","import { createContext, use } from \"react\";\n\nimport type { ApertoClassNames, ApertoMediaItem, RenderImage, RenderVideo } from \"./types\";\n\nexport interface ApertoGroupContextValue {\n classNames?: ApertoClassNames;\n index: number;\n media: ApertoMediaItem[];\n open: boolean;\n openAtIndex: (index: number) => void;\n registerThumbnail: (index: number, node: HTMLButtonElement | null) => void;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n setIndex: (index: number) => void;\n sharedLayoutId: string;\n sharedLayoutIdForIndex: (index: number) => string;\n}\n\nexport const ApertoGroupContext = createContext<ApertoGroupContextValue | null>(null);\n\nexport const useApertoGroup = (): ApertoGroupContextValue => {\n const ctx = use(ApertoGroupContext);\n if (!ctx) {\n throw new Error(\"Aperto.Thumbnail must be used within <Aperto.Group>\");\n }\n return ctx;\n};\n","\"use client\";\n\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { m } from \"motion/react\";\nimport type { Transition } from \"motion/react\";\nimport type { CSSProperties, Ref } from \"react\";\n\nimport { useApertoContext } from \"./context\";\nimport { easings } from \"@howells/motion\";\n\nexport interface ApertoOverlayProps {\n className?: string;\n /** Internal flag used to fade the overlay during measured close transitions. */\n fadeOut?: boolean;\n ref?: Ref<HTMLDivElement>;\n style?: CSSProperties;\n}\n\n/** Overlay always fades gently regardless of the content's motion preset. */\nconst OVERLAY_TRANSITION: Transition = {\n duration: 0.3,\n ease: easings.customGentle,\n};\n\nconst OVERLAY_TRANSITION_REDUCED: Transition = {\n duration: 0.01,\n ease: \"linear\",\n};\n\nconst ApertoOverlay = ({ className, fadeOut, ref, style }: ApertoOverlayProps) => {\n const ctx = useApertoContext();\n const transition = ctx.reduceMotion ? OVERLAY_TRANSITION_REDUCED : OVERLAY_TRANSITION;\n\n return (\n <Dialog.Overlay asChild forceMount>\n <m.div\n animate={{ opacity: fadeOut === true ? 0 : 1 }}\n className={className}\n data-slot=\"aperto-overlay\"\n exit={{ opacity: 0 }}\n initial={{ opacity: 0 }}\n ref={ref}\n style={style}\n transition={transition}\n />\n </Dialog.Overlay>\n );\n};\n\nApertoOverlay.displayName = \"ApertoOverlay\";\n\nexport { ApertoOverlay };\n","\"use client\";\n\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { AnimatePresence } from \"motion/react\";\nimport type { ReactNode } from \"react\";\n\nimport { useApertoContext } from \"./context\";\n\nexport interface ApertoPortalProps {\n children: ReactNode;\n /** Container element for the portal (default: document.body) */\n container?: HTMLElement;\n}\n\nconst ApertoPortal = ({ children, container }: ApertoPortalProps) => {\n const { open } = useApertoContext();\n\n return (\n <AnimatePresence>\n {open && (\n <Dialog.Portal container={container} forceMount>\n {children}\n </Dialog.Portal>\n )}\n </AnimatePresence>\n );\n};\n\nexport { ApertoPortal };\n","\"use client\";\n\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { domMax, LayoutGroup, LazyMotion, useReducedMotion } from \"motion/react\";\nimport { useId, useState } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\n\nimport { ApertoContext } from \"./context\";\nimport { PRESETS } from \"./presets\";\nimport type { DismissibleConfig, MotionPresetName, MotionVariants } from \"./types\";\n\nexport interface ApertoRootProps extends Omit<\n ComponentPropsWithoutRef<typeof Dialog.Root>,\n \"open\" | \"onOpenChange\"\n> {\n children: ReactNode;\n /** Whether dragging can dismiss the content (default: true) */\n dismissible?: boolean | DismissibleConfig;\n /** Layout ID for shared element transition (auto-generated if omitted) */\n layoutId?: string;\n /** Motion preset or per-component variants */\n motion?: MotionPresetName | MotionVariants;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Force reduced motion regardless of system preference */\n reduceMotion?: boolean;\n}\n\nconst ApertoRoot = ({\n children,\n defaultOpen,\n dismissible = true,\n layoutId: layoutIdProp,\n motion: motionProp = \"smooth\",\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n reduceMotion: reduceMotionProp,\n ...dialogProps\n}: ApertoRootProps) => {\n const generatedId = useId();\n const layoutId = layoutIdProp ?? `aperto-${generatedId}`;\n const systemReducedMotion = useReducedMotion() ?? false;\n const shouldReduce = reduceMotionProp ?? systemReducedMotion;\n\n // Uncontrolled state fallback\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n\n const onOpenChange = (nextOpen: boolean) => {\n if (!isControlled) {\n setInternalOpen(nextOpen);\n }\n controlledOnOpenChange?.(nextOpen);\n };\n\n // Resolve global preset name\n const globalPresetName: MotionPresetName = typeof motionProp === \"string\" ? motionProp : \"smooth\";\n const variants: MotionVariants | undefined =\n typeof motionProp === \"object\" ? motionProp : undefined;\n\n const presetName: MotionPresetName = shouldReduce ? \"reduced\" : globalPresetName;\n const preset = PRESETS[presetName];\n const contextValue = {\n dismissible,\n layoutId,\n onOpenChange,\n open,\n preset,\n presetName,\n reduceMotion: shouldReduce,\n variants,\n };\n\n return (\n <ApertoContext.Provider value={contextValue}>\n <Dialog.Root onOpenChange={onOpenChange} open={open} {...dialogProps}>\n <LazyMotion features={domMax}>\n <LayoutGroup id={layoutId}>{children}</LayoutGroup>\n </LazyMotion>\n </Dialog.Root>\n </ApertoContext.Provider>\n );\n};\n\nexport { ApertoRoot };\n","\"use client\";\n\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst ApertoTitle = ({ ref, ...props }: ComponentPropsWithRef<typeof Dialog.Title>) => (\n <Dialog.Title data-slot=\"aperto-title\" ref={ref} {...props} />\n);\n\nApertoTitle.displayName = \"ApertoTitle\";\n\nexport { ApertoTitle };\n","import { AnimatePresence, m } from \"motion/react\";\nimport type { TargetAndTransition, Transition } from \"motion/react\";\n\nimport { useApertoContext } from \"./context\";\nimport { ApertoExpandedMedia } from \"./media-rendering\";\nimport { getMediaKey } from \"./media-utils\";\nimport type {\n ApertoMediaItem,\n NavigationMotionPresetName,\n RenderImage,\n RenderVideo,\n} from \"./types\";\n\nexport type NavigationDirection = -1 | 0 | 1;\n\ninterface NavigationMotionPreset {\n offset: number;\n scale: number;\n transition: Transition;\n}\n\ninterface NavigationAnimationCustom {\n direction: NavigationDirection;\n offset: number;\n scale: number;\n}\n\nconst NAVIGATION_MOTION_PRESETS: Record<NavigationMotionPresetName, NavigationMotionPreset> = {\n float: {\n offset: 96,\n scale: 0.97,\n transition: {\n opacity: { duration: 0.34, ease: [0.45, 0, 0.2, 1] },\n scale: { damping: 26, mass: 1.15, stiffness: 80, type: \"spring\" },\n x: { damping: 26, mass: 1.15, stiffness: 80, type: \"spring\" },\n },\n },\n glide: {\n offset: 58,\n scale: 0.984,\n transition: {\n opacity: { duration: 0.24, ease: [0.4, 0, 0.2, 1] },\n scale: { damping: 28, mass: 0.95, stiffness: 150, type: \"spring\" },\n x: { damping: 28, mass: 0.95, stiffness: 150, type: \"spring\" },\n },\n },\n snap: {\n offset: 38,\n scale: 0.996,\n transition: {\n opacity: { duration: 0.12, ease: [0.2, 0, 0, 1] },\n scale: { damping: 34, mass: 0.7, stiffness: 420, type: \"spring\" },\n x: { damping: 34, mass: 0.7, stiffness: 420, type: \"spring\" },\n },\n },\n};\n\nconst REDUCED_EXPANDED_MEDIA_TRANSITION: Transition = {\n duration: 0.12,\n ease: \"linear\",\n};\n\nconst expandedMediaVariants = {\n center: {\n opacity: 1,\n scale: 1,\n x: 0,\n },\n enter: ({ direction, offset, scale }: NavigationAnimationCustom): TargetAndTransition => ({\n opacity: 0,\n scale: direction === 0 ? 1 : scale,\n x: direction * offset,\n }),\n exit: ({ direction, offset, scale }: NavigationAnimationCustom): TargetAndTransition => ({\n opacity: 0,\n scale: direction === 0 ? 1 : scale,\n x: direction * -offset,\n }),\n};\n\nconst reducedExpandedMediaVariants = {\n center: {\n opacity: 1,\n x: 0,\n },\n enter: {\n opacity: 0,\n x: 0,\n },\n exit: {\n opacity: 0,\n x: 0,\n },\n};\n\nexport const ApertoExpandedMediaStage = ({\n direction,\n index,\n item,\n navigationMotion,\n renderImage,\n renderVideo,\n}: {\n direction: NavigationDirection;\n index: number;\n item: ApertoMediaItem;\n navigationMotion: NavigationMotionPresetName;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n}) => {\n const ctx = useApertoContext();\n const preset = NAVIGATION_MOTION_PRESETS[navigationMotion];\n const transition = ctx.reduceMotion ? REDUCED_EXPANDED_MEDIA_TRANSITION : preset.transition;\n const variants = ctx.reduceMotion ? reducedExpandedMediaVariants : expandedMediaVariants;\n const animationCustom: NavigationAnimationCustom = {\n direction,\n offset: preset.offset,\n scale: preset.scale,\n };\n\n return (\n <AnimatePresence custom={animationCustom} initial={false} mode=\"sync\">\n <m.div\n animate=\"center\"\n custom={animationCustom}\n data-navigation-direction={direction}\n data-navigation-motion={navigationMotion}\n data-slot=\"aperto-media-stage\"\n exit=\"exit\"\n initial=\"enter\"\n key={getMediaKey(item, index)}\n transition={transition}\n variants={variants}\n >\n <ApertoExpandedMedia item={item} renderImage={renderImage} renderVideo={renderVideo} />\n </m.div>\n </AnimatePresence>\n );\n};\n","import { createElement } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport type { ApertoMediaItem, RenderImage, RenderVideo } from \"./types\";\n\nconst renderDefaultImage = (props: Parameters<RenderImage>[0]): ReactNode => {\n const { item: _item, variant: _variant, ...imageProps } = props;\n return createElement(\"img\", { ...imageProps, alt: imageProps.alt ?? \"\" });\n};\n\nconst renderDefaultVideo = (props: Parameters<RenderVideo>[0]): ReactNode => {\n const { item: _item, variant, ...videoProps } = props;\n if (variant === \"thumbnail\") {\n return createElement(\"img\", {\n alt: videoProps[\"aria-label\"] ?? \"\",\n src: props.item.thumbnailSrc,\n });\n }\n return (\n <video {...videoProps}>\n <track kind=\"captions\" src={props.item.captionsSrc ?? \"data:text/vtt,\"} />\n </video>\n );\n};\n\nexport const ApertoThumbnailMedia = ({\n item,\n renderImage,\n renderVideo,\n}: {\n item: ApertoMediaItem;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n}): ReactNode => {\n if (item.type === \"image\") {\n const imageProps: Parameters<RenderImage>[0] = {\n alt: \"\",\n height: item.height,\n item,\n src: item.thumbnailSrc ?? item.src,\n variant: \"thumbnail\",\n width: item.width,\n };\n return (renderImage ?? renderDefaultImage)(imageProps);\n }\n\n const videoProps: Parameters<RenderVideo>[0] = {\n \"aria-label\": item.alt ?? item.title ?? \"Video thumbnail\",\n height: item.height,\n item,\n poster: item.poster,\n src: item.thumbnailSrc,\n variant: \"thumbnail\",\n width: item.width,\n };\n return (renderVideo ?? renderDefaultVideo)(videoProps);\n};\n\nexport const ApertoExpandedMedia = ({\n item,\n renderImage,\n renderVideo,\n}: {\n item: ApertoMediaItem;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n}): ReactNode => {\n if (item.type === \"image\") {\n const imageProps: Parameters<RenderImage>[0] = {\n alt: item.alt,\n height: item.height,\n item,\n src: item.src,\n variant: \"expanded\",\n width: item.width,\n };\n return (renderImage ?? renderDefaultImage)(imageProps);\n }\n\n const videoProps: Parameters<RenderVideo>[0] = {\n \"aria-label\": item.alt ?? item.title ?? \"Video\",\n controls: true,\n height: item.height,\n item,\n poster: item.poster,\n src: item.src,\n variant: \"expanded\",\n width: item.width,\n };\n return (renderVideo ?? renderDefaultVideo)(videoProps);\n};\n\nexport const ApertoTransitionMedia = ({\n item,\n renderImage,\n renderVideo,\n}: {\n item: ApertoMediaItem;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n}): ReactNode => {\n if (item.type === \"image\") {\n const imageProps: Parameters<RenderImage>[0] = {\n alt: item.alt,\n height: item.height,\n item,\n src: item.src,\n variant: \"expanded\",\n width: item.width,\n };\n return (renderImage ?? renderDefaultImage)(imageProps);\n }\n\n const videoProps: Parameters<RenderVideo>[0] = {\n \"aria-label\": item.alt ?? item.title ?? \"Video\",\n height: item.height,\n item,\n poster: item.poster,\n src: item.src,\n variant: \"expanded\",\n width: item.width,\n };\n return (renderVideo ?? renderDefaultVideo)(videoProps);\n};\n","import type { ApertoMediaItem } from \"./types\";\n\nexport const getMediaLabel = (item: ApertoMediaItem): string => item.title ?? item.alt ?? \"media\";\n\nexport const getMediaKey = (item: ApertoMediaItem, index: number): string =>\n item.id ?? `${item.type}:${item.src}:${index}`;\n\nexport const getDescriptionProps = (\n item: ApertoMediaItem,\n): {\n \"aria-describedby\"?: undefined;\n} =>\n item.description === undefined || item.description === \"\"\n ? { \"aria-describedby\": undefined }\n : {};\n","import { m } from \"motion/react\";\nimport { useEffect, useRef } from \"react\";\n\nimport { useApertoContext } from \"./context\";\nimport { ApertoTransitionMedia } from \"./media-rendering\";\nimport { rectTarget, transitionDurationMs } from \"./media-transition-utils\";\nimport type { ApertoMediaTransition } from \"./media-transition-utils\";\nimport type { RenderImage, RenderVideo } from \"./types\";\n\nexport const ApertoMediaTransitionClone = ({\n onComplete,\n renderImage,\n renderVideo,\n transition,\n}: {\n onComplete: () => void;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n transition: ApertoMediaTransition | null;\n}) => {\n const ctx = useApertoContext();\n // Hold the latest onComplete in a ref so parent re-renders (which recreate the\n // callback) do not restart the completion countdown mid-transition.\n const onCompleteRef = useRef(onComplete);\n useEffect(() => {\n onCompleteRef.current = onComplete;\n });\n\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n if (transition?.to !== undefined) {\n timer = setTimeout(() => {\n onCompleteRef.current();\n }, transitionDurationMs(ctx.preset.transition));\n }\n\n return () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n };\n }, [ctx.preset.transition, transition]);\n\n if (transition?.to === undefined) {\n return null;\n }\n\n return (\n <m.div\n animate={rectTarget(transition.to)}\n aria-hidden=\"true\"\n data-slot=\"aperto-transition-media\"\n initial={rectTarget(transition.from)}\n style={{\n borderRadius: \"var(--aperto-radius, 0.5rem)\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n position: \"fixed\",\n zIndex: \"var(--patternmode-aperto-clone-z, 1002)\",\n }}\n transition={ctx.preset.transition}\n >\n <ApertoTransitionMedia\n item={transition.item}\n renderImage={renderImage}\n renderVideo={renderVideo}\n />\n </m.div>\n );\n};\n","import type { TargetAndTransition, Transition } from \"motion/react\";\nimport type { ApertoMediaItem } from \"./types\";\n\nexport interface ApertoRect {\n height: number;\n left: number;\n top: number;\n width: number;\n}\n\nexport interface ApertoMediaTransition {\n from: ApertoRect;\n item: ApertoMediaItem;\n phase: \"opening\" | \"closing\";\n to?: ApertoRect;\n}\n\nexport const rectFromElement = (element: Element | null): ApertoRect | null => {\n if (!element) {\n return null;\n }\n\n const rect = element.getBoundingClientRect();\n return {\n height: rect.height,\n left: rect.left,\n top: rect.top,\n width: rect.width,\n };\n};\n\nexport const rectTarget = (rect: ApertoRect): TargetAndTransition => ({\n height: rect.height,\n left: rect.left,\n top: rect.top,\n width: rect.width,\n});\n\nexport const transitionDurationMs = (transition: Transition): number =>\n typeof transition.duration === \"number\" ? transition.duration * 1000 : 450;\n","import type { NavigationDirection } from \"../expanded-media-stage\";\nimport type { ApertoMediaTransition, ApertoRect } from \"../media-transition-utils\";\n\nexport interface ApertoGroupState {\n closing: boolean;\n internalIndex: number;\n layoutSourceIndex: number;\n mediaTransition: ApertoMediaTransition | null;\n navigationDirection: NavigationDirection;\n open: boolean;\n /** Index of the thumbnail that opened the Media Transition; focus returns here on close. */\n openerIndex: number | null;\n}\n\nexport type ApertoGroupAction =\n | { type: \"close-without-transition\" }\n | { type: \"complete-opening-target\"; rect: ApertoRect }\n | { type: \"finish-transition\" }\n | { type: \"navigate\"; direction: NavigationDirection; index: number }\n | {\n type: \"open-at-index\";\n index: number;\n transition: ApertoMediaTransition | null;\n }\n | { type: \"set-index\"; index: number }\n | { type: \"set-open\"; open: boolean }\n | { type: \"start-close\"; transition: ApertoMediaTransition };\n\nexport const getInitialGroupState = (initialIndex: number): ApertoGroupState => ({\n closing: false,\n internalIndex: initialIndex,\n layoutSourceIndex: initialIndex,\n mediaTransition: null,\n navigationDirection: 0,\n open: false,\n openerIndex: null,\n});\n\nexport const apertoGroupReducer = (\n state: ApertoGroupState,\n action: ApertoGroupAction,\n): ApertoGroupState => {\n switch (action.type) {\n case \"close-without-transition\": {\n return { ...state, closing: false, mediaTransition: null, open: false };\n }\n case \"complete-opening-target\": {\n if (state.mediaTransition?.phase !== \"opening\" || state.mediaTransition.to) {\n return state;\n }\n return {\n ...state,\n mediaTransition: { ...state.mediaTransition, to: action.rect },\n };\n }\n case \"finish-transition\": {\n return {\n ...state,\n closing: false,\n mediaTransition: null,\n open: state.mediaTransition?.phase === \"closing\" ? false : state.open,\n };\n }\n case \"navigate\": {\n return {\n ...state,\n internalIndex: action.index,\n layoutSourceIndex: action.index,\n navigationDirection: action.direction,\n };\n }\n case \"open-at-index\": {\n return {\n ...state,\n closing: false,\n internalIndex: action.index,\n layoutSourceIndex: action.index,\n mediaTransition: action.transition,\n navigationDirection: 0,\n open: true,\n openerIndex: action.index,\n };\n }\n case \"set-index\": {\n return { ...state, internalIndex: action.index };\n }\n case \"set-open\": {\n return action.open\n ? { ...state, closing: false, open: true, openerIndex: state.internalIndex }\n : { ...state, open: false };\n }\n case \"start-close\": {\n return {\n ...state,\n closing: true,\n mediaTransition: action.transition,\n };\n }\n default: {\n return state;\n }\n }\n};\n","export const shouldIgnoreKeyboardNavigationTarget = (target: EventTarget | null): boolean => {\n if (!(target instanceof HTMLElement)) {\n return false;\n }\n\n return (\n target.isContentEditable ||\n Boolean(\n target.closest(\n 'input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"textbox\"], audio, video',\n ),\n )\n );\n};\n","\"use client\";\n\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { X } from \"lucide-react\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst ApertoClose = ({ children, ref, ...props }: ComponentPropsWithRef<typeof Dialog.Close>) => (\n <Dialog.Close data-slot=\"aperto-close\" ref={ref} {...props}>\n {children ?? <X aria-hidden=\"true\" size={17} strokeWidth={2} />}\n </Dialog.Close>\n);\n\nApertoClose.displayName = \"ApertoClose\";\n\nexport { ApertoClose };\n","\"use client\";\n\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { m } from \"motion/react\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nimport { useApertoContext } from \"./context\";\nimport { resolvePreset } from \"./presets\";\nimport type { MotionPresetName } from \"./types\";\n\nconst TRIGGER_OPEN_Z_INDEX = 1000;\n\nexport interface ApertoTriggerProps extends ComponentPropsWithRef<typeof Dialog.Trigger> {\n /** Internal flag used by grouped thumbnails to raise only the active trigger. */\n active?: boolean;\n /** Override motion preset for this trigger */\n motion?: MotionPresetName;\n /** Internal shared layout ID override for grouped thumbnails. */\n sharedLayoutId?: string | false;\n}\n\nconst ApertoTrigger = ({\n active,\n children,\n motion: motionOverride,\n ref,\n sharedLayoutId,\n ...props\n}: ApertoTriggerProps) => {\n const ctx = useApertoContext();\n const shouldRaise = ctx.open && (active ?? true);\n const zIndex = shouldRaise ? TRIGGER_OPEN_Z_INDEX : 0;\n\n const resolved = resolvePreset(\n \"trigger\",\n motionOverride,\n ctx.presetName,\n ctx.variants,\n ctx.reduceMotion,\n );\n const layoutId =\n sharedLayoutId === false ? undefined : (sharedLayoutId ?? `${ctx.layoutId}-shared`);\n\n return (\n <Dialog.Trigger asChild ref={ref} {...props}>\n <m.button\n data-aperto-active={shouldRaise ? \"\" : undefined}\n data-slot=\"aperto-trigger\"\n key={layoutId ?? \"unshared\"}\n layout\n layoutCrossfade={false}\n layoutId={layoutId}\n style={{ zIndex }}\n transition={resolved.transition}\n type=\"button\"\n >\n {children}\n </m.button>\n </Dialog.Trigger>\n );\n};\n\nApertoTrigger.displayName = \"ApertoTrigger\";\n\nexport { ApertoTrigger };\n","\"use client\";\n\nimport { ApertoClose } from \"../aperto-close\";\nimport { ApertoContent } from \"../aperto-content\";\nimport { ApertoDescription } from \"../aperto-description\";\nimport { ApertoOverlay } from \"../aperto-overlay\";\nimport { ApertoPortal } from \"../aperto-portal\";\nimport { ApertoRoot } from \"../aperto-root\";\nimport { ApertoTitle } from \"../aperto-title\";\nimport { ApertoTrigger } from \"../aperto-trigger\";\nimport { ApertoExpandedMedia, ApertoThumbnailMedia } from \"../media-rendering\";\nimport { getDescriptionProps, getMediaLabel } from \"../media-utils\";\nimport type { ApertoProps } from \"./aperto-types\";\n\nexport const ApertoSingle = ({\n classNames,\n dismissible,\n media,\n renderImage,\n renderVideo,\n}: ApertoProps) => {\n const label = getMediaLabel(media);\n const title = media.title ?? label;\n\n return (\n <ApertoRoot dismissible={dismissible}>\n <ApertoTrigger aria-label={`Open ${label}`} className={classNames?.thumbnail}>\n <ApertoThumbnailMedia item={media} renderImage={renderImage} renderVideo={renderVideo} />\n </ApertoTrigger>\n <ApertoPortal>\n <ApertoOverlay className={classNames?.overlay} />\n <ApertoContent className={classNames?.content} {...getDescriptionProps(media)}>\n <ApertoExpandedMedia item={media} renderImage={renderImage} renderVideo={renderVideo} />\n <ApertoTitle>{title}</ApertoTitle>\n {media.description === undefined || media.description === \"\" ? null : (\n <ApertoDescription>{media.description}</ApertoDescription>\n )}\n <ApertoClose aria-label=\"Close\" className={classNames?.closeButton} type=\"button\" />\n </ApertoContent>\n </ApertoPortal>\n </ApertoRoot>\n );\n};\n","\"use client\";\n\nimport { useApertoGroup } from \"../aperto-group-context\";\nimport { ApertoTrigger } from \"../aperto-trigger\";\nimport { ApertoThumbnailMedia } from \"../media-rendering\";\nimport { getMediaLabel } from \"../media-utils\";\nimport type { ApertoThumbnailProps } from \"./aperto-types\";\n\nexport const ApertoThumbnail = ({ children, className, index }: ApertoThumbnailProps) => {\n const group = useApertoGroup();\n const media = group.media[index];\n\n if (!media) {\n return null;\n }\n\n return (\n <ApertoTrigger\n active={group.index === index}\n aria-label={`Open ${getMediaLabel(media)}`}\n className={className ?? group.classNames?.thumbnail}\n onClick={() => {\n group.openAtIndex(index);\n }}\n ref={(node) => {\n group.registerThumbnail(index, node);\n }}\n sharedLayoutId={false}\n >\n {children ?? (\n <ApertoThumbnailMedia\n item={media}\n renderImage={group.renderImage}\n renderVideo={group.renderVideo}\n />\n )}\n </ApertoTrigger>\n );\n};\n","\"use client\";\n\n/**\n * Package: @patternmode/aperto\n *\n * Opinionated thumbnail-to-expanded media transitions.\n * Built on Radix Dialog + Motion.\n *\n * Inspired by Cambio (https://github.com/raphaelsalaja/cambio)\n * by Raphael Salaja.\n *\n * @example\n * ```tsx\n * import { Aperto } from \"@patternmode/aperto\";\n *\n * import { Aperto } from \"@patternmode/aperto\";\n * import \"@patternmode/aperto/styles.css\";\n *\n * <Aperto.Group media={media}>\n * {media.map((item, index) => (\n * <Aperto.Thumbnail key={item.id ?? item.src} index={index} />\n * ))}\n * </Aperto.Group>\n * ```\n */\n\nimport { ApertoGroup, ApertoSingle, ApertoThumbnail } from \"./aperto\";\nimport type { ApertoGroupProps, ApertoProps, ApertoThumbnailProps } from \"./aperto\";\nimport { ApertoClose } from \"./aperto-close\";\nimport { ApertoContent } from \"./aperto-content\";\nimport type { ApertoContentProps } from \"./aperto-content\";\nimport { ApertoDescription } from \"./aperto-description\";\nimport { ApertoOverlay } from \"./aperto-overlay\";\nimport type { ApertoOverlayProps } from \"./aperto-overlay\";\nimport { ApertoPortal } from \"./aperto-portal\";\nimport type { ApertoPortalProps } from \"./aperto-portal\";\nimport { ApertoRoot } from \"./aperto-root\";\nimport type { ApertoRootProps } from \"./aperto-root\";\nimport { ApertoTitle } from \"./aperto-title\";\nimport { ApertoTrigger } from \"./aperto-trigger\";\nimport type { ApertoTriggerProps } from \"./aperto-trigger\";\n\n/** Lower-level compound component namespace for advanced composition. */\nconst ApertoPrimitive = {\n Close: ApertoClose,\n Content: ApertoContent,\n Description: ApertoDescription,\n Overlay: ApertoOverlay,\n Portal: ApertoPortal,\n Root: ApertoRoot,\n Title: ApertoTitle,\n Trigger: ApertoTrigger,\n};\n\n/** Primary media-first component namespace. */\nconst Aperto = Object.assign(ApertoSingle, {\n Group: ApertoGroup,\n Primitive: ApertoPrimitive,\n Thumbnail: ApertoThumbnail,\n});\n\n// Preset system\nexport { PRESETS, resolvePreset } from \"./presets\";\n// Types\nexport type {\n ApertoClassNames,\n ApertoImageItem,\n ApertoMediaItem,\n ApertoVideoItem,\n DismissibleConfig,\n DragSpringConfig,\n MotionPreset,\n MotionPresetName,\n MotionProp,\n MotionVariants,\n NavigationMotionPresetName,\n RenderImage,\n RenderVideo,\n} from \"./types\";\n// Named exports for tree-shaking\nexport {\n Aperto,\n ApertoClose,\n ApertoContent,\n type ApertoContentProps,\n ApertoDescription,\n ApertoGroup,\n type ApertoGroupProps,\n ApertoOverlay,\n type ApertoOverlayProps,\n ApertoPortal,\n type ApertoPortalProps,\n ApertoPrimitive,\n type ApertoProps,\n ApertoRoot,\n type ApertoRootProps,\n ApertoThumbnail,\n type ApertoThumbnailProps,\n ApertoTitle,\n ApertoTrigger,\n type ApertoTriggerProps,\n};\n"],"mappings":"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","names":["useId","useRef","Dialog","jsx","createContext","use","Dialog","m","easings","jsx","m","Dialog","jsx","Dialog","useState","jsx","useState","Dialog","jsx","AnimatePresence","m","jsx","jsx","AnimatePresence","m","m","jsx","m","jsx","useRef","useId","Dialog","X","jsx","Dialog","m","jsx","m","jsx","jsxs","jsx"]}
1
+ {"version":3,"sources":["../src/Aperto/aperto-group.tsx","../src/aperto-content.tsx","../src/context.ts","../src/physics.ts","../src/presets.ts","../src/aperto-description.tsx","../src/aperto-group-context.ts","../src/aperto-overlay.tsx","../src/aperto-portal.tsx","../src/aperto-root.tsx","../src/aperto-title.tsx","../src/expanded-media-stage.tsx","../src/media-rendering.tsx","../src/media-utils.ts","../src/media-transition.tsx","../src/media-transition-utils.ts","../src/Aperto/aperto-group-state.ts","../src/Aperto/aperto-keyboard.ts","../src/aperto-close.tsx","../src/aperto-trigger.tsx","../src/Aperto/aperto-single.tsx","../src/Aperto/aperto-thumbnail.tsx","../src/index.ts"],"sourcesContent":["\"use client\";\n\nimport { ChevronLeft, ChevronRight, X } from \"lucide-react\";\nimport { useId, useLayoutEffect, useReducer, useRef } from \"react\";\nimport type { CSSProperties, Dispatch, KeyboardEvent } from \"react\";\n\nimport { ApertoContent } from \"../aperto-content\";\nimport { ApertoDescription } from \"../aperto-description\";\nimport { ApertoGroupContext } from \"../aperto-group-context\";\nimport { ApertoOverlay } from \"../aperto-overlay\";\nimport { ApertoPortal } from \"../aperto-portal\";\nimport { ApertoRoot } from \"../aperto-root\";\nimport { ApertoTitle } from \"../aperto-title\";\nimport { ApertoExpandedMediaStage } from \"../expanded-media-stage\";\nimport type { NavigationDirection } from \"../expanded-media-stage\";\nimport { ApertoMediaTransitionClone } from \"../media-transition\";\nimport { rectFromElement, rectFromTrigger } from \"../media-transition-utils\";\nimport type { ApertoMediaTransition } from \"../media-transition-utils\";\nimport { getDescriptionProps, getMediaLabel } from \"../media-utils\";\nimport type {\n ApertoClassNames,\n ApertoMediaItem,\n NavigationMotionPresetName,\n RenderImage,\n RenderVideo,\n} from \"../types\";\nimport { apertoGroupReducer, getInitialGroupState } from \"./aperto-group-state\";\nimport type { ApertoGroupAction, ApertoGroupState } from \"./aperto-group-state\";\nimport { shouldIgnoreKeyboardNavigationTarget } from \"./aperto-keyboard\";\nimport type { ApertoGroupProps } from \"./aperto-types\";\n\ntype ApertoExpandedMediaStyle = CSSProperties & {\n \"--aperto-expanded-aspect-ratio\"?: string;\n \"--aperto-expanded-aspect-ratio-height\"?: number;\n \"--aperto-expanded-aspect-ratio-width\"?: number;\n};\ntype ApertoGroupDispatch = Dispatch<ApertoGroupAction>;\n\nconst ApertoMediaNavigationButtons = ({\n classNames,\n enabled,\n onNext,\n onPrevious,\n}: {\n classNames: ApertoClassNames | undefined;\n enabled: boolean;\n onNext: () => void;\n onPrevious: () => void;\n}) => {\n if (!enabled) {\n return null;\n }\n\n return (\n <>\n <button\n aria-label=\"Previous media\"\n className={classNames?.previousButton}\n data-slot=\"aperto-previous-button\"\n onClick={onPrevious}\n type=\"button\"\n >\n <ChevronLeft aria-hidden=\"true\" size={18} strokeWidth={2} />\n </button>\n <button\n aria-label=\"Next media\"\n className={classNames?.nextButton}\n data-slot=\"aperto-next-button\"\n onClick={onNext}\n type=\"button\"\n >\n <ChevronRight aria-hidden=\"true\" size={18} strokeWidth={2} />\n </button>\n </>\n );\n};\n\nconst useThumbnailMap = () => {\n const thumbnailRefs = useRef<Map<number, HTMLButtonElement> | null>(null);\n thumbnailRefs.current ??= new Map();\n return thumbnailRefs.current;\n};\n\nconst getExpandedMediaStyle = (\n activeMedia: ApertoMediaItem | undefined,\n): ApertoExpandedMediaStyle | undefined => {\n if (\n activeMedia === undefined ||\n activeMedia.width === undefined ||\n activeMedia.height === undefined\n ) {\n return undefined;\n }\n\n return {\n \"--aperto-expanded-aspect-ratio\": `${activeMedia.width} / ${activeMedia.height}`,\n \"--aperto-expanded-aspect-ratio-height\": activeMedia.height,\n \"--aperto-expanded-aspect-ratio-width\": activeMedia.width,\n };\n};\n\nconst ApertoGroupPortal = ({\n activeMedia,\n classNames,\n expandedMediaStyle,\n finalFocus,\n handleContentKeyDown,\n handleMediaTransitionComplete,\n hasNavigation,\n index,\n mediaLength,\n navigationDirection,\n navigationMotion,\n renderImage,\n renderVideo,\n setExpandedMediaNode,\n startClose,\n transition,\n goToNext,\n goToPrevious,\n}: {\n activeMedia: ApertoMediaItem | undefined;\n classNames: ApertoClassNames | undefined;\n expandedMediaStyle: ApertoExpandedMediaStyle | undefined;\n finalFocus: () => HTMLElement | null;\n goToNext: () => void;\n goToPrevious: () => void;\n handleContentKeyDown: ((event: KeyboardEvent<HTMLDivElement>) => void) | undefined;\n handleMediaTransitionComplete: () => void;\n hasNavigation: boolean;\n index: number;\n mediaLength: number;\n navigationDirection: NavigationDirection;\n navigationMotion: NavigationMotionPresetName;\n renderImage: RenderImage | undefined;\n renderVideo: RenderVideo | undefined;\n setExpandedMediaNode: (node: HTMLDivElement | null) => void;\n startClose: () => void;\n transition: ApertoMediaTransition | null;\n}) => {\n if (activeMedia === undefined) {\n return null;\n }\n\n return (\n <ApertoPortal>\n <ApertoOverlay className={classNames?.overlay} fadeOut={transition?.phase === \"closing\"} />\n <ApertoContent\n className={classNames?.content}\n data-aperto-transition={transition?.phase}\n finalFocus={finalFocus}\n onKeyDown={handleContentKeyDown}\n sharedLayoutId={false}\n {...getDescriptionProps(activeMedia)}\n >\n <div data-slot=\"aperto-media\" ref={setExpandedMediaNode} style={expandedMediaStyle}>\n <ApertoExpandedMediaStage\n direction={navigationDirection}\n index={index}\n item={activeMedia}\n navigationMotion={navigationMotion}\n renderImage={renderImage}\n renderVideo={renderVideo}\n />\n <ApertoMediaNavigationButtons\n classNames={classNames}\n enabled={hasNavigation}\n onNext={goToNext}\n onPrevious={goToPrevious}\n />\n </div>\n <ApertoTitle>{activeMedia.title ?? getMediaLabel(activeMedia)}</ApertoTitle>\n {activeMedia.description === undefined || activeMedia.description === \"\" ? null : (\n <ApertoDescription>{activeMedia.description}</ApertoDescription>\n )}\n {hasNavigation ? (\n <div className={classNames?.counter} data-slot=\"aperto-counter\">\n {index + 1} / {mediaLength}\n </div>\n ) : null}\n <button\n aria-label=\"Close\"\n className={classNames?.closeButton}\n data-slot=\"aperto-close\"\n onClick={startClose}\n type=\"button\"\n >\n <X aria-hidden=\"true\" size={17} strokeWidth={2} />\n </button>\n </ApertoContent>\n <ApertoMediaTransitionClone\n onComplete={handleMediaTransitionComplete}\n renderImage={renderImage}\n renderVideo={renderVideo}\n transition={transition}\n />\n </ApertoPortal>\n );\n};\n\nconst useApertoMediaLifecycle = ({\n activeMedia,\n dispatch,\n index,\n media,\n onIndexChange,\n state,\n}: {\n activeMedia: ApertoMediaItem | undefined;\n dispatch: ApertoGroupDispatch;\n index: number;\n media: ApertoMediaItem[];\n onIndexChange: ApertoGroupProps[\"onIndexChange\"];\n state: ApertoGroupState;\n}) => {\n const expandedMediaRef = useRef<HTMLDivElement | null>(null);\n const thumbnailMap = useThumbnailMap();\n\n const setExpandedMediaNode = (node: HTMLDivElement | null) => {\n expandedMediaRef.current = node;\n if (node === null) {\n return;\n }\n const targetRect = rectFromElement(node);\n if (targetRect !== null) {\n dispatch({ rect: targetRect, type: \"complete-opening-target\" });\n }\n };\n\n const registerThumbnail = (thumbIndex: number, node: HTMLButtonElement | null) => {\n if (node !== null) {\n thumbnailMap.set(thumbIndex, node);\n return;\n }\n thumbnailMap.delete(thumbIndex);\n };\n\n useLayoutEffect(() => {\n if (\n state.mediaTransition?.phase !== \"opening\" ||\n state.mediaTransition.to !== undefined ||\n expandedMediaRef.current === null\n ) {\n return;\n }\n\n const targetRect = rectFromElement(expandedMediaRef.current);\n if (targetRect !== null) {\n dispatch({ rect: targetRect, type: \"complete-opening-target\" });\n }\n }, [dispatch, state.mediaTransition]);\n\n const openAtIndex = (thumbIndex: number) => {\n // Fly from the media inside the trigger, not the whole card (see rectFromTrigger).\n const sourceRect = rectFromTrigger(thumbnailMap.get(thumbIndex) ?? null);\n const item = media[thumbIndex] ?? null;\n const transition =\n sourceRect === null || item === null\n ? null\n : { from: sourceRect, item, phase: \"opening\" as const };\n\n dispatch({ index: thumbIndex, transition, type: \"open-at-index\" });\n onIndexChange?.(thumbIndex);\n };\n\n const startClose = () => {\n if (!state.open || state.closing) {\n return;\n }\n\n const sourceRect = rectFromElement(expandedMediaRef.current);\n const targetRect = rectFromTrigger(thumbnailMap.get(index) ?? null);\n if (activeMedia === undefined || sourceRect === null || targetRect === null) {\n dispatch({ type: \"close-without-transition\" });\n return;\n }\n\n dispatch({\n transition: { from: sourceRect, item: activeMedia, phase: \"closing\", to: targetRect },\n type: \"start-close\",\n });\n };\n\n // Focus Return target for Base UI's `finalFocus`: the Thumbnail that opened\n // the Media Transition, falling back to the active thumbnail if it unmounted.\n // Base UI's FloatingFocusManager focuses the returned element with\n // `preventScroll: true`, matching the previous manual `onCloseAutoFocus`.\n const finalFocus = (): HTMLElement | null => {\n const openerThumbnail =\n state.openerIndex === null ? undefined : thumbnailMap.get(state.openerIndex);\n return openerThumbnail ?? thumbnailMap.get(index) ?? null;\n };\n\n return { finalFocus, openAtIndex, registerThumbnail, setExpandedMediaNode, startClose };\n};\n\nconst useApertoGroupController = ({\n classNames,\n index: controlledIndex,\n initialIndex = 0,\n media,\n onIndexChange,\n renderImage,\n renderVideo,\n}: Omit<ApertoGroupProps, \"children\" | \"dismissible\" | \"motion\" | \"navigationMotion\">) => {\n const generatedId = useId();\n const [state, dispatch] = useReducer(apertoGroupReducer, initialIndex, getInitialGroupState);\n const isControlled = controlledIndex !== undefined;\n const index = isControlled ? controlledIndex : state.internalIndex;\n const activeMedia = media[index] ?? media[0];\n const lifecycle = useApertoMediaLifecycle({\n activeMedia,\n dispatch,\n index,\n media,\n onIndexChange,\n state,\n });\n const sharedLayoutIdForIndex = (nextIndex: number) =>\n `aperto-group-${generatedId}-${nextIndex}-shared`;\n const sharedLayoutId = sharedLayoutIdForIndex(state.layoutSourceIndex);\n\n const setIndex = (nextIndex: number) => {\n if (!isControlled) {\n dispatch({ index: nextIndex, type: \"set-index\" });\n }\n onIndexChange?.(nextIndex);\n };\n\n const handleMediaTransitionComplete = () => {\n dispatch({ type: \"finish-transition\" });\n };\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (nextOpen) {\n dispatch({ open: true, type: \"set-open\" });\n return;\n }\n\n lifecycle.startClose();\n };\n\n const value = {\n classNames,\n index,\n media,\n open: state.open,\n openAtIndex: lifecycle.openAtIndex,\n registerThumbnail: lifecycle.registerThumbnail,\n renderImage,\n renderVideo,\n setIndex,\n sharedLayoutId,\n sharedLayoutIdForIndex,\n };\n const hasNavigation = media.length > 1;\n const navigateToIndex = (nextIndex: number, direction: NavigationDirection) => {\n dispatch({ direction, index: nextIndex, type: \"navigate\" });\n onIndexChange?.(nextIndex);\n };\n const goToPrevious = () => {\n navigateToIndex((index - 1 + media.length) % media.length, -1);\n };\n const goToNext = () => {\n navigateToIndex((index + 1) % media.length, 1);\n };\n const handleContentKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (\n event.defaultPrevented ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n shouldIgnoreKeyboardNavigationTarget(event.target)\n ) {\n return;\n }\n\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n goToPrevious();\n }\n\n if (event.key === \"ArrowRight\") {\n event.preventDefault();\n goToNext();\n }\n };\n const expandedMediaStyle = getExpandedMediaStyle(activeMedia);\n\n return {\n activeMedia,\n expandedMediaStyle,\n finalFocus: lifecycle.finalFocus,\n goToNext,\n goToPrevious,\n handleContentKeyDown,\n handleMediaTransitionComplete,\n handleOpenChange,\n hasNavigation,\n index,\n setExpandedMediaNode: lifecycle.setExpandedMediaNode,\n startClose: lifecycle.startClose,\n state,\n value,\n };\n};\n\nexport const ApertoGroup = ({\n children,\n classNames,\n dismissible,\n index,\n initialIndex,\n media,\n motion: motionProp,\n navigationMotion = \"glide\",\n onIndexChange,\n renderImage,\n renderVideo,\n}: ApertoGroupProps) => {\n const controller = useApertoGroupController({\n classNames,\n index,\n initialIndex,\n media,\n onIndexChange,\n renderImage,\n renderVideo,\n });\n\n return (\n <ApertoGroupContext.Provider value={controller.value}>\n <ApertoRoot\n dismissible={dismissible}\n motion={motionProp}\n onOpenChange={controller.handleOpenChange}\n open={controller.state.open}\n >\n {children}\n <ApertoGroupPortal\n activeMedia={controller.activeMedia}\n classNames={classNames}\n expandedMediaStyle={controller.expandedMediaStyle}\n finalFocus={controller.finalFocus}\n goToNext={controller.goToNext}\n goToPrevious={controller.goToPrevious}\n handleContentKeyDown={\n controller.hasNavigation ? controller.handleContentKeyDown : undefined\n }\n handleMediaTransitionComplete={controller.handleMediaTransitionComplete}\n hasNavigation={controller.hasNavigation}\n index={controller.index}\n mediaLength={media.length}\n navigationDirection={controller.state.navigationDirection}\n navigationMotion={navigationMotion}\n renderImage={renderImage}\n renderVideo={renderVideo}\n setExpandedMediaNode={controller.setExpandedMediaNode}\n startClose={controller.startClose}\n transition={controller.state.mediaTransition}\n />\n </ApertoRoot>\n </ApertoGroupContext.Provider>\n );\n};\n","\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport { m, useMotionValue, useSpring, useTransform } from \"motion/react\";\nimport type { MotionStyle, PanInfo } from \"motion/react\";\nimport { useState } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties } from \"react\";\n\nimport { useApertoContext } from \"./context\";\nimport {\n calculateResistance,\n DEFAULT_DISTANCE_THRESHOLD,\n DEFAULT_VELOCITY_THRESHOLD,\n OPACITY_INPUT,\n OPACITY_OUTPUT,\n SCALE_INPUT,\n SCALE_OUTPUT,\n} from \"./physics\";\nimport { getDragSpring, resolvePreset } from \"./presets\";\nimport type { DismissibleConfig, MotionPresetName } from \"./types\";\n\nexport interface ApertoContentProps extends Omit<\n ComponentPropsWithRef<typeof Dialog.Popup>,\n \"render\" | \"hidden\" | \"className\" | \"style\"\n> {\n /** Constrained to a plain string/object (Base UI's function forms aren't used). */\n className?: string;\n style?: CSSProperties;\n /** Motion preset override for this content panel, independent of the root preset. */\n motion?: MotionPresetName;\n /** Built-in positioning strategy. Use \"none\" for custom primitive compositions. */\n placement?: \"center\" | \"none\";\n /** Internal shared layout ID override for grouped media. */\n sharedLayoutId?: string | false;\n}\n\nconst ApertoContent = ({\n children,\n className,\n motion: motionOverride,\n placement = \"center\",\n ref,\n sharedLayoutId,\n style,\n ...props\n}: ApertoContentProps) => {\n const ctx = useApertoContext();\n const [isDragging, setIsDragging] = useState(false);\n const resolved = resolvePreset(\n \"content\",\n motionOverride,\n ctx.presetName,\n ctx.variants,\n ctx.reduceMotion,\n );\n\n const contentLayoutId =\n sharedLayoutId === false ? undefined : (sharedLayoutId ?? `${ctx.layoutId}-shared`);\n\n const dragSpring = getDragSpring(resolved);\n const isDismissible = ctx.dismissible !== false;\n\n const dismissConfig: DismissibleConfig =\n typeof ctx.dismissible === \"object\" ? ctx.dismissible : {};\n const distanceThreshold = dismissConfig.threshold ?? DEFAULT_DISTANCE_THRESHOLD;\n const velocityThreshold = dismissConfig.velocity ?? DEFAULT_VELOCITY_THRESHOLD;\n\n const dragX = useMotionValue(0);\n const dragY = useMotionValue(0);\n const springX = useSpring(dragX, dragSpring);\n const springY = useSpring(dragY, dragSpring);\n\n const distance = useTransform(() => Math.hypot(springX.get(), springY.get()));\n const scaleMotion = useTransform(distance, SCALE_INPUT, SCALE_OUTPUT);\n const opacityMotion = useTransform(distance, OPACITY_INPUT, OPACITY_OUTPUT);\n const resistance = useTransform(distance, calculateResistance);\n const { onOpenChange } = ctx;\n\n const handleDrag = (_event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {\n if (!isDragging) {\n setIsDragging(true);\n }\n const r = resistance.get();\n dragX.set(info.offset.x * r);\n dragY.set(info.offset.y * r);\n };\n\n const handleDragEnd = (_event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {\n setIsDragging(false);\n const speed = Math.hypot(info.velocity.x, info.velocity.y);\n const dist = Math.hypot(info.offset.x, info.offset.y);\n\n if (speed > velocityThreshold || dist > distanceThreshold) {\n onOpenChange(false);\n return;\n }\n\n dragX.set(0);\n dragY.set(0);\n };\n\n const placementStyle =\n placement === \"center\"\n ? {\n left: \"50%\",\n top: \"50%\",\n translate: \"-50% -50%\",\n }\n : {};\n let cursor: MotionStyle[\"cursor\"];\n\n if (isDragging) {\n cursor = \"grabbing\";\n } else if (isDismissible) {\n cursor = \"grab\";\n }\n\n const motionStyle: MotionStyle = {\n cursor,\n opacity: opacityMotion,\n scale: scaleMotion,\n x: springX,\n y: springY,\n ...placementStyle,\n ...style,\n };\n\n return (\n // `hidden={false}` neutralises Base UI's `hidden: !mounted` so the content\n // stays visible while Motion plays the drag-dismiss / shared-layout exit on\n // close (Motion animations are invisible to Base UI's `getAnimations()`\n // unmount detection); `AnimatePresence` in the portal owns the real unmount.\n <Dialog.Popup\n className={className}\n hidden={false}\n ref={ref}\n render={\n <m.div\n data-slot=\"aperto-content\"\n drag={isDismissible}\n dragConstraints={{ bottom: 0, left: 0, right: 0, top: 0 }}\n dragElastic={0}\n dragMomentum={false}\n dragSnapToOrigin\n layout={contentLayoutId === undefined || contentLayoutId === \"\" ? undefined : true}\n layoutId={contentLayoutId}\n onDrag={isDismissible ? handleDrag : undefined}\n onDragEnd={isDismissible ? handleDragEnd : undefined}\n style={motionStyle}\n transition={resolved.transition}\n >\n {children}\n </m.div>\n }\n {...props}\n />\n );\n};\n\nApertoContent.displayName = \"ApertoContent\";\n\nexport { ApertoContent };\n","\"use client\";\n\nimport { createContext, use } from \"react\";\n\nimport type { ApertoContextValue } from \"./types\";\n\nexport const ApertoContext = createContext<ApertoContextValue | null>(null);\n\nexport const useApertoContext = (): ApertoContextValue => {\n const ctx = use(ApertoContext);\n if (!ctx) {\n throw new Error(\"Aperto components must be used within <Aperto.Root>\");\n }\n return ctx;\n};\n","/**\n * Drag physics utilities.\n *\n * The logarithmic resistance function creates a rubber-band feel:\n * initial movement is free, but gets progressively harder the further\n * you drag. Combined with spring-smoothed motion values, this produces\n * a natural, elastic gesture.\n */\n\nconst RESISTANCE_DIVISOR = 20;\nconst RESISTANCE_SCALE = 4;\nconst RESISTANCE_MIN = 0.1;\n\n/**\n * Logarithmic resistance — decelerates drag progressively.\n * Returns a multiplier between RESISTANCE_MIN and 1.0.\n *\n * At distance 0: returns 1.0 (full movement)\n * At distance 50: returns ~0.77\n * At distance 100: returns ~0.58\n * At distance 200: returns ~0.42\n */\nexport const calculateResistance = (distance: number): number =>\n Math.max(RESISTANCE_MIN, 1 - Math.log(distance / RESISTANCE_DIVISOR + 1) / RESISTANCE_SCALE);\n\n/** Scale mapping: distance → visual scale (1.0 → 0.95) */\nexport const SCALE_INPUT = [0, 50, 100];\nexport const SCALE_OUTPUT = [1, 0.98, 0.95];\n\n/** Opacity mapping: distance → visual opacity (1.0 → 0.96) */\nexport const OPACITY_INPUT = [0, 80];\nexport const OPACITY_OUTPUT = [1, 0.96];\n\n/** Default dismissal thresholds */\nexport const DEFAULT_DISTANCE_THRESHOLD = 100;\nexport const DEFAULT_VELOCITY_THRESHOLD = 500;\n","import { durations, easings, springs } from \"@howells/motion\";\nimport type { DragSpringConfig, MotionPreset, MotionPresetName, MotionVariants } from \"./types\";\n\n/**\n * Motion presets — each bundles transition timing AND drag physics\n * so \"snappy\" feels snappy everywhere: open, close, and drag.\n *\n * Curves and springs come from the shared @howells/motion tokens so motion\n * feel stays consistent across the catalog.\n */\nexport const PRESETS: Record<MotionPresetName, MotionPreset> = {\n bouncy: {\n drag: {\n damping: springs.snappy.damping,\n restDelta: 0.01,\n stiffness: springs.snappy.stiffness,\n },\n transition: {\n damping: springs.bouncy.damping,\n mass: springs.bouncy.mass,\n stiffness: springs.bouncy.stiffness,\n type: \"spring\",\n },\n },\n reduced: {\n drag: { damping: 50, restDelta: 0.1, stiffness: 1000 },\n transition: { duration: 0.01, ease: \"linear\" },\n },\n smooth: {\n drag: {\n damping: springs.natural.damping,\n restDelta: 0.01,\n stiffness: springs.natural.stiffness,\n },\n transition: { duration: durations.moderate, ease: easings.customGentle },\n },\n snappy: {\n drag: {\n damping: springs.stiff.damping,\n restDelta: 0.01,\n stiffness: springs.stiff.stiffness,\n },\n transition: { duration: durations.snappy, ease: easings.snappy },\n },\n};\n\ntype ComponentType = \"trigger\" | \"content\" | \"backdrop\";\n\n/**\n * Three-level motion resolution:\n * 1. Component-level override (highest)\n * 2. Per-component variant from Root\n * 3. Global preset from Root (lowest)\n *\n * If `prefers-reduced-motion` is active, always returns \"reduced\".\n */\nexport const resolvePreset = (\n componentType: ComponentType,\n componentMotion: MotionPresetName | undefined,\n globalPreset: MotionPresetName,\n variants: MotionVariants | undefined,\n reduceMotion: boolean,\n): MotionPreset => {\n if (reduceMotion) {\n return PRESETS.reduced;\n }\n\n // 1. Component-level override\n if (componentMotion) {\n return PRESETS[componentMotion];\n }\n\n // 2. Per-component variant\n if (variants?.[componentType]) {\n return PRESETS[variants[componentType]];\n }\n\n // 3. Global preset\n return PRESETS[globalPreset];\n};\n\n/** Extract the drag spring config from a preset */\nexport const getDragSpring = (preset: MotionPreset): DragSpringConfig => preset.drag;\n","\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst ApertoDescription = ({ ref, ...props }: ComponentPropsWithRef<typeof Dialog.Description>) => (\n <Dialog.Description data-slot=\"aperto-description\" ref={ref} {...props} />\n);\n\nApertoDescription.displayName = \"ApertoDescription\";\n\nexport { ApertoDescription };\n","import { createContext, use } from \"react\";\n\nimport type { ApertoClassNames, ApertoMediaItem, RenderImage, RenderVideo } from \"./types\";\n\nexport interface ApertoGroupContextValue {\n classNames?: ApertoClassNames;\n index: number;\n media: ApertoMediaItem[];\n open: boolean;\n openAtIndex: (index: number) => void;\n registerThumbnail: (index: number, node: HTMLButtonElement | null) => void;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n setIndex: (index: number) => void;\n sharedLayoutId: string;\n sharedLayoutIdForIndex: (index: number) => string;\n}\n\nexport const ApertoGroupContext = createContext<ApertoGroupContextValue | null>(null);\n\nexport const useApertoGroup = (): ApertoGroupContextValue => {\n const ctx = use(ApertoGroupContext);\n if (!ctx) {\n throw new Error(\"Aperto.Thumbnail must be used within <Aperto.Group>\");\n }\n return ctx;\n};\n","\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport { m } from \"motion/react\";\nimport type { Transition } from \"motion/react\";\nimport type { CSSProperties, Ref } from \"react\";\n\nimport { useApertoContext } from \"./context\";\nimport { easings } from \"@howells/motion\";\n\nexport interface ApertoOverlayProps {\n className?: string;\n /** Internal flag used to fade the overlay during measured close transitions. */\n fadeOut?: boolean;\n ref?: Ref<HTMLDivElement>;\n style?: CSSProperties;\n}\n\n/** Overlay always fades gently regardless of the content's motion preset. */\nconst OVERLAY_TRANSITION: Transition = {\n duration: 0.3,\n ease: easings.customGentle,\n};\n\nconst OVERLAY_TRANSITION_REDUCED: Transition = {\n duration: 0.01,\n ease: \"linear\",\n};\n\nconst ApertoOverlay = ({ className, fadeOut, ref, style }: ApertoOverlayProps) => {\n const ctx = useApertoContext();\n const transition = ctx.reduceMotion ? OVERLAY_TRANSITION_REDUCED : OVERLAY_TRANSITION;\n\n return (\n // `hidden={false}` neutralises Base UI's `hidden: !mounted` so the backdrop\n // stays visible while Motion fades it out on close (Motion animations are\n // invisible to Base UI's `getAnimations()`-based unmount detection).\n <Dialog.Backdrop\n hidden={false}\n render={\n <m.div\n animate={{ opacity: fadeOut === true ? 0 : 1 }}\n className={className}\n data-slot=\"aperto-overlay\"\n exit={{ opacity: 0 }}\n initial={{ opacity: 0 }}\n ref={ref}\n style={style}\n transition={transition}\n />\n }\n />\n );\n};\n\nApertoOverlay.displayName = \"ApertoOverlay\";\n\nexport { ApertoOverlay };\n","\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport { AnimatePresence } from \"motion/react\";\nimport type { ReactNode } from \"react\";\n\nimport { useApertoContext } from \"./context\";\n\nexport interface ApertoPortalProps {\n children: ReactNode;\n /** Container element for the portal (default: document.body) */\n container?: HTMLElement;\n}\n\nconst ApertoPortal = ({ children, container }: ApertoPortalProps) => {\n const { open } = useApertoContext();\n\n // `AnimatePresence` owns mount/unmount so Motion can play exit animations\n // (and the shared-element layout morph) before the subtree leaves the DOM.\n // `keepMounted` keeps Base UI's Portal rendering its children even after its\n // internal `mounted` state flips to false on close, so those exit animations\n // run instead of the content vanishing instantly. The Popup/Backdrop then\n // override Base UI's `hidden` attribute to stay visible until Motion is done.\n return (\n <AnimatePresence>\n {open && (\n <Dialog.Portal container={container} keepMounted>\n {children}\n </Dialog.Portal>\n )}\n </AnimatePresence>\n );\n};\n\nexport { ApertoPortal };\n","\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport { domMax, LayoutGroup, LazyMotion, useReducedMotion } from \"motion/react\";\nimport { useId, useState } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\n\nimport { ApertoContext } from \"./context\";\nimport { PRESETS } from \"./presets\";\nimport type { DismissibleConfig, MotionPresetName, MotionVariants } from \"./types\";\n\nexport interface ApertoRootProps extends Omit<\n ComponentPropsWithoutRef<typeof Dialog.Root>,\n \"open\" | \"onOpenChange\"\n> {\n children: ReactNode;\n /** Whether dragging can dismiss the content (default: true) */\n dismissible?: boolean | DismissibleConfig;\n /** Layout ID for shared element transition (auto-generated if omitted) */\n layoutId?: string;\n /** Motion preset or per-component variants */\n motion?: MotionPresetName | MotionVariants;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Force reduced motion regardless of system preference */\n reduceMotion?: boolean;\n}\n\nconst ApertoRoot = ({\n children,\n defaultOpen,\n dismissible = true,\n layoutId: layoutIdProp,\n motion: motionProp = \"smooth\",\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n reduceMotion: reduceMotionProp,\n ...dialogProps\n}: ApertoRootProps) => {\n const generatedId = useId();\n const layoutId = layoutIdProp ?? `aperto-${generatedId}`;\n const systemReducedMotion = useReducedMotion() ?? false;\n const shouldReduce = reduceMotionProp ?? systemReducedMotion;\n\n // Uncontrolled state fallback\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n\n const onOpenChange = (nextOpen: boolean) => {\n if (!isControlled) {\n setInternalOpen(nextOpen);\n }\n controlledOnOpenChange?.(nextOpen);\n };\n\n // Resolve global preset name\n const globalPresetName: MotionPresetName = typeof motionProp === \"string\" ? motionProp : \"smooth\";\n const variants: MotionVariants | undefined =\n typeof motionProp === \"object\" ? motionProp : undefined;\n\n const presetName: MotionPresetName = shouldReduce ? \"reduced\" : globalPresetName;\n const preset = PRESETS[presetName];\n const contextValue = {\n dismissible,\n layoutId,\n onOpenChange,\n open,\n preset,\n presetName,\n reduceMotion: shouldReduce,\n variants,\n };\n\n return (\n <ApertoContext.Provider value={contextValue}>\n <Dialog.Root onOpenChange={onOpenChange} open={open} {...dialogProps}>\n <LazyMotion features={domMax}>\n <LayoutGroup id={layoutId}>{children}</LayoutGroup>\n </LazyMotion>\n </Dialog.Root>\n </ApertoContext.Provider>\n );\n};\n\nexport { ApertoRoot };\n","\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst ApertoTitle = ({ ref, ...props }: ComponentPropsWithRef<typeof Dialog.Title>) => (\n <Dialog.Title data-slot=\"aperto-title\" ref={ref} {...props} />\n);\n\nApertoTitle.displayName = \"ApertoTitle\";\n\nexport { ApertoTitle };\n","import { AnimatePresence, m } from \"motion/react\";\nimport type { TargetAndTransition, Transition } from \"motion/react\";\n\nimport { useApertoContext } from \"./context\";\nimport { ApertoExpandedMedia } from \"./media-rendering\";\nimport { getMediaKey } from \"./media-utils\";\nimport type {\n ApertoMediaItem,\n NavigationMotionPresetName,\n RenderImage,\n RenderVideo,\n} from \"./types\";\n\nexport type NavigationDirection = -1 | 0 | 1;\n\ninterface NavigationMotionPreset {\n offset: number;\n scale: number;\n transition: Transition;\n}\n\ninterface NavigationAnimationCustom {\n direction: NavigationDirection;\n offset: number;\n scale: number;\n}\n\nconst NAVIGATION_MOTION_PRESETS: Record<NavigationMotionPresetName, NavigationMotionPreset> = {\n float: {\n offset: 96,\n scale: 0.97,\n transition: {\n opacity: { duration: 0.34, ease: [0.45, 0, 0.2, 1] },\n scale: { damping: 26, mass: 1.15, stiffness: 80, type: \"spring\" },\n x: { damping: 26, mass: 1.15, stiffness: 80, type: \"spring\" },\n },\n },\n glide: {\n offset: 58,\n scale: 0.984,\n transition: {\n opacity: { duration: 0.24, ease: [0.4, 0, 0.2, 1] },\n scale: { damping: 28, mass: 0.95, stiffness: 150, type: \"spring\" },\n x: { damping: 28, mass: 0.95, stiffness: 150, type: \"spring\" },\n },\n },\n snap: {\n offset: 38,\n scale: 0.996,\n transition: {\n opacity: { duration: 0.12, ease: [0.2, 0, 0, 1] },\n scale: { damping: 34, mass: 0.7, stiffness: 420, type: \"spring\" },\n x: { damping: 34, mass: 0.7, stiffness: 420, type: \"spring\" },\n },\n },\n};\n\nconst REDUCED_EXPANDED_MEDIA_TRANSITION: Transition = {\n duration: 0.12,\n ease: \"linear\",\n};\n\nconst expandedMediaVariants = {\n center: {\n opacity: 1,\n scale: 1,\n x: 0,\n },\n enter: ({ direction, offset, scale }: NavigationAnimationCustom): TargetAndTransition => ({\n opacity: 0,\n scale: direction === 0 ? 1 : scale,\n x: direction * offset,\n }),\n exit: ({ direction, offset, scale }: NavigationAnimationCustom): TargetAndTransition => ({\n opacity: 0,\n scale: direction === 0 ? 1 : scale,\n x: direction * -offset,\n }),\n};\n\nconst reducedExpandedMediaVariants = {\n center: {\n opacity: 1,\n x: 0,\n },\n enter: {\n opacity: 0,\n x: 0,\n },\n exit: {\n opacity: 0,\n x: 0,\n },\n};\n\nexport const ApertoExpandedMediaStage = ({\n direction,\n index,\n item,\n navigationMotion,\n renderImage,\n renderVideo,\n}: {\n direction: NavigationDirection;\n index: number;\n item: ApertoMediaItem;\n navigationMotion: NavigationMotionPresetName;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n}) => {\n const ctx = useApertoContext();\n const preset = NAVIGATION_MOTION_PRESETS[navigationMotion];\n const transition = ctx.reduceMotion ? REDUCED_EXPANDED_MEDIA_TRANSITION : preset.transition;\n const variants = ctx.reduceMotion ? reducedExpandedMediaVariants : expandedMediaVariants;\n const animationCustom: NavigationAnimationCustom = {\n direction,\n offset: preset.offset,\n scale: preset.scale,\n };\n\n return (\n <AnimatePresence custom={animationCustom} initial={false} mode=\"sync\">\n <m.div\n animate=\"center\"\n custom={animationCustom}\n data-navigation-direction={direction}\n data-navigation-motion={navigationMotion}\n data-slot=\"aperto-media-stage\"\n exit=\"exit\"\n initial=\"enter\"\n key={getMediaKey(item, index)}\n transition={transition}\n variants={variants}\n >\n <ApertoExpandedMedia item={item} renderImage={renderImage} renderVideo={renderVideo} />\n </m.div>\n </AnimatePresence>\n );\n};\n","import { createElement } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport type { ApertoMediaItem, RenderImage, RenderVideo } from \"./types\";\n\nconst renderDefaultImage = (props: Parameters<RenderImage>[0]): ReactNode => {\n const { item: _item, variant: _variant, ...imageProps } = props;\n return createElement(\"img\", { ...imageProps, alt: imageProps.alt ?? \"\" });\n};\n\nconst renderDefaultVideo = (props: Parameters<RenderVideo>[0]): ReactNode => {\n const { item: _item, variant, ...videoProps } = props;\n if (variant === \"thumbnail\") {\n return createElement(\"img\", {\n alt: videoProps[\"aria-label\"] ?? \"\",\n src: props.item.thumbnailSrc,\n });\n }\n return (\n <video {...videoProps}>\n <track kind=\"captions\" src={props.item.captionsSrc ?? \"data:text/vtt,\"} />\n </video>\n );\n};\n\nexport const ApertoThumbnailMedia = ({\n item,\n renderImage,\n renderVideo,\n}: {\n item: ApertoMediaItem;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n}): ReactNode => {\n if (item.type === \"image\") {\n const imageProps: Parameters<RenderImage>[0] = {\n alt: \"\",\n height: item.height,\n item,\n src: item.thumbnailSrc ?? item.src,\n variant: \"thumbnail\",\n width: item.width,\n };\n return (renderImage ?? renderDefaultImage)(imageProps);\n }\n\n const videoProps: Parameters<RenderVideo>[0] = {\n \"aria-label\": item.alt ?? item.title ?? \"Video thumbnail\",\n height: item.height,\n item,\n poster: item.poster,\n src: item.thumbnailSrc,\n variant: \"thumbnail\",\n width: item.width,\n };\n return (renderVideo ?? renderDefaultVideo)(videoProps);\n};\n\nexport const ApertoExpandedMedia = ({\n item,\n renderImage,\n renderVideo,\n}: {\n item: ApertoMediaItem;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n}): ReactNode => {\n if (item.type === \"image\") {\n const imageProps: Parameters<RenderImage>[0] = {\n alt: item.alt,\n height: item.height,\n item,\n src: item.src,\n variant: \"expanded\",\n width: item.width,\n };\n return (renderImage ?? renderDefaultImage)(imageProps);\n }\n\n const videoProps: Parameters<RenderVideo>[0] = {\n \"aria-label\": item.alt ?? item.title ?? \"Video\",\n controls: true,\n height: item.height,\n item,\n poster: item.poster,\n src: item.src,\n variant: \"expanded\",\n width: item.width,\n };\n return (renderVideo ?? renderDefaultVideo)(videoProps);\n};\n\nexport const ApertoTransitionMedia = ({\n item,\n renderImage,\n renderVideo,\n}: {\n item: ApertoMediaItem;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n}): ReactNode => {\n if (item.type === \"image\") {\n const imageProps: Parameters<RenderImage>[0] = {\n alt: item.alt,\n height: item.height,\n item,\n // The clone flies with the thumbnail's pixels — they are already decoded\n // and on screen, so the shared element stays seamless in flight. Using\n // the full-size `src` here makes the morph pop to a blank/half-loaded\n // frame whenever the expanded asset differs from the thumbnail and has\n // not finished loading yet. `variant: \"thumbnail\"` matters for the same\n // reason: consumers key srcset/sizes off the variant, and only the\n // thumbnail variant reproduces the exact URL the browser already has in\n // cache.\n src: item.thumbnailSrc ?? item.src,\n variant: \"thumbnail\",\n width: item.width,\n };\n return (renderImage ?? renderDefaultImage)(imageProps);\n }\n\n const videoProps: Parameters<RenderVideo>[0] = {\n \"aria-label\": item.alt ?? item.title ?? \"Video\",\n height: item.height,\n item,\n poster: item.poster,\n src: item.src,\n variant: \"expanded\",\n width: item.width,\n };\n return (renderVideo ?? renderDefaultVideo)(videoProps);\n};\n","import type { ApertoMediaItem } from \"./types\";\n\nexport const getMediaLabel = (item: ApertoMediaItem): string => item.title ?? item.alt ?? \"media\";\n\nexport const getMediaKey = (item: ApertoMediaItem, index: number): string =>\n item.id ?? `${item.type}:${item.src}:${index}`;\n\nexport const getDescriptionProps = (\n item: ApertoMediaItem,\n): {\n \"aria-describedby\"?: undefined;\n} =>\n item.description === undefined || item.description === \"\"\n ? { \"aria-describedby\": undefined }\n : {};\n","import { m } from \"motion/react\";\nimport { useEffect, useRef } from \"react\";\n\nimport { useApertoContext } from \"./context\";\nimport { ApertoTransitionMedia } from \"./media-rendering\";\nimport { rectTarget, transitionDurationMs } from \"./media-transition-utils\";\nimport type { ApertoMediaTransition } from \"./media-transition-utils\";\nimport type { RenderImage, RenderVideo } from \"./types\";\n\nexport const ApertoMediaTransitionClone = ({\n onComplete,\n renderImage,\n renderVideo,\n transition,\n}: {\n onComplete: () => void;\n renderImage?: RenderImage;\n renderVideo?: RenderVideo;\n transition: ApertoMediaTransition | null;\n}) => {\n const ctx = useApertoContext();\n // Hold the latest onComplete in a ref so parent re-renders (which recreate the\n // callback) do not restart the completion countdown mid-transition.\n const onCompleteRef = useRef(onComplete);\n useEffect(() => {\n onCompleteRef.current = onComplete;\n });\n\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n if (transition?.to !== undefined) {\n timer = setTimeout(() => {\n onCompleteRef.current();\n }, transitionDurationMs(ctx.preset.transition));\n }\n\n return () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n };\n }, [ctx.preset.transition, transition]);\n\n if (transition?.to === undefined) {\n return null;\n }\n\n return (\n <m.div\n animate={rectTarget(transition.to)}\n aria-hidden=\"true\"\n data-slot=\"aperto-transition-media\"\n initial={rectTarget(transition.from)}\n style={{\n borderRadius: \"var(--aperto-radius, 0.5rem)\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n position: \"fixed\",\n zIndex: \"var(--patternmode-aperto-clone-z, 1002)\",\n }}\n transition={ctx.preset.transition}\n >\n <ApertoTransitionMedia\n item={transition.item}\n renderImage={renderImage}\n renderVideo={renderVideo}\n />\n </m.div>\n );\n};\n","import type { TargetAndTransition, Transition } from \"motion/react\";\nimport type { ApertoMediaItem } from \"./types\";\n\nexport interface ApertoRect {\n height: number;\n left: number;\n top: number;\n width: number;\n}\n\nexport interface ApertoMediaTransition {\n from: ApertoRect;\n item: ApertoMediaItem;\n phase: \"opening\" | \"closing\";\n to?: ApertoRect;\n}\n\nexport const rectFromElement = (element: Element | null): ApertoRect | null => {\n if (!element) {\n return null;\n }\n\n const rect = element.getBoundingClientRect();\n return {\n height: rect.height,\n left: rect.left,\n top: rect.top,\n width: rect.width,\n };\n};\n\n/**\n * The rect the shared element actually flies from/to on the thumbnail side.\n *\n * Thumbnails commonly wrap the media in extra chrome (captions, badges), so\n * measuring the trigger itself would fly the clone from the whole card —\n * visibly distorting the media's aspect in flight. Measure the media instead:\n * an explicit `[data-aperto-media-source]`, else the first `img`/`video`,\n * falling back to the trigger.\n */\nexport const rectFromTrigger = (trigger: Element | null): ApertoRect | null => {\n if (!trigger) {\n return null;\n }\n\n const media = trigger.querySelector(\"[data-aperto-media-source], img, video\");\n return rectFromElement(media ?? trigger);\n};\n\nexport const rectTarget = (rect: ApertoRect): TargetAndTransition => ({\n height: rect.height,\n left: rect.left,\n top: rect.top,\n width: rect.width,\n});\n\nexport const transitionDurationMs = (transition: Transition): number =>\n typeof transition.duration === \"number\" ? transition.duration * 1000 : 450;\n","import type { NavigationDirection } from \"../expanded-media-stage\";\nimport type { ApertoMediaTransition, ApertoRect } from \"../media-transition-utils\";\n\nexport interface ApertoGroupState {\n closing: boolean;\n internalIndex: number;\n layoutSourceIndex: number;\n mediaTransition: ApertoMediaTransition | null;\n navigationDirection: NavigationDirection;\n open: boolean;\n /** Index of the thumbnail that opened the Media Transition; focus returns here on close. */\n openerIndex: number | null;\n}\n\nexport type ApertoGroupAction =\n | { type: \"close-without-transition\" }\n | { type: \"complete-opening-target\"; rect: ApertoRect }\n | { type: \"finish-transition\" }\n | { type: \"navigate\"; direction: NavigationDirection; index: number }\n | {\n type: \"open-at-index\";\n index: number;\n transition: ApertoMediaTransition | null;\n }\n | { type: \"set-index\"; index: number }\n | { type: \"set-open\"; open: boolean }\n | { type: \"start-close\"; transition: ApertoMediaTransition };\n\nexport const getInitialGroupState = (initialIndex: number): ApertoGroupState => ({\n closing: false,\n internalIndex: initialIndex,\n layoutSourceIndex: initialIndex,\n mediaTransition: null,\n navigationDirection: 0,\n open: false,\n openerIndex: null,\n});\n\nexport const apertoGroupReducer = (\n state: ApertoGroupState,\n action: ApertoGroupAction,\n): ApertoGroupState => {\n switch (action.type) {\n case \"close-without-transition\": {\n return { ...state, closing: false, mediaTransition: null, open: false };\n }\n case \"complete-opening-target\": {\n if (state.mediaTransition?.phase !== \"opening\" || state.mediaTransition.to) {\n return state;\n }\n return {\n ...state,\n mediaTransition: { ...state.mediaTransition, to: action.rect },\n };\n }\n case \"finish-transition\": {\n return {\n ...state,\n closing: false,\n mediaTransition: null,\n open: state.mediaTransition?.phase === \"closing\" ? false : state.open,\n };\n }\n case \"navigate\": {\n return {\n ...state,\n internalIndex: action.index,\n layoutSourceIndex: action.index,\n navigationDirection: action.direction,\n };\n }\n case \"open-at-index\": {\n return {\n ...state,\n closing: false,\n internalIndex: action.index,\n layoutSourceIndex: action.index,\n mediaTransition: action.transition,\n navigationDirection: 0,\n open: true,\n openerIndex: action.index,\n };\n }\n case \"set-index\": {\n return { ...state, internalIndex: action.index };\n }\n case \"set-open\": {\n return action.open\n ? { ...state, closing: false, open: true, openerIndex: state.internalIndex }\n : { ...state, open: false };\n }\n case \"start-close\": {\n return {\n ...state,\n closing: true,\n mediaTransition: action.transition,\n };\n }\n default: {\n return state;\n }\n }\n};\n","export const shouldIgnoreKeyboardNavigationTarget = (target: EventTarget | null): boolean => {\n if (!(target instanceof HTMLElement)) {\n return false;\n }\n\n return (\n target.isContentEditable ||\n Boolean(\n target.closest(\n 'input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"textbox\"], audio, video',\n ),\n )\n );\n};\n","\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport { X } from \"lucide-react\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst ApertoClose = ({ children, ref, ...props }: ComponentPropsWithRef<typeof Dialog.Close>) => (\n <Dialog.Close data-slot=\"aperto-close\" ref={ref} {...props}>\n {children ?? <X aria-hidden=\"true\" size={17} strokeWidth={2} />}\n </Dialog.Close>\n);\n\nApertoClose.displayName = \"ApertoClose\";\n\nexport { ApertoClose };\n","\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport { m } from \"motion/react\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nimport { useApertoContext } from \"./context\";\nimport { resolvePreset } from \"./presets\";\nimport type { MotionPresetName } from \"./types\";\n\nconst TRIGGER_OPEN_Z_INDEX = 1000;\n\nexport interface ApertoTriggerProps extends ComponentPropsWithRef<typeof Dialog.Trigger> {\n /** Internal flag used by grouped thumbnails to raise only the active trigger. */\n active?: boolean;\n /** Override motion preset for this trigger */\n motion?: MotionPresetName;\n /** Internal shared layout ID override for grouped thumbnails. */\n sharedLayoutId?: string | false;\n}\n\nconst ApertoTrigger = ({\n active,\n children,\n motion: motionOverride,\n ref,\n sharedLayoutId,\n ...props\n}: ApertoTriggerProps) => {\n const ctx = useApertoContext();\n const shouldRaise = ctx.open && (active ?? true);\n const zIndex = shouldRaise ? TRIGGER_OPEN_Z_INDEX : 0;\n\n const resolved = resolvePreset(\n \"trigger\",\n motionOverride,\n ctx.presetName,\n ctx.variants,\n ctx.reduceMotion,\n );\n const layoutId =\n sharedLayoutId === false ? undefined : (sharedLayoutId ?? `${ctx.layoutId}-shared`);\n\n return (\n // `key` sits on the Trigger (not the render element, which Base UI re-clones)\n // so a changing shared `layoutId` still remounts the Motion button and\n // resets its layout animation.\n <Dialog.Trigger\n key={layoutId ?? \"unshared\"}\n ref={ref}\n render={\n <m.button\n data-aperto-active={shouldRaise ? \"\" : undefined}\n data-slot=\"aperto-trigger\"\n layout\n layoutCrossfade={false}\n layoutId={layoutId}\n style={{ zIndex }}\n transition={resolved.transition}\n type=\"button\"\n >\n {children}\n </m.button>\n }\n {...props}\n />\n );\n};\n\nApertoTrigger.displayName = \"ApertoTrigger\";\n\nexport { ApertoTrigger };\n","\"use client\";\n\nimport { ApertoClose } from \"../aperto-close\";\nimport { ApertoContent } from \"../aperto-content\";\nimport { ApertoDescription } from \"../aperto-description\";\nimport { ApertoOverlay } from \"../aperto-overlay\";\nimport { ApertoPortal } from \"../aperto-portal\";\nimport { ApertoRoot } from \"../aperto-root\";\nimport { ApertoTitle } from \"../aperto-title\";\nimport { ApertoTrigger } from \"../aperto-trigger\";\nimport { ApertoExpandedMedia, ApertoThumbnailMedia } from \"../media-rendering\";\nimport { getDescriptionProps, getMediaLabel } from \"../media-utils\";\nimport type { ApertoProps } from \"./aperto-types\";\n\nexport const ApertoSingle = ({\n classNames,\n dismissible,\n media,\n renderImage,\n renderVideo,\n}: ApertoProps) => {\n const label = getMediaLabel(media);\n const title = media.title ?? label;\n\n return (\n <ApertoRoot dismissible={dismissible}>\n <ApertoTrigger aria-label={`Open ${label}`} className={classNames?.thumbnail}>\n <ApertoThumbnailMedia item={media} renderImage={renderImage} renderVideo={renderVideo} />\n </ApertoTrigger>\n <ApertoPortal>\n <ApertoOverlay className={classNames?.overlay} />\n <ApertoContent className={classNames?.content} {...getDescriptionProps(media)}>\n <ApertoExpandedMedia item={media} renderImage={renderImage} renderVideo={renderVideo} />\n <ApertoTitle>{title}</ApertoTitle>\n {media.description === undefined || media.description === \"\" ? null : (\n <ApertoDescription>{media.description}</ApertoDescription>\n )}\n <ApertoClose aria-label=\"Close\" className={classNames?.closeButton} type=\"button\" />\n </ApertoContent>\n </ApertoPortal>\n </ApertoRoot>\n );\n};\n","\"use client\";\n\nimport { useApertoGroup } from \"../aperto-group-context\";\nimport { ApertoTrigger } from \"../aperto-trigger\";\nimport { ApertoThumbnailMedia } from \"../media-rendering\";\nimport { getMediaLabel } from \"../media-utils\";\nimport type { ApertoThumbnailProps } from \"./aperto-types\";\n\nexport const ApertoThumbnail = ({ children, className, index }: ApertoThumbnailProps) => {\n const group = useApertoGroup();\n const media = group.media[index];\n\n if (!media) {\n return null;\n }\n\n return (\n <ApertoTrigger\n active={group.index === index}\n aria-label={`Open ${getMediaLabel(media)}`}\n className={className ?? group.classNames?.thumbnail}\n onClick={() => {\n group.openAtIndex(index);\n }}\n ref={(node: HTMLButtonElement | null) => {\n group.registerThumbnail(index, node);\n }}\n sharedLayoutId={false}\n >\n {children ?? (\n <ApertoThumbnailMedia\n item={media}\n renderImage={group.renderImage}\n renderVideo={group.renderVideo}\n />\n )}\n </ApertoTrigger>\n );\n};\n","\"use client\";\n\n/**\n * Package: @patternmode/aperto\n *\n * Opinionated thumbnail-to-expanded media transitions.\n * Built on Radix Dialog + Motion.\n *\n * Inspired by Cambio (https://github.com/raphaelsalaja/cambio)\n * by Raphael Salaja.\n *\n * @example\n * ```tsx\n * import { Aperto } from \"@patternmode/aperto\";\n *\n * import { Aperto } from \"@patternmode/aperto\";\n * import \"@patternmode/aperto/styles.css\";\n *\n * <Aperto.Group media={media}>\n * {media.map((item, index) => (\n * <Aperto.Thumbnail key={item.id ?? item.src} index={index} />\n * ))}\n * </Aperto.Group>\n * ```\n */\n\nimport { ApertoGroup, ApertoSingle, ApertoThumbnail } from \"./aperto\";\nimport type { ApertoGroupProps, ApertoProps, ApertoThumbnailProps } from \"./aperto\";\nimport { ApertoClose } from \"./aperto-close\";\nimport { ApertoContent } from \"./aperto-content\";\nimport type { ApertoContentProps } from \"./aperto-content\";\nimport { ApertoDescription } from \"./aperto-description\";\nimport { ApertoOverlay } from \"./aperto-overlay\";\nimport type { ApertoOverlayProps } from \"./aperto-overlay\";\nimport { ApertoPortal } from \"./aperto-portal\";\nimport type { ApertoPortalProps } from \"./aperto-portal\";\nimport { ApertoRoot } from \"./aperto-root\";\nimport type { ApertoRootProps } from \"./aperto-root\";\nimport { ApertoTitle } from \"./aperto-title\";\nimport { ApertoTrigger } from \"./aperto-trigger\";\nimport type { ApertoTriggerProps } from \"./aperto-trigger\";\n\n/** Lower-level compound component namespace for advanced composition. */\nconst ApertoPrimitive = {\n Close: ApertoClose,\n Content: ApertoContent,\n Description: ApertoDescription,\n Overlay: ApertoOverlay,\n Portal: ApertoPortal,\n Root: ApertoRoot,\n Title: ApertoTitle,\n Trigger: ApertoTrigger,\n};\n\n/** Primary media-first component namespace. */\nconst Aperto = Object.assign(ApertoSingle, {\n Group: ApertoGroup,\n Primitive: ApertoPrimitive,\n Thumbnail: ApertoThumbnail,\n});\n\n// Preset system\nexport { PRESETS, resolvePreset } from \"./presets\";\n// Types\nexport type {\n ApertoClassNames,\n ApertoImageItem,\n ApertoMediaItem,\n ApertoVideoItem,\n DismissibleConfig,\n DragSpringConfig,\n MotionPreset,\n MotionPresetName,\n MotionProp,\n MotionVariants,\n NavigationMotionPresetName,\n RenderImage,\n RenderVideo,\n} from \"./types\";\n// Named exports for tree-shaking\nexport {\n Aperto,\n ApertoClose,\n ApertoContent,\n type ApertoContentProps,\n ApertoDescription,\n ApertoGroup,\n type ApertoGroupProps,\n ApertoOverlay,\n type ApertoOverlayProps,\n ApertoPortal,\n type ApertoPortalProps,\n ApertoPrimitive,\n type ApertoProps,\n ApertoRoot,\n type ApertoRootProps,\n ApertoThumbnail,\n type ApertoThumbnailProps,\n ApertoTitle,\n ApertoTrigger,\n type ApertoTriggerProps,\n};\n"],"mappings":"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","names":["useId","useRef","Dialog","jsx","createContext","use","Dialog","m","easings","jsx","Dialog","m","Dialog","jsx","Dialog","Dialog","useState","jsx","useState","Dialog","Dialog","jsx","AnimatePresence","m","jsx","jsx","AnimatePresence","m","m","jsx","m","jsx","useRef","useId","Dialog","X","jsx","Dialog","m","jsx","Dialog","m","jsx","jsxs","jsx"]}
package/dist/styles.css CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-ease:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-leading:initial;--tw-font-weight:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}[data-slot=aperto-trigger]{border-radius:var(--aperto-radius,.5rem);border-style:var(--tw-border-style);padding:calc(var(--spacing,.25rem) * 0);text-align:left;--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-outline-style:none;cursor:zoom-in;transition-property:filter,transform;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s));--tw-duration:.2s;--tw-ease:var(--ease-out,cubic-bezier(0, 0, .2, 1));transition-duration:.2s;transition-timing-function:var(--ease-out,cubic-bezier(0, 0, .2, 1));background-color:#0000;border-width:0;outline-style:none;display:block;position:relative;overflow:hidden}[data-slot=aperto-trigger]:hover{--tw-brightness:brightness(.96);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}[data-slot=aperto-trigger]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:#fffc}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-trigger]:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-white,#fff) 80%, transparent)}}[data-slot=aperto-trigger]:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-offset-color:var(--color-black,#000)}[data-slot=aperto-trigger]>img,[data-slot=aperto-trigger]>video{object-fit:cover;width:100%;height:100%;display:block}[data-slot=aperto-trigger][data-aperto-active]>img,[data-slot=aperto-trigger][data-aperto-active]>video{visibility:hidden}[data-slot=aperto-overlay]{inset:calc(var(--spacing,.25rem) * 0);z-index:1000;background-color:#000c;position:fixed}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-overlay]{background-color:color-mix(in oklab, var(--color-black,#000) 80%, transparent)}}[data-slot=aperto-content]{z-index:1001;justify-content:center;align-items:center;gap:calc(var(--spacing,.25rem) * 3);border-radius:var(--aperto-radius,.5rem);width:fit-content;max-width:min(92vw,1200px);height:fit-content;max-height:min(90vh,920px);padding:calc(var(--spacing,.25rem) * 0);color:var(--color-white,#fff);--tw-outline-style:none;overscroll-behavior:contain;outline-style:none;flex-direction:column;display:flex;position:fixed;overflow:visible}[data-slot=aperto-content]>img,[data-slot=aperto-content]>video,[data-slot=aperto-content]>[data-slot=aperto-media]{border-radius:var(--aperto-radius,.5rem);aspect-ratio:var(--aperto-expanded-aspect-ratio,3 / 2);max-width:90vw;height:auto;max-height:calc(100dvh - 8rem);width:min(var(--aperto-expanded-width,76vw), calc((100dvh - 8rem) * ( var(--aperto-expanded-aspect-ratio-width,3) / var(--aperto-expanded-aspect-ratio-height,2) )), 1000px, 90vw);display:block}[data-slot=aperto-media]{position:relative;overflow:hidden}[data-slot=aperto-media]>img,[data-slot=aperto-media]>video,[data-slot=aperto-media-stage]>img,[data-slot=aperto-media-stage]>video,[data-slot=aperto-transition-media]>img,[data-slot=aperto-transition-media]>video{width:100%;height:100%;display:block}[data-slot=aperto-media-stage]{inset:calc(var(--spacing,.25rem) * 0);position:absolute}[data-slot=aperto-content][data-aperto-transition] [data-slot=aperto-media-stage],[data-slot=aperto-transition-media]{will-change:opacity, transform}[data-slot=aperto-content][data-aperto-transition]>*{pointer-events:none;opacity:0}@keyframes aperto-control-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-close],[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-media]>[data-slot=aperto-previous-button],[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-media]>[data-slot=aperto-next-button]{animation:.35s cubic-bezier(.25,.1,.12,1) 80ms both aperto-control-in}[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-title],[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-description],[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-counter]{animation:.4s cubic-bezier(.25,.1,.12,1) .18s both aperto-control-in}[data-slot=aperto-title]{text-align:center;--tw-leading:var(--leading-snug,1.375);max-width:60ch;font-size:13px;line-height:var(--leading-snug,1.375);--tw-font-weight:var(--font-weight-medium,500);font-weight:var(--font-weight-medium,500);color:#ffffffe6}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-title]{color:color-mix(in oklab, var(--color-white,#fff) 90%, transparent)}}[data-slot=aperto-description]{margin-top:calc(var(--spacing,.25rem) * -1.5);text-align:center;--tw-leading:var(--leading-snug,1.375);max-width:60ch;font-size:13px;line-height:var(--leading-snug,1.375);color:#fff9}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-description]{color:color-mix(in oklab, var(--color-white,#fff) 60%, transparent)}}[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{z-index:10;width:calc(var(--spacing,.25rem) * 8);height:calc(var(--spacing,.25rem) * 8);border-style:var(--tw-border-style);background-color:#ffffff1a;border-width:0;border-radius:3.40282e38px;place-items:center;display:grid;position:absolute}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{background-color:color-mix(in oklab, var(--color-white,#fff) 10%, transparent)}}[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{color:color-mix(in oklab, var(--color-white,#fff) 70%, transparent)}}[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{transition-property:background,color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s));--tw-duration:.15s;--tw-ease:var(--ease-out,cubic-bezier(0, 0, .2, 1));transition-duration:.15s;transition-timing-function:var(--ease-out,cubic-bezier(0, 0, .2, 1))}@media (hover:hover) and (pointer:fine){[data-slot=aperto-close]:hover,[data-slot=aperto-previous-button]:hover,[data-slot=aperto-next-button]:hover{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-close]:hover,[data-slot=aperto-previous-button]:hover,[data-slot=aperto-next-button]:hover{background-color:color-mix(in oklab, var(--color-white,#fff) 20%, transparent)}}[data-slot=aperto-close]:hover,[data-slot=aperto-previous-button]:hover,[data-slot=aperto-next-button]:hover{color:var(--color-white,#fff)}}[data-slot=aperto-close]:focus-visible,[data-slot=aperto-previous-button]:focus-visible,[data-slot=aperto-next-button]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:#fff9}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-close]:focus-visible,[data-slot=aperto-previous-button]:focus-visible,[data-slot=aperto-next-button]:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-white,#fff) 60%, transparent)}}[data-slot=aperto-close]:focus-visible,[data-slot=aperto-previous-button]:focus-visible,[data-slot=aperto-next-button]:focus-visible{--tw-outline-style:none;outline-style:none}[data-slot=aperto-close]{top:calc(var(--spacing,.25rem) * 3);right:calc(var(--spacing,.25rem) * 3)}[data-slot=aperto-previous-button]{top:50%;left:calc(var(--spacing,.25rem) * 3);--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}[data-slot=aperto-next-button]{top:50%;right:calc(var(--spacing,.25rem) * 3);--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}[data-slot=aperto-close]>svg,[data-slot=aperto-previous-button]>svg,[data-slot=aperto-next-button]>svg{pointer-events:none;width:calc(var(--spacing,.25rem) * 4);height:calc(var(--spacing,.25rem) * 4)}[data-slot=aperto-counter]{background-color:#ffffff1a;border-radius:3.40282e38px}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-counter]{background-color:color-mix(in oklab, var(--color-white,#fff) 10%, transparent)}}[data-slot=aperto-counter]{padding-inline:calc(var(--spacing,.25rem) * 2.5);padding-block:calc(var(--spacing,.25rem) * .5);--tw-font-weight:var(--font-weight-medium,500);font-size:11px;font-weight:var(--font-weight-medium,500);color:#ffffff80}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-counter]{color:color-mix(in oklab, var(--color-white,#fff) 50%, transparent)}}@media (max-width:560px){[data-slot=aperto-content]{gap:calc(var(--spacing,.25rem) * 2);max-width:calc(100vw - 1rem)}[data-slot=aperto-content]>img,[data-slot=aperto-content]>video,[data-slot=aperto-content]>[data-slot=aperto-media]{width:min(100vw - 2rem,150dvh - 18rem);max-width:calc(100vw - 2rem);max-height:calc(100dvh - 12rem)}[data-slot=aperto-title],[data-slot=aperto-description]{max-width:calc(100vw - 2rem)}[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{width:calc(var(--spacing,.25rem) * 11);height:calc(var(--spacing,.25rem) * 11);touch-action:manipulation}[data-slot=aperto-close]{top:calc(var(--spacing,.25rem) * 2);right:calc(var(--spacing,.25rem) * 2)}[data-slot=aperto-previous-button]{left:calc(var(--spacing,.25rem) * 2)}[data-slot=aperto-next-button]{right:calc(var(--spacing,.25rem) * 2)}}@media (prefers-reduced-motion:reduce){[data-slot=aperto-content]:not([data-aperto-transition])>*{animation:none!important}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-ease:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-leading:initial;--tw-font-weight:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}[data-slot=aperto-trigger]{border-radius:var(--aperto-radius,.5rem);border-style:var(--tw-border-style);padding:calc(var(--spacing,.25rem) * 0);text-align:left;--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-outline-style:none;cursor:zoom-in;transition-property:filter,transform;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s));--tw-duration:.2s;--tw-ease:var(--ease-out,cubic-bezier(0, 0, .2, 1));transition-duration:.2s;transition-timing-function:var(--ease-out,cubic-bezier(0, 0, .2, 1));background-color:#0000;border-width:0;outline-style:none;display:block;position:relative;overflow:hidden}[data-slot=aperto-trigger]:hover{--tw-brightness:brightness(.96);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}[data-slot=aperto-trigger]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:#fffc}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-trigger]:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-white,#fff) 80%, transparent)}}[data-slot=aperto-trigger]:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-offset-color:var(--color-black,#000)}[data-slot=aperto-trigger]>img,[data-slot=aperto-trigger]>video{object-fit:cover;width:100%;height:100%;display:block}[data-slot=aperto-trigger][data-aperto-active] img,[data-slot=aperto-trigger][data-aperto-active] video{visibility:hidden}[data-slot=aperto-overlay]{inset:calc(var(--spacing,.25rem) * 0);z-index:1000;background-color:#000c;position:fixed}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-overlay]{background-color:color-mix(in oklab, var(--color-black,#000) 80%, transparent)}}[data-slot=aperto-content]{--aperto-panel-max-h:min(90vh, 920px);z-index:1001;height:fit-content;max-height:var(--aperto-panel-max-h);justify-content:center;align-items:center;gap:calc(var(--spacing,.25rem) * 3);border-radius:var(--aperto-radius,.5rem);width:fit-content;max-width:min(92vw,1200px);padding:calc(var(--spacing,.25rem) * 0);color:var(--color-white,#fff);--tw-outline-style:none;overscroll-behavior:contain;outline-style:none;flex-direction:column;display:flex;position:fixed;overflow:visible}[data-slot=aperto-content]>img,[data-slot=aperto-content]>video,[data-slot=aperto-content]>[data-slot=aperto-media]{--aperto-media-max-h:min(calc(100dvh - 8rem), calc(var(--aperto-panel-max-h,min(90vh, 920px)) - var(--aperto-caption-allowance,6rem)));border-radius:var(--aperto-radius,.5rem);aspect-ratio:var(--aperto-expanded-aspect-ratio,3 / 2);height:auto;max-height:var(--aperto-media-max-h);max-width:90vw;width:min(var(--aperto-expanded-width,76vw), calc(var(--aperto-media-max-h) * ( var(--aperto-expanded-aspect-ratio-width,3) / var(--aperto-expanded-aspect-ratio-height,2) )), 1000px, 90vw);flex-shrink:0;display:block}[data-slot=aperto-media]{position:relative;overflow:hidden}[data-slot=aperto-media]>img,[data-slot=aperto-media]>video,[data-slot=aperto-media-stage]>img,[data-slot=aperto-media-stage]>video,[data-slot=aperto-transition-media]>img,[data-slot=aperto-transition-media]>video{width:100%;height:100%;display:block}[data-slot=aperto-media-stage]{inset:calc(var(--spacing,.25rem) * 0);position:absolute}[data-slot=aperto-content][data-aperto-transition] [data-slot=aperto-media-stage],[data-slot=aperto-transition-media]{will-change:opacity, transform}[data-slot=aperto-content][data-aperto-transition]>*{pointer-events:none;opacity:0}@keyframes aperto-control-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-close],[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-media]>[data-slot=aperto-previous-button],[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-media]>[data-slot=aperto-next-button]{animation:.35s cubic-bezier(.25,.1,.12,1) 80ms both aperto-control-in}[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-title],[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-description],[data-slot=aperto-content]:not([data-aperto-transition])>[data-slot=aperto-counter]{animation:.4s cubic-bezier(.25,.1,.12,1) .18s both aperto-control-in}[data-slot=aperto-title]{text-align:center;--tw-leading:var(--leading-snug,1.375);max-width:60ch;font-size:13px;line-height:var(--leading-snug,1.375);--tw-font-weight:var(--font-weight-medium,500);font-weight:var(--font-weight-medium,500);color:#ffffffe6}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-title]{color:color-mix(in oklab, var(--color-white,#fff) 90%, transparent)}}[data-slot=aperto-description]{margin-top:calc(var(--spacing,.25rem) * -1.5);text-align:center;--tw-leading:var(--leading-snug,1.375);max-width:60ch;font-size:13px;line-height:var(--leading-snug,1.375);color:#fff9}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-description]{color:color-mix(in oklab, var(--color-white,#fff) 60%, transparent)}}[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{z-index:10;width:calc(var(--spacing,.25rem) * 8);height:calc(var(--spacing,.25rem) * 8);border-style:var(--tw-border-style);background-color:#ffffff1a;border-width:0;border-radius:3.40282e38px;place-items:center;display:grid;position:absolute}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{background-color:color-mix(in oklab, var(--color-white,#fff) 10%, transparent)}}[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{color:color-mix(in oklab, var(--color-white,#fff) 70%, transparent)}}[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{transition-property:background,color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s));--tw-duration:.15s;--tw-ease:var(--ease-out,cubic-bezier(0, 0, .2, 1));transition-duration:.15s;transition-timing-function:var(--ease-out,cubic-bezier(0, 0, .2, 1))}@media (hover:hover) and (pointer:fine){[data-slot=aperto-close]:hover,[data-slot=aperto-previous-button]:hover,[data-slot=aperto-next-button]:hover{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-close]:hover,[data-slot=aperto-previous-button]:hover,[data-slot=aperto-next-button]:hover{background-color:color-mix(in oklab, var(--color-white,#fff) 20%, transparent)}}[data-slot=aperto-close]:hover,[data-slot=aperto-previous-button]:hover,[data-slot=aperto-next-button]:hover{color:var(--color-white,#fff)}}[data-slot=aperto-close]:focus-visible,[data-slot=aperto-previous-button]:focus-visible,[data-slot=aperto-next-button]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:#fff9}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-close]:focus-visible,[data-slot=aperto-previous-button]:focus-visible,[data-slot=aperto-next-button]:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-white,#fff) 60%, transparent)}}[data-slot=aperto-close]:focus-visible,[data-slot=aperto-previous-button]:focus-visible,[data-slot=aperto-next-button]:focus-visible{--tw-outline-style:none;outline-style:none}[data-slot=aperto-close]{top:calc(var(--spacing,.25rem) * 3);right:calc(var(--spacing,.25rem) * 3)}[data-slot=aperto-previous-button]{top:50%;left:calc(var(--spacing,.25rem) * 3);--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}[data-slot=aperto-next-button]{top:50%;right:calc(var(--spacing,.25rem) * 3);--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}[data-slot=aperto-close]>svg,[data-slot=aperto-previous-button]>svg,[data-slot=aperto-next-button]>svg{pointer-events:none;width:calc(var(--spacing,.25rem) * 4);height:calc(var(--spacing,.25rem) * 4)}[data-slot=aperto-counter]{background-color:#ffffff1a;border-radius:3.40282e38px}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-counter]{background-color:color-mix(in oklab, var(--color-white,#fff) 10%, transparent)}}[data-slot=aperto-counter]{padding-inline:calc(var(--spacing,.25rem) * 2.5);padding-block:calc(var(--spacing,.25rem) * .5);--tw-font-weight:var(--font-weight-medium,500);font-size:11px;font-weight:var(--font-weight-medium,500);color:#ffffff80}@supports (color:color-mix(in lab, red, red)){[data-slot=aperto-counter]{color:color-mix(in oklab, var(--color-white,#fff) 50%, transparent)}}@media (max-width:560px){[data-slot=aperto-content]{gap:calc(var(--spacing,.25rem) * 2);max-width:calc(100vw - 1rem)}[data-slot=aperto-content]>img,[data-slot=aperto-content]>video,[data-slot=aperto-content]>[data-slot=aperto-media]{--aperto-media-max-h:min(calc(100dvh - 12rem), calc(var(--aperto-panel-max-h,min(90vh, 920px)) - var(--aperto-caption-allowance,6rem)));max-height:var(--aperto-media-max-h);max-width:calc(100vw - 2rem);width:min(calc(100vw - 2rem), calc(var(--aperto-media-max-h) * ( var(--aperto-expanded-aspect-ratio-width,3) / var(--aperto-expanded-aspect-ratio-height,2) )))}[data-slot=aperto-title],[data-slot=aperto-description]{max-width:calc(100vw - 2rem)}[data-slot=aperto-close],[data-slot=aperto-previous-button],[data-slot=aperto-next-button]{width:calc(var(--spacing,.25rem) * 11);height:calc(var(--spacing,.25rem) * 11);touch-action:manipulation}[data-slot=aperto-close]{top:calc(var(--spacing,.25rem) * 2);right:calc(var(--spacing,.25rem) * 2)}[data-slot=aperto-previous-button]{left:calc(var(--spacing,.25rem) * 2)}[data-slot=aperto-next-button]{right:calc(var(--spacing,.25rem) * 2)}}@media (prefers-reduced-motion:reduce){[data-slot=aperto-content]:not([data-aperto-transition])>*{animation:none!important}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternmode/aperto",
3
- "version": "0.2.2",
3
+ "version": "2.0.0",
4
4
  "description": "Opinionated, styled thumbnail-to-expanded media transitions for React.",
5
5
  "homepage": "https://github.com/howells/patternmode/tree/main/packages/aperto#readme",
6
6
  "bugs": {
@@ -33,10 +33,9 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@radix-ui/react-dialog": "^1.1.15",
37
- "lucide-react": "^1.17.0",
36
+ "@base-ui/react": "^1.6.0",
38
37
  "motion": "^12.40.0",
39
- "@howells/motion": "0.1.0"
38
+ "@howells/motion": "0.2.0"
40
39
  },
41
40
  "devDependencies": {
42
41
  "@howells/lint": "^0.5.0",
@@ -49,6 +48,7 @@
49
48
  "@types/react-dom": "^19.2.3",
50
49
  "concurrently": "^9.2.1",
51
50
  "jsdom": "^29.1.1",
51
+ "lucide-react": "^1.17.0",
52
52
  "react": "^19.2.7",
53
53
  "react-dom": "^19.2.7",
54
54
  "tailwindcss": "^4.3.0",
@@ -57,6 +57,7 @@
57
57
  "vitest": "^4.1.8"
58
58
  },
59
59
  "peerDependencies": {
60
+ "lucide-react": "^1.17.0",
60
61
  "react": "^19.0.0",
61
62
  "react-dom": "^19.0.0"
62
63
  },