@patternmode/aperto 0.1.4 → 0.2.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 +34 -0
- package/dist/index.d.ts +163 -43
- package/dist/index.js +447 -641
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -35,6 +35,40 @@ export function MediaGroupExample() {
|
|
|
35
35
|
}
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
## Optimized images
|
|
39
|
+
|
|
40
|
+
Aperto's built-in image renderer uses a plain `img` so the package stays
|
|
41
|
+
framework agnostic. If your app uses Next.js, pass `renderImage` and return
|
|
42
|
+
your own `next/image` `Image` component:
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import Image from "next/image";
|
|
46
|
+
|
|
47
|
+
const leadSrc = media[0]?.src;
|
|
48
|
+
|
|
49
|
+
<Aperto.Group
|
|
50
|
+
media={media}
|
|
51
|
+
renderImage={({ alt, item, src, variant }) => {
|
|
52
|
+
const isLeadImage = variant === "expanded" || item.src === leadSrc;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<Image
|
|
56
|
+
alt={alt ?? ""}
|
|
57
|
+
fetchPriority={isLeadImage ? "high" : "auto"}
|
|
58
|
+
fill
|
|
59
|
+
loading={isLeadImage || variant === "thumbnail" ? "eager" : "lazy"}
|
|
60
|
+
sizes={variant === "thumbnail" ? "(max-width: 640px) 50vw, 320px" : "90vw"}
|
|
61
|
+
src={String(src)}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{media.map((item, index) => (
|
|
67
|
+
<Aperto.Thumbnail key={item.id ?? item.src} index={index} />
|
|
68
|
+
))}
|
|
69
|
+
</Aperto.Group>;
|
|
70
|
+
```
|
|
71
|
+
|
|
38
72
|
## Install
|
|
39
73
|
|
|
40
74
|
```bash
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
1
2
|
import * as react from 'react';
|
|
2
|
-
import { ImgHTMLAttributes, ReactNode, VideoHTMLAttributes, ComponentPropsWithoutRef } from 'react';
|
|
3
|
+
import { ImgHTMLAttributes, ReactNode, VideoHTMLAttributes, ComponentPropsWithRef, Ref, CSSProperties, ComponentPropsWithoutRef } from 'react';
|
|
3
4
|
import * as Dialog from '@radix-ui/react-dialog';
|
|
4
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
import { Transition } from 'motion/react';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* @patternmode/aperto
|
|
8
|
+
* Package: @patternmode/aperto
|
|
9
9
|
*
|
|
10
10
|
* Shared element transitions with physics-based drag dismissal.
|
|
11
11
|
* Built on Radix Dialog + Motion.
|
|
@@ -23,22 +23,42 @@ interface BaseMediaItem {
|
|
|
23
23
|
title?: string;
|
|
24
24
|
width?: number;
|
|
25
25
|
}
|
|
26
|
+
/** Image media item rendered as a thumbnail and expanded image. */
|
|
26
27
|
interface ApertoImageItem extends BaseMediaItem {
|
|
28
|
+
/** Required alt text for the image renderer. */
|
|
27
29
|
alt: string;
|
|
28
30
|
type: "image";
|
|
29
31
|
}
|
|
32
|
+
/** Video media item rendered with a thumbnail and expanded player. */
|
|
30
33
|
interface ApertoVideoItem extends BaseMediaItem {
|
|
31
34
|
alt?: string;
|
|
35
|
+
/** Optional captions track URL for the expanded video. */
|
|
32
36
|
captionsSrc?: string;
|
|
33
37
|
poster?: string;
|
|
38
|
+
/** Required thumbnail image shown before expansion. */
|
|
34
39
|
thumbnailSrc: string;
|
|
35
40
|
type: "video";
|
|
36
41
|
}
|
|
42
|
+
/** Media item supported by Aperto's grouped media API. */
|
|
37
43
|
type ApertoMediaItem = ApertoImageItem | ApertoVideoItem;
|
|
44
|
+
/**
|
|
45
|
+
* Custom image renderer for image media.
|
|
46
|
+
*
|
|
47
|
+
* Aperto's default renderer is a plain `img` so the package stays framework
|
|
48
|
+
* agnostic. Next.js consumers should return their own `next/image` `Image`
|
|
49
|
+
* component here, using `variant` to choose thumbnail vs expanded sizing,
|
|
50
|
+
* loading, or fetch priority behavior.
|
|
51
|
+
*/
|
|
38
52
|
type RenderImage = (props: ImgHTMLAttributes<HTMLImageElement> & {
|
|
39
53
|
item: ApertoImageItem;
|
|
40
54
|
variant: "expanded" | "thumbnail";
|
|
41
55
|
}) => ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* Custom video renderer for video media.
|
|
58
|
+
*
|
|
59
|
+
* Use this to replace the default `video` element while preserving the supplied
|
|
60
|
+
* accessibility, poster, and control props.
|
|
61
|
+
*/
|
|
42
62
|
type RenderVideo = (props: VideoHTMLAttributes<HTMLVideoElement> & {
|
|
43
63
|
item: ApertoVideoItem;
|
|
44
64
|
variant: "expanded" | "thumbnail";
|
|
@@ -77,50 +97,98 @@ interface MotionPreset {
|
|
|
77
97
|
}
|
|
78
98
|
/** Dismissal behaviour config */
|
|
79
99
|
interface DismissibleConfig {
|
|
80
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* Distance in px to trigger dismissal.
|
|
102
|
+
*
|
|
103
|
+
* Default `100`.
|
|
104
|
+
*/
|
|
81
105
|
threshold?: number;
|
|
82
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* Velocity in px/s to trigger dismissal.
|
|
108
|
+
*
|
|
109
|
+
* Default `500`.
|
|
110
|
+
*/
|
|
83
111
|
velocity?: number;
|
|
84
112
|
}
|
|
85
113
|
|
|
86
114
|
interface ApertoProps {
|
|
87
115
|
classNames?: ApertoClassNames;
|
|
88
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* Whether dragging can dismiss the expanded media.
|
|
118
|
+
*
|
|
119
|
+
* Default `true`.
|
|
120
|
+
*/
|
|
89
121
|
dismissible?: boolean | DismissibleConfig;
|
|
122
|
+
/** Single media item rendered by the standalone Aperto component. */
|
|
90
123
|
media: ApertoMediaItem;
|
|
124
|
+
/**
|
|
125
|
+
* Overrides Aperto's plain `img` renderer for image media.
|
|
126
|
+
*
|
|
127
|
+
* Use this to render framework-specific image components such as Next.js
|
|
128
|
+
* `Image` while keeping Aperto itself framework agnostic.
|
|
129
|
+
*/
|
|
91
130
|
renderImage?: RenderImage;
|
|
92
131
|
renderVideo?: RenderVideo;
|
|
93
132
|
}
|
|
94
133
|
interface ApertoGroupProps {
|
|
95
134
|
children: ReactNode;
|
|
96
135
|
classNames?: ApertoClassNames;
|
|
97
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* Whether dragging can dismiss the expanded media.
|
|
138
|
+
*
|
|
139
|
+
* Default `true`.
|
|
140
|
+
*/
|
|
98
141
|
dismissible?: boolean | DismissibleConfig;
|
|
142
|
+
/** Controlled active media index. Pair with `onIndexChange`. */
|
|
99
143
|
index?: number;
|
|
144
|
+
/**
|
|
145
|
+
* Initial active media index for uncontrolled groups.
|
|
146
|
+
*
|
|
147
|
+
* Default `0`.
|
|
148
|
+
*/
|
|
100
149
|
initialIndex?: number;
|
|
101
150
|
media: ApertoMediaItem[];
|
|
102
|
-
/**
|
|
151
|
+
/**
|
|
152
|
+
* Motion preset for open/close transitions, or per-part motion overrides.
|
|
153
|
+
*
|
|
154
|
+
* Default `"smooth"`.
|
|
155
|
+
*/
|
|
103
156
|
motion?: MotionPresetName | MotionVariants;
|
|
157
|
+
/**
|
|
158
|
+
* Motion preset for next/previous navigation inside expanded media.
|
|
159
|
+
*
|
|
160
|
+
* Default `"glide"`.
|
|
161
|
+
*/
|
|
104
162
|
navigationMotion?: NavigationMotionPresetName;
|
|
163
|
+
/** Called whenever grouped media navigation changes the active index. */
|
|
105
164
|
onIndexChange?: (index: number) => void;
|
|
165
|
+
/**
|
|
166
|
+
* Overrides Aperto's plain `img` renderer for image media.
|
|
167
|
+
*
|
|
168
|
+
* Use this to render framework-specific image components such as Next.js
|
|
169
|
+
* `Image` while keeping Aperto itself framework agnostic.
|
|
170
|
+
*/
|
|
106
171
|
renderImage?: RenderImage;
|
|
107
172
|
renderVideo?: RenderVideo;
|
|
108
173
|
}
|
|
109
174
|
interface ApertoThumbnailProps {
|
|
175
|
+
/** Optional custom thumbnail content; defaults to media thumbnail rendering. */
|
|
110
176
|
children?: ReactNode;
|
|
111
177
|
className?: string;
|
|
178
|
+
/** Index into the parent group's `media` array. */
|
|
112
179
|
index: number;
|
|
113
180
|
}
|
|
114
181
|
|
|
115
|
-
declare
|
|
116
|
-
|
|
117
|
-
declare function ApertoSingle({ classNames, dismissible, media, renderImage, renderVideo, }: ApertoProps): react_jsx_runtime.JSX.Element;
|
|
182
|
+
declare const ApertoGroup: ({ children, classNames, dismissible, index: controlledIndex, initialIndex, media, motion: motionProp, navigationMotion, onIndexChange, renderImage, renderVideo, }: ApertoGroupProps) => react_jsx_runtime.JSX.Element;
|
|
118
183
|
|
|
119
|
-
declare
|
|
184
|
+
declare const ApertoThumbnail: ({ children, className, index }: ApertoThumbnailProps) => react_jsx_runtime.JSX.Element | null;
|
|
120
185
|
|
|
121
|
-
declare const ApertoClose:
|
|
186
|
+
declare const ApertoClose: {
|
|
187
|
+
({ children, ref, ...props }: ComponentPropsWithRef<typeof Dialog.Close>): react_jsx_runtime.JSX.Element;
|
|
188
|
+
displayName: string;
|
|
189
|
+
};
|
|
122
190
|
|
|
123
|
-
interface ApertoContentProps extends Omit<
|
|
191
|
+
interface ApertoContentProps extends Omit<ComponentPropsWithRef<typeof Dialog.Content>, "asChild" | "forceMount"> {
|
|
124
192
|
/** Motion preset override for this content panel, independent of the root preset. */
|
|
125
193
|
motion?: MotionPresetName;
|
|
126
194
|
/** Built-in positioning strategy. Use "none" for custom primitive compositions. */
|
|
@@ -128,24 +196,34 @@ interface ApertoContentProps extends Omit<ComponentPropsWithoutRef<typeof Dialog
|
|
|
128
196
|
/** Internal shared layout ID override for grouped media. */
|
|
129
197
|
sharedLayoutId?: string | false;
|
|
130
198
|
}
|
|
131
|
-
declare const ApertoContent:
|
|
199
|
+
declare const ApertoContent: {
|
|
200
|
+
({ children, className, motion: motionOverride, placement, ref, sharedLayoutId, style, ...props }: ApertoContentProps): react_jsx_runtime.JSX.Element;
|
|
201
|
+
displayName: string;
|
|
202
|
+
};
|
|
132
203
|
|
|
133
|
-
declare const ApertoDescription:
|
|
204
|
+
declare const ApertoDescription: {
|
|
205
|
+
({ ref, ...props }: ComponentPropsWithRef<typeof Dialog.Description>): react_jsx_runtime.JSX.Element;
|
|
206
|
+
displayName: string;
|
|
207
|
+
};
|
|
134
208
|
|
|
135
209
|
interface ApertoOverlayProps {
|
|
136
210
|
className?: string;
|
|
137
211
|
/** Internal flag used to fade the overlay during measured close transitions. */
|
|
138
212
|
fadeOut?: boolean;
|
|
139
|
-
|
|
213
|
+
ref?: Ref<HTMLDivElement>;
|
|
214
|
+
style?: CSSProperties;
|
|
140
215
|
}
|
|
141
|
-
declare const ApertoOverlay:
|
|
216
|
+
declare const ApertoOverlay: {
|
|
217
|
+
({ className, fadeOut, ref, style }: ApertoOverlayProps): react_jsx_runtime.JSX.Element;
|
|
218
|
+
displayName: string;
|
|
219
|
+
};
|
|
142
220
|
|
|
143
221
|
interface ApertoPortalProps {
|
|
144
222
|
children: ReactNode;
|
|
145
223
|
/** Container element for the portal (default: document.body) */
|
|
146
224
|
container?: HTMLElement;
|
|
147
225
|
}
|
|
148
|
-
declare
|
|
226
|
+
declare const ApertoPortal: ({ children, container }: ApertoPortalProps) => react_jsx_runtime.JSX.Element;
|
|
149
227
|
|
|
150
228
|
interface ApertoRootProps extends Omit<ComponentPropsWithoutRef<typeof Dialog.Root>, "open" | "onOpenChange"> {
|
|
151
229
|
children: ReactNode;
|
|
@@ -162,11 +240,14 @@ interface ApertoRootProps extends Omit<ComponentPropsWithoutRef<typeof Dialog.Ro
|
|
|
162
240
|
/** Force reduced motion regardless of system preference */
|
|
163
241
|
reduceMotion?: boolean;
|
|
164
242
|
}
|
|
165
|
-
declare
|
|
243
|
+
declare const ApertoRoot: ({ children, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react_jsx_runtime.JSX.Element;
|
|
166
244
|
|
|
167
|
-
declare const ApertoTitle:
|
|
245
|
+
declare const ApertoTitle: {
|
|
246
|
+
({ ref, ...props }: ComponentPropsWithRef<typeof Dialog.Title>): react_jsx_runtime.JSX.Element;
|
|
247
|
+
displayName: string;
|
|
248
|
+
};
|
|
168
249
|
|
|
169
|
-
interface ApertoTriggerProps extends
|
|
250
|
+
interface ApertoTriggerProps extends ComponentPropsWithRef<typeof Dialog.Trigger> {
|
|
170
251
|
/** Internal flag used by grouped thumbnails to raise only the active trigger. */
|
|
171
252
|
active?: boolean;
|
|
172
253
|
/** Override motion preset for this trigger */
|
|
@@ -174,7 +255,10 @@ interface ApertoTriggerProps extends ComponentPropsWithoutRef<typeof Dialog.Trig
|
|
|
174
255
|
/** Internal shared layout ID override for grouped thumbnails. */
|
|
175
256
|
sharedLayoutId?: string | false;
|
|
176
257
|
}
|
|
177
|
-
declare const ApertoTrigger:
|
|
258
|
+
declare const ApertoTrigger: {
|
|
259
|
+
({ active, children, motion: motionOverride, ref, sharedLayoutId, ...props }: ApertoTriggerProps): react_jsx_runtime.JSX.Element;
|
|
260
|
+
displayName: string;
|
|
261
|
+
};
|
|
178
262
|
|
|
179
263
|
/**
|
|
180
264
|
* Motion presets — each bundles transition timing AND drag physics
|
|
@@ -193,33 +277,69 @@ type ComponentType = "trigger" | "content" | "backdrop";
|
|
|
193
277
|
*
|
|
194
278
|
* If `prefers-reduced-motion` is active, always returns "reduced".
|
|
195
279
|
*/
|
|
196
|
-
declare
|
|
280
|
+
declare const resolvePreset: (componentType: ComponentType, componentMotion: MotionPresetName | undefined, globalPreset: MotionPresetName, variants: MotionVariants | undefined, reduceMotion: boolean) => MotionPreset;
|
|
197
281
|
|
|
198
282
|
/** Lower-level compound component namespace for advanced composition. */
|
|
199
283
|
declare const ApertoPrimitive: {
|
|
200
|
-
Close:
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
284
|
+
Close: {
|
|
285
|
+
({ children, ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogCloseProps & react.RefAttributes<HTMLButtonElement>>>): react_jsx_runtime.JSX.Element;
|
|
286
|
+
displayName: string;
|
|
287
|
+
};
|
|
288
|
+
Content: {
|
|
289
|
+
({ children, className, motion: motionOverride, placement, ref, sharedLayoutId, style, ...props }: ApertoContentProps): react_jsx_runtime.JSX.Element;
|
|
290
|
+
displayName: string;
|
|
291
|
+
};
|
|
292
|
+
Description: {
|
|
293
|
+
({ ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogDescriptionProps & react.RefAttributes<HTMLParagraphElement>>>): react_jsx_runtime.JSX.Element;
|
|
294
|
+
displayName: string;
|
|
295
|
+
};
|
|
296
|
+
Overlay: {
|
|
297
|
+
({ className, fadeOut, ref, style }: ApertoOverlayProps): react_jsx_runtime.JSX.Element;
|
|
298
|
+
displayName: string;
|
|
299
|
+
};
|
|
300
|
+
Portal: ({ children, container }: ApertoPortalProps) => react_jsx_runtime.JSX.Element;
|
|
301
|
+
Root: ({ children, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react_jsx_runtime.JSX.Element;
|
|
302
|
+
Title: {
|
|
303
|
+
({ ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogTitleProps & react.RefAttributes<HTMLHeadingElement>>>): react_jsx_runtime.JSX.Element;
|
|
304
|
+
displayName: string;
|
|
305
|
+
};
|
|
306
|
+
Trigger: {
|
|
307
|
+
({ active, children, motion: motionOverride, ref, sharedLayoutId, ...props }: ApertoTriggerProps): react_jsx_runtime.JSX.Element;
|
|
308
|
+
displayName: string;
|
|
309
|
+
};
|
|
208
310
|
};
|
|
209
311
|
/** Primary media-first component namespace. */
|
|
210
|
-
declare const Aperto:
|
|
211
|
-
Group:
|
|
312
|
+
declare const Aperto: (({ classNames, dismissible, media, renderImage, renderVideo, }: ApertoProps) => react_jsx_runtime.JSX.Element) & {
|
|
313
|
+
Group: ({ children, classNames, dismissible, index: controlledIndex, initialIndex, media, motion: motionProp, navigationMotion, onIndexChange, renderImage, renderVideo, }: ApertoGroupProps) => react_jsx_runtime.JSX.Element;
|
|
212
314
|
Primitive: {
|
|
213
|
-
Close:
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
315
|
+
Close: {
|
|
316
|
+
({ children, ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogCloseProps & react.RefAttributes<HTMLButtonElement>>>): react_jsx_runtime.JSX.Element;
|
|
317
|
+
displayName: string;
|
|
318
|
+
};
|
|
319
|
+
Content: {
|
|
320
|
+
({ children, className, motion: motionOverride, placement, ref, sharedLayoutId, style, ...props }: ApertoContentProps): react_jsx_runtime.JSX.Element;
|
|
321
|
+
displayName: string;
|
|
322
|
+
};
|
|
323
|
+
Description: {
|
|
324
|
+
({ ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogDescriptionProps & react.RefAttributes<HTMLParagraphElement>>>): react_jsx_runtime.JSX.Element;
|
|
325
|
+
displayName: string;
|
|
326
|
+
};
|
|
327
|
+
Overlay: {
|
|
328
|
+
({ className, fadeOut, ref, style }: ApertoOverlayProps): react_jsx_runtime.JSX.Element;
|
|
329
|
+
displayName: string;
|
|
330
|
+
};
|
|
331
|
+
Portal: ({ children, container }: ApertoPortalProps) => react_jsx_runtime.JSX.Element;
|
|
332
|
+
Root: ({ children, dismissible, layoutId: layoutIdProp, motion: motionProp, open: controlledOpen, onOpenChange: controlledOnOpenChange, reduceMotion: reduceMotionProp, ...dialogProps }: ApertoRootProps) => react_jsx_runtime.JSX.Element;
|
|
333
|
+
Title: {
|
|
334
|
+
({ ref, ...props }: react.ComponentPropsWithRef<react.ForwardRefExoticComponent<Dialog.DialogTitleProps & react.RefAttributes<HTMLHeadingElement>>>): react_jsx_runtime.JSX.Element;
|
|
335
|
+
displayName: string;
|
|
336
|
+
};
|
|
337
|
+
Trigger: {
|
|
338
|
+
({ active, children, motion: motionOverride, ref, sharedLayoutId, ...props }: ApertoTriggerProps): react_jsx_runtime.JSX.Element;
|
|
339
|
+
displayName: string;
|
|
340
|
+
};
|
|
221
341
|
};
|
|
222
|
-
Thumbnail:
|
|
342
|
+
Thumbnail: ({ children, className, index }: ApertoThumbnailProps) => react_jsx_runtime.JSX.Element | null;
|
|
223
343
|
};
|
|
224
344
|
|
|
225
345
|
export { Aperto, type ApertoClassNames, ApertoClose, ApertoContent, type ApertoContentProps, ApertoDescription, ApertoGroup, type ApertoGroupProps, type ApertoImageItem, type ApertoMediaItem, ApertoOverlay, type ApertoOverlayProps, ApertoPortal, type ApertoPortalProps, ApertoPrimitive, type ApertoProps, ApertoRoot, type ApertoRootProps, ApertoThumbnail, type ApertoThumbnailProps, ApertoTitle, ApertoTrigger, type ApertoTriggerProps, type ApertoVideoItem, type DismissibleConfig, type DragSpringConfig, type MotionPreset, type MotionPresetName, type MotionProp, type MotionVariants, type NavigationMotionPresetName, PRESETS, type RenderImage, type RenderVideo, resolvePreset };
|