@syncsnap/react 1.0.1 → 1.0.2

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.d.ts CHANGED
@@ -77,5 +77,10 @@ declare function useSyncsnapJob(options?: UseSyncsnapJobOptions): UseSyncsnapJob
77
77
  declare function createUploadUrl(jobId: string, options?: {
78
78
  baseUrl?: string;
79
79
  }): string;
80
+ /** Thrown when the Syncsnap API returns 429 Too Many Requests (rate limit exceeded). */
81
+ declare class SyncsnapRateLimitError extends Error {
82
+ readonly statusCode = 429;
83
+ constructor(message: string);
84
+ }
80
85
 
81
- export { type CompletedJobResponse, type CreateJobResponse, type Job, type JobStatus, type PresignedUrlResponse, SyncsnapQrCode, type SyncsnapQrCodeProps, SyncsnapUploadButton, type SyncsnapUploadButtonProps, type UseSyncsnapJobOptions, type UseSyncsnapJobResult, createUploadUrl, useSyncsnapJob };
86
+ export { type CompletedJobResponse, type CreateJobResponse, type Job, type JobStatus, type PresignedUrlResponse, SyncsnapQrCode, type SyncsnapQrCodeProps, SyncsnapRateLimitError, SyncsnapUploadButton, type SyncsnapUploadButtonProps, type UseSyncsnapJobOptions, type UseSyncsnapJobResult, createUploadUrl, useSyncsnapJob };
package/dist/index.js CHANGED
@@ -9,11 +9,22 @@ function createUploadUrl(jobId, options) {
9
9
  url.searchParams.set("job_id", jobId);
10
10
  return url.toString();
11
11
  }
