react-sharesheet 1.7.0 → 1.9.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 +9 -0
- package/dist/content.d.mts +3 -3
- package/dist/content.d.ts +3 -3
- package/dist/content.js +87 -18
- package/dist/content.js.map +1 -1
- package/dist/content.mjs +87 -18
- 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 +105 -19
- package/dist/drawer.js.map +1 -1
- package/dist/drawer.mjs +105 -19
- package/dist/drawer.mjs.map +1 -1
- package/dist/{headless-BTnsV8ZO.d.ts → headless-lxSw27f0.d.ts} +6 -2
- package/dist/{headless-DzKMJ3eW.d.mts → headless-x5iUF86E.d.mts} +6 -2
- package/dist/headless.d.mts +2 -2
- package/dist/headless.d.ts +2 -2
- package/dist/headless.js +41 -2
- package/dist/headless.js.map +1 -1
- package/dist/headless.mjs +41 -2
- 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 +105 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +105 -19
- package/dist/index.mjs.map +1 -1
- package/dist/{platforms-BgGzSDRk.d.mts → platforms-BtmTZmgl.d.mts} +10 -2
- package/dist/{platforms-BgGzSDRk.d.ts → platforms-BtmTZmgl.d.ts} +10 -2
- package/package.json +2 -2
- package/src/ShareSheetContent.tsx +55 -20
- package/src/ShareSheetDrawer.tsx +21 -2
- package/src/hooks.ts +60 -2
- package/src/types.ts +9 -1
|
@@ -17,7 +17,7 @@ declare const CSS_VAR_UI_DEFAULTS: {
|
|
|
17
17
|
readonly "--sharesheet-overlay-bg": "rgba(0, 0, 0, 0.7)";
|
|
18
18
|
readonly "--sharesheet-drawer-bg": "#09090b";
|
|
19
19
|
readonly "--sharesheet-drawer-border": "#27272a";
|
|
20
|
-
readonly "--sharesheet-handle-bg": "
|
|
20
|
+
readonly "--sharesheet-handle-bg": "rgba(255, 255, 255, 0.2)";
|
|
21
21
|
readonly "--sharesheet-title-color": "#ffffff";
|
|
22
22
|
readonly "--sharesheet-subtitle-color": "#a1a1aa";
|
|
23
23
|
readonly "--sharesheet-button-label-color": "#ffffff";
|
|
@@ -85,6 +85,12 @@ interface ShareSheetContentProps {
|
|
|
85
85
|
downloadUrl?: string | null;
|
|
86
86
|
/** Filename for downloaded file */
|
|
87
87
|
downloadFilename?: string;
|
|
88
|
+
/** Custom preview image URL (skips OG fetching if provided) */
|
|
89
|
+
previewImage?: string | null;
|
|
90
|
+
/** File to share via native share (data URL or Blob) - takes priority over URL sharing */
|
|
91
|
+
shareFile?: string | Blob | null;
|
|
92
|
+
/** Filename for the shared file */
|
|
93
|
+
shareFilename?: string;
|
|
88
94
|
/** Custom class name for the container (shorthand for classNames.root) */
|
|
89
95
|
className?: string;
|
|
90
96
|
/** Override class names for sub-components */
|
|
@@ -99,6 +105,8 @@ interface ShareSheetContentProps {
|
|
|
99
105
|
onCopy?: () => void;
|
|
100
106
|
/** Called when download starts */
|
|
101
107
|
onDownload?: () => void;
|
|
108
|
+
/** Called on every share option click, with the option id (analytics-friendly) */
|
|
109
|
+
onShare?: (option: ShareOption) => void;
|
|
102
110
|
/** Hide specific share options */
|
|
103
111
|
hide?: ShareOption[];
|
|
104
112
|
/** Show only these platforms, in this exact order */
|
|
@@ -199,7 +207,7 @@ declare const CSS_VAR_DEFAULTS: {
|
|
|
199
207
|
readonly "--sharesheet-overlay-bg": "rgba(0, 0, 0, 0.7)";
|
|
200
208
|
readonly "--sharesheet-drawer-bg": "#09090b";
|
|
201
209
|
readonly "--sharesheet-drawer-border": "#27272a";
|
|
202
|
-
readonly "--sharesheet-handle-bg": "
|
|
210
|
+
readonly "--sharesheet-handle-bg": "rgba(255, 255, 255, 0.2)";
|
|
203
211
|
readonly "--sharesheet-title-color": "#ffffff";
|
|
204
212
|
readonly "--sharesheet-subtitle-color": "#a1a1aa";
|
|
205
213
|
readonly "--sharesheet-button-label-color": "#ffffff";
|
|
@@ -17,7 +17,7 @@ declare const CSS_VAR_UI_DEFAULTS: {
|
|
|
17
17
|
readonly "--sharesheet-overlay-bg": "rgba(0, 0, 0, 0.7)";
|
|
18
18
|
readonly "--sharesheet-drawer-bg": "#09090b";
|
|
19
19
|
readonly "--sharesheet-drawer-border": "#27272a";
|
|
20
|
-
readonly "--sharesheet-handle-bg": "
|
|
20
|
+
readonly "--sharesheet-handle-bg": "rgba(255, 255, 255, 0.2)";
|
|
21
21
|
readonly "--sharesheet-title-color": "#ffffff";
|
|
22
22
|
readonly "--sharesheet-subtitle-color": "#a1a1aa";
|
|
23
23
|
readonly "--sharesheet-button-label-color": "#ffffff";
|
|
@@ -85,6 +85,12 @@ interface ShareSheetContentProps {
|
|
|
85
85
|
downloadUrl?: string | null;
|
|
86
86
|
/** Filename for downloaded file */
|
|
87
87
|
downloadFilename?: string;
|
|
88
|
+
/** Custom preview image URL (skips OG fetching if provided) */
|
|
89
|
+
previewImage?: string | null;
|
|
90
|
+
/** File to share via native share (data URL or Blob) - takes priority over URL sharing */
|
|
91
|
+
shareFile?: string | Blob | null;
|
|
92
|
+
/** Filename for the shared file */
|
|
93
|
+
shareFilename?: string;
|
|
88
94
|
/** Custom class name for the container (shorthand for classNames.root) */
|
|
89
95
|
className?: string;
|
|
90
96
|
/** Override class names for sub-components */
|
|
@@ -99,6 +105,8 @@ interface ShareSheetContentProps {
|
|
|
99
105
|
onCopy?: () => void;
|
|
100
106
|
/** Called when download starts */
|
|
101
107
|
onDownload?: () => void;
|
|
108
|
+
/** Called on every share option click, with the option id (analytics-friendly) */
|
|
109
|
+
onShare?: (option: ShareOption) => void;
|
|
102
110
|
/** Hide specific share options */
|
|
103
111
|
hide?: ShareOption[];
|
|
104
112
|
/** Show only these platforms, in this exact order */
|
|
@@ -199,7 +207,7 @@ declare const CSS_VAR_DEFAULTS: {
|
|
|
199
207
|
readonly "--sharesheet-overlay-bg": "rgba(0, 0, 0, 0.7)";
|
|
200
208
|
readonly "--sharesheet-drawer-bg": "#09090b";
|
|
201
209
|
readonly "--sharesheet-drawer-border": "#27272a";
|
|
202
|
-
readonly "--sharesheet-handle-bg": "
|
|
210
|
+
readonly "--sharesheet-handle-bg": "rgba(255, 255, 255, 0.2)";
|
|
203
211
|
readonly "--sharesheet-title-color": "#ffffff";
|
|
204
212
|
readonly "--sharesheet-subtitle-color": "#a1a1aa";
|
|
205
213
|
readonly "--sharesheet-button-label-color": "#ffffff";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-sharesheet",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "A mobile-first share sheet for React with native share support, Open Graph previews, 15+ social platforms, and headless APIs. Tailwind-styled by default, fully customizable.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"test:watch": "vitest",
|
|
43
43
|
"test:coverage": "vitest run --coverage",
|
|
44
44
|
"prepack": "npm run clean && npm run build",
|
|
45
|
-
"prepublishOnly": "
|
|
45
|
+
"prepublishOnly": "pnpm run type-check && pnpm run test && pnpm run build",
|
|
46
46
|
"publish-patch": "npm version patch && npm publish",
|
|
47
47
|
"publish-minor": "npm version minor && npm publish",
|
|
48
48
|
"publish-major": "npm version major && npm publish",
|
|
@@ -28,9 +28,9 @@ const defaultClasses = {
|
|
|
28
28
|
header: "text-center mb-2",
|
|
29
29
|
title: "text-2xl font-black",
|
|
30
30
|
subtitle: "mt-1 text-sm",
|
|
31
|
-
preview: "flex justify-center
|
|
31
|
+
preview: "flex justify-center my-4 px-4",
|
|
32
32
|
previewSkeleton: "rounded-xl overflow-hidden",
|
|
33
|
-
previewImage: "border border-white/10",
|
|
33
|
+
previewImage: "border border-white/10 rounded-xl",
|
|
34
34
|
previewMeta: "",
|
|
35
35
|
grid: "px-2 py-6 flex flex-row items-start gap-4 gap-y-6 flex-wrap justify-center",
|
|
36
36
|
button: "flex flex-col items-center gap-0 text-xs w-[60px] outline-none cursor-pointer group",
|
|
@@ -38,12 +38,19 @@ const defaultClasses = {
|
|
|
38
38
|
buttonLabel: "",
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
// Shimmer keyframes as inline style
|
|
41
|
+
// Shimmer and fade-in keyframes as inline style
|
|
42
42
|
const shimmerKeyframes = `
|
|
43
43
|
@keyframes sharesheet-shimmer {
|
|
44
44
|
0% { transform: translateX(-100%); }
|
|
45
45
|
100% { transform: translateX(100%); }
|
|
46
46
|
}
|
|
47
|
+
@keyframes sharesheet-fadein {
|
|
48
|
+
0% { opacity: 0; }
|
|
49
|
+
100% { opacity: 1; }
|
|
50
|
+
}
|
|
51
|
+
.sharesheet-fadein {
|
|
52
|
+
animation: sharesheet-fadein 0.3s ease-out forwards;
|
|
53
|
+
}
|
|
47
54
|
`;
|
|
48
55
|
|
|
49
56
|
// Helper to create var() with fallback
|
|
@@ -57,12 +64,16 @@ export function ShareSheetContent({
|
|
|
57
64
|
shareText,
|
|
58
65
|
downloadUrl,
|
|
59
66
|
downloadFilename,
|
|
67
|
+
previewImage,
|
|
68
|
+
shareFile,
|
|
69
|
+
shareFilename,
|
|
60
70
|
className,
|
|
61
71
|
classNames = {},
|
|
62
72
|
buttonSize = DEFAULT_BUTTON_SIZE,
|
|
63
73
|
iconSize = DEFAULT_ICON_SIZE,
|
|
64
74
|
onNativeShare,
|
|
65
75
|
onCopy,
|
|
76
|
+
onShare,
|
|
66
77
|
onDownload,
|
|
67
78
|
hide = [],
|
|
68
79
|
show,
|
|
@@ -72,8 +83,8 @@ export function ShareSheetContent({
|
|
|
72
83
|
const [imageLoaded, setImageLoaded] = useState(false);
|
|
73
84
|
const [imageError, setImageError] = useState(false);
|
|
74
85
|
|
|
75
|
-
//
|
|
76
|
-
const { ogData, loading: ogLoading } = useOGData(shareUrl);
|
|
86
|
+
// Only fetch OG data if previewImage is not provided
|
|
87
|
+
const { ogData, loading: ogLoading } = useOGData(previewImage ? undefined : shareUrl);
|
|
77
88
|
|
|
78
89
|
const handleImageLoad = useCallback(() => {
|
|
79
90
|
setImageLoaded(true);
|
|
@@ -89,6 +100,8 @@ export function ShareSheetContent({
|
|
|
89
100
|
downloadUrl,
|
|
90
101
|
downloadFilename,
|
|
91
102
|
emailSubject: shareText,
|
|
103
|
+
shareFile,
|
|
104
|
+
shareFilename,
|
|
92
105
|
onNativeShare,
|
|
93
106
|
onCopy,
|
|
94
107
|
onDownload,
|
|
@@ -144,11 +157,14 @@ export function ShareSheetContent({
|
|
|
144
157
|
// Use CSS var with fallback to platform color
|
|
145
158
|
bgColor: cssVar(PLATFORM_CSS_VARS[id], PLATFORM_COLORS[id].bg),
|
|
146
159
|
textColor: PLATFORM_COLORS[id].text,
|
|
147
|
-
onClick:
|
|
160
|
+
onClick: () => {
|
|
161
|
+
onShare?.(id);
|
|
162
|
+
shareActions[id]();
|
|
163
|
+
},
|
|
148
164
|
condition,
|
|
149
165
|
};
|
|
150
166
|
});
|
|
151
|
-
}, [iconSize, labels, icons, dynamicLabels, shareActions, shareSheet.canNativeShare, shareSheet.platformAvailability, downloadUrl]);
|
|
167
|
+
}, [iconSize, labels, icons, dynamicLabels, shareActions, onShare, shareSheet.canNativeShare, shareSheet.platformAvailability, downloadUrl]);
|
|
152
168
|
|
|
153
169
|
const visibleButtons = useMemo(() => {
|
|
154
170
|
// If show is provided, use its order
|
|
@@ -177,11 +193,13 @@ export function ShareSheetContent({
|
|
|
177
193
|
|
|
178
194
|
// Render OG preview
|
|
179
195
|
const renderPreview = () => {
|
|
180
|
-
|
|
196
|
+
// Use previewImage if provided, otherwise use OG data
|
|
197
|
+
const ogImage = previewImage || ogData?.image;
|
|
181
198
|
const hasImage = ogImage && !imageError;
|
|
199
|
+
const isLoading = !previewImage && ogLoading;
|
|
182
200
|
|
|
183
|
-
// Loading state
|
|
184
|
-
if (
|
|
201
|
+
// Loading state (only when fetching OG data, not when previewImage is provided)
|
|
202
|
+
if (isLoading) {
|
|
185
203
|
return (
|
|
186
204
|
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
187
205
|
<div
|
|
@@ -214,8 +232,8 @@ export function ShareSheetContent({
|
|
|
214
232
|
);
|
|
215
233
|
}
|
|
216
234
|
|
|
217
|
-
// No
|
|
218
|
-
if (!
|
|
235
|
+
// No image available - show link placeholder (skip if previewImage was provided)
|
|
236
|
+
if (!hasImage) {
|
|
219
237
|
return (
|
|
220
238
|
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
221
239
|
<div
|
|
@@ -267,7 +285,27 @@ export function ShareSheetContent({
|
|
|
267
285
|
);
|
|
268
286
|
}
|
|
269
287
|
|
|
270
|
-
//
|
|
288
|
+
// If previewImage is a data URL, show it directly (no preloading needed)
|
|
289
|
+
const isDataUrl = typeof ogImage === "string" && ogImage.startsWith("data:");
|
|
290
|
+
if (isDataUrl) {
|
|
291
|
+
return (
|
|
292
|
+
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
293
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
294
|
+
<img
|
|
295
|
+
src={ogImage}
|
|
296
|
+
alt="Preview"
|
|
297
|
+
className={cn(defaultClasses.previewImage, classNames.previewImage)}
|
|
298
|
+
style={{
|
|
299
|
+
width: "100%",
|
|
300
|
+
maxWidth: "320px",
|
|
301
|
+
height: "auto",
|
|
302
|
+
}}
|
|
303
|
+
/>
|
|
304
|
+
</div>
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Image loading state (for remote URLs)
|
|
271
309
|
if (!imageLoaded) {
|
|
272
310
|
return (
|
|
273
311
|
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
@@ -301,7 +339,7 @@ export function ShareSheetContent({
|
|
|
301
339
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
302
340
|
<img
|
|
303
341
|
src={ogImage}
|
|
304
|
-
alt={ogData
|
|
342
|
+
alt={ogData?.title || "Preview"}
|
|
305
343
|
onLoad={handleImageLoad}
|
|
306
344
|
onError={handleImageError}
|
|
307
345
|
style={{ display: "none" }}
|
|
@@ -310,21 +348,18 @@ export function ShareSheetContent({
|
|
|
310
348
|
);
|
|
311
349
|
}
|
|
312
350
|
|
|
313
|
-
// Image loaded - show it
|
|
351
|
+
// Image loaded - show it with fade-in
|
|
314
352
|
return (
|
|
315
353
|
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }}>
|
|
316
354
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
317
355
|
<img
|
|
318
356
|
src={ogImage}
|
|
319
|
-
alt={ogData
|
|
320
|
-
className={cn(defaultClasses.previewImage, classNames.previewImage)}
|
|
357
|
+
alt={ogData?.title || "Preview"}
|
|
358
|
+
className={cn(defaultClasses.previewImage, classNames.previewImage, "sharesheet-fadein")}
|
|
321
359
|
style={{
|
|
322
360
|
width: "100%",
|
|
323
361
|
maxWidth: "320px",
|
|
324
362
|
height: "auto",
|
|
325
|
-
borderRadius: "12px",
|
|
326
|
-
opacity: 1,
|
|
327
|
-
transition: "opacity 0.3s ease-in-out",
|
|
328
363
|
}}
|
|
329
364
|
/>
|
|
330
365
|
</div>
|
package/src/ShareSheetDrawer.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useState } from "react";
|
|
3
|
+
import React, { useState } from "react";
|
|
4
4
|
import { Drawer } from "vaul";
|
|
5
5
|
|
|
6
6
|
import { cn } from "./utils";
|
|
@@ -21,12 +21,28 @@ function cssVar(name: string, fallback: string): string {
|
|
|
21
21
|
return `var(${name}, ${fallback})`;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// Screen reader only styles (inline to avoid Tailwind dependency)
|
|
25
|
+
const srOnlyStyle: React.CSSProperties = {
|
|
26
|
+
position: "absolute",
|
|
27
|
+
width: "1px",
|
|
28
|
+
height: "1px",
|
|
29
|
+
padding: 0,
|
|
30
|
+
margin: "-1px",
|
|
31
|
+
overflow: "hidden",
|
|
32
|
+
clip: "rect(0, 0, 0, 0)",
|
|
33
|
+
whiteSpace: "nowrap",
|
|
34
|
+
borderWidth: 0,
|
|
35
|
+
};
|
|
36
|
+
|
|
24
37
|
export function ShareSheetDrawer({
|
|
25
38
|
title = "Share",
|
|
26
39
|
shareUrl,
|
|
27
40
|
shareText,
|
|
28
41
|
downloadUrl,
|
|
29
42
|
downloadFilename,
|
|
43
|
+
previewImage,
|
|
44
|
+
shareFile,
|
|
45
|
+
shareFilename,
|
|
30
46
|
disabled,
|
|
31
47
|
children,
|
|
32
48
|
open: controlledOpen,
|
|
@@ -78,7 +94,7 @@ export function ShareSheetDrawer({
|
|
|
78
94
|
borderColor: cssVar(CSS_VARS_UI.drawerBorder, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.drawerBorder]),
|
|
79
95
|
}}
|
|
80
96
|
>
|
|
81
|
-
<Drawer.Title
|
|
97
|
+
<Drawer.Title style={srOnlyStyle}>{title}</Drawer.Title>
|
|
82
98
|
<div
|
|
83
99
|
className={cn(defaultDrawerClasses.drawerInner, classNames.drawerInner)}
|
|
84
100
|
style={{
|
|
@@ -98,6 +114,9 @@ export function ShareSheetDrawer({
|
|
|
98
114
|
shareText={shareText}
|
|
99
115
|
downloadUrl={downloadUrl}
|
|
100
116
|
downloadFilename={downloadFilename}
|
|
117
|
+
previewImage={previewImage}
|
|
118
|
+
shareFile={shareFile}
|
|
119
|
+
shareFilename={shareFilename}
|
|
101
120
|
className={className}
|
|
102
121
|
classNames={classNames}
|
|
103
122
|
buttonSize={buttonSize}
|
package/src/hooks.ts
CHANGED
|
@@ -50,6 +50,10 @@ export interface UseShareSheetOptions {
|
|
|
50
50
|
downloadFilename?: string;
|
|
51
51
|
/** Email subject (optional) */
|
|
52
52
|
emailSubject?: string;
|
|
53
|
+
/** File to share via native share (data URL or Blob) - takes priority over URL sharing */
|
|
54
|
+
shareFile?: string | Blob | null;
|
|
55
|
+
/** Filename for the shared file */
|
|
56
|
+
shareFilename?: string;
|
|
53
57
|
/** Callback after native share */
|
|
54
58
|
onNativeShare?: () => void;
|
|
55
59
|
/** Callback after copy */
|
|
@@ -68,6 +72,8 @@ export function useShareSheet({
|
|
|
68
72
|
downloadUrl,
|
|
69
73
|
downloadFilename,
|
|
70
74
|
emailSubject = "Share",
|
|
75
|
+
shareFile,
|
|
76
|
+
shareFilename = "share.png",
|
|
71
77
|
onNativeShare,
|
|
72
78
|
onCopy,
|
|
73
79
|
onDownload,
|
|
@@ -105,12 +111,64 @@ export function useShareSheet({
|
|
|
105
111
|
}, [safeUrl, onCopy]);
|
|
106
112
|
|
|
107
113
|
const nativeShare = useCallback(async () => {
|
|
108
|
-
if (!safeUrl) return;
|
|
109
114
|
const nav = navigator as Navigator & {
|
|
110
115
|
share?: (data: ShareData) => Promise<void>;
|
|
116
|
+
canShare?: (data: ShareData) => boolean;
|
|
111
117
|
};
|
|
112
118
|
if (!("share" in nav) || typeof nav.share !== "function") return;
|
|
119
|
+
|
|
113
120
|
try {
|
|
121
|
+
// If shareFile is provided, try to share as a file
|
|
122
|
+
if (shareFile) {
|
|
123
|
+
let blob: Blob;
|
|
124
|
+
|
|
125
|
+
// Convert data URL to Blob if needed
|
|
126
|
+
if (typeof shareFile === "string" && shareFile.startsWith("data:")) {
|
|
127
|
+
const response = await fetch(shareFile);
|
|
128
|
+
blob = await response.blob();
|
|
129
|
+
} else if (shareFile instanceof Blob) {
|
|
130
|
+
blob = shareFile;
|
|
131
|
+
} else {
|
|
132
|
+
// Invalid shareFile, fall back to URL sharing
|
|
133
|
+
if (!safeUrl) return;
|
|
134
|
+
await nav.share({
|
|
135
|
+
title: shareText,
|
|
136
|
+
text: shareText,
|
|
137
|
+
url: safeUrl,
|
|
138
|
+
});
|
|
139
|
+
onNativeShare?.();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Create a File from the Blob
|
|
144
|
+
const file = new File([blob], shareFilename, { type: blob.type || "image/png" });
|
|
145
|
+
|
|
146
|
+
// Check if file sharing is supported
|
|
147
|
+
const shareData: ShareData = {
|
|
148
|
+
files: [file],
|
|
149
|
+
title: shareText,
|
|
150
|
+
text: shareText,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
if (nav.canShare && !nav.canShare(shareData)) {
|
|
154
|
+
// File sharing not supported, fall back to URL sharing
|
|
155
|
+
if (!safeUrl) return;
|
|
156
|
+
await nav.share({
|
|
157
|
+
title: shareText,
|
|
158
|
+
text: shareText,
|
|
159
|
+
url: safeUrl,
|
|
160
|
+
});
|
|
161
|
+
onNativeShare?.();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
await nav.share(shareData);
|
|
166
|
+
onNativeShare?.();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Fall back to URL sharing
|
|
171
|
+
if (!safeUrl) return;
|
|
114
172
|
await nav.share({
|
|
115
173
|
title: shareText,
|
|
116
174
|
text: shareText,
|
|
@@ -120,7 +178,7 @@ export function useShareSheet({
|
|
|
120
178
|
} catch {
|
|
121
179
|
// user canceled or share failed -> ignore
|
|
122
180
|
}
|
|
123
|
-
}, [safeUrl, shareText, onNativeShare]);
|
|
181
|
+
}, [safeUrl, shareText, shareFile, shareFilename, onNativeShare]);
|
|
124
182
|
|
|
125
183
|
const downloadFile = useCallback(async () => {
|
|
126
184
|
const url = (downloadUrl ?? "").trim();
|
package/src/types.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const CSS_VAR_UI_DEFAULTS = {
|
|
|
21
21
|
[CSS_VARS_UI.overlayBg]: "rgba(0, 0, 0, 0.7)",
|
|
22
22
|
[CSS_VARS_UI.drawerBg]: "#09090b",
|
|
23
23
|
[CSS_VARS_UI.drawerBorder]: "#27272a",
|
|
24
|
-
[CSS_VARS_UI.handleBg]: "
|
|
24
|
+
[CSS_VARS_UI.handleBg]: "rgba(255, 255, 255, 0.2)",
|
|
25
25
|
[CSS_VARS_UI.titleColor]: "#ffffff",
|
|
26
26
|
[CSS_VARS_UI.subtitleColor]: "#a1a1aa",
|
|
27
27
|
[CSS_VARS_UI.buttonLabelColor]: "#ffffff",
|
|
@@ -108,6 +108,12 @@ export interface ShareSheetContentProps {
|
|
|
108
108
|
downloadUrl?: string | null;
|
|
109
109
|
/** Filename for downloaded file */
|
|
110
110
|
downloadFilename?: string;
|
|
111
|
+
/** Custom preview image URL (skips OG fetching if provided) */
|
|
112
|
+
previewImage?: string | null;
|
|
113
|
+
/** File to share via native share (data URL or Blob) - takes priority over URL sharing */
|
|
114
|
+
shareFile?: string | Blob | null;
|
|
115
|
+
/** Filename for the shared file */
|
|
116
|
+
shareFilename?: string;
|
|
111
117
|
/** Custom class name for the container (shorthand for classNames.root) */
|
|
112
118
|
className?: string;
|
|
113
119
|
/** Override class names for sub-components */
|
|
@@ -122,6 +128,8 @@ export interface ShareSheetContentProps {
|
|
|
122
128
|
onCopy?: () => void;
|
|
123
129
|
/** Called when download starts */
|
|
124
130
|
onDownload?: () => void;
|
|
131
|
+
/** Called on every share option click, with the option id (analytics-friendly) */
|
|
132
|
+
onShare?: (option: ShareOption) => void;
|
|
125
133
|
/** Hide specific share options */
|
|
126
134
|
hide?: ShareOption[];
|
|
127
135
|
/** Show only these platforms, in this exact order */
|