@arcadiasystems/morse-uploader 0.3.0 → 0.4.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/CHANGELOG.md +27 -0
- package/README.md +9 -3
- package/dist/{chunk-K2J3ZILI.js → chunk-ZV3GFXNW.js} +265 -28
- package/dist/chunk-ZV3GFXNW.js.map +1 -0
- package/dist/index.d.ts +57 -14
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/{types-C6w30zCM.d.ts → types-C5hwiHjr.d.ts} +63 -6
- package/dist/ui.d.ts +5 -4
- package/dist/ui.js +2 -3
- package/dist/ui.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-K2J3ZILI.js.map +0 -1
package/dist/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/morse-file-downloader.tsx","../src/utils/clamp.ts","../src/ui/morse-file-uploader.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"ui.js","sourcesContent":["import { formatUserMessage } from \"@arcadiasystems/morse-sdk\";\nimport { type ReactElement, useMemo } from \"react\";\nimport type { MorseFileDownloaderProps, SealMaterial } from \"../files/types.js\";\nimport { useFileDownload } from \"../files/use-file-download.js\";\nimport { formatBytes } from \"../utils/format-bytes.js\";\n\n/**\n * Drop-in single-file viewer/downloader for a share link. Loads the on-chain\n * metadata, then downloads (public read) or decrypts (recipient) the bytes with\n * the correct filename and MIME type. A RecipientFile has no on-chain encrypted\n * flag, so encryption is inferred from Seal material in the share link. Logic\n * lives in {@link useFileDownload}.\n */\nexport function MorseFileDownloader(\n\tprops: MorseFileDownloaderProps,\n): ReactElement {\n\tconst { fileId, sealIdPrefix, sealNonce, className } = props;\n\tconst seal = useMemo<SealMaterial | null>(() => {\n\t\tif (sealIdPrefix === undefined || sealIdPrefix === null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (sealNonce === undefined || sealNonce === null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { sealIdPrefix, sealNonce };\n\t}, [sealIdPrefix, sealNonce]);\n\n\tconst dl = useFileDownload(fileId, seal);\n\tconst { file } = dl;\n\n\tif (dl.metaStatus === \"loading\" || dl.metaStatus === \"idle\") {\n\t\treturn (\n\t\t\t<section className={`mu-view ${className ?? \"\"}`} data-mu=\"view\">\n\t\t\t\t<span className=\"mu-muted\">Loading file...</span>\n\t\t\t</section>\n\t\t);\n\t}\n\n\tif (dl.metaStatus === \"error\" || file === null) {\n\t\treturn (\n\t\t\t<section className={`mu-view ${className ?? \"\"}`} data-mu=\"view\">\n\t\t\t\t<p className=\"mu-error\" role=\"alert\">\n\t\t\t\t\tCould not load this file. The id may be wrong or the record may have\n\t\t\t\t\tbeen deleted.\n\t\t\t\t</p>\n\t\t\t</section>\n\t\t);\n\t}\n\n\tconst bytesError = dl.error === null ? null : formatUserMessage(dl.error);\n\n\treturn (\n\t\t<section className={`mu-view ${className ?? \"\"}`} data-mu=\"view\">\n\t\t\t<header className=\"mu-view-head\">\n\t\t\t\t<strong className=\"mu-view-name\">{file.name}</strong>\n\t\t\t\t<span className=\"mu-muted\">\n\t\t\t\t\t{file.contentType} · {formatBytes(file.size)}\n\t\t\t\t\t{dl.encrypted ? \" · encrypted\" : \"\"}\n\t\t\t\t</span>\n\t\t\t</header>\n\n\t\t\t<div className=\"mu-view-body\">\n\t\t\t\t{dl.status === \"ready\" && dl.isImage && dl.objectUrl !== null ? (\n\t\t\t\t\t<img className=\"mu-view-img\" src={dl.objectUrl} alt={file.name} />\n\t\t\t\t) : null}\n\n\t\t\t\t{dl.status === \"ready\" ? (\n\t\t\t\t\t<button type=\"button\" className=\"mu-upload\" onClick={() => dl.save()}>\n\t\t\t\t\t\tSave file\n\t\t\t\t\t</button>\n\t\t\t\t) : (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"mu-upload\"\n\t\t\t\t\t\tdisabled={dl.status === \"loading\"}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tvoid (dl.isImage ? dl.load() : dl.download());\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{dl.status === \"loading\"\n\t\t\t\t\t\t\t? dl.encrypted\n\t\t\t\t\t\t\t\t? \"Decrypting...\"\n\t\t\t\t\t\t\t\t: \"Downloading...\"\n\t\t\t\t\t\t\t: dl.encrypted\n\t\t\t\t\t\t\t\t? \"Decrypt and open\"\n\t\t\t\t\t\t\t\t: \"Download\"}\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\n\t\t\t\t{bytesError !== null ? (\n\t\t\t\t\t<div className=\"mu-error\" role=\"alert\">\n\t\t\t\t\t\t<strong>{bytesError.title}</strong>\n\t\t\t\t\t\t<span>{bytesError.description}</span>\n\t\t\t\t\t</div>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t</section>\n\t);\n}\n","/** Clamp a number to the inclusive [min, max] range. */\nexport function clamp(value: number, min: number, max: number): number {\n\tif (value < min) {\n\t\treturn min;\n\t}\n\tif (value > max) {\n\t\treturn max;\n\t}\n\treturn value;\n}\n","import { type ReactElement, useState } from \"react\";\nimport type { MorseFileUploaderProps } from \"../files/types.js\";\nimport { uploadErrorMessage } from \"../files/upload-error-message.js\";\nimport { uploadPhaseLabel } from \"../files/upload-phase-label.js\";\nimport { uploadPhases } from \"../files/upload-phases.js\";\nimport { useFileUpload } from \"../files/use-file-upload.js\";\nimport { useMorseFilesContext } from \"../files/use-morse-files-context.js\";\nimport { useStorageCostEstimate } from \"../files/use-storage-cost-estimate.js\";\nimport { useClipboard } from \"../primitives/use-clipboard.js\";\nimport { useDropzone } from \"../primitives/use-dropzone.js\";\nimport { clamp } from \"../utils/clamp.js\";\nimport { formatBytes } from \"../utils/format-bytes.js\";\nimport { formatUsd } from \"../utils/format-usd.js\";\n\nconst DEFAULT_EPOCHS = 5;\n// Walrus caps a lease at 53 epochs ahead on both networks.\nconst WALRUS_MAX_EPOCHS = 53;\n\n/**\n * Drop-in file uploader for the 0.4.0 RecipientFile flow. Pick a file, choose a\n * storage duration, and upload. Encryption and the recipient set are controlled\n * by props (`encrypt`, `recipients`); the connected wallet is auto-added as a\n * recipient on chain. Emits the completed upload (with seal material and share\n * link) via `onUploaded`. All logic lives in hooks; this component only renders.\n */\nexport function MorseFileUploader(props: MorseFileUploaderProps): ReactElement {\n\tconst {\n\t\tclassName,\n\t\trecipients,\n\t\tencrypt = false,\n\t\tdefaultEpochs,\n\t\tminEpochs = 1,\n\t\tmaxEpochs = WALRUS_MAX_EPOCHS,\n\t\tonUploaded,\n\t} = props;\n\n\tconst [file, setFile] = useState<File | null>(null);\n\tconst [epochs, setEpochs] = useState(defaultEpochs ?? DEFAULT_EPOCHS);\n\tconst upload = useFileUpload();\n\tconst clipboard = useClipboard();\n\tconst { network } = useMorseFilesContext();\n\n\tconst { estimate } = useStorageCostEstimate({\n\t\tsizeBytes: file?.size ?? 0,\n\t\tepochs,\n\t\tencrypt,\n\t});\n\n\tconst { getRootProps, getInputProps } = useDropzone({\n\t\tmultiple: false,\n\t\tariaLabel: \"Choose a file to upload\",\n\t\tonFiles: (files) => setFile(files[0] ?? null),\n\t});\n\n\tconst handleUpload = async () => {\n\t\tif (file === null) {\n\t\t\treturn;\n\t\t}\n\t\tconst result = await upload.upload({\n\t\t\tfile,\n\t\t\tepochs,\n\t\t\tencrypt,\n\t\t\t...(recipients === undefined ? {} : { recipients }),\n\t\t});\n\t\tonUploaded?.(result);\n\t};\n\n\tconst handleReset = () => {\n\t\tupload.reset();\n\t\tsetFile(null);\n\t};\n\n\tconst phases = uploadPhases(encrypt);\n\tconst activeIndex = upload.phase === null ? -1 : phases.indexOf(upload.phase);\n\tconst errorMessage =\n\t\tupload.error === null ? null : uploadErrorMessage(upload.error, network);\n\n\treturn (\n\t\t<div className={`mu-uploader ${className ?? \"\"}`} data-mu=\"uploader\">\n\t\t\t<div className=\"mu-dropzone\" {...getRootProps()}>\n\t\t\t\t<input className=\"mu-file-input\" {...getInputProps()} />\n\t\t\t\t<span className=\"mu-dropzone-icon\" aria-hidden=\"true\" />\n\t\t\t\t{file === null ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span className=\"mu-dropzone-hint\">\n\t\t\t\t\t\t\tDrag a file here, or click to browse\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"mu-dropzone-sub\">Any file type</span>\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span className=\"mu-dropzone-hint\">{file.name}</span>\n\t\t\t\t\t\t<span className=\"mu-dropzone-sub\">\n\t\t\t\t\t\t\t{formatBytes(file.size)} · click to replace\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<label className=\"mu-field\">\n\t\t\t\t<span className=\"mu-field-label\">Storage duration (epochs)</span>\n\t\t\t\t<input\n\t\t\t\t\tclassName=\"mu-epochs-input\"\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\tmin={minEpochs}\n\t\t\t\t\tmax={maxEpochs}\n\t\t\t\t\tvalue={epochs}\n\t\t\t\t\tonChange={(event) =>\n\t\t\t\t\t\tsetEpochs(\n\t\t\t\t\t\t\tclamp(\n\t\t\t\t\t\t\t\tNumber.parseInt(event.target.value, 10) || minEpochs,\n\t\t\t\t\t\t\t\tminEpochs,\n\t\t\t\t\t\t\t\tmaxEpochs,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t\t<span\n\t\t\t\t\tclassName=\"mu-field-help\"\n\t\t\t\t\ttitle={`Walrus storage is a lease, not permanent. You can buy at most ${maxEpochs} epochs ahead. An epoch is about 1 day on testnet and about 2 weeks on mainnet.`}\n\t\t\t\t>\n\t\t\t\t\t{`≈ ${Math.round(estimate.days)} day${\n\t\t\t\t\t\tMath.round(estimate.days) === 1 ? \"\" : \"s\"\n\t\t\t\t\t} of storage · max ${maxEpochs} epochs`}\n\t\t\t\t</span>\n\t\t\t</label>\n\n\t\t\t<div className=\"mu-cost\" data-mu=\"cost\">\n\t\t\t\t<span className=\"mu-cost-label\">\n\t\t\t\t\t{encrypt\n\t\t\t\t\t\t? \"Estimated storage cost (encrypted)\"\n\t\t\t\t\t\t: \"Estimated storage cost\"}\n\t\t\t\t</span>\n\t\t\t\t<span className=\"mu-cost-value\">{formatUsd(estimate.usd)}</span>\n\t\t\t</div>\n\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"mu-upload\"\n\t\t\t\tdisabled={file === null || upload.status === \"uploading\"}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tvoid handleUpload();\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{upload.status === \"uploading\"\n\t\t\t\t\t? \"Uploading...\"\n\t\t\t\t\t: encrypt\n\t\t\t\t\t\t? \"Encrypt and upload\"\n\t\t\t\t\t\t: \"Upload\"}\n\t\t\t</button>\n\n\t\t\t{upload.status === \"uploading\" ? (\n\t\t\t\t<ol className=\"mu-stepper\" data-mu=\"stepper\">\n\t\t\t\t\t{phases.map((phase, index) => (\n\t\t\t\t\t\t<li\n\t\t\t\t\t\t\tkey={phase}\n\t\t\t\t\t\t\tclassName=\"mu-step\"\n\t\t\t\t\t\t\tdata-state={\n\t\t\t\t\t\t\t\tindex < activeIndex\n\t\t\t\t\t\t\t\t\t? \"done\"\n\t\t\t\t\t\t\t\t\t: index === activeIndex\n\t\t\t\t\t\t\t\t\t\t? \"active\"\n\t\t\t\t\t\t\t\t\t\t: \"pending\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"mu-step-dot\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t{index + 1}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span className=\"mu-step-label\">{uploadPhaseLabel(phase)}</span>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ol>\n\t\t\t) : null}\n\n\t\t\t{errorMessage !== null ? (\n\t\t\t\t<div className=\"mu-error\" role=\"alert\">\n\t\t\t\t\t<strong>{errorMessage.title}</strong>\n\t\t\t\t\t<span>{errorMessage.description}</span>\n\t\t\t\t</div>\n\t\t\t) : null}\n\n\t\t\t{upload.data !== null ? (\n\t\t\t\t<div className=\"mu-result\" data-mu=\"result\">\n\t\t\t\t\t<span className=\"mu-result-head\">\n\t\t\t\t\t\t<span className=\"mu-result-badge\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t✓\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<strong>\n\t\t\t\t\t\t\t{upload.data.encrypted ? \"Encrypted and uploaded\" : \"Uploaded\"}\n\t\t\t\t\t\t</strong>\n\t\t\t\t\t</span>\n\t\t\t\t\t<div className=\"mu-result-actions\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclassName=\"mu-upload mu-result-link\"\n\t\t\t\t\t\t\thref={upload.data.shareLink}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tOpen share link\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"mu-ghost mu-result-copy\"\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tvoid clipboard.copy(upload.data?.shareLink ?? \"\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{clipboard.copied ? \"Copied!\" : \"Copy link\"}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button type=\"button\" className=\"mu-ghost\" onClick={handleReset}>\n\t\t\t\t\t\t\tUpload another\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<code className=\"mu-result-id\">{upload.data.fileId}</code>\n\t\t\t\t\t{upload.data.encrypted ? (\n\t\t\t\t\t\t<span className=\"mu-result-note\">\n\t\t\t\t\t\t\tThe share link carries the decryption key; only recipients can\n\t\t\t\t\t\t\topen it.\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/ui/morse-file-downloader.tsx","../src/utils/clamp.ts","../src/ui/morse-file-uploader.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"ui.js","sourcesContent":["import { type ReactElement, useMemo } from \"react\";\nimport { downloadErrorMessage } from \"../files/download-error-message.js\";\nimport type { MorseFileDownloaderProps, SealMaterial } from \"../files/types.js\";\nimport { useFileDownload } from \"../files/use-file-download.js\";\nimport { formatBytes } from \"../utils/format-bytes.js\";\n\n/**\n * Drop-in single-file viewer/downloader for a share link. Loads the on-chain\n * metadata, then downloads (public read) or decrypts (recipient) the bytes with\n * the correct filename and MIME type. A file with an on-chain Seal prefix\n * opened without its Seal material shows an error asking for the full link\n * instead of serving ciphertext. Logic lives in {@link useFileDownload}.\n */\nexport function MorseFileDownloader(\n\tprops: MorseFileDownloaderProps,\n): ReactElement {\n\tconst { fileId, sealIdPrefix, sealNonce, className } = props;\n\tconst seal = useMemo<SealMaterial | null>(() => {\n\t\tif (sealIdPrefix === undefined || sealIdPrefix === null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (sealNonce === undefined || sealNonce === null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { sealIdPrefix, sealNonce };\n\t}, [sealIdPrefix, sealNonce]);\n\n\tconst dl = useFileDownload(fileId, seal);\n\tconst { file } = dl;\n\n\tif (dl.metaStatus === \"loading\" || dl.metaStatus === \"idle\") {\n\t\treturn (\n\t\t\t<section className={`mu-view ${className ?? \"\"}`} data-mu=\"view\">\n\t\t\t\t<span className=\"mu-muted\">Loading file...</span>\n\t\t\t</section>\n\t\t);\n\t}\n\n\tif (dl.metaStatus === \"error\" || file === null) {\n\t\treturn (\n\t\t\t<section className={`mu-view ${className ?? \"\"}`} data-mu=\"view\">\n\t\t\t\t<p className=\"mu-error\" role=\"alert\">\n\t\t\t\t\tCould not load this file. The id may be wrong or the record may have\n\t\t\t\t\tbeen deleted.\n\t\t\t\t</p>\n\t\t\t</section>\n\t\t);\n\t}\n\n\tconst bytesError = dl.error === null ? null : downloadErrorMessage(dl.error);\n\n\treturn (\n\t\t<section className={`mu-view ${className ?? \"\"}`} data-mu=\"view\">\n\t\t\t<header className=\"mu-view-head\">\n\t\t\t\t<strong className=\"mu-view-name\">{file.name}</strong>\n\t\t\t\t<span className=\"mu-muted\">\n\t\t\t\t\t{file.contentType} · {formatBytes(file.size)}\n\t\t\t\t\t{dl.encrypted ? \" · encrypted\" : \"\"}\n\t\t\t\t</span>\n\t\t\t</header>\n\n\t\t\t<div className=\"mu-view-body\">\n\t\t\t\t{dl.status === \"ready\" && dl.isImage && dl.objectUrl !== null ? (\n\t\t\t\t\t<img className=\"mu-view-img\" src={dl.objectUrl} alt={file.name} />\n\t\t\t\t) : null}\n\n\t\t\t\t{dl.status === \"ready\" ? (\n\t\t\t\t\t<button type=\"button\" className=\"mu-upload\" onClick={() => dl.save()}>\n\t\t\t\t\t\tSave file\n\t\t\t\t\t</button>\n\t\t\t\t) : (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"mu-upload\"\n\t\t\t\t\t\tdisabled={dl.status === \"loading\"}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tvoid (dl.isImage ? dl.load() : dl.download());\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{dl.status === \"loading\"\n\t\t\t\t\t\t\t? dl.encrypted\n\t\t\t\t\t\t\t\t? \"Decrypting...\"\n\t\t\t\t\t\t\t\t: \"Downloading...\"\n\t\t\t\t\t\t\t: dl.encrypted\n\t\t\t\t\t\t\t\t? \"Decrypt and open\"\n\t\t\t\t\t\t\t\t: \"Download\"}\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\n\t\t\t\t{bytesError !== null ? (\n\t\t\t\t\t<div className=\"mu-error\" role=\"alert\">\n\t\t\t\t\t\t<strong>{bytesError.title}</strong>\n\t\t\t\t\t\t<span>{bytesError.description}</span>\n\t\t\t\t\t</div>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t</section>\n\t);\n}\n","/** Clamp a number to the inclusive [min, max] range. */\nexport function clamp(value: number, min: number, max: number): number {\n\tif (value < min) {\n\t\treturn min;\n\t}\n\tif (value > max) {\n\t\treturn max;\n\t}\n\treturn value;\n}\n","import { type ReactElement, useState } from \"react\";\nimport type { MorseFileUploaderProps } from \"../files/types.js\";\nimport { uploadErrorMessage } from \"../files/upload-error-message.js\";\nimport { uploadPhaseLabel } from \"../files/upload-phase-label.js\";\nimport { uploadPhases } from \"../files/upload-phases.js\";\nimport { useFileUpload } from \"../files/use-file-upload.js\";\nimport { useMorseFilesContext } from \"../files/use-morse-files-context.js\";\nimport { useStorageCostEstimate } from \"../files/use-storage-cost-estimate.js\";\nimport { useClipboard } from \"../primitives/use-clipboard.js\";\nimport { useDropzone } from \"../primitives/use-dropzone.js\";\nimport { clamp } from \"../utils/clamp.js\";\nimport { formatBytes } from \"../utils/format-bytes.js\";\nimport { formatUsd } from \"../utils/format-usd.js\";\n\nconst DEFAULT_EPOCHS = 5;\n// Walrus caps a lease at 53 epochs ahead on both networks.\nconst WALRUS_MAX_EPOCHS = 53;\n\n/**\n * Drop-in file uploader for the 0.4.0 RecipientFile flow. Pick a file, choose a\n * storage duration, and upload. Encryption and the recipient set are controlled\n * by props (`encrypt`, `recipients`); the connected wallet is auto-added as a\n * recipient on chain. Emits the completed upload (with seal material and share\n * link) via `onUploaded`. All logic lives in hooks; this component only renders.\n */\nexport function MorseFileUploader(props: MorseFileUploaderProps): ReactElement {\n\tconst {\n\t\tclassName,\n\t\trecipients,\n\t\tencrypt = false,\n\t\tdefaultEpochs,\n\t\tminEpochs = 1,\n\t\tmaxEpochs = WALRUS_MAX_EPOCHS,\n\t\tonUploaded,\n\t} = props;\n\n\tconst [file, setFile] = useState<File | null>(null);\n\tconst [epochs, setEpochs] = useState(defaultEpochs ?? DEFAULT_EPOCHS);\n\tconst upload = useFileUpload();\n\tconst clipboard = useClipboard();\n\tconst { network } = useMorseFilesContext();\n\n\tconst { estimate } = useStorageCostEstimate({\n\t\tsizeBytes: file?.size ?? 0,\n\t\tepochs,\n\t\tencrypt,\n\t});\n\n\tconst { getRootProps, getInputProps } = useDropzone({\n\t\tmultiple: false,\n\t\tariaLabel: \"Choose a file to upload\",\n\t\tonFiles: (files) => setFile(files[0] ?? null),\n\t});\n\n\tconst handleUpload = async () => {\n\t\tif (file === null) {\n\t\t\treturn;\n\t\t}\n\t\tconst result = await upload.upload({\n\t\t\tfile,\n\t\t\tepochs,\n\t\t\tencrypt,\n\t\t\t...(recipients === undefined ? {} : { recipients }),\n\t\t});\n\t\tonUploaded?.(result);\n\t};\n\n\tconst handleReset = () => {\n\t\tupload.reset();\n\t\tsetFile(null);\n\t};\n\n\tconst phases = uploadPhases(encrypt);\n\tconst activeIndex = upload.phase === null ? -1 : phases.indexOf(upload.phase);\n\tconst errorMessage =\n\t\tupload.error === null ? null : uploadErrorMessage(upload.error, network);\n\n\treturn (\n\t\t<div className={`mu-uploader ${className ?? \"\"}`} data-mu=\"uploader\">\n\t\t\t<div className=\"mu-dropzone\" {...getRootProps()}>\n\t\t\t\t<input className=\"mu-file-input\" {...getInputProps()} />\n\t\t\t\t<span className=\"mu-dropzone-icon\" aria-hidden=\"true\" />\n\t\t\t\t{file === null ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span className=\"mu-dropzone-hint\">\n\t\t\t\t\t\t\tDrag a file here, or click to browse\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"mu-dropzone-sub\">Any file type</span>\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span className=\"mu-dropzone-hint\">{file.name}</span>\n\t\t\t\t\t\t<span className=\"mu-dropzone-sub\">\n\t\t\t\t\t\t\t{formatBytes(file.size)} · click to replace\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<label className=\"mu-field\">\n\t\t\t\t<span className=\"mu-field-label\">Storage duration (epochs)</span>\n\t\t\t\t<input\n\t\t\t\t\tclassName=\"mu-epochs-input\"\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\tmin={minEpochs}\n\t\t\t\t\tmax={maxEpochs}\n\t\t\t\t\tvalue={epochs}\n\t\t\t\t\tonChange={(event) =>\n\t\t\t\t\t\tsetEpochs(\n\t\t\t\t\t\t\tclamp(\n\t\t\t\t\t\t\t\tNumber.parseInt(event.target.value, 10) || minEpochs,\n\t\t\t\t\t\t\t\tminEpochs,\n\t\t\t\t\t\t\t\tmaxEpochs,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t\t<span\n\t\t\t\t\tclassName=\"mu-field-help\"\n\t\t\t\t\ttitle={`Walrus storage is a lease, not permanent. You can buy at most ${maxEpochs} epochs ahead. An epoch is about 1 day on testnet and about 2 weeks on mainnet.`}\n\t\t\t\t>\n\t\t\t\t\t{`≈ ${Math.round(estimate.days)} day${\n\t\t\t\t\t\tMath.round(estimate.days) === 1 ? \"\" : \"s\"\n\t\t\t\t\t} of storage · max ${maxEpochs} epochs`}\n\t\t\t\t</span>\n\t\t\t</label>\n\n\t\t\t<div className=\"mu-cost\" data-mu=\"cost\">\n\t\t\t\t<span className=\"mu-cost-label\">\n\t\t\t\t\t{encrypt\n\t\t\t\t\t\t? \"Estimated storage cost (encrypted)\"\n\t\t\t\t\t\t: \"Estimated storage cost\"}\n\t\t\t\t</span>\n\t\t\t\t<span className=\"mu-cost-value\">{formatUsd(estimate.usd)}</span>\n\t\t\t</div>\n\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"mu-upload\"\n\t\t\t\tdisabled={file === null || upload.status === \"uploading\"}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tvoid handleUpload();\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{upload.status === \"uploading\"\n\t\t\t\t\t? \"Uploading...\"\n\t\t\t\t\t: encrypt\n\t\t\t\t\t\t? \"Encrypt and upload\"\n\t\t\t\t\t\t: \"Upload\"}\n\t\t\t</button>\n\n\t\t\t{upload.status === \"uploading\" ? (\n\t\t\t\t<ol className=\"mu-stepper\" data-mu=\"stepper\">\n\t\t\t\t\t{phases.map((phase, index) => (\n\t\t\t\t\t\t<li\n\t\t\t\t\t\t\tkey={phase}\n\t\t\t\t\t\t\tclassName=\"mu-step\"\n\t\t\t\t\t\t\tdata-state={\n\t\t\t\t\t\t\t\tindex < activeIndex\n\t\t\t\t\t\t\t\t\t? \"done\"\n\t\t\t\t\t\t\t\t\t: index === activeIndex\n\t\t\t\t\t\t\t\t\t\t? \"active\"\n\t\t\t\t\t\t\t\t\t\t: \"pending\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"mu-step-dot\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t{index + 1}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span className=\"mu-step-label\">{uploadPhaseLabel(phase)}</span>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ol>\n\t\t\t) : null}\n\n\t\t\t{errorMessage !== null ? (\n\t\t\t\t<div className=\"mu-error\" role=\"alert\">\n\t\t\t\t\t<strong>{errorMessage.title}</strong>\n\t\t\t\t\t<span>{errorMessage.description}</span>\n\t\t\t\t</div>\n\t\t\t) : null}\n\n\t\t\t{upload.data !== null ? (\n\t\t\t\t<div className=\"mu-result\" data-mu=\"result\">\n\t\t\t\t\t<span className=\"mu-result-head\">\n\t\t\t\t\t\t<span className=\"mu-result-badge\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t✓\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<strong>\n\t\t\t\t\t\t\t{upload.data.encrypted ? \"Encrypted and uploaded\" : \"Uploaded\"}\n\t\t\t\t\t\t</strong>\n\t\t\t\t\t</span>\n\t\t\t\t\t<div className=\"mu-result-actions\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclassName=\"mu-upload mu-result-link\"\n\t\t\t\t\t\t\thref={upload.data.shareLink}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tOpen share link\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"mu-ghost mu-result-copy\"\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tvoid clipboard.copy(upload.data?.shareLink ?? \"\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{clipboard.copied ? \"Copied!\" : \"Copy link\"}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button type=\"button\" className=\"mu-ghost\" onClick={handleReset}>\n\t\t\t\t\t\t\tUpload another\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<code className=\"mu-result-id\">{upload.data.fileId}</code>\n\t\t\t\t\t{upload.data.encrypted ? (\n\t\t\t\t\t\t<span className=\"mu-result-note\">\n\t\t\t\t\t\t\tThe share link carries the decryption key; only recipients can\n\t\t\t\t\t\t\topen it.\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcadiasystems/morse-uploader",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Headless-first React components and hooks for encrypted file sharing on Sui and Walrus, built on morse-sdk.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Arcadia Systems",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants/default-encryption-overhead-bytes.ts","../src/utils/bytes-to-hex.ts","../src/utils/resolve-origin.ts","../src/utils/trim-trailing-slashes.ts","../src/files/build-share-link.ts","../src/files/epoch-duration-ms.ts","../src/files/estimate-storage-usd.ts","../src/files/upload-error-message.ts","../src/files/upload-phase-label.ts","../src/files/upload-phases.ts","../src/files/context.ts","../src/files/use-morse-files-context.ts","../src/files/assert-signer-matches-address.ts","../src/files/use-file-decrypt.ts","../src/utils/is-previewable-image.ts","../src/utils/trigger-download.ts","../src/files/use-recipient-file.ts","../src/files/use-file-download.ts","../src/files/use-file-upload.ts","../src/files/use-storage-cost-estimate.ts","../src/primitives/use-clipboard.ts","../src/primitives/use-dropzone.ts","../src/utils/format-bytes.ts","../src/utils/format-usd.ts"],"names":["useState","useCallback","useRef","useEffect","SEAL_UNAVAILABLE"],"mappings":"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","file":"chunk-K2J3ZILI.js","sourcesContent":["/**\n * Approximate bytes the Seal envelope adds to a ciphertext, used to nudge the\n * cost estimate when encryption is enabled. Small relative to most files;\n * consumers override per-call via `encryptionOverheadBytes`.\n */\nexport const DEFAULT_ENCRYPTION_OVERHEAD_BYTES = 150;\n","/** Encode bytes as a lowercase hex string (no `0x` prefix). */\nexport function bytesToHex(bytes: Uint8Array): string {\n\tlet out = \"\";\n\tfor (const byte of bytes) {\n\t\tout += byte.toString(16).padStart(2, \"0\");\n\t}\n\treturn out;\n}\n","/**\n * Return the current browser origin (e.g. \"https://app.example.com\"), or null\n * when running outside a browser (SSR, Node, web worker without a location).\n *\n * SSR-safe: never throws on a missing `window`.\n */\nexport function resolveOrigin(): string | null {\n\t// `typeof` guards are the SSR-safe way to probe globals that may be absent.\n\tif (typeof window === \"undefined\" || typeof window.location === \"undefined\") {\n\t\treturn null;\n\t}\n\tconst { origin } = window.location;\n\treturn origin.length > 0 ? origin : null;\n}\n","/** Remove any trailing slashes from a URL or path segment. */\nexport function trimTrailingSlashes(value: string): string {\n\treturn value.replace(/\\/+$/, \"\");\n}\n","import { bytesToHex } from \"../utils/bytes-to-hex.js\";\nimport { resolveOrigin } from \"../utils/resolve-origin.js\";\nimport { trimTrailingSlashes } from \"../utils/trim-trailing-slashes.js\";\nimport type { BuildShareLinkArgs } from \"./types.js\";\n\nconst DEFAULT_PATTERN = \"/#/f/:fileId\";\n\n/**\n * Build a share link for a RecipientFile. The fileId goes in the URL fragment,\n * with the network as `net` and the Seal material (prefix + nonce, if any) as\n * hex `p`/`n` queries inside that fragment, so none of it reaches a server log.\n * The seal material is not a secret: decryption is still gated by the file's\n * recipient set. SSR-safe (falls back to an empty base outside a browser).\n */\nexport function buildShareLink(args: BuildShareLinkArgs): string {\n\tconst base = trimTrailingSlashes(args.baseUrl ?? resolveOrigin() ?? \"\");\n\tconst path = (args.pattern ?? DEFAULT_PATTERN).replace(\n\t\t\":fileId\",\n\t\tencodeURIComponent(args.fileId),\n\t);\n\tconst params: string[] = [];\n\tif (args.network !== undefined) {\n\t\tparams.push(`net=${args.network}`);\n\t}\n\tif (args.sealIdPrefix !== undefined && args.sealNonce !== undefined) {\n\t\tparams.push(`p=${bytesToHex(args.sealIdPrefix)}`);\n\t\tparams.push(`n=${bytesToHex(args.sealNonce)}`);\n\t}\n\tconst query = params.length === 0 ? \"\" : `?${params.join(\"&\")}`;\n\treturn `${base}${path}${query}`;\n}\n","/** One day in milliseconds. */\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\n\n/** Walrus epoch length per network: testnet ~1 day, mainnet ~2 weeks. */\nconst EPOCH_DURATION_MS: Record<\"testnet\" | \"mainnet\", number> = {\n\ttestnet: ONE_DAY_MS,\n\tmainnet: 14 * ONE_DAY_MS,\n};\n\n/**\n * Nominal Walrus epoch length in milliseconds for a network. Used by the USD\n * cost estimate to convert an epoch count into months. These are the documented\n * nominal lengths (testnet 1 day, mainnet 2 weeks), not a live chain read.\n */\nexport function epochDurationMs(network: \"testnet\" | \"mainnet\"): number {\n\treturn EPOCH_DURATION_MS[network];\n}\n","import type { UsdCostArgs, UsdCostEstimate } from \"./types.js\";\n\n// Walrus predictable pricing: $0.023 per GB per month, paid in WAL but pegged.\n// https://blog.walrus.xyz/announcing-predictable-pricing-in-usd-on-walrus/\nconst DEFAULT_USD_PER_GB_PER_MONTH = 0.023;\nconst BYTES_PER_GB = 1_000_000_000;\nconst MS_PER_DAY = 24 * 60 * 60 * 1000;\nconst MS_PER_MONTH = 30 * MS_PER_DAY;\n\n/**\n * Estimate Walrus storage cost in USD from a blob size and a storage duration.\n * Duration is given in epochs plus the epoch length (read from chain), since an\n * epoch is 1 day on testnet and 2 weeks on mainnet. Encryption overhead can be\n * folded in so the encrypt toggle moves the figure.\n */\nexport function estimateStorageUsd(args: UsdCostArgs): UsdCostEstimate {\n\tconst sizeBytes = args.sizeBytes + (args.encryptionOverheadBytes ?? 0);\n\tconst gb = sizeBytes / BYTES_PER_GB;\n\tconst totalMs = args.epochs * args.epochDurationMs;\n\tconst months = totalMs / MS_PER_MONTH;\n\tconst days = totalMs / MS_PER_DAY;\n\tconst rate = args.usdPerGbPerMonth ?? DEFAULT_USD_PER_GB_PER_MONTH;\n\treturn { usd: gb * months * rate, gb, months, days, sizeBytes };\n}\n","import {\n\ttype FormattedError,\n\tformatUserMessage,\n} from \"@arcadiasystems/morse-sdk\";\n\n/**\n * Render an upload failure for the UI. Defers to the SDK's `formatUserMessage`\n * except for an insufficient-balance failure, which the SDK sees only as a\n * transport error carrying `@mysten/sui`'s raw text: a coin type, an address,\n * and two unscaled integers. That reads as a network problem when it is really\n * \"top up the wallet\", so it is rewritten here with the amounts in whole coins\n * and the network's way of getting more.\n */\nexport function uploadErrorMessage(\n\terror: unknown,\n\tnetwork?: \"testnet\" | \"mainnet\",\n): FormattedError {\n\tconst shortfall = parseInsufficientBalance(errorText(error));\n\tif (shortfall === null) {\n\t\treturn formatUserMessage(error);\n\t}\n\treturn {\n\t\ttitle: `Not enough ${shortfall.symbol}`,\n\t\tdescription: describe(shortfall, network),\n\t\tcause: error,\n\t};\n}\n\ninterface Shortfall {\n\treadonly symbol: string;\n\treadonly decimals: number | null;\n\treadonly required: bigint;\n\treadonly available: bigint;\n}\n\n// @mysten/sui's CoinWithBalance intent, thrown while resolving the coins the\n// transaction spends: \"Insufficient balance of <coinType> for owner <address>.\n// Required: <n>, Available: <n>\".\nconst INSUFFICIENT_RE =\n\t/Insufficient balance of (\\S+) for owner \\S+?\\.\\s*Required:\\s*(\\d+),\\s*Available:\\s*(\\d+)/;\n\nfunction parseInsufficientBalance(text: string): Shortfall | null {\n\tconst match = INSUFFICIENT_RE.exec(text);\n\tif (match === null) {\n\t\treturn null;\n\t}\n\tconst [, coinType, required, available] = match;\n\treturn {\n\t\t...coin(coinType as string),\n\t\trequired: BigInt(required as string),\n\t\tavailable: BigInt(available as string),\n\t};\n}\n\n/**\n * Both coins Walrus charges use 9 decimals. Anything else is reported in raw\n * units rather than scaled by a guessed exponent.\n */\nfunction coin(coinType: string): { symbol: string; decimals: number | null } {\n\tif (coinType.endsWith(\"::wal::WAL\")) {\n\t\treturn { symbol: \"WAL\", decimals: 9 };\n\t}\n\tif (coinType.endsWith(\"::sui::SUI\")) {\n\t\treturn { symbol: \"SUI\", decimals: 9 };\n\t}\n\tconst symbol = coinType.split(\"::\").pop();\n\treturn { symbol: symbol ?? \"coins\", decimals: null };\n}\n\nfunction describe(shortfall: Shortfall, network?: string): string {\n\tconst need = amount(shortfall.required, shortfall.decimals, shortfall.symbol);\n\tconst have = amount(\n\t\tshortfall.available,\n\t\tshortfall.decimals,\n\t\tshortfall.symbol,\n\t);\n\treturn `This upload needs ${need} and the connected wallet has ${have}. ${topUp(shortfall.symbol, network)}`;\n}\n\nfunction topUp(symbol: string, network?: string): string {\n\tif (network === \"testnet\") {\n\t\treturn symbol === \"WAL\"\n\t\t\t? \"Swap some testnet SUI for WAL at https://stake-wal.wal.app/?network=testnet, then retry.\"\n\t\t\t: \"Get testnet SUI from https://faucet.sui.io/, then retry.\";\n\t}\n\tif (network === \"mainnet\") {\n\t\treturn `There is no faucet on mainnet, so ${symbol} has to be acquired (Walrus charges WAL for storage and SUI for gas). Top up the wallet, then retry.`;\n\t}\n\treturn `Top up the wallet with ${symbol}, then retry.`;\n}\n\nfunction amount(\n\tvalue: bigint,\n\tdecimals: number | null,\n\tsymbol: string,\n): string {\n\tif (decimals === null) {\n\t\treturn `${value.toString()} ${symbol}`;\n\t}\n\tconst scale = 10n ** BigInt(decimals);\n\tconst whole = value / scale;\n\tconst fraction = (value % scale).toString().padStart(decimals, \"0\");\n\tconst trimmed = fraction.replace(/0+$/, \"\");\n\tconst text = trimmed === \"\" ? whole.toString() : `${whole}.${trimmed}`;\n\treturn `${text} ${symbol}`;\n}\n\n/** Flatten the error and its causes, since the text can sit on either. */\nfunction errorText(error: unknown): string {\n\tconst parts: string[] = [];\n\tlet current = error;\n\tfor (\n\t\tlet depth = 0;\n\t\tcurrent !== null && current !== undefined && depth < 5;\n\t\tdepth += 1\n\t) {\n\t\tif (current instanceof Error) {\n\t\t\tparts.push(current.message);\n\t\t\tcurrent = current.cause;\n\t\t\tcontinue;\n\t\t}\n\t\tparts.push(String(current));\n\t\tbreak;\n\t}\n\treturn parts.join(\" | \");\n}\n","import type { FilePhase } from \"./types.js\";\n\nconst LABELS: Record<FilePhase, string> = {\n\tencrypting: \"Encrypting\",\n\tuploading: \"Uploading to Walrus\",\n\tsubmitting: \"Submitting transaction\",\n\tcomplete: \"Complete\",\n};\n\n/** Human-readable label for an upload phase, for the progress stepper. */\nexport function uploadPhaseLabel(phase: FilePhase): string {\n\treturn LABELS[phase];\n}\n","import type { FilePhase } from \"./types.js\";\n\nconst ENCRYPTED_PHASES: readonly FilePhase[] = [\n\t\"encrypting\",\n\t\"uploading\",\n\t\"submitting\",\n\t\"complete\",\n];\nconst PUBLIC_PHASES: readonly FilePhase[] = [\n\t\"uploading\",\n\t\"submitting\",\n\t\"complete\",\n];\n\n/**\n * The ordered upload phases for the progress stepper. Public uploads skip the\n * `encrypting` phase since there is no Seal step.\n */\nexport function uploadPhases(encrypted: boolean): readonly FilePhase[] {\n\treturn encrypted ? ENCRYPTED_PHASES : PUBLIC_PHASES;\n}\n","import { createContext } from \"react\";\nimport type { MorseFilesHandles } from \"./types.js\";\n\n/**\n * Holds the injected SDK handles for the files flow. Null until a\n * {@link MorseFilesProvider} supplies them; the consumer hook throws on null.\n */\nexport const MorseFilesContext = createContext<MorseFilesHandles | null>(null);\n","import { useContext } from \"react\";\nimport { MorseFilesContext } from \"./context.js\";\nimport type { MorseFilesHandles } from \"./types.js\";\n\n/**\n * Read the files-flow handles.\n *\n * @throws {Error} when used outside a {@link MorseFilesProvider}.\n */\nexport function useMorseFilesContext(): MorseFilesHandles {\n\tconst handles = useContext(MorseFilesContext);\n\tif (handles === null) {\n\t\tthrow new Error(\n\t\t\t\"useMorseFilesContext must be used within a MorseFilesProvider.\",\n\t\t);\n\t}\n\treturn handles;\n}\n","import { UserError } from \"@mysten/seal\";\nimport type { Signer } from \"@mysten/sui/cryptography\";\nimport { normalizeSuiAddress } from \"@mysten/sui/utils\";\n\n/**\n * Refuse to build a Seal session for `address` with a signer for another\n * account.\n *\n * `@mysten/seal` up to 1.4 made this check inside `SessionKey.create`; 1.5\n * dropped it to allow address aliases. Without it a mismatch costs a wallet\n * popup and then fails at the key servers, and `useFileDecrypt` would by then\n * have cached the session for `address`, so every later decrypt reuses it and\n * fails the same way. Handles from `useMorseFiles` always agree, because the\n * SDK's `WalletStandardSigner` requires the account's key to derive to its\n * address; this keeps hand-built handles failing early, as they did before.\n *\n * @throws {UserError} When the signer's address is not `address`. Same class\n * and leading message as the check Seal used to make.\n */\nexport function assertSignerMatchesAddress(\n\tsigner: Signer,\n\taddress: string,\n): void {\n\tconst signerAddress = normalizeSuiAddress(signer.toSuiAddress());\n\tconst sessionAddress = normalizeSuiAddress(address);\n\tif (signerAddress !== sessionAddress) {\n\t\tthrow new UserError(\n\t\t\t`Signer address does not match session key address: the signer is ${signerAddress}, the session is for ${sessionAddress}. Build the handles with useMorseFiles, or pass a signer for the same account.`,\n\t\t);\n\t}\n}\n","import { buildRecipientFileSealId, SealError } from \"@arcadiasystems/morse-sdk\";\nimport { SessionKey } from \"@mysten/seal\";\nimport { useCallback, useRef, useState } from \"react\";\nimport { assertSignerMatchesAddress } from \"./assert-signer-matches-address.js\";\nimport type {\n\tFileDecryptInput,\n\tFileDecryptStatus,\n\tUseFileDecryptResult,\n} from \"./types.js\";\nimport { useMorseFilesContext } from \"./use-morse-files-context.js\";\n\n/** Message for when the provider has no key servers to decrypt with. */\nconst SEAL_UNAVAILABLE =\n\t\"No Seal key servers are configured, so decryption is unavailable. Testnet pins an open set; mainnet pins none, because every operator there is commercial. Pass `sealKeyServers` to MorseFilesProvider, starting from the SDK's MAINNET_SEAL_COMMITTEE with the apiKeyName and apiKey your operator issues.\";\n\nconst DEFAULT_TTL_MIN = 10;\n\ninterface CachedSession {\n\treadonly address: string;\n\treadonly packageId: string;\n\treadonly key: SessionKey;\n}\n\n/**\n * Decrypt + return the plaintext of an encrypted RecipientFile. Reads the\n * ciphertext from Walrus, creates (and reuses) a Seal SessionKey, and decrypts\n * under the file's recipient policy. Re-signs once on a session-expired error.\n * The SessionKey is reusable across files for the same address and package, so\n * it is cached and re-signed only when one of those changes.\n */\nexport function useFileDecrypt(): UseFileDecryptResult {\n\tconst { seal, walrusRead, signer, client, config, address } =\n\t\tuseMorseFilesContext();\n\tconst [status, setStatus] = useState<FileDecryptStatus>(\"idle\");\n\tconst [data, setData] = useState<Uint8Array | null>(null);\n\tconst [error, setError] = useState<unknown>(null);\n\t// A SessionKey is bound to the address that signed it and to one package, so\n\t// the cache carries both. Reusing one across a wallet switch would sign the\n\t// new account's reads with the old account's session and fail at the key\n\t// servers, or silently keep the old account's access.\n\tconst sessionRef = useRef<CachedSession | null>(null);\n\n\tconst reset = useCallback(() => {\n\t\tsetStatus(\"idle\");\n\t\tsetData(null);\n\t\tsetError(null);\n\t}, []);\n\n\tconst decrypt = useCallback(\n\t\tasync (input: FileDecryptInput): Promise<Uint8Array> => {\n\t\t\tsetStatus(\"working\");\n\t\t\tsetData(null);\n\t\t\tsetError(null);\n\n\t\t\tif (seal === null) {\n\t\t\t\tconst unavailable = new Error(SEAL_UNAVAILABLE);\n\t\t\t\tsetError(unavailable);\n\t\t\t\tsetStatus(\"error\");\n\t\t\t\tthrow unavailable;\n\t\t\t}\n\n\t\t\tconst packageId = config.originalPackageId ?? config.packageId;\n\t\t\tconst getSession = async () => {\n\t\t\t\tconst cached = sessionRef.current;\n\t\t\t\tif (\n\t\t\t\t\tcached !== null &&\n\t\t\t\t\tcached.address === address &&\n\t\t\t\t\tcached.packageId === packageId\n\t\t\t\t) {\n\t\t\t\t\treturn cached.key;\n\t\t\t\t}\n\t\t\t\tassertSignerMatchesAddress(signer, address);\n\t\t\t\tconst key = await SessionKey.create({\n\t\t\t\t\taddress,\n\t\t\t\t\tpackageId,\n\t\t\t\t\tttlMin: input.ttlMin ?? DEFAULT_TTL_MIN,\n\t\t\t\t\tsigner,\n\t\t\t\t\tsuiClient: client,\n\t\t\t\t});\n\t\t\t\tsessionRef.current = { address, packageId, key };\n\t\t\t\treturn key;\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\tconst ciphertext = await walrusRead.readBlob(input.file.blobId);\n\t\t\t\tconst options = {\n\t\t\t\t\tsealId: buildRecipientFileSealId(input.sealIdPrefix, input.sealNonce),\n\t\t\t\t\tfileId: input.file.id,\n\t\t\t\t};\n\t\t\t\ttry {\n\t\t\t\t\tconst plaintext = await seal.decryptUnderRecipientFile(ciphertext, {\n\t\t\t\t\t\t...options,\n\t\t\t\t\t\tsessionKey: await getSession(),\n\t\t\t\t\t});\n\t\t\t\t\tsetData(plaintext);\n\t\t\t\t\tsetStatus(\"success\");\n\t\t\t\t\treturn plaintext;\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// Stale session: drop the cache, re-sign once, and retry.\n\t\t\t\t\tif (err instanceof SealError && err.code === \"session-expired\") {\n\t\t\t\t\t\tsessionRef.current = null;\n\t\t\t\t\t\tconst plaintext = await seal.decryptUnderRecipientFile(ciphertext, {\n\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\tsessionKey: await getSession(),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tsetData(plaintext);\n\t\t\t\t\t\tsetStatus(\"success\");\n\t\t\t\t\t\treturn plaintext;\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tsetError(err);\n\t\t\t\tsetStatus(\"error\");\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t\t[seal, walrusRead, signer, client, config, address],\n\t);\n\n\treturn { status, data, error, decrypt, reset };\n}\n","/** Content types the downloader renders inline as an image preview. */\nconst PREVIEWABLE_IMAGE_TYPES = new Set([\n\t\"image/png\",\n\t\"image/jpeg\",\n\t\"image/gif\",\n\t\"image/webp\",\n\t\"image/avif\",\n\t\"image/svg+xml\",\n]);\n\n/** True when a content type is a browser-previewable image. */\nexport function isPreviewableImage(contentType: string): boolean {\n\treturn PREVIEWABLE_IMAGE_TYPES.has(contentType.toLowerCase());\n}\n","/**\n * Trigger a browser download of an object URL under a given filename. Creates a\n * transient anchor, clicks it, and removes it. No-op outside a DOM.\n */\nexport function triggerDownload(objectUrl: string, filename: string): void {\n\tif (typeof document === \"undefined\") {\n\t\treturn;\n\t}\n\tconst anchor = document.createElement(\"a\");\n\tanchor.href = objectUrl;\n\tanchor.download = filename;\n\tanchor.rel = \"noopener\";\n\tdocument.body.appendChild(anchor);\n\tanchor.click();\n\tanchor.remove();\n}\n","import type { RecipientFile, RecipientFileId } from \"@arcadiasystems/morse-sdk\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { LoadStatus, UseRecipientFileResult } from \"./types.js\";\nimport { useMorseFilesContext } from \"./use-morse-files-context.js\";\n\n/** Load a RecipientFile's on-chain metadata by id. Loads on mount. */\nexport function useRecipientFile(\n\tfileId: RecipientFileId | null,\n): UseRecipientFileResult {\n\tconst { reader } = useMorseFilesContext();\n\tconst [status, setStatus] = useState<LoadStatus>(\"idle\");\n\tconst [file, setFile] = useState<RecipientFile | null>(null);\n\tconst [error, setError] = useState<unknown>(null);\n\n\tconst refresh = useCallback(async (): Promise<RecipientFile | null> => {\n\t\tif (fileId === null) {\n\t\t\treturn null;\n\t\t}\n\t\tsetStatus(\"loading\");\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst loaded = await reader.getRecipientFile(fileId);\n\t\t\tsetFile(loaded);\n\t\t\tsetStatus(\"success\");\n\t\t\treturn loaded;\n\t\t} catch (err) {\n\t\t\tsetError(err);\n\t\t\tsetStatus(\"error\");\n\t\t\tthrow err;\n\t\t}\n\t}, [reader, fileId]);\n\n\tuseEffect(() => {\n\t\tif (fileId !== null) {\n\t\t\trefresh().catch(() => undefined);\n\t\t}\n\t}, [refresh, fileId]);\n\n\treturn { status, file, error, refresh };\n}\n","import type { RecipientFileId } from \"@arcadiasystems/morse-sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { isPreviewableImage } from \"../utils/is-previewable-image.js\";\nimport { triggerDownload } from \"../utils/trigger-download.js\";\nimport type {\n\tFileDownloadStatus,\n\tSealMaterial,\n\tUseFileDownloadResult,\n} from \"./types.js\";\nimport { useFileDecrypt } from \"./use-file-decrypt.js\";\nimport { useMorseFilesContext } from \"./use-morse-files-context.js\";\nimport { useRecipientFile } from \"./use-recipient-file.js\";\n\n/**\n * Drive the single-file download page. Loads the on-chain metadata, then\n * fetches the bytes on demand. A RecipientFile has no on-chain \"encrypted\"\n * flag, so the caller signals encryption by passing the Seal material from the\n * share link: when present, the bytes are decrypted (one SessionKey signature);\n * when null, they are read straight from Walrus as a public file.\n *\n * @param fileId The on-chain RecipientFile id (from the share link).\n * @param seal The Seal material (prefix + nonce) for encrypted files; null for public.\n */\nexport function useFileDownload(\n\tfileId: RecipientFileId | null,\n\tseal: SealMaterial | null,\n): UseFileDownloadResult {\n\tconst { walrusRead } = useMorseFilesContext();\n\tconst { status: metaStatus, file } = useRecipientFile(fileId);\n\tconst { decrypt } = useFileDecrypt();\n\tconst [status, setStatus] = useState<FileDownloadStatus>(\"idle\");\n\tconst [objectUrl, setObjectUrl] = useState<string | null>(null);\n\tconst [error, setError] = useState<unknown>(null);\n\tconst urlRef = useRef<string | null>(null);\n\n\t// Revoke the object URL when it is replaced or the component unmounts.\n\tuseEffect(() => {\n\t\tif (objectUrl === null) {\n\t\t\treturn;\n\t\t}\n\t\treturn () => URL.revokeObjectURL(objectUrl);\n\t}, [objectUrl]);\n\n\tconst encrypted = seal !== null;\n\tconst isImage = file === null ? false : isPreviewableImage(file.contentType);\n\n\t// Fetch the plaintext bytes and build an object URL. Shared by load/download.\n\tconst fetchToUrl = useCallback(async (): Promise<string | null> => {\n\t\tif (file === null) {\n\t\t\treturn null;\n\t\t}\n\t\tsetStatus(\"loading\");\n\t\tsetError(null);\n\t\ttry {\n\t\t\tlet bytes: Uint8Array;\n\t\t\tif (seal !== null) {\n\t\t\t\tbytes = await decrypt({\n\t\t\t\t\tfile,\n\t\t\t\t\tsealIdPrefix: seal.sealIdPrefix,\n\t\t\t\t\tsealNonce: seal.sealNonce,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tbytes = await walrusRead.readBlob(file.blobId);\n\t\t\t}\n\t\t\tconst url = URL.createObjectURL(\n\t\t\t\tnew Blob([bytes as BlobPart], { type: file.contentType }),\n\t\t\t);\n\t\t\turlRef.current = url;\n\t\t\tsetObjectUrl(url);\n\t\t\tsetStatus(\"ready\");\n\t\t\treturn url;\n\t\t} catch (err) {\n\t\t\tsetError(err);\n\t\t\tsetStatus(\"error\");\n\t\t\treturn null;\n\t\t}\n\t}, [file, seal, decrypt, walrusRead]);\n\n\tconst load = useCallback(async (): Promise<void> => {\n\t\tawait fetchToUrl();\n\t}, [fetchToUrl]);\n\n\tconst save = useCallback(() => {\n\t\tif (urlRef.current !== null && file !== null) {\n\t\t\ttriggerDownload(urlRef.current, file.name);\n\t\t}\n\t}, [file]);\n\n\tconst download = useCallback(async (): Promise<void> => {\n\t\tconst url = urlRef.current ?? (await fetchToUrl());\n\t\tif (url !== null && file !== null) {\n\t\t\ttriggerDownload(url, file.name);\n\t\t}\n\t}, [fetchToUrl, file]);\n\n\treturn {\n\t\tmetaStatus,\n\t\tfile,\n\t\tstatus,\n\t\tobjectUrl,\n\t\tencrypted,\n\t\tisImage,\n\t\terror,\n\t\tload,\n\t\tsave,\n\t\tdownload,\n\t};\n}\n","import {\n\tuploadEncryptedRecipientFileFromBytes,\n\tuploadRecipientFileFromBytes,\n} from \"@arcadiasystems/morse-sdk\";\nimport { useCallback, useState } from \"react\";\nimport { buildShareLink } from \"./build-share-link.js\";\nimport type {\n\tCompletedFileUpload,\n\tFilePhase,\n\tFileUploadInput,\n\tFileUploadStatus,\n\tUseFileUploadResult,\n} from \"./types.js\";\nimport { useMorseFilesContext } from \"./use-morse-files-context.js\";\n\n/** Shared message for the encrypted paths when no key servers exist. */\nconst SEAL_UNAVAILABLE =\n\t\"No Seal key servers are configured, so encrypted files are unavailable. Testnet pins an open set; mainnet pins none, because every operator there is commercial. Pass `sealKeyServers` to MorseFilesProvider, starting from the SDK's MAINNET_SEAL_COMMITTEE with the apiKeyName and apiKey your operator issues.\";\n\nconst FALLBACK_CONTENT_TYPE = \"application/octet-stream\";\n\n/**\n * Upload one file as a RecipientFile. With `encrypt`, it encrypts under Seal\n * (only the recipients, plus the connected wallet, can decrypt); otherwise it\n * uploads a public file. Either way the recipient set is set at creation in two\n * wallet popups. Tracks the phase stepper and returns the fileId, the seal\n * material (encrypted only), and a share link.\n */\nexport function useFileUpload(): UseFileUploadResult {\n\tconst { adapter, config, walrusWrite, seal, network } =\n\t\tuseMorseFilesContext();\n\tconst [status, setStatus] = useState<FileUploadStatus>(\"idle\");\n\tconst [phase, setPhase] = useState<FilePhase | null>(null);\n\tconst [data, setData] = useState<CompletedFileUpload | null>(null);\n\tconst [error, setError] = useState<unknown>(null);\n\n\tconst reset = useCallback(() => {\n\t\tsetStatus(\"idle\");\n\t\tsetPhase(null);\n\t\tsetData(null);\n\t\tsetError(null);\n\t}, []);\n\n\tconst upload = useCallback(\n\t\tasync (input: FileUploadInput): Promise<CompletedFileUpload> => {\n\t\t\tsetStatus(\"uploading\");\n\t\t\tsetPhase(null);\n\t\t\tsetData(null);\n\t\t\tsetError(null);\n\t\t\ttry {\n\t\t\t\tconst bytes = new Uint8Array(await input.file.arrayBuffer());\n\t\t\t\tconst contentType = input.file.type || FALLBACK_CONTENT_TYPE;\n\t\t\t\tconst recipients = input.recipients ?? [];\n\t\t\t\tconst uploadOptions = {\n\t\t\t\t\tepochs: input.epochs,\n\t\t\t\t\tdeletable: input.deletable ?? true,\n\t\t\t\t};\n\t\t\t\tconst onProgress = (event: { phase: FilePhase }) =>\n\t\t\t\t\tsetPhase(event.phase);\n\n\t\t\t\tlet completed: CompletedFileUpload;\n\t\t\t\tif (input.encrypt === true) {\n\t\t\t\t\tif (seal === null) {\n\t\t\t\t\t\tthrow new Error(SEAL_UNAVAILABLE);\n\t\t\t\t\t}\n\t\t\t\t\tconst result = await uploadEncryptedRecipientFileFromBytes(\n\t\t\t\t\t\tadapter,\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\twalrus: walrusWrite,\n\t\t\t\t\t\t\tseal,\n\t\t\t\t\t\t\tplaintext: bytes,\n\t\t\t\t\t\t\trecipients,\n\t\t\t\t\t\t\tname: input.file.name,\n\t\t\t\t\t\t\tcontentType,\n\t\t\t\t\t\t\tupload: uploadOptions,\n\t\t\t\t\t\t\tonProgress,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tcompleted = {\n\t\t\t\t\t\tfileId: result.fileId,\n\t\t\t\t\t\tblobId: result.blobId,\n\t\t\t\t\t\tencrypted: true,\n\t\t\t\t\t\tsealIdPrefix: result.sealIdPrefix,\n\t\t\t\t\t\tsealNonce: result.sealNonce,\n\t\t\t\t\t\tshareLink: buildShareLink({\n\t\t\t\t\t\t\tfileId: result.fileId,\n\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\tsealIdPrefix: result.sealIdPrefix,\n\t\t\t\t\t\t\tsealNonce: result.sealNonce,\n\t\t\t\t\t\t}),\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tconst result = await uploadRecipientFileFromBytes(adapter, config, {\n\t\t\t\t\t\twalrus: walrusWrite,\n\t\t\t\t\t\tbytes,\n\t\t\t\t\t\trecipients,\n\t\t\t\t\t\tname: input.file.name,\n\t\t\t\t\t\tcontentType,\n\t\t\t\t\t\tupload: uploadOptions,\n\t\t\t\t\t\tonProgress,\n\t\t\t\t\t});\n\t\t\t\t\tcompleted = {\n\t\t\t\t\t\tfileId: result.fileId,\n\t\t\t\t\t\tblobId: result.blobId,\n\t\t\t\t\t\tencrypted: false,\n\t\t\t\t\t\tsealIdPrefix: null,\n\t\t\t\t\t\tsealNonce: null,\n\t\t\t\t\t\tshareLink: buildShareLink({ fileId: result.fileId, network }),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tsetData(completed);\n\t\t\t\tsetStatus(\"success\");\n\t\t\t\treturn completed;\n\t\t\t} catch (err) {\n\t\t\t\tsetError(err);\n\t\t\t\tsetStatus(\"error\");\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t\t[adapter, config, walrusWrite, seal, network],\n\t);\n\n\treturn { status, phase, data, error, upload, reset };\n}\n","import { useMemo } from \"react\";\nimport { DEFAULT_ENCRYPTION_OVERHEAD_BYTES } from \"../constants/default-encryption-overhead-bytes.js\";\nimport { epochDurationMs } from \"./epoch-duration-ms.js\";\nimport { estimateStorageUsd } from \"./estimate-storage-usd.js\";\nimport type {\n\tUseStorageCostEstimateOptions,\n\tUseStorageCostEstimateResult,\n} from \"./types.js\";\nimport { useMorseFilesContext } from \"./use-morse-files-context.js\";\n\n/**\n * Deterministic USD storage-cost estimate for a pending upload. Uses Walrus\n * predictable pricing ($0.023/GB/month) with the network's nominal epoch length\n * from the active handles. When `encrypt` is set, the Seal envelope overhead is\n * folded into the priced size so the figure tracks the encrypt toggle.\n */\nexport function useStorageCostEstimate(\n\toptions: UseStorageCostEstimateOptions,\n): UseStorageCostEstimateResult {\n\tconst { network } = useMorseFilesContext();\n\tconst { sizeBytes, epochs, encrypt, usdPerGbPerMonth } = options;\n\n\tconst estimate = useMemo(\n\t\t() =>\n\t\t\testimateStorageUsd({\n\t\t\t\tsizeBytes,\n\t\t\t\tepochs,\n\t\t\t\tepochDurationMs: epochDurationMs(network),\n\t\t\t\tencryptionOverheadBytes: encrypt\n\t\t\t\t\t? DEFAULT_ENCRYPTION_OVERHEAD_BYTES\n\t\t\t\t\t: 0,\n\t\t\t\t...(usdPerGbPerMonth === undefined ? {} : { usdPerGbPerMonth }),\n\t\t\t}),\n\t\t[network, sizeBytes, epochs, encrypt, usdPerGbPerMonth],\n\t);\n\n\treturn { estimate };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { UseClipboardResult } from \"../types.js\";\n\n/**\n * Copy text to the clipboard and flag success for a short window so a button\n * can show \"Copied\". The `copied` flag resets after `resetMs`. No-op (returns\n * false) when the Clipboard API is unavailable or the write is rejected.\n */\nexport function useClipboard(resetMs = 2000): UseClipboardResult {\n\tconst [copied, setCopied] = useState(false);\n\tconst timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n\tuseEffect(() => () => clearTimeout(timer.current), []);\n\n\tconst copy = useCallback(\n\t\tasync (text: string): Promise<boolean> => {\n\t\t\tif (\n\t\t\t\ttypeof navigator === \"undefined\" ||\n\t\t\t\tnavigator.clipboard === undefined\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait navigator.clipboard.writeText(text);\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tsetCopied(true);\n\t\t\tclearTimeout(timer.current);\n\t\t\ttimer.current = setTimeout(() => setCopied(false), resetMs);\n\t\t\treturn true;\n\t\t},\n\t\t[resetMs],\n\t);\n\n\treturn { copied, copy };\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport type {\n\tDropzoneInputProps,\n\tDropzoneRootProps,\n\tUseDropzoneOptions,\n\tUseDropzoneResult,\n} from \"../types.js\";\n\n/**\n * Headless drag-and-drop file selection. Returns prop-getters for a root\n * element (keyboard-operable button with ARIA + drag state) and a hidden file\n * input, so consumers own all markup and styling. No `window`/`document`\n * access; SSR-safe.\n */\nexport function useDropzone(options: UseDropzoneOptions): UseDropzoneResult {\n\tconst {\n\t\tonFiles,\n\t\taccept,\n\t\tmultiple = true,\n\t\tdisabled = false,\n\t\tariaLabel,\n\t} = options;\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst [isDragging, setIsDragging] = useState(false);\n\n\tconst open = useCallback(() => {\n\t\tif (disabled) {\n\t\t\treturn;\n\t\t}\n\t\tinputRef.current?.click();\n\t}, [disabled]);\n\n\tconst emit = useCallback(\n\t\t(list: FileList | null) => {\n\t\t\tif (list === null || list.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tonFiles(Array.from(list));\n\t\t},\n\t\t[onFiles],\n\t);\n\n\tconst getRootProps = useCallback(\n\t\t(): DropzoneRootProps => ({\n\t\t\trole: \"button\",\n\t\t\ttabIndex: disabled ? -1 : 0,\n\t\t\t\"aria-disabled\": disabled,\n\t\t\t\"data-dragging\": isDragging ? \"true\" : undefined,\n\t\t\t...(ariaLabel === undefined ? {} : { \"aria-label\": ariaLabel }),\n\t\t\tonClick: () => open(),\n\t\t\tonKeyDown: (event) => {\n\t\t\t\tif (disabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Enter and Space activate a role=button element.\n\t\t\t\tif (event.key === \"Enter\" || event.key === \" \") {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\topen();\n\t\t\t\t}\n\t\t\t},\n\t\t\tonDragEnter: (event) => {\n\t\t\t\tif (disabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tevent.preventDefault();\n\t\t\t\tsetIsDragging(true);\n\t\t\t},\n\t\t\tonDragOver: (event) => {\n\t\t\t\t// preventDefault is required for the drop event to fire.\n\t\t\t\tif (!disabled) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t},\n\t\t\tonDragLeave: (event) => {\n\t\t\t\tif (disabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tevent.preventDefault();\n\t\t\t\tsetIsDragging(false);\n\t\t\t},\n\t\t\tonDrop: (event) => {\n\t\t\t\tif (disabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tevent.preventDefault();\n\t\t\t\tsetIsDragging(false);\n\t\t\t\temit(event.dataTransfer?.files ?? null);\n\t\t\t},\n\t\t}),\n\t\t[disabled, isDragging, open, emit, ariaLabel],\n\t);\n\n\tconst getInputProps = useCallback(\n\t\t(): DropzoneInputProps => ({\n\t\t\tref: inputRef,\n\t\t\ttype: \"file\",\n\t\t\tmultiple,\n\t\t\ttabIndex: -1,\n\t\t\tdisabled,\n\t\t\t...(accept === undefined ? {} : { accept }),\n\t\t\tonChange: (event) => emit(event.target.files),\n\t\t\t// The root's onClick calls input.click(); stop that programmatic click\n\t\t\t// from bubbling back to the root and re-opening the dialog.\n\t\t\tonClick: (event) => event.stopPropagation(),\n\t\t}),\n\t\t[accept, multiple, disabled, emit],\n\t);\n\n\treturn { isDragging, open, getRootProps, getInputProps, inputRef };\n}\n","// Binary (1024-based) units, ordered from smallest to largest.\nconst UNITS = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"] as const;\nconst BASE = 1024;\n\n/**\n * Format a byte count as a human-readable size (e.g. 2348 -> \"2.29 KB\").\n *\n * Uses binary units. Whole bytes are shown without a fraction; larger units use\n * `fractionDigits` decimals. Non-finite or non-positive input returns \"0 B\".\n */\nexport function formatBytes(bytes: number, fractionDigits = 2): string {\n\tif (!Number.isFinite(bytes) || bytes <= 0) {\n\t\treturn \"0 B\";\n\t}\n\tconst exponent = Math.min(\n\t\tMath.floor(Math.log(bytes) / Math.log(BASE)),\n\t\tUNITS.length - 1,\n\t);\n\tconst value = bytes / BASE ** exponent;\n\tconst unit = UNITS[exponent] ?? \"B\";\n\t// Bytes are always whole, so skip the fractional part for the base unit.\n\tif (exponent === 0) {\n\t\treturn `${value} ${unit}`;\n\t}\n\treturn `${value.toFixed(fractionDigits)} ${unit}`;\n}\n","// Below this the figure is not worth showing precisely; display a floor.\nconst TINY_FLOOR = 0.000001;\n\n/**\n * Format a USD amount for display. A cent or more uses two decimals; sub-cent\n * amounts (common for short Walrus leases) show two significant digits in plain\n * decimal notation; amounts below a millionth of a dollar show a `< $` floor.\n * Never uses scientific notation.\n */\nexport function formatUsd(usd: number): string {\n\tif (usd <= 0) {\n\t\treturn \"$0.00\";\n\t}\n\tif (usd >= 0.01) {\n\t\treturn `$${usd.toFixed(2)}`;\n\t}\n\tif (usd < TINY_FLOOR) {\n\t\treturn `< $${TINY_FLOOR}`;\n\t}\n\treturn `$${usd.toLocaleString(\"en-US\", {\n\t\tmaximumSignificantDigits: 2,\n\t\tuseGrouping: false,\n\t})}`;\n}\n"]}
|