react-sharesheet 1.0.0 → 1.1.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 +40 -53
- package/dist/content.d.mts +3 -3
- package/dist/content.d.ts +3 -3
- package/dist/content.js +192 -268
- package/dist/content.js.map +1 -1
- package/dist/content.mjs +194 -270
- package/dist/content.mjs.map +1 -1
- package/dist/drawer.d.mts +3 -3
- package/dist/drawer.d.ts +3 -3
- package/dist/drawer.js +194 -272
- package/dist/drawer.js.map +1 -1
- package/dist/drawer.mjs +196 -274
- package/dist/drawer.mjs.map +1 -1
- package/dist/headless.d.mts +22 -3
- package/dist/headless.d.ts +22 -3
- package/dist/headless.js +72 -0
- package/dist/headless.js.map +1 -1
- package/dist/headless.mjs +70 -1
- package/dist/headless.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +203 -272
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +202 -274
- package/dist/index.mjs.map +1 -1
- package/dist/{platforms-DU1DVDFq.d.mts → platforms-CDJmSY8E.d.mts} +2 -19
- package/dist/{platforms-DU1DVDFq.d.ts → platforms-CDJmSY8E.d.ts} +2 -19
- package/package.json +12 -3
- package/src/ShareSheetContent.tsx +143 -306
- package/src/ShareSheetDrawer.tsx +2 -4
- package/src/__tests__/hooks.test.ts +213 -0
- package/src/__tests__/og-fetcher.test.ts +144 -0
- package/src/__tests__/platforms.test.ts +148 -0
- package/src/__tests__/setup.ts +22 -0
- package/src/__tests__/share-functions.test.ts +155 -0
- package/src/__tests__/utils.test.ts +64 -0
- package/src/headless.ts +4 -1
- package/src/hooks.ts +49 -1
- package/src/index.ts +4 -3
- package/src/og-fetcher.ts +64 -0
- package/src/types.ts +1 -20
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useMemo, useState, useCallback } from "react";
|
|
4
|
-
import { Image,
|
|
4
|
+
import { Image, Link2 } from "lucide-react";
|
|
5
5
|
import { cn } from "./utils";
|
|
6
|
-
import { useShareSheet } from "./hooks";
|
|
6
|
+
import { useShareSheet, useOGData } from "./hooks";
|
|
7
7
|
import {
|
|
8
8
|
PLATFORM_IDS,
|
|
9
9
|
PLATFORM_COLORS,
|
|
@@ -17,49 +17,11 @@ import {
|
|
|
17
17
|
type ShareSheetContentProps,
|
|
18
18
|
type ShareOption,
|
|
19
19
|
type ShareButtonConfig,
|
|
20
|
-
type PreviewConfig,
|
|
21
|
-
type PreviewType,
|
|
22
20
|
} from "./types";
|
|
23
21
|
|
|
24
22
|
const DEFAULT_BUTTON_SIZE = 45;
|
|
25
23
|
const DEFAULT_ICON_SIZE = 22;
|
|
26
24
|
|
|
27
|
-
// File extension mappings
|
|
28
|
-
const IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "webp", "svg", "bmp", "ico", "avif"];
|
|
29
|
-
const VIDEO_EXTENSIONS = ["mp4", "webm", "mov", "avi", "mkv", "m4v", "ogv"];
|
|
30
|
-
const AUDIO_EXTENSIONS = ["mp3", "wav", "ogg", "m4a", "aac", "flac", "wma"];
|
|
31
|
-
|
|
32
|
-
// Detect content type from URL
|
|
33
|
-
function detectPreviewType(url: string): PreviewType {
|
|
34
|
-
try {
|
|
35
|
-
const pathname = new URL(url, "http://localhost").pathname;
|
|
36
|
-
const ext = pathname.split(".").pop()?.toLowerCase() || "";
|
|
37
|
-
|
|
38
|
-
if (IMAGE_EXTENSIONS.includes(ext)) return "image";
|
|
39
|
-
if (VIDEO_EXTENSIONS.includes(ext)) return "video";
|
|
40
|
-
if (AUDIO_EXTENSIONS.includes(ext)) return "audio";
|
|
41
|
-
|
|
42
|
-
// Check for common patterns
|
|
43
|
-
if (url.includes("/api/og") || url.includes("og-image")) return "image";
|
|
44
|
-
if (url.includes("youtube.com") || url.includes("vimeo.com")) return "video";
|
|
45
|
-
|
|
46
|
-
return "link";
|
|
47
|
-
} catch {
|
|
48
|
-
return "link";
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Get filename from URL
|
|
53
|
-
function getFilenameFromUrl(url: string): string {
|
|
54
|
-
try {
|
|
55
|
-
const pathname = new URL(url, "http://localhost").pathname;
|
|
56
|
-
const filename = pathname.split("/").pop() || "";
|
|
57
|
-
return decodeURIComponent(filename);
|
|
58
|
-
} catch {
|
|
59
|
-
return url;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
25
|
// Default class names
|
|
64
26
|
const defaultClasses = {
|
|
65
27
|
root: "max-w-md mx-auto",
|
|
@@ -69,12 +31,8 @@ const defaultClasses = {
|
|
|
69
31
|
preview: "flex justify-center mb-4 px-4",
|
|
70
32
|
previewSkeleton: "rounded-xl overflow-hidden",
|
|
71
33
|
previewImage: "",
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
previewFileIcon: "",
|
|
75
|
-
previewFilename: "truncate",
|
|
76
|
-
previewLink: "",
|
|
77
|
-
grid: "px-2 py-6 flex flex-row items-center gap-4 gap-y-6 flex-wrap justify-center",
|
|
34
|
+
previewMeta: "",
|
|
35
|
+
grid: "px-2 py-6 flex flex-row items-start gap-4 gap-y-6 flex-wrap justify-center",
|
|
78
36
|
button: "flex flex-col items-center gap-0 text-xs w-[60px] outline-none cursor-pointer group",
|
|
79
37
|
buttonIcon: "p-2 rounded-full transition-all flex items-center justify-center group-hover:scale-110 group-active:scale-95 mb-2",
|
|
80
38
|
buttonLabel: "",
|
|
@@ -93,34 +51,10 @@ function cssVar(name: string, fallback: string): string {
|
|
|
93
51
|
return `var(${name}, ${fallback})`;
|
|
94
52
|
}
|
|
95
53
|
|
|
96
|
-
// Normalize preview prop to PreviewConfig
|
|
97
|
-
function normalizePreview(preview: string | PreviewConfig | null | undefined): PreviewConfig | null {
|
|
98
|
-
if (!preview) return null;
|
|
99
|
-
|
|
100
|
-
if (typeof preview === "string") {
|
|
101
|
-
const type = detectPreviewType(preview);
|
|
102
|
-
return {
|
|
103
|
-
url: preview,
|
|
104
|
-
type,
|
|
105
|
-
filename: getFilenameFromUrl(preview),
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// It's already a config object
|
|
110
|
-
const type = preview.type === "auto" || !preview.type ? detectPreviewType(preview.url) : preview.type;
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
...preview,
|
|
114
|
-
type,
|
|
115
|
-
filename: preview.filename || getFilenameFromUrl(preview.url),
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
54
|
export function ShareSheetContent({
|
|
120
55
|
title = "Share",
|
|
121
56
|
shareUrl,
|
|
122
57
|
shareText,
|
|
123
|
-
preview,
|
|
124
58
|
downloadUrl,
|
|
125
59
|
downloadFilename,
|
|
126
60
|
className,
|
|
@@ -135,19 +69,19 @@ export function ShareSheetContent({
|
|
|
135
69
|
labels = {},
|
|
136
70
|
icons = {},
|
|
137
71
|
}: ShareSheetContentProps) {
|
|
138
|
-
const [
|
|
139
|
-
const [
|
|
72
|
+
const [imageLoaded, setImageLoaded] = useState(false);
|
|
73
|
+
const [imageError, setImageError] = useState(false);
|
|
140
74
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}, []);
|
|
75
|
+
// Fetch OG data automatically from shareUrl
|
|
76
|
+
const { ogData, loading: ogLoading } = useOGData(shareUrl);
|
|
144
77
|
|
|
145
|
-
const
|
|
146
|
-
|
|
78
|
+
const handleImageLoad = useCallback(() => {
|
|
79
|
+
setImageLoaded(true);
|
|
147
80
|
}, []);
|
|
148
81
|
|
|
149
|
-
|
|
150
|
-
|
|
82
|
+
const handleImageError = useCallback(() => {
|
|
83
|
+
setImageError(true);
|
|
84
|
+
}, []);
|
|
151
85
|
|
|
152
86
|
const shareSheet = useShareSheet({
|
|
153
87
|
shareUrl,
|
|
@@ -219,60 +153,33 @@ export function ShareSheetContent({
|
|
|
219
153
|
});
|
|
220
154
|
}, [buttons, show, hide]);
|
|
221
155
|
|
|
222
|
-
const
|
|
156
|
+
const bgColor = cssVar(CSS_VARS_UI.previewBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewBg]);
|
|
157
|
+
const shimmerColor = cssVar(CSS_VARS_UI.previewShimmer, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewShimmer]);
|
|
158
|
+
const textColor = cssVar(CSS_VARS_UI.subtitleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.subtitleColor]);
|
|
223
159
|
|
|
224
|
-
// Render preview
|
|
160
|
+
// Render OG preview
|
|
225
161
|
const renderPreview = () => {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const { type, url, filename, alt, poster } = previewConfig;
|
|
229
|
-
const bgColor = cssVar(CSS_VARS_UI.previewBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewBg]);
|
|
230
|
-
const shimmerColor = cssVar(CSS_VARS_UI.previewShimmer, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewShimmer]);
|
|
231
|
-
const textColor = cssVar(CSS_VARS_UI.subtitleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.subtitleColor]);
|
|
162
|
+
const ogImage = ogData?.image;
|
|
163
|
+
const hasImage = ogImage && !imageError;
|
|
232
164
|
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
icon: IconComponent,
|
|
252
|
-
isLoading = false,
|
|
253
|
-
label,
|
|
254
|
-
displayUrl,
|
|
255
|
-
}: {
|
|
256
|
-
icon: typeof Link2;
|
|
257
|
-
isLoading?: boolean;
|
|
258
|
-
label?: string;
|
|
259
|
-
displayUrl?: string;
|
|
260
|
-
}) => (
|
|
261
|
-
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
|
|
262
|
-
<div
|
|
263
|
-
className={cn(defaultClasses.previewSkeleton, classNames.previewSkeleton)}
|
|
264
|
-
style={{
|
|
265
|
-
position: "relative",
|
|
266
|
-
backgroundColor: bgColor,
|
|
267
|
-
width: "200px",
|
|
268
|
-
height: "120px",
|
|
269
|
-
overflow: "hidden",
|
|
270
|
-
display: "flex",
|
|
271
|
-
alignItems: "center",
|
|
272
|
-
justifyContent: "center",
|
|
273
|
-
}}
|
|
274
|
-
>
|
|
275
|
-
{isLoading && (
|
|
165
|
+
// Loading state
|
|
166
|
+
if (ogLoading) {
|
|
167
|
+
return (
|
|
168
|
+
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
169
|
+
<div
|
|
170
|
+
className={cn(defaultClasses.previewSkeleton, classNames.previewSkeleton)}
|
|
171
|
+
style={{
|
|
172
|
+
position: "relative",
|
|
173
|
+
backgroundColor: bgColor,
|
|
174
|
+
width: "100%",
|
|
175
|
+
maxWidth: "320px",
|
|
176
|
+
aspectRatio: "1.91 / 1",
|
|
177
|
+
overflow: "hidden",
|
|
178
|
+
display: "flex",
|
|
179
|
+
alignItems: "center",
|
|
180
|
+
justifyContent: "center",
|
|
181
|
+
}}
|
|
182
|
+
>
|
|
276
183
|
<div style={{ position: "absolute", inset: 0, overflow: "hidden" }}>
|
|
277
184
|
<div
|
|
278
185
|
style={{
|
|
@@ -283,194 +190,127 @@ export function ShareSheetContent({
|
|
|
283
190
|
}}
|
|
284
191
|
/>
|
|
285
192
|
</div>
|
|
286
|
-
|
|
193
|
+
<Link2 size={32} style={{ color: textColor, opacity: 0.4 }} />
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// No OG data or no image - show link placeholder
|
|
200
|
+
if (!ogData || !hasImage) {
|
|
201
|
+
return (
|
|
202
|
+
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
287
203
|
<div
|
|
204
|
+
className={cn(defaultClasses.previewSkeleton, classNames.previewSkeleton)}
|
|
288
205
|
style={{
|
|
206
|
+
position: "relative",
|
|
207
|
+
backgroundColor: bgColor,
|
|
208
|
+
width: "100%",
|
|
209
|
+
maxWidth: "320px",
|
|
210
|
+
aspectRatio: "1.91 / 1",
|
|
211
|
+
overflow: "hidden",
|
|
289
212
|
display: "flex",
|
|
290
|
-
flexDirection: "column",
|
|
291
213
|
alignItems: "center",
|
|
292
214
|
justifyContent: "center",
|
|
293
|
-
gap: "8px",
|
|
294
215
|
}}
|
|
295
216
|
>
|
|
296
|
-
<
|
|
297
|
-
{label && (
|
|
298
|
-
<span style={{ color: textColor, fontSize: "11px", opacity: 0.4 }}>
|
|
299
|
-
{label}
|
|
300
|
-
</span>
|
|
301
|
-
)}
|
|
302
|
-
</div>
|
|
303
|
-
</div>
|
|
304
|
-
<UrlLabel displayUrl={displayUrl} />
|
|
305
|
-
</div>
|
|
306
|
-
);
|
|
307
|
-
|
|
308
|
-
// If there was an error loading media, show fallback
|
|
309
|
-
if (mediaError && (type === "image" || type === "video")) {
|
|
310
|
-
return <PlaceholderCard icon={Link2} displayUrl={url} />;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
switch (type) {
|
|
314
|
-
case "image":
|
|
315
|
-
// Show placeholder while loading, then show image with correct aspect ratio
|
|
316
|
-
if (!mediaLoaded) {
|
|
317
|
-
return (
|
|
318
|
-
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
|
|
319
|
-
<div
|
|
320
|
-
className={cn(defaultClasses.previewSkeleton, classNames.previewSkeleton)}
|
|
321
|
-
style={{
|
|
322
|
-
position: "relative",
|
|
323
|
-
backgroundColor: bgColor,
|
|
324
|
-
width: "200px",
|
|
325
|
-
height: "120px",
|
|
326
|
-
overflow: "hidden",
|
|
327
|
-
display: "flex",
|
|
328
|
-
alignItems: "center",
|
|
329
|
-
justifyContent: "center",
|
|
330
|
-
}}
|
|
331
|
-
>
|
|
332
|
-
<div style={{ position: "absolute", inset: 0, overflow: "hidden" }}>
|
|
333
|
-
<div
|
|
334
|
-
style={{
|
|
335
|
-
position: "absolute",
|
|
336
|
-
inset: 0,
|
|
337
|
-
background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
|
|
338
|
-
animation: "sharesheet-shimmer 1.5s infinite",
|
|
339
|
-
}}
|
|
340
|
-
/>
|
|
341
|
-
</div>
|
|
342
|
-
<Image size={32} style={{ color: textColor, opacity: 0.4 }} />
|
|
343
|
-
</div>
|
|
344
|
-
<UrlLabel />
|
|
345
|
-
{/* Hidden image for preloading */}
|
|
346
|
-
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
347
|
-
<img
|
|
348
|
-
src={url}
|
|
349
|
-
alt={alt || "Preview"}
|
|
350
|
-
onLoad={handleMediaLoad}
|
|
351
|
-
onError={handleMediaError}
|
|
352
|
-
style={{ display: "none" }}
|
|
353
|
-
/>
|
|
354
|
-
</div>
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
// Image loaded - show with correct aspect ratio
|
|
358
|
-
return (
|
|
359
|
-
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
|
|
360
|
-
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
361
|
-
<img
|
|
362
|
-
src={url}
|
|
363
|
-
alt={alt || "Preview"}
|
|
364
|
-
className={cn(defaultClasses.previewImage, classNames.previewImage)}
|
|
217
|
+
<div
|
|
365
218
|
style={{
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
219
|
+
display: "flex",
|
|
220
|
+
flexDirection: "column",
|
|
221
|
+
alignItems: "center",
|
|
222
|
+
justifyContent: "center",
|
|
223
|
+
gap: "8px",
|
|
224
|
+
padding: "16px",
|
|
371
225
|
}}
|
|
372
|
-
|
|
373
|
-
|
|
226
|
+
>
|
|
227
|
+
<Link2 size={32} style={{ color: textColor, opacity: 0.4 }} />
|
|
228
|
+
{ogData?.title && (
|
|
229
|
+
<span
|
|
230
|
+
style={{
|
|
231
|
+
color: textColor,
|
|
232
|
+
fontSize: "12px",
|
|
233
|
+
opacity: 0.6,
|
|
234
|
+
textAlign: "center",
|
|
235
|
+
maxWidth: "280px",
|
|
236
|
+
overflow: "hidden",
|
|
237
|
+
textOverflow: "ellipsis",
|
|
238
|
+
display: "-webkit-box",
|
|
239
|
+
WebkitLineClamp: 2,
|
|
240
|
+
WebkitBoxOrient: "vertical",
|
|
241
|
+
}}
|
|
242
|
+
>
|
|
243
|
+
{ogData.title}
|
|
244
|
+
</span>
|
|
245
|
+
)}
|
|
246
|
+
</div>
|
|
374
247
|
</div>
|
|
375
|
-
|
|
248
|
+
</div>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
376
251
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
style={{
|
|
397
|
-
position: "absolute",
|
|
398
|
-
inset: 0,
|
|
399
|
-
background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
|
|
400
|
-
animation: "sharesheet-shimmer 1.5s infinite",
|
|
401
|
-
}}
|
|
402
|
-
/>
|
|
403
|
-
</div>
|
|
404
|
-
<Film size={32} style={{ color: textColor, opacity: 0.4 }} />
|
|
405
|
-
</div>
|
|
406
|
-
<UrlLabel />
|
|
407
|
-
{/* Hidden video for preloading */}
|
|
408
|
-
<video
|
|
409
|
-
src={url}
|
|
410
|
-
poster={poster}
|
|
411
|
-
onLoadedData={handleMediaLoad}
|
|
412
|
-
onError={handleMediaError}
|
|
413
|
-
style={{ display: "none" }}
|
|
414
|
-
muted
|
|
415
|
-
playsInline
|
|
416
|
-
preload="metadata"
|
|
417
|
-
/>
|
|
418
|
-
</div>
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
// Video loaded
|
|
422
|
-
return (
|
|
423
|
-
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
|
|
424
|
-
<div style={{ position: "relative", borderRadius: "12px", overflow: "hidden" }}>
|
|
425
|
-
<video
|
|
426
|
-
src={url}
|
|
427
|
-
poster={poster}
|
|
428
|
-
className={cn(defaultClasses.previewVideo, classNames.previewVideo)}
|
|
429
|
-
style={{
|
|
430
|
-
maxWidth: "100%",
|
|
431
|
-
maxHeight: "180px",
|
|
432
|
-
display: "block",
|
|
433
|
-
}}
|
|
434
|
-
muted
|
|
435
|
-
playsInline
|
|
436
|
-
preload="metadata"
|
|
437
|
-
/>
|
|
438
|
-
{/* Play icon overlay */}
|
|
252
|
+
// Image loading state
|
|
253
|
+
if (!imageLoaded) {
|
|
254
|
+
return (
|
|
255
|
+
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
256
|
+
<div
|
|
257
|
+
className={cn(defaultClasses.previewSkeleton, classNames.previewSkeleton)}
|
|
258
|
+
style={{
|
|
259
|
+
position: "relative",
|
|
260
|
+
backgroundColor: bgColor,
|
|
261
|
+
width: "100%",
|
|
262
|
+
maxWidth: "320px",
|
|
263
|
+
aspectRatio: "1.91 / 1",
|
|
264
|
+
overflow: "hidden",
|
|
265
|
+
display: "flex",
|
|
266
|
+
alignItems: "center",
|
|
267
|
+
justifyContent: "center",
|
|
268
|
+
}}
|
|
269
|
+
>
|
|
270
|
+
<div style={{ position: "absolute", inset: 0, overflow: "hidden" }}>
|
|
439
271
|
<div
|
|
440
272
|
style={{
|
|
441
273
|
position: "absolute",
|
|
442
274
|
inset: 0,
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
justifyContent: "center",
|
|
446
|
-
pointerEvents: "none",
|
|
275
|
+
background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
|
|
276
|
+
animation: "sharesheet-shimmer 1.5s infinite",
|
|
447
277
|
}}
|
|
448
|
-
|
|
449
|
-
<div
|
|
450
|
-
style={{
|
|
451
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
452
|
-
borderRadius: "50%",
|
|
453
|
-
padding: "10px",
|
|
454
|
-
}}
|
|
455
|
-
>
|
|
456
|
-
<Play size={20} fill="white" color="white" />
|
|
457
|
-
</div>
|
|
458
|
-
</div>
|
|
278
|
+
/>
|
|
459
279
|
</div>
|
|
460
|
-
<
|
|
280
|
+
<Image size={32} style={{ color: textColor, opacity: 0.4 }} />
|
|
461
281
|
</div>
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
282
|
+
{/* Hidden image for preloading */}
|
|
283
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
284
|
+
<img
|
|
285
|
+
src={ogImage}
|
|
286
|
+
alt={ogData.title || "Preview"}
|
|
287
|
+
onLoad={handleImageLoad}
|
|
288
|
+
onError={handleImageError}
|
|
289
|
+
style={{ display: "none" }}
|
|
290
|
+
/>
|
|
291
|
+
</div>
|
|
292
|
+
);
|
|
473
293
|
}
|
|
294
|
+
|
|
295
|
+
// Image loaded - show it
|
|
296
|
+
return (
|
|
297
|
+
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
298
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
299
|
+
<img
|
|
300
|
+
src={ogImage}
|
|
301
|
+
alt={ogData.title || "Preview"}
|
|
302
|
+
className={cn(defaultClasses.previewImage, classNames.previewImage)}
|
|
303
|
+
style={{
|
|
304
|
+
width: "100%",
|
|
305
|
+
maxWidth: "320px",
|
|
306
|
+
height: "auto",
|
|
307
|
+
borderRadius: "12px",
|
|
308
|
+
opacity: 1,
|
|
309
|
+
transition: "opacity 0.3s ease-in-out",
|
|
310
|
+
}}
|
|
311
|
+
/>
|
|
312
|
+
</div>
|
|
313
|
+
);
|
|
474
314
|
};
|
|
475
315
|
|
|
476
316
|
return (
|
|
@@ -493,12 +333,10 @@ export function ShareSheetContent({
|
|
|
493
333
|
</div>
|
|
494
334
|
</div>
|
|
495
335
|
|
|
496
|
-
{/*
|
|
497
|
-
{
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
</div>
|
|
501
|
-
)}
|
|
336
|
+
{/* OG Preview - always shown */}
|
|
337
|
+
<div className={cn(defaultClasses.preview, classNames.preview)}>
|
|
338
|
+
{renderPreview()}
|
|
339
|
+
</div>
|
|
502
340
|
|
|
503
341
|
<div className={cn(defaultClasses.grid, classNames.grid)}>
|
|
504
342
|
{visibleButtons.map((btn) => (
|
|
@@ -535,4 +373,3 @@ export function ShareSheetContent({
|
|
|
535
373
|
// Legacy export for backwards compatibility
|
|
536
374
|
/** @deprecated Use ShareSheetContent instead */
|
|
537
375
|
export const ShareMenuContent = ShareSheetContent;
|
|
538
|
-
|
package/src/ShareSheetDrawer.tsx
CHANGED
|
@@ -10,8 +10,8 @@ import { CSS_VARS_UI, CSS_VAR_UI_DEFAULTS, type ShareSheetDrawerProps } from "./
|
|
|
10
10
|
// Default class names for drawer
|
|
11
11
|
const defaultDrawerClasses = {
|
|
12
12
|
overlay: "fixed inset-0 z-[70]",
|
|
13
|
-
drawer: "flex flex-col rounded-t-[14px] h-[
|
|
14
|
-
drawerInner: "p-4 rounded-t-[14px]
|
|
13
|
+
drawer: "flex flex-col rounded-t-[14px] max-h-[90%] fixed bottom-0 left-0 right-0 z-[80] border-t outline-none",
|
|
14
|
+
drawerInner: "p-4 pb-8 rounded-t-[14px] overflow-auto",
|
|
15
15
|
handle: "mx-auto w-12 h-1.5 shrink-0 rounded-full mb-6",
|
|
16
16
|
trigger: "",
|
|
17
17
|
};
|
|
@@ -25,7 +25,6 @@ export function ShareSheetDrawer({
|
|
|
25
25
|
title = "Share",
|
|
26
26
|
shareUrl,
|
|
27
27
|
shareText,
|
|
28
|
-
preview,
|
|
29
28
|
downloadUrl,
|
|
30
29
|
downloadFilename,
|
|
31
30
|
disabled,
|
|
@@ -97,7 +96,6 @@ export function ShareSheetDrawer({
|
|
|
97
96
|
title={title}
|
|
98
97
|
shareUrl={shareUrl}
|
|
99
98
|
shareText={shareText}
|
|
100
|
-
preview={preview}
|
|
101
99
|
downloadUrl={downloadUrl}
|
|
102
100
|
downloadFilename={downloadFilename}
|
|
103
101
|
className={className}
|