12
+ var SyncsnapRateLimitError = class _SyncsnapRateLimitError extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.statusCode = 429;
16
+ this.name = "SyncsnapRateLimitError";
17
+ Object.setPrototypeOf(this, _SyncsnapRateLimitError.prototype);
18
+ }
19
+ };
12
20
  async function fetchJson(url, init) {
13
21
  const res = await fetch(url, init);
14
22
  const data = await res.json().catch(() => ({}));
15
23
  if (!res.ok) {
16
24
  const message = typeof data === "object" && data && "error" in data && data.error ? String(data.error) : `Syncsnap request failed (${res.status})`;
25
+ if (res.status === 429) {
26
+ throw new SyncsnapRateLimitError(message);
27
+ }
17
28
  throw new Error(message);
18
29
  }
19
30
  return data;
@@ -318,7 +329,8 @@ function DialogContent({
318
329
  maxWidth: "24rem",
319
330
  width: "100%",
320
331
  padding: "1rem",
321
- backgroundColor: "white",
332
+ backgroundColor: "var(--background, #fff)",
333
+ color: "var(--foreground, #0a0a0a)",
322
334
  borderRadius: "0.75rem",
323
335
  boxShadow: "0 25px 50px -12px rgba(0,0,0,0.25)"
324
336
  },
@@ -385,7 +397,7 @@ function DialogDescription({
385
397
  }
386
398
 
387
399
  // src/components/SyncsnapUploadButton.tsx
388
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
400
+ import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
389
401
  function SyncsnapUploadButton({
390
402
  buttonText = "Start upload",
391
403
  className,
@@ -443,8 +455,14 @@ function SyncsnapUploadButton({
443
455
  const downloadUrl = completedResult?.result && typeof completedResult.result === "object" && completedResult.result !== null && "downloadUrl" in completedResult.result ? completedResult.result.downloadUrl : void 0;
444
456
  return /* @__PURE__ */ jsxs2("div", { className, children: [
445
457
  /* @__PURE__ */ jsx4(Button, { type: "button", onClick, disabled: isWaiting, children: isWaiting ? "Preparing..." : buttonText }),
446
- error ? /* @__PURE__ */ jsx4("p", { style: { color: "#dc2626", marginTop: 8 }, children: error.message }) : null,
447
- completedError ? /* @__PURE__ */ jsx4("p", { style: { color: "#dc2626", marginTop: 8 }, children: completedError.message }) : null,
458
+ error ? /* @__PURE__ */ jsx4("div", { style: { color: "#dc2626", marginTop: 8 }, children: error instanceof SyncsnapRateLimitError ? /* @__PURE__ */ jsxs2(Fragment, { children: [
459
+ /* @__PURE__ */ jsx4("p", { style: { fontWeight: 600, margin: 0 }, children: "Rate limit exceeded" }),
460
+ /* @__PURE__ */ jsx4("p", { style: { margin: "4px 0 0", fontSize: 14 }, children: error.message })
461
+ ] }) : /* @__PURE__ */ jsx4("p", { style: { margin: 0 }, children: error.message }) }) : null,
462
+ completedError ? /* @__PURE__ */ jsx4("div", { style: { color: "#dc2626", marginTop: 8 }, children: completedError instanceof SyncsnapRateLimitError ? /* @__PURE__ */ jsxs2(Fragment, { children: [
463
+ /* @__PURE__ */ jsx4("p", { style: { fontWeight: 600, margin: 0 }, children: "Rate limit exceeded" }),
464
+ /* @__PURE__ */ jsx4("p", { style: { margin: "4px 0 0", fontSize: 14 }, children: completedError.message })
465
+ ] }) : /* @__PURE__ */ jsx4("p", { style: { margin: 0 }, children: completedError.message }) }) : null,
448
466
  downloadUrl ? /* @__PURE__ */ jsxs2(
449
467
  "div",
450
468
  {
@@ -516,17 +534,27 @@ function SyncsnapUploadButton({
516
534
  )
517
535
  }
518
536
  ),
519
- status ? /* @__PURE__ */ jsxs2("p", { style: { margin: "8px 0 0", fontSize: 14 }, children: [
520
- "Status: ",
521
- status
522
- ] }) : null,
537
+ status ? /* @__PURE__ */ jsxs2(
538
+ "p",
539
+ {
540
+ style: {
541
+ margin: "8px 0 0",
542
+ fontSize: 14,
543
+ color: "var(--foreground, inherit)"
544
+ },
545
+ children: [
546
+ "Status: ",
547
+ status
548
+ ]
549
+ }
550
+ ) : null,
523
551
  /* @__PURE__ */ jsxs2(
524
552
  "p",
525
553
  {
526
554
  style: {
527
555
  margin: "16px 0 0",
528
556
  fontSize: 13,
529
- color: "#64748b"
557
+ color: "var(--muted-foreground, #64748b)"
530
558
  },
531
559
  children: [
532
560
  "Powered by",
@@ -553,6 +581,7 @@ function SyncsnapUploadButton({
553
581
  }
554
582
  export {
555
583
  SyncsnapQrCode,
584
+ SyncsnapRateLimitError,
556
585
  SyncsnapUploadButton,
557
586
  createUploadUrl,
558
587
  useSyncsnapJob
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/SyncsnapQrCode.tsx","../src/utils.ts","../src/components/SyncsnapUploadButton.tsx","../src/hooks/useSyncsnapJob.ts","../src/components/ui/button.tsx","../src/lib/utils.ts","../src/components/ui/dialog.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport QRCode from 'qrcode';\nimport type { SyncsnapQrCodeProps } from '../types';\nimport { createUploadUrl } from '../utils';\n\nexport function SyncsnapQrCode({\n jobId,\n baseUrl,\n size = 240,\n className,\n errorCorrectionLevel = 'M',\n}: SyncsnapQrCodeProps) {\n const [dataUrl, setDataUrl] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n let mounted = true;\n const url = createUploadUrl(jobId, { baseUrl });\n\n QRCode.toDataURL(url, {\n width: size,\n errorCorrectionLevel,\n })\n .then((value) => {\n if (!mounted) return;\n setDataUrl(value);\n setError(null);\n })\n .catch((err) => {\n if (!mounted) return;\n setDataUrl(null);\n setError(\n err instanceof Error ? err : new Error('Failed to generate QR')\n );\n });\n\n return () => {\n mounted = false;\n };\n }, [jobId, baseUrl, size, errorCorrectionLevel]);\n\n if (error) {\n return null;\n }\n\n if (!dataUrl) {\n return null;\n }\n\n return (\n <img\n src={dataUrl}\n alt=\"Syncsnap QR code\"\n width={size}\n height={size}\n className={className}\n style={{\n display: 'block',\n margin: '0 auto',\n width: size,\n height: size,\n }}\n />\n );\n}\n","export function createUploadUrl(\n jobId: string,\n options?: { baseUrl?: string }\n): string {\n const baseUrl = options?.baseUrl ?? 'https://upload.syncsnap.xyz/';\n const url = new URL(baseUrl);\n url.searchParams.set('job_id', jobId);\n return url.toString();\n}\n\nexport async function fetchJson<T>(\n url: string,\n init?: RequestInit\n): Promise<T> {\n const res = await fetch(url, init);\n const data = (await res.json().catch(() => ({}))) as T & {\n error?: string;\n };\n\n if (!res.ok) {\n const message =\n typeof data === 'object' && data && 'error' in data && data.error\n ? String(data.error)\n : `Syncsnap request failed (${res.status})`;\n throw new Error(message);\n }\n\n return data as T;\n}\n","'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport type { Job, SyncsnapUploadButtonProps } from '../types';\nimport { SyncsnapQrCode } from './SyncsnapQrCode';\nimport { useSyncsnapJob } from '../hooks/useSyncsnapJob';\nimport { Button } from './ui/button';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from './ui/dialog';\n\ntype CompletionResult = { job: Job; result?: unknown };\ntype ResultWithDownloadUrl = { downloadUrl?: string };\n\nexport function SyncsnapUploadButton({\n buttonText = 'Start upload',\n className,\n qrSize = 240,\n qrBaseUrl,\n errorCorrectionLevel = 'M',\n onCompleted: userOnCompleted,\n onError: userOnError,\n ...options\n}: SyncsnapUploadButtonProps) {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [completedResult, setCompletedResult] =\n useState<CompletionResult | null>(null);\n const [completedError, setCompletedError] = useState<Error | null>(null);\n\n const handleCompleted = useCallback(\n (job: Job, result?: unknown) => {\n setCompletedResult({ job, result });\n setCompletedError(null);\n setDialogOpen(false);\n userOnCompleted?.(job, result);\n },\n [userOnCompleted]\n );\n\n const handleError = useCallback(\n (err: Error) => {\n setCompletedError(err);\n setCompletedResult(null);\n setDialogOpen(false);\n userOnError?.(err);\n },\n [userOnError]\n );\n\n const { jobId, status, start, isWaiting, error, reset } = useSyncsnapJob({\n ...options,\n onCompleted: handleCompleted,\n onError: handleError,\n });\n\n // Open dialog when we have a job id\n useEffect(() => {\n if (jobId) setDialogOpen(true);\n }, [jobId]);\n\n const onClick = useCallback(() => {\n setCompletedResult(null);\n setCompletedError(null);\n setDialogOpen(true);\n void start();\n }, [start]);\n\n const onOpenChange = useCallback(\n (open: boolean) => {\n setDialogOpen(open);\n if (!open) {\n reset();\n }\n },\n [reset]\n );\n\n const downloadUrl =\n completedResult?.result &&\n typeof completedResult.result === 'object' &&\n completedResult.result !== null &&\n 'downloadUrl' in completedResult.result\n ? (completedResult.result as ResultWithDownloadUrl).downloadUrl\n : undefined;\n\n return (\n <div className={className}>\n <Button type=\"button\" onClick={onClick} disabled={isWaiting}>\n {isWaiting ? 'Preparing...' : buttonText}\n </Button>\n {error ? (\n <p style={{ color: '#dc2626', marginTop: 8 }}>{error.message}</p>\n ) : null}\n {completedError ? (\n <p style={{ color: '#dc2626', marginTop: 8 }}>\n {completedError.message}\n </p>\n ) : null}\n {downloadUrl ? (\n <div\n style={{\n marginTop: 16,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n }}\n >\n <p style={{ margin: '0 0 8px', fontSize: 14, color: '#555' }}>\n Upload complete\n </p>\n <img\n src={downloadUrl}\n alt=\"Uploaded\"\n style={{\n maxWidth: '100%',\n height: 'auto',\n borderRadius: 8,\n border: '1px solid #e5e5e5',\n }}\n />\n </div>\n ) : null}\n <Dialog open={dialogOpen} onOpenChange={onOpenChange}>\n <DialogContent\n style={{\n display: 'grid',\n gridTemplateColumns: '1fr',\n justifyItems: 'center',\n }}\n >\n <DialogHeader>\n <DialogTitle>Scan to upload</DialogTitle>\n <DialogDescription>\n Scan this QR code with your phone to upload files\n </DialogDescription>\n </DialogHeader>\n {jobId ? (\n <div\n style={{\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n marginTop: 16,\n }}\n >\n <div\n style={{\n display: 'flex',\n justifyContent: 'center',\n width: '100%',\n }}\n >\n <SyncsnapQrCode\n jobId={jobId}\n baseUrl={qrBaseUrl}\n size={qrSize}\n errorCorrectionLevel={errorCorrectionLevel}\n />\n </div>\n {status ? (\n <p style={{ margin: '8px 0 0', fontSize: 14 }}>\n Status: {status}\n </p>\n ) : null}\n <p\n style={{\n margin: '16px 0 0',\n fontSize: 13,\n color: '#64748b',\n }}\n >\n Powered by{' '}\n <a\n href=\"https://syncsnap.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n SyncSnap\n </a>\n </p>\n </div>\n ) : null}\n </DialogContent>\n </Dialog>\n </div>\n );\n}\n","'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type {\n CreateJobResponse,\n Job,\n UseSyncsnapJobOptions,\n UseSyncsnapJobResult,\n} from '../types';\nimport { fetchJson } from '../utils';\n\nfunction defaultGetJobUrl(jobId: string): string {\n return `/api/syncsnap/job/${encodeURIComponent(jobId)}`;\n}\n\nfunction defaultGetWaitForCompletionUrl(\n getJobUrl: (jobId: string) => string\n): (jobId: string) => string {\n return (jobId: string): string => {\n const base = getJobUrl(jobId).replace(/\\/$/, '');\n return `${base}/wait`;\n };\n}\n\ninterface WaitCompletionResponse {\n job: Job;\n result?: unknown;\n}\n\nexport function useSyncsnapJob(\n options: UseSyncsnapJobOptions = {}\n): UseSyncsnapJobResult {\n const getJobUrlFn = options.getJobUrl ?? defaultGetJobUrl;\n const {\n createJobUrl = '/api/syncsnap/job',\n getWaitForCompletionUrl = defaultGetWaitForCompletionUrl(getJobUrlFn),\n waitTimeoutMs = 120000,\n waitIntervalMs = 2000,\n autoStart = false,\n onJobCreated,\n onCompleted,\n onError,\n } = options;\n\n const [job, setJob] = useState<Job | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [isWaiting, setIsWaiting] = useState(false);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const start = useCallback(async () => {\n setError(null);\n abortControllerRef.current?.abort();\n abortControllerRef.current = new AbortController();\n const signal = abortControllerRef.current.signal;\n\n try {\n const created = await fetchJson<CreateJobResponse>(createJobUrl, {\n method: 'POST',\n });\n const createdJob: Job = {\n ...created,\n fileName: null,\n };\n setJob(createdJob);\n onJobCreated?.(created);\n\n const waitUrl = getWaitForCompletionUrl(created.id);\n const url = new URL(\n waitUrl,\n typeof window !== 'undefined'\n ? window.location.origin\n : 'http://localhost'\n );\n url.searchParams.set('timeoutMs', String(waitTimeoutMs));\n url.searchParams.set('intervalMs', String(waitIntervalMs));\n\n setIsWaiting(true);\n const { job: finalJob, result } = await fetchJson<WaitCompletionResponse>(\n url.toString(),\n {\n signal,\n }\n );\n setJob(null);\n setIsWaiting(false);\n onCompleted?.(finalJob, result);\n } catch (err) {\n setIsWaiting(false);\n setJob(null);\n if (signal.aborted) {\n return;\n }\n const error =\n err instanceof Error ? err : new Error('Syncsnap job failed');\n setError(error);\n onError?.(error);\n }\n }, [\n createJobUrl,\n getWaitForCompletionUrl,\n waitTimeoutMs,\n waitIntervalMs,\n onJobCreated,\n onCompleted,\n onError,\n ]);\n\n const reset = useCallback(() => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n setJob(null);\n setIsWaiting(false);\n setError(null);\n }, []);\n\n useEffect(() => {\n if (autoStart) {\n void start();\n }\n }, [autoStart, start]);\n\n return {\n job,\n jobId: job?.id ?? null,\n status: job?.status ?? null,\n error,\n isWaiting,\n start,\n reset,\n };\n}\n","import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { cn } from '../../lib/utils';\n\nconst buttonVariants = cva(\n \"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none\",\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',\n outline:\n 'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',\n ghost:\n 'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',\n destructive:\n 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default:\n 'h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: 'h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3',\n icon: 'size-8',\n 'icon-xs':\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm':\n 'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',\n 'icon-lg': 'size-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nconst Button = React.forwardRef<\n HTMLButtonElement,\n React.ComponentProps<'button'> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }\n>(function Button(\n {\n className,\n variant = 'default',\n size = 'default',\n asChild = false,\n ...props\n },\n ref\n) {\n const Comp = asChild ? Slot.Root : 'button';\n\n return (\n <Comp\n ref={ref}\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n});\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from 'react';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\n\nimport { cn } from '../../lib/utils';\nimport { Button } from './button';\nimport { XIcon } from 'lucide-react';\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nconst DialogOverlay = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Overlay>,\n React.ComponentProps<typeof DialogPrimitive.Overlay>\n>(function DialogOverlay({ className, style, ...props }, ref) {\n return (\n <DialogPrimitive.Overlay\n ref={ref}\n data-slot=\"dialog-overlay\"\n className={cn(\n 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50',\n className\n )}\n style={{\n position: 'fixed',\n inset: 0,\n zIndex: 50,\n backgroundColor: 'rgba(0,0,0,0.5)',\n ...style,\n }}\n {...props}\n />\n );\n});\nDialogOverlay.displayName = 'DialogOverlay';\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n style,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean;\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n {/* Wrapper ensures dialog is centered on screen (flexbox avoids transform/containing-block issues) */}\n <div\n style={{\n position: 'fixed',\n inset: 0,\n zIndex: 50,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '1rem',\n pointerEvents: 'none',\n }}\n >\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-4 rounded-xl p-4 text-sm ring-1 duration-100 sm:max-w-sm w-full outline-none',\n className\n )}\n style={{\n ...style,\n position: 'relative',\n pointerEvents: 'auto',\n maxWidth: '24rem',\n width: '100%',\n padding: '1rem',\n backgroundColor: 'white',\n borderRadius: '0.75rem',\n boxShadow: '0 25px 50px -12px rgba(0,0,0,0.25)',\n }}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close data-slot=\"dialog-close\" asChild>\n <Button\n variant=\"ghost\"\n className=\"absolute top-2 right-2\"\n size=\"icon-sm\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </Button>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </div>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn('gap-2 flex flex-col', className)}\n {...props}\n />\n );\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<'div'> & {\n showCloseButton?: boolean;\n}) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n 'bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end',\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close asChild>\n <Button variant=\"outline\">Close</Button>\n </DialogPrimitive.Close>\n )}\n </div>\n );\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn('text-base leading-none font-medium', className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\n 'text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3',\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n"],"mappings":"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","names":["useCallback","useEffect","useState","useEffect","useState","useState","error","useEffect","jsx","Button","React","jsx","jsx","DialogOverlay","jsx","jsx","jsx","jsxs","useState","useCallback","useEffect"]}
1
+ {"version":3,"sources":["../src/components/SyncsnapQrCode.tsx","../src/utils.ts","../src/components/SyncsnapUploadButton.tsx","../src/hooks/useSyncsnapJob.ts","../src/components/ui/button.tsx","../src/lib/utils.ts","../src/components/ui/dialog.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport QRCode from 'qrcode';\nimport type { SyncsnapQrCodeProps } from '../types';\nimport { createUploadUrl } from '../utils';\n\nexport function SyncsnapQrCode({\n jobId,\n baseUrl,\n size = 240,\n className,\n errorCorrectionLevel = 'M',\n}: SyncsnapQrCodeProps) {\n const [dataUrl, setDataUrl] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n let mounted = true;\n const url = createUploadUrl(jobId, { baseUrl });\n\n QRCode.toDataURL(url, {\n width: size,\n errorCorrectionLevel,\n })\n .then((value) => {\n if (!mounted) return;\n setDataUrl(value);\n setError(null);\n })\n .catch((err) => {\n if (!mounted) return;\n setDataUrl(null);\n setError(\n err instanceof Error ? err : new Error('Failed to generate QR')\n );\n });\n\n return () => {\n mounted = false;\n };\n }, [jobId, baseUrl, size, errorCorrectionLevel]);\n\n if (error) {\n return null;\n }\n\n if (!dataUrl) {\n return null;\n }\n\n return (\n <img\n src={dataUrl}\n alt=\"Syncsnap QR code\"\n width={size}\n height={size}\n className={className}\n style={{\n display: 'block',\n margin: '0 auto',\n width: size,\n height: size,\n }}\n />\n );\n}\n","export function createUploadUrl(\n jobId: string,\n options?: { baseUrl?: string }\n): string {\n const baseUrl = options?.baseUrl ?? 'https://upload.syncsnap.xyz/';\n const url = new URL(baseUrl);\n url.searchParams.set('job_id', jobId);\n return url.toString();\n}\n\n/** Thrown when the Syncsnap API returns 429 Too Many Requests (rate limit exceeded). */\nexport class SyncsnapRateLimitError extends Error {\n readonly statusCode = 429;\n\n constructor(message: string) {\n super(message);\n this.name = 'SyncsnapRateLimitError';\n Object.setPrototypeOf(this, SyncsnapRateLimitError.prototype);\n }\n}\n\nexport async function fetchJson<T>(\n url: string,\n init?: RequestInit\n): Promise<T> {\n const res = await fetch(url, init);\n const data = (await res.json().catch(() => ({}))) as T & {\n error?: string;\n };\n\n if (!res.ok) {\n const message =\n typeof data === 'object' && data && 'error' in data && data.error\n ? String(data.error)\n : `Syncsnap request failed (${res.status})`;\n if (res.status === 429) {\n throw new SyncsnapRateLimitError(message);\n }\n throw new Error(message);\n }\n\n return data as T;\n}\n","'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport type { Job, SyncsnapUploadButtonProps } from '../types';\nimport { SyncsnapQrCode } from './SyncsnapQrCode';\nimport { useSyncsnapJob } from '../hooks/useSyncsnapJob';\nimport { SyncsnapRateLimitError } from '../utils';\nimport { Button } from './ui/button';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from './ui/dialog';\n\ntype CompletionResult = { job: Job; result?: unknown };\ntype ResultWithDownloadUrl = { downloadUrl?: string };\n\nexport function SyncsnapUploadButton({\n buttonText = 'Start upload',\n className,\n qrSize = 240,\n qrBaseUrl,\n errorCorrectionLevel = 'M',\n onCompleted: userOnCompleted,\n onError: userOnError,\n ...options\n}: SyncsnapUploadButtonProps) {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [completedResult, setCompletedResult] =\n useState<CompletionResult | null>(null);\n const [completedError, setCompletedError] = useState<Error | null>(null);\n\n const handleCompleted = useCallback(\n (job: Job, result?: unknown) => {\n setCompletedResult({ job, result });\n setCompletedError(null);\n setDialogOpen(false);\n userOnCompleted?.(job, result);\n },\n [userOnCompleted]\n );\n\n const handleError = useCallback(\n (err: Error) => {\n setCompletedError(err);\n setCompletedResult(null);\n setDialogOpen(false);\n userOnError?.(err);\n },\n [userOnError]\n );\n\n const { jobId, status, start, isWaiting, error, reset } = useSyncsnapJob({\n ...options,\n onCompleted: handleCompleted,\n onError: handleError,\n });\n\n // Open dialog when we have a job id\n useEffect(() => {\n if (jobId) setDialogOpen(true);\n }, [jobId]);\n\n const onClick = useCallback(() => {\n setCompletedResult(null);\n setCompletedError(null);\n setDialogOpen(true);\n void start();\n }, [start]);\n\n const onOpenChange = useCallback(\n (open: boolean) => {\n setDialogOpen(open);\n if (!open) {\n reset();\n }\n },\n [reset]\n );\n\n const downloadUrl =\n completedResult?.result &&\n typeof completedResult.result === 'object' &&\n completedResult.result !== null &&\n 'downloadUrl' in completedResult.result\n ? (completedResult.result as ResultWithDownloadUrl).downloadUrl\n : undefined;\n\n return (\n <div className={className}>\n <Button type=\"button\" onClick={onClick} disabled={isWaiting}>\n {isWaiting ? 'Preparing...' : buttonText}\n </Button>\n {error ? (\n <div style={{ color: '#dc2626', marginTop: 8 }}>\n {error instanceof SyncsnapRateLimitError ? (\n <>\n <p style={{ fontWeight: 600, margin: 0 }}>Rate limit exceeded</p>\n <p style={{ margin: '4px 0 0', fontSize: 14 }}>{error.message}</p>\n </>\n ) : (\n <p style={{ margin: 0 }}>{error.message}</p>\n )}\n </div>\n ) : null}\n {completedError ? (\n <div style={{ color: '#dc2626', marginTop: 8 }}>\n {completedError instanceof SyncsnapRateLimitError ? (\n <>\n <p style={{ fontWeight: 600, margin: 0 }}>Rate limit exceeded</p>\n <p style={{ margin: '4px 0 0', fontSize: 14 }}>\n {completedError.message}\n </p>\n </>\n ) : (\n <p style={{ margin: 0 }}>{completedError.message}</p>\n )}\n </div>\n ) : null}\n {downloadUrl ? (\n <div\n style={{\n marginTop: 16,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n }}\n >\n <p style={{ margin: '0 0 8px', fontSize: 14, color: '#555' }}>\n Upload complete\n </p>\n <img\n src={downloadUrl}\n alt=\"Uploaded\"\n style={{\n maxWidth: '100%',\n height: 'auto',\n borderRadius: 8,\n border: '1px solid #e5e5e5',\n }}\n />\n </div>\n ) : null}\n <Dialog open={dialogOpen} onOpenChange={onOpenChange}>\n <DialogContent\n style={{\n display: 'grid',\n gridTemplateColumns: '1fr',\n justifyItems: 'center',\n }}\n >\n <DialogHeader>\n <DialogTitle>Scan to upload</DialogTitle>\n <DialogDescription>\n Scan this QR code with your phone to upload files\n </DialogDescription>\n </DialogHeader>\n {jobId ? (\n <div\n style={{\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n marginTop: 16,\n }}\n >\n <div\n style={{\n display: 'flex',\n justifyContent: 'center',\n width: '100%',\n }}\n >\n <SyncsnapQrCode\n jobId={jobId}\n baseUrl={qrBaseUrl}\n size={qrSize}\n errorCorrectionLevel={errorCorrectionLevel}\n />\n </div>\n {status ? (\n <p\n style={{\n margin: '8px 0 0',\n fontSize: 14,\n color: 'var(--foreground, inherit)',\n }}\n >\n Status: {status}\n </p>\n ) : null}\n <p\n style={{\n margin: '16px 0 0',\n fontSize: 13,\n color: 'var(--muted-foreground, #64748b)',\n }}\n >\n Powered by{' '}\n <a\n href=\"https://syncsnap.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n SyncSnap\n </a>\n </p>\n </div>\n ) : null}\n </DialogContent>\n </Dialog>\n </div>\n );\n}\n","'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type {\n CreateJobResponse,\n Job,\n UseSyncsnapJobOptions,\n UseSyncsnapJobResult,\n} from '../types';\nimport { fetchJson } from '../utils';\n\nfunction defaultGetJobUrl(jobId: string): string {\n return `/api/syncsnap/job/${encodeURIComponent(jobId)}`;\n}\n\nfunction defaultGetWaitForCompletionUrl(\n getJobUrl: (jobId: string) => string\n): (jobId: string) => string {\n return (jobId: string): string => {\n const base = getJobUrl(jobId).replace(/\\/$/, '');\n return `${base}/wait`;\n };\n}\n\ninterface WaitCompletionResponse {\n job: Job;\n result?: unknown;\n}\n\nexport function useSyncsnapJob(\n options: UseSyncsnapJobOptions = {}\n): UseSyncsnapJobResult {\n const getJobUrlFn = options.getJobUrl ?? defaultGetJobUrl;\n const {\n createJobUrl = '/api/syncsnap/job',\n getWaitForCompletionUrl = defaultGetWaitForCompletionUrl(getJobUrlFn),\n waitTimeoutMs = 120000,\n waitIntervalMs = 2000,\n autoStart = false,\n onJobCreated,\n onCompleted,\n onError,\n } = options;\n\n const [job, setJob] = useState<Job | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [isWaiting, setIsWaiting] = useState(false);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const start = useCallback(async () => {\n setError(null);\n abortControllerRef.current?.abort();\n abortControllerRef.current = new AbortController();\n const signal = abortControllerRef.current.signal;\n\n try {\n const created = await fetchJson<CreateJobResponse>(createJobUrl, {\n method: 'POST',\n });\n const createdJob: Job = {\n ...created,\n fileName: null,\n };\n setJob(createdJob);\n onJobCreated?.(created);\n\n const waitUrl = getWaitForCompletionUrl(created.id);\n const url = new URL(\n waitUrl,\n typeof window !== 'undefined'\n ? window.location.origin\n : 'http://localhost'\n );\n url.searchParams.set('timeoutMs', String(waitTimeoutMs));\n url.searchParams.set('intervalMs', String(waitIntervalMs));\n\n setIsWaiting(true);\n const { job: finalJob, result } = await fetchJson<WaitCompletionResponse>(\n url.toString(),\n {\n signal,\n }\n );\n setJob(null);\n setIsWaiting(false);\n onCompleted?.(finalJob, result);\n } catch (err) {\n setIsWaiting(false);\n setJob(null);\n if (signal.aborted) {\n return;\n }\n const error =\n err instanceof Error ? err : new Error('Syncsnap job failed');\n setError(error);\n onError?.(error);\n }\n }, [\n createJobUrl,\n getWaitForCompletionUrl,\n waitTimeoutMs,\n waitIntervalMs,\n onJobCreated,\n onCompleted,\n onError,\n ]);\n\n const reset = useCallback(() => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n setJob(null);\n setIsWaiting(false);\n setError(null);\n }, []);\n\n useEffect(() => {\n if (autoStart) {\n void start();\n }\n }, [autoStart, start]);\n\n return {\n job,\n jobId: job?.id ?? null,\n status: job?.status ?? null,\n error,\n isWaiting,\n start,\n reset,\n };\n}\n","import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { cn } from '../../lib/utils';\n\nconst buttonVariants = cva(\n \"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none\",\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',\n outline:\n 'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',\n ghost:\n 'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',\n destructive:\n 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default:\n 'h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: 'h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3',\n icon: 'size-8',\n 'icon-xs':\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm':\n 'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',\n 'icon-lg': 'size-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nconst Button = React.forwardRef<\n HTMLButtonElement,\n React.ComponentProps<'button'> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }\n>(function Button(\n {\n className,\n variant = 'default',\n size = 'default',\n asChild = false,\n ...props\n },\n ref\n) {\n const Comp = asChild ? Slot.Root : 'button';\n\n return (\n <Comp\n ref={ref}\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n});\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from 'react';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\n\nimport { cn } from '../../lib/utils';\nimport { Button } from './button';\nimport { XIcon } from 'lucide-react';\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nconst DialogOverlay = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Overlay>,\n React.ComponentProps<typeof DialogPrimitive.Overlay>\n>(function DialogOverlay({ className, style, ...props }, ref) {\n return (\n <DialogPrimitive.Overlay\n ref={ref}\n data-slot=\"dialog-overlay\"\n className={cn(\n 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50',\n className\n )}\n style={{\n position: 'fixed',\n inset: 0,\n zIndex: 50,\n backgroundColor: 'rgba(0,0,0,0.5)',\n ...style,\n }}\n {...props}\n />\n );\n});\nDialogOverlay.displayName = 'DialogOverlay';\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n style,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean;\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n {/* Wrapper ensures dialog is centered on screen (flexbox avoids transform/containing-block issues) */}\n <div\n style={{\n position: 'fixed',\n inset: 0,\n zIndex: 50,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '1rem',\n pointerEvents: 'none',\n }}\n >\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-4 rounded-xl p-4 text-sm ring-1 duration-100 sm:max-w-sm w-full outline-none',\n className\n )}\n style={{\n ...style,\n position: 'relative',\n pointerEvents: 'auto',\n maxWidth: '24rem',\n width: '100%',\n padding: '1rem',\n backgroundColor: 'var(--background, #fff)',\n color: 'var(--foreground, #0a0a0a)',\n borderRadius: '0.75rem',\n boxShadow: '0 25px 50px -12px rgba(0,0,0,0.25)',\n }}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close data-slot=\"dialog-close\" asChild>\n <Button\n variant=\"ghost\"\n className=\"absolute top-2 right-2\"\n size=\"icon-sm\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </Button>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </div>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn('gap-2 flex flex-col', className)}\n {...props}\n />\n );\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<'div'> & {\n showCloseButton?: boolean;\n}) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n 'bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end',\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close asChild>\n <Button variant=\"outline\">Close</Button>\n </DialogPrimitive.Close>\n )}\n </div>\n );\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn('text-base leading-none font-medium', className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\n 'text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3',\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n"],"mappings":"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","names":["useCallback","useEffect","useState","useEffect","useState","useState","error","useEffect","jsx","Button","React","jsx","jsx","DialogOverlay","jsx","jsx","jsx","jsxs","useState","useCallback","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncsnap/react",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Syncsnap client SDK for React",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,12 +32,12 @@
32
32
  },
33
33
  "repository": {
34
34
  "type": "git",
35
- "url": "https://github.com/syncsnap/packages.git",
35
+ "url": "https://github.com/syncsnapxyz/packages.git",
36
36
  "directory": "react"
37
37
  },
38
- "homepage": "https://github.com/syncsnap/packages/react#readme",
38
+ "homepage": "https://github.com/syncsnapxyz/packages/react#readme",
39
39
  "bugs": {
40
- "url": "https://github.com/syncsnap/packages/react/issues"
40
+ "url": "https://github.com/syncsnapxyz/packages/react/issues"
41
41
  },
42
42
  "publishConfig": {
43
43
  "access": "public"