@patternmode/aperto 0.2.1 → 1.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 +66 -0
- package/dist/index.d.ts +16 -12
- package/dist/index.js +140 -80
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
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,
|
|
3
|
-
import * as
|
|
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.
|
|
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. */
|
|
@@ -239,7 +243,7 @@ interface ApertoRootProps extends Omit<ComponentPropsWithoutRef<typeof Dialog.Ro
|
|
|
239
243
|
/** Force reduced motion regardless of system preference */
|
|
240
244
|
reduceMotion?: boolean;
|
|
241
245
|
}
|
|
242
|
-
declare const ApertoRoot: ({ children, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react.JSX.Element;
|
|
246
|
+
declare const ApertoRoot: ({ children, defaultOpen, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react.JSX.Element;
|
|
243
247
|
|
|
244
248
|
declare const ApertoTitle: {
|
|
245
249
|
({ ref, ...props }: ComponentPropsWithRef<typeof Dialog.Title>): react.JSX.Element;
|
|
@@ -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<
|
|
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<
|
|
296
|
+
({ ref, ...props }: react.ComponentPropsWithRef<typeof _base_ui_react.DialogDescription>): react.JSX.Element;
|
|
293
297
|
displayName: string;
|
|
294
298
|
};
|
|
295
299
|
Overlay: {
|
|
@@ -297,9 +301,9 @@ declare const ApertoPrimitive: {
|
|
|
297
301
|
displayName: string;
|
|
298
302
|
};
|
|
299
303
|
Portal: ({ children, container }: ApertoPortalProps) => react.JSX.Element;
|
|
300
|
-
Root: ({ children, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react.JSX.Element;
|
|
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<
|
|
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<
|
|
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<
|
|
327
|
+
({ ref, ...props }: react.ComponentPropsWithRef<typeof _base_ui_react.DialogDescription>): react.JSX.Element;
|
|
324
328
|
displayName: string;
|
|
325
329
|
};
|
|
326
330
|
Overlay: {
|
|
@@ -328,9 +332,9 @@ declare const Aperto: (({ classNames, dismissible, media, renderImage, renderVid
|
|
|
328
332
|
displayName: string;
|
|
329
333
|
};
|
|
330
334
|
Portal: ({ children, container }: ApertoPortalProps) => react.JSX.Element;
|
|
331
|
-
Root: ({ children, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react.JSX.Element;
|
|
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<
|
|
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
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
// src/Aperto/aperto-group.tsx
|
|
4
4
|
import { ChevronLeft, ChevronRight, X } from "lucide-react";
|
|
5
|
-
import { useId as useId2, useLayoutEffect, useReducer, useRef } from "react";
|
|
5
|
+
import { useId as useId2, useLayoutEffect, useReducer, useRef as useRef2 } from "react";
|
|
6
6
|
|
|
7
7
|
// src/aperto-content.tsx
|
|
8
|
-
import
|
|
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
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
|
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
|
|
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,38 +227,50 @@ 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
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
|
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,
|
|
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
|
|
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";
|
|
247
271
|
var ApertoRoot = ({
|
|
248
272
|
children,
|
|
273
|
+
defaultOpen,
|
|
249
274
|
dismissible = true,
|
|
250
275
|
layoutId: layoutIdProp,
|
|
251
276
|
motion: motionProp = "smooth",
|
|
@@ -258,7 +283,7 @@ var ApertoRoot = ({
|
|
|
258
283
|
const layoutId = layoutIdProp ?? `aperto-${generatedId}`;
|
|
259
284
|
const systemReducedMotion = useReducedMotion() ?? false;
|
|
260
285
|
const shouldReduce = reduceMotionProp ?? systemReducedMotion;
|
|
261
|
-
const [internalOpen, setInternalOpen] = useState2(false);
|
|
286
|
+
const [internalOpen, setInternalOpen] = useState2(defaultOpen ?? false);
|
|
262
287
|
const isControlled = controlledOpen !== void 0;
|
|
263
288
|
const open = isControlled ? controlledOpen : internalOpen;
|
|
264
289
|
const onOpenChange = (nextOpen) => {
|
|
@@ -285,7 +310,7 @@ var ApertoRoot = ({
|
|
|
285
310
|
};
|
|
286
311
|
|
|
287
312
|
// src/aperto-title.tsx
|
|
288
|
-
import
|
|
313
|
+
import { Dialog as Dialog6 } from "@base-ui/react/dialog";
|
|
289
314
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
290
315
|
var ApertoTitle = ({ ref, ...props }) => /* @__PURE__ */ jsx6(Dialog6.Title, { "data-slot": "aperto-title", ref, ...props });
|
|
291
316
|
ApertoTitle.displayName = "ApertoTitle";
|
|
@@ -375,8 +400,16 @@ var ApertoTransitionMedia = ({
|
|
|
375
400
|
alt: item.alt,
|
|
376
401
|
height: item.height,
|
|
377
402
|
item,
|
|
378
|
-
|
|
379
|
-
|
|
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",
|
|
380
413
|
width: item.width
|
|
381
414
|
};
|
|
382
415
|
return (renderImage ?? renderDefaultImage)(imageProps);
|
|
@@ -501,7 +534,7 @@ var ApertoExpandedMediaStage = ({
|
|
|
501
534
|
|
|
502
535
|
// src/media-transition.tsx
|
|
503
536
|
import { m as m4 } from "motion/react";
|
|
504
|
-
import { useEffect } from "react";
|
|
537
|
+
import { useEffect, useRef } from "react";
|
|
505
538
|
|
|
506
539
|
// src/media-transition-utils.ts
|
|
507
540
|
var rectFromElement = (element) => {
|
|
@@ -516,6 +549,13 @@ var rectFromElement = (element) => {
|
|
|
516
549
|
width: rect.width
|
|
517
550
|
};
|
|
518
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
|
+
};
|
|
519
559
|
var rectTarget = (rect) => ({
|
|
520
560
|
height: rect.height,
|
|
521
561
|
left: rect.left,
|
|
@@ -533,17 +573,23 @@ var ApertoMediaTransitionClone = ({
|
|
|
533
573
|
transition
|
|
534
574
|
}) => {
|
|
535
575
|
const ctx = useApertoContext();
|
|
576
|
+
const onCompleteRef = useRef(onComplete);
|
|
577
|
+
useEffect(() => {
|
|
578
|
+
onCompleteRef.current = onComplete;
|
|
579
|
+
});
|
|
536
580
|
useEffect(() => {
|
|
537
581
|
let timer;
|
|
538
582
|
if (transition?.to !== void 0) {
|
|
539
|
-
timer = setTimeout(
|
|
583
|
+
timer = setTimeout(() => {
|
|
584
|
+
onCompleteRef.current();
|
|
585
|
+
}, transitionDurationMs(ctx.preset.transition));
|
|
540
586
|
}
|
|
541
587
|
return () => {
|
|
542
588
|
if (timer !== void 0) {
|
|
543
589
|
clearTimeout(timer);
|
|
544
590
|
}
|
|
545
591
|
};
|
|
546
|
-
}, [ctx.preset.transition,
|
|
592
|
+
}, [ctx.preset.transition, transition]);
|
|
547
593
|
if (transition?.to === void 0) {
|
|
548
594
|
return null;
|
|
549
595
|
}
|
|
@@ -559,7 +605,7 @@ var ApertoMediaTransitionClone = ({
|
|
|
559
605
|
overflow: "hidden",
|
|
560
606
|
pointerEvents: "none",
|
|
561
607
|
position: "fixed",
|
|
562
|
-
zIndex:
|
|
608
|
+
zIndex: "var(--patternmode-aperto-clone-z, 1002)"
|
|
563
609
|
},
|
|
564
610
|
transition: ctx.preset.transition,
|
|
565
611
|
children: /* @__PURE__ */ jsx9(
|
|
@@ -581,7 +627,8 @@ var getInitialGroupState = (initialIndex) => ({
|
|
|
581
627
|
layoutSourceIndex: initialIndex,
|
|
582
628
|
mediaTransition: null,
|
|
583
629
|
navigationDirection: 0,
|
|
584
|
-
open: false
|
|
630
|
+
open: false,
|
|
631
|
+
openerIndex: null
|
|
585
632
|
});
|
|
586
633
|
var apertoGroupReducer = (state, action) => {
|
|
587
634
|
switch (action.type) {
|
|
@@ -621,14 +668,15 @@ var apertoGroupReducer = (state, action) => {
|
|
|
621
668
|
layoutSourceIndex: action.index,
|
|
622
669
|
mediaTransition: action.transition,
|
|
623
670
|
navigationDirection: 0,
|
|
624
|
-
open: true
|
|
671
|
+
open: true,
|
|
672
|
+
openerIndex: action.index
|
|
625
673
|
};
|
|
626
674
|
}
|
|
627
675
|
case "set-index": {
|
|
628
676
|
return { ...state, internalIndex: action.index };
|
|
629
677
|
}
|
|
630
678
|
case "set-open": {
|
|
631
|
-
return action.open ? { ...state, closing: false, open: true } : { ...state, open: false };
|
|
679
|
+
return action.open ? { ...state, closing: false, open: true, openerIndex: state.internalIndex } : { ...state, open: false };
|
|
632
680
|
}
|
|
633
681
|
case "start-close": {
|
|
634
682
|
return {
|
|
@@ -692,7 +740,7 @@ var ApertoMediaNavigationButtons = ({
|
|
|
692
740
|
] });
|
|
693
741
|
};
|
|
694
742
|
var useThumbnailMap = () => {
|
|
695
|
-
const thumbnailRefs =
|
|
743
|
+
const thumbnailRefs = useRef2(null);
|
|
696
744
|
thumbnailRefs.current ??= /* @__PURE__ */ new Map();
|
|
697
745
|
return thumbnailRefs.current;
|
|
698
746
|
};
|
|
@@ -710,7 +758,7 @@ var ApertoGroupPortal = ({
|
|
|
710
758
|
activeMedia,
|
|
711
759
|
classNames,
|
|
712
760
|
expandedMediaStyle,
|
|
713
|
-
|
|
761
|
+
finalFocus,
|
|
714
762
|
handleContentKeyDown,
|
|
715
763
|
handleMediaTransitionComplete,
|
|
716
764
|
hasNavigation,
|
|
@@ -736,7 +784,7 @@ var ApertoGroupPortal = ({
|
|
|
736
784
|
{
|
|
737
785
|
className: classNames?.content,
|
|
738
786
|
"data-aperto-transition": transition?.phase,
|
|
739
|
-
|
|
787
|
+
finalFocus,
|
|
740
788
|
onKeyDown: handleContentKeyDown,
|
|
741
789
|
sharedLayoutId: false,
|
|
742
790
|
...getDescriptionProps(activeMedia),
|
|
@@ -803,7 +851,7 @@ var useApertoMediaLifecycle = ({
|
|
|
803
851
|
onIndexChange,
|
|
804
852
|
state
|
|
805
853
|
}) => {
|
|
806
|
-
const expandedMediaRef =
|
|
854
|
+
const expandedMediaRef = useRef2(null);
|
|
807
855
|
const thumbnailMap = useThumbnailMap();
|
|
808
856
|
const setExpandedMediaNode = (node) => {
|
|
809
857
|
expandedMediaRef.current = node;
|
|
@@ -832,7 +880,7 @@ var useApertoMediaLifecycle = ({
|
|
|
832
880
|
}
|
|
833
881
|
}, [dispatch, state.mediaTransition]);
|
|
834
882
|
const openAtIndex = (thumbIndex) => {
|
|
835
|
-
const sourceRect =
|
|
883
|
+
const sourceRect = rectFromTrigger(thumbnailMap.get(thumbIndex) ?? null);
|
|
836
884
|
const item = media[thumbIndex] ?? null;
|
|
837
885
|
const transition = sourceRect === null || item === null ? null : { from: sourceRect, item, phase: "opening" };
|
|
838
886
|
dispatch({ index: thumbIndex, transition, type: "open-at-index" });
|
|
@@ -843,7 +891,7 @@ var useApertoMediaLifecycle = ({
|
|
|
843
891
|
return;
|
|
844
892
|
}
|
|
845
893
|
const sourceRect = rectFromElement(expandedMediaRef.current);
|
|
846
|
-
const targetRect =
|
|
894
|
+
const targetRect = rectFromTrigger(thumbnailMap.get(index) ?? null);
|
|
847
895
|
if (activeMedia === void 0 || sourceRect === null || targetRect === null) {
|
|
848
896
|
dispatch({ type: "close-without-transition" });
|
|
849
897
|
return;
|
|
@@ -853,11 +901,11 @@ var useApertoMediaLifecycle = ({
|
|
|
853
901
|
type: "start-close"
|
|
854
902
|
});
|
|
855
903
|
};
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
thumbnailMap.get(index)
|
|
904
|
+
const finalFocus = () => {
|
|
905
|
+
const openerThumbnail = state.openerIndex === null ? void 0 : thumbnailMap.get(state.openerIndex);
|
|
906
|
+
return openerThumbnail ?? thumbnailMap.get(index) ?? null;
|
|
859
907
|
};
|
|
860
|
-
return {
|
|
908
|
+
return { finalFocus, openAtIndex, registerThumbnail, setExpandedMediaNode, startClose };
|
|
861
909
|
};
|
|
862
910
|
var useApertoGroupController = ({
|
|
863
911
|
classNames,
|
|
@@ -940,9 +988,9 @@ var useApertoGroupController = ({
|
|
|
940
988
|
return {
|
|
941
989
|
activeMedia,
|
|
942
990
|
expandedMediaStyle,
|
|
991
|
+
finalFocus: lifecycle.finalFocus,
|
|
943
992
|
goToNext,
|
|
944
993
|
goToPrevious,
|
|
945
|
-
handleCloseAutoFocus: lifecycle.handleCloseAutoFocus,
|
|
946
994
|
handleContentKeyDown,
|
|
947
995
|
handleMediaTransitionComplete,
|
|
948
996
|
handleOpenChange,
|
|
@@ -991,9 +1039,9 @@ var ApertoGroup = ({
|
|
|
991
1039
|
activeMedia: controller.activeMedia,
|
|
992
1040
|
classNames,
|
|
993
1041
|
expandedMediaStyle: controller.expandedMediaStyle,
|
|
1042
|
+
finalFocus: controller.finalFocus,
|
|
994
1043
|
goToNext: controller.goToNext,
|
|
995
1044
|
goToPrevious: controller.goToPrevious,
|
|
996
|
-
handleCloseAutoFocus: controller.handleCloseAutoFocus,
|
|
997
1045
|
handleContentKeyDown: controller.hasNavigation ? controller.handleContentKeyDown : void 0,
|
|
998
1046
|
handleMediaTransitionComplete: controller.handleMediaTransitionComplete,
|
|
999
1047
|
hasNavigation: controller.hasNavigation,
|
|
@@ -1014,14 +1062,14 @@ var ApertoGroup = ({
|
|
|
1014
1062
|
};
|
|
1015
1063
|
|
|
1016
1064
|
// src/aperto-close.tsx
|
|
1017
|
-
import
|
|
1065
|
+
import { Dialog as Dialog7 } from "@base-ui/react/dialog";
|
|
1018
1066
|
import { X as X2 } from "lucide-react";
|
|
1019
1067
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1020
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 }) });
|
|
1021
1069
|
ApertoClose.displayName = "ApertoClose";
|
|
1022
1070
|
|
|
1023
1071
|
// src/aperto-trigger.tsx
|
|
1024
|
-
import
|
|
1072
|
+
import { Dialog as Dialog8 } from "@base-ui/react/dialog";
|
|
1025
1073
|
import { m as m5 } from "motion/react";
|
|
1026
1074
|
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1027
1075
|
var TRIGGER_OPEN_Z_INDEX = 1e3;
|
|
@@ -1044,21 +1092,33 @@ var ApertoTrigger = ({
|
|
|
1044
1092
|
ctx.reduceMotion
|
|
1045
1093
|
);
|
|
1046
1094
|
const layoutId = sharedLayoutId === false ? void 0 : sharedLayoutId ?? `${ctx.layoutId}-shared`;
|
|
1047
|
-
return
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
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
|
+
);
|
|
1062
1122
|
};
|
|
1063
1123
|
ApertoTrigger.displayName = "ApertoTrigger";
|
|
1064
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 thumbnailMap.get(index)?.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 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(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 } 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\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n if (transition?.to !== undefined) {\n timer = setTimeout(onComplete, transitionDurationMs(ctx.preset.transition));\n }\n\n return () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n };\n }, [ctx.preset.transition, onComplete, 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: 30,\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}\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});\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 };\n }\n case \"set-index\": {\n return { ...state, internalIndex: action.index };\n }\n case \"set-open\": {\n return action.open ? { ...state, closing: false, open: true } : { ...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","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","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]>*{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.
|
|
3
|
+
"version": "1.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,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@
|
|
36
|
+
"@base-ui/react": "^1.6.0",
|
|
37
37
|
"lucide-react": "^1.17.0",
|
|
38
38
|
"motion": "^12.40.0",
|
|
39
39
|
"@howells/motion": "0.1.0"
|