react-sharesheet 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/dist/index.js ADDED
@@ -0,0 +1,1040 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ CSS_VARS: () => CSS_VARS,
24
+ CSS_VARS_UI: () => CSS_VARS_UI,
25
+ CSS_VAR_DEFAULTS: () => CSS_VAR_DEFAULTS,
26
+ CSS_VAR_UI_DEFAULTS: () => CSS_VAR_UI_DEFAULTS,
27
+ PLATFORMS: () => PLATFORMS,
28
+ PLATFORM_COLORS: () => PLATFORM_COLORS,
29
+ PLATFORM_CSS_VARS: () => PLATFORM_CSS_VARS,
30
+ PLATFORM_ICONS: () => PLATFORM_ICONS,
31
+ PLATFORM_IDS: () => PLATFORM_IDS,
32
+ PLATFORM_LABELS: () => PLATFORM_LABELS,
33
+ ShareMenuContent: () => ShareMenuContent,
34
+ ShareMenuDrawer: () => ShareMenuDrawer,
35
+ ShareSheetContent: () => ShareSheetContent,
36
+ ShareSheetDrawer: () => ShareSheetDrawer,
37
+ cn: () => cn,
38
+ generateCssVarDefaults: () => generateCssVarDefaults,
39
+ getAllPlatforms: () => getAllPlatforms,
40
+ getPlatform: () => getPlatform,
41
+ getPlatformColor: () => getPlatformColor,
42
+ getPlatformIcon: () => getPlatformIcon,
43
+ getPlatformLabel: () => getPlatformLabel,
44
+ getSafeUrl: () => getSafeUrl,
45
+ openInstagram: () => openInstagram,
46
+ openThreads: () => openThreads,
47
+ openTikTok: () => openTikTok,
48
+ openUrl: () => openUrl,
49
+ shareToFacebook: () => shareToFacebook,
50
+ shareToLinkedIn: () => shareToLinkedIn,
51
+ shareToReddit: () => shareToReddit,
52
+ shareToSnapchat: () => shareToSnapchat,
53
+ shareToTelegram: () => shareToTelegram,
54
+ shareToWhatsApp: () => shareToWhatsApp,
55
+ shareToX: () => shareToX,
56
+ shareViaEmail: () => shareViaEmail,
57
+ shareViaSMS: () => shareViaSMS,
58
+ useShareMenu: () => useShareMenu,
59
+ useShareSheet: () => useShareSheet
60
+ });
61
+ module.exports = __toCommonJS(src_exports);
62
+
63
+ // src/ShareSheetContent.tsx
64
+ var import_react2 = require("react");
65
+ var import_lucide_react2 = require("lucide-react");
66
+
67
+ // src/utils.ts
68
+ var import_clsx = require("clsx");
69
+ var import_tailwind_merge = require("tailwind-merge");
70
+ function cn(...inputs) {
71
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
72
+ }
73
+ function openUrl(url) {
74
+ window.open(url, "_blank", "noopener,noreferrer");
75
+ }
76
+ function getSafeUrl(shareUrl) {
77
+ return shareUrl || (typeof window !== "undefined" ? window.location.href : "");
78
+ }
79
+
80
+ // src/hooks.ts
81
+ var import_react = require("react");
82
+
83
+ // src/share-functions.ts
84
+ function shareToWhatsApp(url, text) {
85
+ const encoded = encodeURIComponent(`${text}
86
+ ${url}`);
87
+ openUrl(`https://api.whatsapp.com/send?text=${encoded}`);
88
+ }
89
+ function shareToTelegram(url, text) {
90
+ const encodedText = encodeURIComponent(text);
91
+ const encodedUrl = encodeURIComponent(url);
92
+ openUrl(`https://t.me/share/url?url=${encodedUrl}&text=${encodedText}`);
93
+ }
94
+ function shareToX(url, text) {
95
+ const encodedText = encodeURIComponent(text);
96
+ const encodedUrl = encodeURIComponent(url);
97
+ openUrl(`https://x.com/intent/tweet?text=${encodedText}&url=${encodedUrl}`);
98
+ }
99
+ function shareToFacebook(url) {
100
+ const encodedUrl = encodeURIComponent(url);
101
+ openUrl(`https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`);
102
+ }
103
+ function openInstagram() {
104
+ window.location.href = "instagram://";
105
+ }
106
+ function openTikTok() {
107
+ window.location.href = "tiktok://";
108
+ }
109
+ function openThreads() {
110
+ window.location.href = "threads://";
111
+ }
112
+ function shareToSnapchat(url) {
113
+ const encodedUrl = encodeURIComponent(url);
114
+ openUrl(`https://www.snapchat.com/scan?attachmentUrl=${encodedUrl}`);
115
+ }
116
+ function shareViaSMS(url, text) {
117
+ const body = encodeURIComponent(`${text}
118
+ ${url}`);
119
+ window.location.href = `sms:?body=${body}`;
120
+ }
121
+ function shareViaEmail(url, text, subject = "Share") {
122
+ const encodedSubject = encodeURIComponent(subject);
123
+ const body = encodeURIComponent(`${text}
124
+
125
+ ${url}`);
126
+ window.location.href = `mailto:?subject=${encodedSubject}&body=${body}`;
127
+ }
128
+ function shareToLinkedIn(url) {
129
+ const encodedUrl = encodeURIComponent(url);
130
+ openUrl(`https://www.linkedin.com/sharing/share-offsite/?url=${encodedUrl}`);
131
+ }
132
+ function shareToReddit(url, text) {
133
+ const encodedText = encodeURIComponent(text);
134
+ const encodedUrl = encodeURIComponent(url);
135
+ openUrl(`https://www.reddit.com/submit?url=${encodedUrl}&title=${encodedText}`);
136
+ }
137
+
138
+ // src/hooks.ts
139
+ function useShareSheet({
140
+ shareUrl,
141
+ shareText,
142
+ downloadUrl,
143
+ downloadFilename,
144
+ emailSubject = "Share",
145
+ onNativeShare,
146
+ onCopy,
147
+ onDownload
148
+ }) {
149
+ const [copied, setCopied] = (0, import_react.useState)(false);
150
+ const [downloading, setDownloading] = (0, import_react.useState)(false);
151
+ const canNativeShare = (0, import_react.useMemo)(() => {
152
+ return typeof navigator !== "undefined" && "share" in navigator;
153
+ }, []);
154
+ const safeUrl = getSafeUrl(shareUrl);
155
+ const copyLink = (0, import_react.useCallback)(async () => {
156
+ if (!safeUrl) return;
157
+ try {
158
+ await navigator.clipboard.writeText(safeUrl);
159
+ setCopied(true);
160
+ onCopy?.();
161
+ setTimeout(() => setCopied(false), 1200);
162
+ } catch {
163
+ }
164
+ }, [safeUrl, onCopy]);
165
+ const nativeShare = (0, import_react.useCallback)(async () => {
166
+ if (!safeUrl) return;
167
+ const nav = navigator;
168
+ if (!("share" in nav) || typeof nav.share !== "function") return;
169
+ try {
170
+ await nav.share({
171
+ title: shareText,
172
+ text: shareText,
173
+ url: safeUrl
174
+ });
175
+ onNativeShare?.();
176
+ } catch {
177
+ }
178
+ }, [safeUrl, shareText, onNativeShare]);
179
+ const downloadFile = (0, import_react.useCallback)(async () => {
180
+ const url = (downloadUrl ?? "").trim();
181
+ if (!url) return;
182
+ try {
183
+ setDownloading(true);
184
+ onDownload?.();
185
+ const res = await fetch(url);
186
+ if (!res.ok) throw new Error(`Failed to fetch file (${res.status})`);
187
+ const blob = await res.blob();
188
+ const href = URL.createObjectURL(blob);
189
+ const a = document.createElement("a");
190
+ a.href = href;
191
+ a.download = downloadFilename || "download";
192
+ document.body.appendChild(a);
193
+ a.click();
194
+ a.remove();
195
+ URL.revokeObjectURL(href);
196
+ } catch {
197
+ } finally {
198
+ setDownloading(false);
199
+ }
200
+ }, [downloadUrl, downloadFilename, onDownload]);
201
+ const shareWhatsApp = (0, import_react.useCallback)(() => {
202
+ shareToWhatsApp(safeUrl, shareText);
203
+ }, [safeUrl, shareText]);
204
+ const shareTelegram = (0, import_react.useCallback)(() => {
205
+ shareToTelegram(safeUrl, shareText);
206
+ }, [safeUrl, shareText]);
207
+ const shareX = (0, import_react.useCallback)(() => {
208
+ shareToX(safeUrl, shareText);
209
+ }, [safeUrl, shareText]);
210
+ const shareFacebook = (0, import_react.useCallback)(() => {
211
+ shareToFacebook(safeUrl);
212
+ }, [safeUrl]);
213
+ const shareInstagram = (0, import_react.useCallback)(() => {
214
+ openInstagram();
215
+ }, []);
216
+ const shareTikTok = (0, import_react.useCallback)(() => {
217
+ openTikTok();
218
+ }, []);
219
+ const shareThreads = (0, import_react.useCallback)(() => {
220
+ openThreads();
221
+ }, []);
222
+ const shareSnapchat = (0, import_react.useCallback)(() => {
223
+ shareToSnapchat(safeUrl);
224
+ }, [safeUrl]);
225
+ const shareSMS = (0, import_react.useCallback)(() => {
226
+ shareViaSMS(safeUrl, shareText);
227
+ }, [safeUrl, shareText]);
228
+ const shareEmail = (0, import_react.useCallback)(() => {
229
+ shareViaEmail(safeUrl, shareText, emailSubject);
230
+ }, [safeUrl, shareText, emailSubject]);
231
+ const shareLinkedIn = (0, import_react.useCallback)(() => {
232
+ shareToLinkedIn(safeUrl);
233
+ }, [safeUrl]);
234
+ const shareReddit = (0, import_react.useCallback)(() => {
235
+ shareToReddit(safeUrl, shareText);
236
+ }, [safeUrl, shareText]);
237
+ return {
238
+ canNativeShare,
239
+ copied,
240
+ downloading,
241
+ safeUrl,
242
+ copyLink,
243
+ nativeShare,
244
+ downloadFile,
245
+ shareWhatsApp,
246
+ shareTelegram,
247
+ shareX,
248
+ shareFacebook,
249
+ shareInstagram,
250
+ shareTikTok,
251
+ shareThreads,
252
+ shareSnapchat,
253
+ shareSMS,
254
+ shareEmail,
255
+ shareLinkedIn,
256
+ shareReddit
257
+ };
258
+ }
259
+ var useShareMenu = useShareSheet;
260
+
261
+ // src/platforms.tsx
262
+ var import_lucide_react = require("lucide-react");
263
+ var import_fa = require("react-icons/fa");
264
+ var import_fa6 = require("react-icons/fa6");
265
+ var import_jsx_runtime = require("react/jsx-runtime");
266
+ var PLATFORM_IDS = [
267
+ "native",
268
+ "copy",
269
+ "download",
270
+ "whatsapp",
271
+ "telegram",
272
+ "instagram",
273
+ "facebook",
274
+ "snapchat",
275
+ "sms",
276
+ "email",
277
+ "linkedin",
278
+ "reddit",
279
+ "x",
280
+ "tiktok",
281
+ "threads"
282
+ ];
283
+ var PLATFORM_COLORS = {
284
+ native: { bg: "#7c3aed", text: "#ffffff" },
285
+ copy: { bg: "#3b82f6", text: "#ffffff" },
286
+ download: { bg: "#ef4444", text: "#ffffff" },
287
+ whatsapp: { bg: "#25D366", text: "#ffffff" },
288
+ telegram: { bg: "#229ED9", text: "#ffffff" },
289
+ instagram: { bg: "#E1306C", text: "#ffffff" },
290
+ facebook: { bg: "#1877F2", text: "#ffffff" },
291
+ snapchat: { bg: "#FFFC00", text: "#000000" },
292
+ sms: { bg: "#22c55e", text: "#ffffff" },
293
+ email: { bg: "#f97316", text: "#ffffff" },
294
+ linkedin: { bg: "#0A66C2", text: "#ffffff" },
295
+ reddit: { bg: "#FF4500", text: "#ffffff" },
296
+ x: { bg: "#000000", text: "#ffffff" },
297
+ tiktok: { bg: "#000000", text: "#ffffff" },
298
+ threads: { bg: "#000000", text: "#ffffff" }
299
+ };
300
+ var PLATFORM_LABELS = {
301
+ native: "Share\u2026",
302
+ copy: "Copy",
303
+ download: "Download",
304
+ whatsapp: "WhatsApp",
305
+ telegram: "Telegram",
306
+ instagram: "Instagram",
307
+ facebook: "Facebook",
308
+ snapchat: "Snapchat",
309
+ sms: "SMS",
310
+ email: "Email",
311
+ linkedin: "LinkedIn",
312
+ reddit: "Reddit",
313
+ x: "X",
314
+ tiktok: "TikTok",
315
+ threads: "Threads"
316
+ };
317
+ var PLATFORM_ICONS = {
318
+ native: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Send, { size, className }),
319
+ copy: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Link, { size, className }),
320
+ download: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Download, { size, className }),
321
+ whatsapp: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaWhatsapp, { size, className }),
322
+ telegram: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaTelegramPlane, { size, className }),
323
+ instagram: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaInstagram, { size, className }),
324
+ facebook: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaFacebookF, { size, className }),
325
+ snapchat: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa6.FaSnapchat, { size, className }),
326
+ sms: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.MessageCircle, { size, className }),
327
+ email: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Mail, { size, className }),
328
+ linkedin: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaLinkedin, { size, className }),
329
+ reddit: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaReddit, { size, className }),
330
+ x: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa6.FaXTwitter, { size, className }),
331
+ tiktok: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaTiktok, { size, className }),
332
+ threads: ({ size = 22, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa6.FaThreads, { size, className })
333
+ };
334
+ var PLATFORM_CSS_VARS = {
335
+ native: "--sharesheet-native-bg",
336
+ copy: "--sharesheet-copy-bg",
337
+ download: "--sharesheet-download-bg",
338
+ whatsapp: "--sharesheet-whatsapp-bg",
339
+ telegram: "--sharesheet-telegram-bg",
340
+ instagram: "--sharesheet-instagram-bg",
341
+ facebook: "--sharesheet-facebook-bg",
342
+ snapchat: "--sharesheet-snapchat-bg",
343
+ sms: "--sharesheet-sms-bg",
344
+ email: "--sharesheet-email-bg",
345
+ linkedin: "--sharesheet-linkedin-bg",
346
+ reddit: "--sharesheet-reddit-bg",
347
+ x: "--sharesheet-x-bg",
348
+ tiktok: "--sharesheet-tiktok-bg",
349
+ threads: "--sharesheet-threads-bg"
350
+ };
351
+ var PLATFORMS = Object.fromEntries(
352
+ PLATFORM_IDS.map((id) => [
353
+ id,
354
+ {
355
+ id,
356
+ label: PLATFORM_LABELS[id],
357
+ colors: PLATFORM_COLORS[id],
358
+ Icon: PLATFORM_ICONS[id],
359
+ cssVar: PLATFORM_CSS_VARS[id]
360
+ }
361
+ ])
362
+ );
363
+ function getPlatform(id) {
364
+ return PLATFORMS[id];
365
+ }
366
+ function getAllPlatforms() {
367
+ return PLATFORM_IDS.map((id) => PLATFORMS[id]);
368
+ }
369
+ function getPlatformColor(id) {
370
+ return PLATFORM_COLORS[id];
371
+ }
372
+ function getPlatformIcon(id) {
373
+ return PLATFORM_ICONS[id];
374
+ }
375
+ function getPlatformLabel(id) {
376
+ return PLATFORM_LABELS[id];
377
+ }
378
+ function generateCssVarDefaults() {
379
+ const defaults = {};
380
+ PLATFORM_IDS.forEach((id) => {
381
+ defaults[PLATFORM_CSS_VARS[id]] = PLATFORM_COLORS[id].bg;
382
+ });
383
+ return defaults;
384
+ }
385
+
386
+ // src/types.ts
387
+ var CSS_VARS_UI = {
388
+ // Drawer
389
+ overlayBg: "--sharesheet-overlay-bg",
390
+ drawerBg: "--sharesheet-drawer-bg",
391
+ drawerBorder: "--sharesheet-drawer-border",
392
+ handleBg: "--sharesheet-handle-bg",
393
+ // Content
394
+ titleColor: "--sharesheet-title-color",
395
+ subtitleColor: "--sharesheet-subtitle-color",
396
+ buttonLabelColor: "--sharesheet-button-label-color",
397
+ // Preview
398
+ previewBg: "--sharesheet-preview-bg",
399
+ previewShimmer: "--sharesheet-preview-shimmer"
400
+ };
401
+ var CSS_VAR_UI_DEFAULTS = {
402
+ [CSS_VARS_UI.overlayBg]: "rgba(0, 0, 0, 0.7)",
403
+ [CSS_VARS_UI.drawerBg]: "#09090b",
404
+ [CSS_VARS_UI.drawerBorder]: "#27272a",
405
+ [CSS_VARS_UI.handleBg]: "#27272a",
406
+ [CSS_VARS_UI.titleColor]: "#ffffff",
407
+ [CSS_VARS_UI.subtitleColor]: "#a1a1aa",
408
+ [CSS_VARS_UI.buttonLabelColor]: "#ffffff",
409
+ [CSS_VARS_UI.previewBg]: "rgba(255, 255, 255, 0.05)",
410
+ [CSS_VARS_UI.previewShimmer]: "rgba(255, 255, 255, 0.1)"
411
+ };
412
+ var CSS_VARS = CSS_VARS_UI;
413
+ var CSS_VAR_DEFAULTS = CSS_VAR_UI_DEFAULTS;
414
+
415
+ // src/ShareSheetContent.tsx
416
+ var import_jsx_runtime2 = require("react/jsx-runtime");
417
+ var DEFAULT_BUTTON_SIZE = 45;
418
+ var DEFAULT_ICON_SIZE = 22;
419
+ var IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "webp", "svg", "bmp", "ico", "avif"];
420
+ var VIDEO_EXTENSIONS = ["mp4", "webm", "mov", "avi", "mkv", "m4v", "ogv"];
421
+ var AUDIO_EXTENSIONS = ["mp3", "wav", "ogg", "m4a", "aac", "flac", "wma"];
422
+ function detectPreviewType(url) {
423
+ try {
424
+ const pathname = new URL(url, "http://localhost").pathname;
425
+ const ext = pathname.split(".").pop()?.toLowerCase() || "";
426
+ if (IMAGE_EXTENSIONS.includes(ext)) return "image";
427
+ if (VIDEO_EXTENSIONS.includes(ext)) return "video";
428
+ if (AUDIO_EXTENSIONS.includes(ext)) return "audio";
429
+ if (url.includes("/api/og") || url.includes("og-image")) return "image";
430
+ if (url.includes("youtube.com") || url.includes("vimeo.com")) return "video";
431
+ return "link";
432
+ } catch {
433
+ return "link";
434
+ }
435
+ }
436
+ function getFilenameFromUrl(url) {
437
+ try {
438
+ const pathname = new URL(url, "http://localhost").pathname;
439
+ const filename = pathname.split("/").pop() || "";
440
+ return decodeURIComponent(filename);
441
+ } catch {
442
+ return url;
443
+ }
444
+ }
445
+ var defaultClasses = {
446
+ root: "max-w-md mx-auto",
447
+ header: "text-center mb-2",
448
+ title: "text-2xl font-black",
449
+ subtitle: "mt-1 text-sm",
450
+ preview: "flex justify-center mb-4 px-4",
451
+ previewSkeleton: "rounded-xl overflow-hidden",
452
+ previewImage: "",
453
+ previewVideo: "",
454
+ previewFile: "",
455
+ previewFileIcon: "",
456
+ previewFilename: "truncate",
457
+ previewLink: "",
458
+ grid: "px-2 py-6 flex flex-row items-center gap-4 gap-y-6 flex-wrap justify-center",
459
+ button: "flex flex-col items-center gap-0 text-xs w-[60px] outline-none cursor-pointer group",
460
+ buttonIcon: "p-2 rounded-full transition-all flex items-center justify-center group-hover:scale-110 group-active:scale-95 mb-2",
461
+ buttonLabel: ""
462
+ };
463
+ var shimmerKeyframes = `
464
+ @keyframes sharesheet-shimmer {
465
+ 0% { transform: translateX(-100%); }
466
+ 100% { transform: translateX(100%); }
467
+ }
468
+ `;
469
+ function cssVar(name, fallback) {
470
+ return `var(${name}, ${fallback})`;
471
+ }
472
+ function normalizePreview(preview) {
473
+ if (!preview) return null;
474
+ if (typeof preview === "string") {
475
+ const type2 = detectPreviewType(preview);
476
+ return {
477
+ url: preview,
478
+ type: type2,
479
+ filename: getFilenameFromUrl(preview)
480
+ };
481
+ }
482
+ const type = preview.type === "auto" || !preview.type ? detectPreviewType(preview.url) : preview.type;
483
+ return {
484
+ ...preview,
485
+ type,
486
+ filename: preview.filename || getFilenameFromUrl(preview.url)
487
+ };
488
+ }
489
+ function ShareSheetContent({
490
+ title = "Share",
491
+ shareUrl,
492
+ shareText,
493
+ preview,
494
+ downloadUrl,
495
+ downloadFilename,
496
+ className,
497
+ classNames = {},
498
+ buttonSize = DEFAULT_BUTTON_SIZE,
499
+ iconSize = DEFAULT_ICON_SIZE,
500
+ onNativeShare,
501
+ onCopy,
502
+ onDownload,
503
+ hide = [],
504
+ show,
505
+ labels = {},
506
+ icons = {}
507
+ }) {
508
+ const [mediaLoaded, setMediaLoaded] = (0, import_react2.useState)(false);
509
+ const [mediaError, setMediaError] = (0, import_react2.useState)(false);
510
+ const handleMediaLoad = (0, import_react2.useCallback)(() => {
511
+ setMediaLoaded(true);
512
+ }, []);
513
+ const handleMediaError = (0, import_react2.useCallback)(() => {
514
+ setMediaError(true);
515
+ }, []);
516
+ const previewConfig = (0, import_react2.useMemo)(() => normalizePreview(preview), [preview]);
517
+ const shareSheet = useShareSheet({
518
+ shareUrl,
519
+ shareText,
520
+ downloadUrl,
521
+ downloadFilename,
522
+ emailSubject: title,
523
+ onNativeShare,
524
+ onCopy,
525
+ onDownload
526
+ });
527
+ const shareActions = (0, import_react2.useMemo)(() => ({
528
+ native: () => void shareSheet.nativeShare(),
529
+ copy: () => void shareSheet.copyLink(),
530
+ download: () => void shareSheet.downloadFile(),
531
+ whatsapp: shareSheet.shareWhatsApp,
532
+ telegram: shareSheet.shareTelegram,
533
+ instagram: shareSheet.shareInstagram,
534
+ facebook: shareSheet.shareFacebook,
535
+ snapchat: shareSheet.shareSnapchat,
536
+ sms: shareSheet.shareSMS,
537
+ email: shareSheet.shareEmail,
538
+ linkedin: shareSheet.shareLinkedIn,
539
+ reddit: shareSheet.shareReddit,
540
+ x: shareSheet.shareX,
541
+ tiktok: shareSheet.shareTikTok,
542
+ threads: shareSheet.shareThreads
543
+ }), [shareSheet]);
544
+ const dynamicLabels = (0, import_react2.useMemo)(() => ({
545
+ copy: shareSheet.copied ? "Copied!" : PLATFORM_LABELS.copy,
546
+ download: shareSheet.downloading ? "..." : PLATFORM_LABELS.download
547
+ }), [shareSheet.copied, shareSheet.downloading]);
548
+ const buttons = (0, import_react2.useMemo)(() => {
549
+ return PLATFORM_IDS.map((id) => {
550
+ const Icon = PLATFORM_ICONS[id];
551
+ const defaultLabel = dynamicLabels[id] ?? PLATFORM_LABELS[id];
552
+ return {
553
+ id,
554
+ label: labels[id] ?? defaultLabel,
555
+ icon: icons[id] ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { size: iconSize }),
556
+ // Use CSS var with fallback to platform color
557
+ bgColor: cssVar(PLATFORM_CSS_VARS[id], PLATFORM_COLORS[id].bg),
558
+ textColor: PLATFORM_COLORS[id].text,
559
+ onClick: shareActions[id],
560
+ // Conditions for showing certain buttons
561
+ condition: id === "native" ? shareSheet.canNativeShare : id === "download" ? !!downloadUrl : true
562
+ };
563
+ });
564
+ }, [iconSize, labels, icons, dynamicLabels, shareActions, shareSheet.canNativeShare, downloadUrl]);
565
+ const visibleButtons = (0, import_react2.useMemo)(() => {
566
+ return buttons.filter((btn) => {
567
+ if (btn.condition === false) return false;
568
+ if (show && show.length > 0) return show.includes(btn.id);
569
+ if (hide.includes(btn.id)) return false;
570
+ return true;
571
+ });
572
+ }, [buttons, show, hide]);
573
+ const showPreview = !!previewConfig;
574
+ const renderPreview = () => {
575
+ if (!previewConfig) return null;
576
+ const { type, url, filename, alt, poster } = previewConfig;
577
+ const bgColor = cssVar(CSS_VARS_UI.previewBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewBg]);
578
+ const shimmerColor = cssVar(CSS_VARS_UI.previewShimmer, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewShimmer]);
579
+ const textColor = cssVar(CSS_VARS_UI.subtitleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.subtitleColor]);
580
+ const UrlLabel = ({ displayUrl = url }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
581
+ "div",
582
+ {
583
+ className: cn(defaultClasses.previewFilename, classNames.previewFilename),
584
+ style: {
585
+ color: textColor,
586
+ fontSize: "10px",
587
+ opacity: 0.5,
588
+ textAlign: "center",
589
+ marginTop: "6px"
590
+ },
591
+ children: displayUrl
592
+ }
593
+ );
594
+ const PlaceholderCard = ({
595
+ icon: IconComponent,
596
+ isLoading = false,
597
+ label,
598
+ displayUrl
599
+ }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
600
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
601
+ "div",
602
+ {
603
+ className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
604
+ style: {
605
+ position: "relative",
606
+ backgroundColor: bgColor,
607
+ width: "200px",
608
+ height: "120px",
609
+ overflow: "hidden",
610
+ display: "flex",
611
+ alignItems: "center",
612
+ justifyContent: "center"
613
+ },
614
+ children: [
615
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
616
+ "div",
617
+ {
618
+ style: {
619
+ position: "absolute",
620
+ inset: 0,
621
+ background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
622
+ animation: "sharesheet-shimmer 1.5s infinite"
623
+ }
624
+ }
625
+ ) }),
626
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
627
+ "div",
628
+ {
629
+ style: {
630
+ display: "flex",
631
+ flexDirection: "column",
632
+ alignItems: "center",
633
+ justifyContent: "center",
634
+ gap: "8px"
635
+ },
636
+ children: [
637
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconComponent, { size: 32, style: { color: textColor, opacity: 0.4 } }),
638
+ label && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: textColor, fontSize: "11px", opacity: 0.4 }, children: label })
639
+ ]
640
+ }
641
+ )
642
+ ]
643
+ }
644
+ ),
645
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(UrlLabel, { displayUrl })
646
+ ] });
647
+ if (mediaError && (type === "image" || type === "video")) {
648
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PlaceholderCard, { icon: import_lucide_react2.Link2, displayUrl: url });
649
+ }
650
+ switch (type) {
651
+ case "image":
652
+ if (!mediaLoaded) {
653
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
654
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
655
+ "div",
656
+ {
657
+ className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
658
+ style: {
659
+ position: "relative",
660
+ backgroundColor: bgColor,
661
+ width: "200px",
662
+ height: "120px",
663
+ overflow: "hidden",
664
+ display: "flex",
665
+ alignItems: "center",
666
+ justifyContent: "center"
667
+ },
668
+ children: [
669
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
670
+ "div",
671
+ {
672
+ style: {
673
+ position: "absolute",
674
+ inset: 0,
675
+ background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
676
+ animation: "sharesheet-shimmer 1.5s infinite"
677
+ }
678
+ }
679
+ ) }),
680
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Image, { size: 32, style: { color: textColor, opacity: 0.4 } })
681
+ ]
682
+ }
683
+ ),
684
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(UrlLabel, {}),
685
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
686
+ "img",
687
+ {
688
+ src: url,
689
+ alt: alt || "Preview",
690
+ onLoad: handleMediaLoad,
691
+ onError: handleMediaError,
692
+ style: { display: "none" }
693
+ }
694
+ )
695
+ ] });
696
+ }
697
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
698
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
699
+ "img",
700
+ {
701
+ src: url,
702
+ alt: alt || "Preview",
703
+ className: cn(defaultClasses.previewImage, classNames.previewImage),
704
+ style: {
705
+ maxWidth: "100%",
706
+ maxHeight: "180px",
707
+ borderRadius: "12px",
708
+ opacity: 1,
709
+ transition: "opacity 0.3s ease-in-out"
710
+ }
711
+ }
712
+ ),
713
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(UrlLabel, {})
714
+ ] });
715
+ case "video":
716
+ if (!mediaLoaded) {
717
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
718
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
719
+ "div",
720
+ {
721
+ className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
722
+ style: {
723
+ position: "relative",
724
+ backgroundColor: bgColor,
725
+ width: "200px",
726
+ height: "120px",
727
+ overflow: "hidden",
728
+ display: "flex",
729
+ alignItems: "center",
730
+ justifyContent: "center"
731
+ },
732
+ children: [
733
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
734
+ "div",
735
+ {
736
+ style: {
737
+ position: "absolute",
738
+ inset: 0,
739
+ background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
740
+ animation: "sharesheet-shimmer 1.5s infinite"
741
+ }
742
+ }
743
+ ) }),
744
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Film, { size: 32, style: { color: textColor, opacity: 0.4 } })
745
+ ]
746
+ }
747
+ ),
748
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(UrlLabel, {}),
749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
750
+ "video",
751
+ {
752
+ src: url,
753
+ poster,
754
+ onLoadedData: handleMediaLoad,
755
+ onError: handleMediaError,
756
+ style: { display: "none" },
757
+ muted: true,
758
+ playsInline: true,
759
+ preload: "metadata"
760
+ }
761
+ )
762
+ ] });
763
+ }
764
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
765
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", borderRadius: "12px", overflow: "hidden" }, children: [
766
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
767
+ "video",
768
+ {
769
+ src: url,
770
+ poster,
771
+ className: cn(defaultClasses.previewVideo, classNames.previewVideo),
772
+ style: {
773
+ maxWidth: "100%",
774
+ maxHeight: "180px",
775
+ display: "block"
776
+ },
777
+ muted: true,
778
+ playsInline: true,
779
+ preload: "metadata"
780
+ }
781
+ ),
782
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
783
+ "div",
784
+ {
785
+ style: {
786
+ position: "absolute",
787
+ inset: 0,
788
+ display: "flex",
789
+ alignItems: "center",
790
+ justifyContent: "center",
791
+ pointerEvents: "none"
792
+ },
793
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
794
+ "div",
795
+ {
796
+ style: {
797
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
798
+ borderRadius: "50%",
799
+ padding: "10px"
800
+ },
801
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Play, { size: 20, fill: "white", color: "white" })
802
+ }
803
+ )
804
+ }
805
+ )
806
+ ] }),
807
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(UrlLabel, {})
808
+ ] });
809
+ case "audio":
810
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PlaceholderCard, { icon: import_lucide_react2.Music, label: filename || "Audio", displayUrl: url });
811
+ case "file":
812
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PlaceholderCard, { icon: import_lucide_react2.FileText, label: filename || "File", displayUrl: url });
813
+ case "link":
814
+ default:
815
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PlaceholderCard, { icon: import_lucide_react2.Link2, displayUrl: url });
816
+ }
817
+ };
818
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: cn(defaultClasses.root, classNames.root, className), children: [
819
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { dangerouslySetInnerHTML: { __html: shimmerKeyframes } }),
820
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: cn(defaultClasses.header, classNames.header), children: [
821
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
822
+ "div",
823
+ {
824
+ className: cn(defaultClasses.title, classNames.title),
825
+ style: { color: cssVar(CSS_VARS_UI.titleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.titleColor]) },
826
+ children: title
827
+ }
828
+ ),
829
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
830
+ "div",
831
+ {
832
+ className: cn(defaultClasses.subtitle, classNames.subtitle),
833
+ style: { color: cssVar(CSS_VARS_UI.subtitleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.subtitleColor]) },
834
+ children: shareText
835
+ }
836
+ )
837
+ ] }),
838
+ showPreview && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: cn(defaultClasses.preview, classNames.preview), children: renderPreview() }),
839
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: cn(defaultClasses.grid, classNames.grid), children: visibleButtons.map((btn) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
840
+ "button",
841
+ {
842
+ type: "button",
843
+ className: cn(defaultClasses.button, classNames.button),
844
+ onClick: btn.onClick,
845
+ children: [
846
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
847
+ "div",
848
+ {
849
+ className: cn(defaultClasses.buttonIcon, classNames.buttonIcon),
850
+ style: {
851
+ width: buttonSize,
852
+ height: buttonSize,
853
+ backgroundColor: btn.bgColor,
854
+ color: btn.textColor
855
+ },
856
+ children: btn.icon
857
+ }
858
+ ),
859
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
860
+ "div",
861
+ {
862
+ className: cn(defaultClasses.buttonLabel, classNames.buttonLabel),
863
+ style: { color: cssVar(CSS_VARS_UI.buttonLabelColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.buttonLabelColor]) },
864
+ children: btn.label
865
+ }
866
+ )
867
+ ]
868
+ },
869
+ btn.id
870
+ )) })
871
+ ] });
872
+ }
873
+ var ShareMenuContent = ShareSheetContent;
874
+
875
+ // src/ShareSheetDrawer.tsx
876
+ var import_react3 = require("react");
877
+ var import_vaul = require("vaul");
878
+ var import_jsx_runtime3 = require("react/jsx-runtime");
879
+ var defaultDrawerClasses = {
880
+ overlay: "fixed inset-0 z-[70]",
881
+ drawer: "flex flex-col rounded-t-[14px] h-[70%] mt-24 fixed bottom-0 left-0 right-0 z-[80] border-t outline-none",
882
+ drawerInner: "p-4 rounded-t-[14px] flex-1 overflow-auto",
883
+ handle: "mx-auto w-12 h-1.5 shrink-0 rounded-full mb-6",
884
+ trigger: ""
885
+ };
886
+ function cssVar2(name, fallback) {
887
+ return `var(${name}, ${fallback})`;
888
+ }
889
+ function ShareSheetDrawer({
890
+ title = "Share",
891
+ shareUrl,
892
+ shareText,
893
+ preview,
894
+ downloadUrl,
895
+ downloadFilename,
896
+ disabled,
897
+ children,
898
+ open: controlledOpen,
899
+ onOpenChange: controlledOnOpenChange,
900
+ className,
901
+ classNames = {},
902
+ buttonSize,
903
+ iconSize,
904
+ onNativeShare,
905
+ onCopy,
906
+ onDownload,
907
+ hide,
908
+ show,
909
+ labels,
910
+ icons
911
+ }) {
912
+ const [internalOpen, setInternalOpen] = (0, import_react3.useState)(false);
913
+ const isControlled = controlledOpen !== void 0;
914
+ const open = isControlled ? controlledOpen : internalOpen;
915
+ const setOpen = isControlled ? (value) => controlledOnOpenChange?.(value) : setInternalOpen;
916
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_vaul.Drawer.Root, { open, onOpenChange: setOpen, shouldScaleBackground: true, children: [
917
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_vaul.Drawer.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
918
+ "div",
919
+ {
920
+ className: cn(
921
+ defaultDrawerClasses.trigger,
922
+ classNames.trigger,
923
+ disabled ? "pointer-events-none opacity-50" : ""
924
+ ),
925
+ children
926
+ }
927
+ ) }),
928
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_vaul.Drawer.Portal, { children: [
929
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
930
+ import_vaul.Drawer.Overlay,
931
+ {
932
+ className: cn(defaultDrawerClasses.overlay, classNames.overlay),
933
+ style: {
934
+ backgroundColor: cssVar2(CSS_VARS_UI.overlayBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.overlayBg])
935
+ }
936
+ }
937
+ ),
938
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
939
+ import_vaul.Drawer.Content,
940
+ {
941
+ className: cn(defaultDrawerClasses.drawer, classNames.drawer),
942
+ style: {
943
+ backgroundColor: cssVar2(CSS_VARS_UI.drawerBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.drawerBg]),
944
+ borderColor: cssVar2(CSS_VARS_UI.drawerBorder, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.drawerBorder])
945
+ },
946
+ children: [
947
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_vaul.Drawer.Title, { className: "sr-only", children: title }),
948
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
949
+ "div",
950
+ {
951
+ className: cn(defaultDrawerClasses.drawerInner, classNames.drawerInner),
952
+ style: {
953
+ backgroundColor: cssVar2(CSS_VARS_UI.drawerBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.drawerBg])
954
+ },
955
+ children: [
956
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
957
+ "div",
958
+ {
959
+ className: cn(defaultDrawerClasses.handle, classNames.handle),
960
+ style: {
961
+ backgroundColor: cssVar2(CSS_VARS_UI.handleBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.handleBg])
962
+ }
963
+ }
964
+ ),
965
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
966
+ ShareSheetContent,
967
+ {
968
+ title,
969
+ shareUrl,
970
+ shareText,
971
+ preview,
972
+ downloadUrl,
973
+ downloadFilename,
974
+ className,
975
+ classNames,
976
+ buttonSize,
977
+ iconSize,
978
+ onNativeShare: () => {
979
+ onNativeShare?.();
980
+ setOpen(false);
981
+ },
982
+ onCopy,
983
+ onDownload,
984
+ hide,
985
+ show,
986
+ labels,
987
+ icons
988
+ }
989
+ )
990
+ ]
991
+ }
992
+ )
993
+ ]
994
+ }
995
+ )
996
+ ] })
997
+ ] });
998
+ }
999
+ var ShareMenuDrawer = ShareSheetDrawer;
1000
+ // Annotate the CommonJS export names for ESM import in node:
1001
+ 0 && (module.exports = {
1002
+ CSS_VARS,
1003
+ CSS_VARS_UI,
1004
+ CSS_VAR_DEFAULTS,
1005
+ CSS_VAR_UI_DEFAULTS,
1006
+ PLATFORMS,
1007
+ PLATFORM_COLORS,
1008
+ PLATFORM_CSS_VARS,
1009
+ PLATFORM_ICONS,
1010
+ PLATFORM_IDS,
1011
+ PLATFORM_LABELS,
1012
+ ShareMenuContent,
1013
+ ShareMenuDrawer,
1014
+ ShareSheetContent,
1015
+ ShareSheetDrawer,
1016
+ cn,
1017
+ generateCssVarDefaults,
1018
+ getAllPlatforms,
1019
+ getPlatform,
1020
+ getPlatformColor,
1021
+ getPlatformIcon,
1022
+ getPlatformLabel,
1023
+ getSafeUrl,
1024
+ openInstagram,
1025
+ openThreads,
1026
+ openTikTok,
1027
+ openUrl,
1028
+ shareToFacebook,
1029
+ shareToLinkedIn,
1030
+ shareToReddit,
1031
+ shareToSnapchat,
1032
+ shareToTelegram,
1033
+ shareToWhatsApp,
1034
+ shareToX,
1035
+ shareViaEmail,
1036
+ shareViaSMS,
1037
+ useShareMenu,
1038
+ useShareSheet
1039
+ });
1040
+ //# sourceMappingURL=index.js.map