@medialane/ui 0.257.0 → 0.259.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/account/add-guardian-dialog.cjs +1 -1
- package/dist/components/account/add-guardian-dialog.cjs.map +1 -1
- package/dist/components/account/add-guardian-dialog.js +1 -1
- package/dist/components/account/add-guardian-dialog.js.map +1 -1
- package/dist/components/account/device-approval-dialog.cjs +2 -2
- package/dist/components/account/device-approval-dialog.cjs.map +1 -1
- package/dist/components/account/device-approval-dialog.js +2 -2
- package/dist/components/account/device-approval-dialog.js.map +1 -1
- package/dist/components/account/devices-section.cjs +1 -1
- package/dist/components/account/devices-section.cjs.map +1 -1
- package/dist/components/account/devices-section.js +1 -1
- package/dist/components/account/devices-section.js.map +1 -1
- package/dist/components/account/guardian-recovery-section.cjs +1 -1
- package/dist/components/account/guardian-recovery-section.cjs.map +1 -1
- package/dist/components/account/guardian-recovery-section.js +1 -1
- package/dist/components/account/guardian-recovery-section.js.map +1 -1
- package/dist/components/comments-section.cjs +5 -4
- package/dist/components/comments-section.cjs.map +1 -1
- package/dist/components/comments-section.js +5 -4
- package/dist/components/comments-section.js.map +1 -1
- package/dist/components/drop/create/launch-dialog.cjs +1 -1
- package/dist/components/drop/create/launch-dialog.cjs.map +1 -1
- package/dist/components/drop/create/launch-dialog.js +1 -1
- package/dist/components/drop/create/launch-dialog.js.map +1 -1
- package/dist/components/drop/page/drop-manage.cjs +1 -1
- package/dist/components/drop/page/drop-manage.cjs.map +1 -1
- package/dist/components/drop/page/drop-manage.js +1 -1
- package/dist/components/drop/page/drop-manage.js.map +1 -1
- package/dist/components/drop/page/drop-mint-dialog.cjs +1 -1
- package/dist/components/drop/page/drop-mint-dialog.cjs.map +1 -1
- package/dist/components/drop/page/drop-mint-dialog.js +1 -1
- package/dist/components/drop/page/drop-mint-dialog.js.map +1 -1
- package/dist/components/empty-or-error.cjs +2 -2
- package/dist/components/empty-or-error.cjs.map +1 -1
- package/dist/components/empty-or-error.js +2 -2
- package/dist/components/empty-or-error.js.map +1 -1
- package/dist/components/fast-mint/fast-mint.cjs +2 -1
- package/dist/components/fast-mint/fast-mint.cjs.map +1 -1
- package/dist/components/fast-mint/fast-mint.js +2 -1
- package/dist/components/fast-mint/fast-mint.js.map +1 -1
- package/dist/components/launchpad/coin-create.cjs +9 -7
- package/dist/components/launchpad/coin-create.cjs.map +1 -1
- package/dist/components/launchpad/coin-create.js +9 -7
- package/dist/components/launchpad/coin-create.js.map +1 -1
- package/dist/components/launchpad/collection-create-form.cjs +11 -14
- package/dist/components/launchpad/collection-create-form.cjs.map +1 -1
- package/dist/components/launchpad/collection-create-form.js +12 -15
- package/dist/components/launchpad/collection-create-form.js.map +1 -1
- package/dist/components/launchpad/collection-create-presets.cjs +8 -8
- package/dist/components/launchpad/collection-create-presets.cjs.map +1 -1
- package/dist/components/launchpad/collection-create-presets.d.cts +2 -1
- package/dist/components/launchpad/collection-create-presets.d.ts +2 -1
- package/dist/components/launchpad/collection-create-presets.js +8 -8
- package/dist/components/launchpad/collection-create-presets.js.map +1 -1
- package/dist/components/launchpad/edition-mint.cjs +9 -7
- package/dist/components/launchpad/edition-mint.cjs.map +1 -1
- package/dist/components/launchpad/edition-mint.js +9 -7
- package/dist/components/launchpad/edition-mint.js.map +1 -1
- package/dist/components/launchpad/pop-create.cjs +5 -6
- package/dist/components/launchpad/pop-create.cjs.map +1 -1
- package/dist/components/launchpad/pop-create.js +5 -6
- package/dist/components/launchpad/pop-create.js.map +1 -1
- package/dist/components/launchpad/remix-mint.cjs +9 -7
- package/dist/components/launchpad/remix-mint.cjs.map +1 -1
- package/dist/components/launchpad/remix-mint.js +9 -7
- package/dist/components/launchpad/remix-mint.js.map +1 -1
- package/dist/components/launchpad/single-edition-mint.cjs +9 -7
- package/dist/components/launchpad/single-edition-mint.cjs.map +1 -1
- package/dist/components/launchpad/single-edition-mint.js +9 -7
- package/dist/components/launchpad/single-edition-mint.js.map +1 -1
- package/dist/components/launchpad/sponsorship-create.cjs +5 -6
- package/dist/components/launchpad/sponsorship-create.cjs.map +1 -1
- package/dist/components/launchpad/sponsorship-create.js +5 -6
- package/dist/components/launchpad/sponsorship-create.js.map +1 -1
- package/dist/components/launchpad/tier-mint-form.cjs +5 -6
- package/dist/components/launchpad/tier-mint-form.cjs.map +1 -1
- package/dist/components/launchpad/tier-mint-form.js +5 -6
- package/dist/components/launchpad/tier-mint-form.js.map +1 -1
- package/dist/components/launchpad/tier-mint-presets.cjs +2 -2
- package/dist/components/launchpad/tier-mint-presets.cjs.map +1 -1
- package/dist/components/launchpad/tier-mint-presets.d.cts +2 -1
- package/dist/components/launchpad/tier-mint-presets.d.ts +2 -1
- package/dist/components/launchpad/tier-mint-presets.js +2 -2
- package/dist/components/launchpad/tier-mint-presets.js.map +1 -1
- package/dist/components/license-request-page.cjs +1 -1
- package/dist/components/license-request-page.cjs.map +1 -1
- package/dist/components/license-request-page.js +1 -1
- package/dist/components/license-request-page.js.map +1 -1
- package/dist/components/marketplace-dialog-primitives.cjs +0 -30
- package/dist/components/marketplace-dialog-primitives.cjs.map +1 -1
- package/dist/components/marketplace-dialog-primitives.d.cts +1 -12
- package/dist/components/marketplace-dialog-primitives.d.ts +1 -12
- package/dist/components/marketplace-dialog-primitives.js +1 -30
- package/dist/components/marketplace-dialog-primitives.js.map +1 -1
- package/dist/components/media-wallet/activate-card.cjs +1 -1
- package/dist/components/media-wallet/activate-card.cjs.map +1 -1
- package/dist/components/media-wallet/activate-card.js +1 -1
- package/dist/components/media-wallet/activate-card.js.map +1 -1
- package/dist/components/media-wallet/media-wallet-activity.cjs +1 -1
- package/dist/components/media-wallet/media-wallet-activity.cjs.map +1 -1
- package/dist/components/media-wallet/media-wallet-activity.js +1 -1
- package/dist/components/media-wallet/media-wallet-activity.js.map +1 -1
- package/dist/components/media-wallet/media-wallet-send.cjs +2 -6
- package/dist/components/media-wallet/media-wallet-send.cjs.map +1 -1
- package/dist/components/media-wallet/media-wallet-send.js +2 -6
- package/dist/components/media-wallet/media-wallet-send.js.map +1 -1
- package/dist/components/pop-claim-button.cjs +5 -4
- package/dist/components/pop-claim-button.cjs.map +1 -1
- package/dist/components/pop-claim-button.js +5 -4
- package/dist/components/pop-claim-button.js.map +1 -1
- package/dist/components/pop-manage-page.cjs +2 -2
- package/dist/components/pop-manage-page.cjs.map +1 -1
- package/dist/components/pop-manage-page.js +2 -2
- package/dist/components/pop-manage-page.js.map +1 -1
- package/dist/components/portfolio-sponsorships.cjs +2 -2
- package/dist/components/portfolio-sponsorships.cjs.map +1 -1
- package/dist/components/portfolio-sponsorships.js +2 -2
- package/dist/components/portfolio-sponsorships.js.map +1 -1
- package/dist/components/sponsorship-offer-page.cjs +5 -4
- package/dist/components/sponsorship-offer-page.cjs.map +1 -1
- package/dist/components/sponsorship-offer-page.js +5 -4
- package/dist/components/sponsorship-offer-page.js.map +1 -1
- package/dist/components/transaction-dialog.cjs +4 -4
- package/dist/components/transaction-dialog.cjs.map +1 -1
- package/dist/components/transaction-dialog.d.cts +3 -1
- package/dist/components/transaction-dialog.d.ts +3 -1
- package/dist/components/transaction-dialog.js +4 -4
- package/dist/components/transaction-dialog.js.map +1 -1
- package/dist/components/{creation-success.cjs → transaction-success.cjs} +14 -15
- package/dist/components/transaction-success.cjs.map +1 -0
- package/dist/components/transaction-success.d.cts +20 -0
- package/dist/components/transaction-success.d.ts +20 -0
- package/dist/components/{creation-success.js → transaction-success.js} +10 -11
- package/dist/components/transaction-success.js.map +1 -0
- package/dist/components/transfer-collection-ownership.cjs +5 -4
- package/dist/components/transfer-collection-ownership.cjs.map +1 -1
- package/dist/components/transfer-collection-ownership.js +5 -4
- package/dist/components/transfer-collection-ownership.js.map +1 -1
- package/dist/components/wallet/export-key-section.cjs +3 -3
- package/dist/components/wallet/export-key-section.cjs.map +1 -1
- package/dist/components/wallet/export-key-section.d.cts +1 -2
- package/dist/components/wallet/export-key-section.d.ts +1 -2
- package/dist/components/wallet/export-key-section.js +3 -3
- package/dist/components/wallet/export-key-section.js.map +1 -1
- package/dist/index.cjs +6 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -8
- package/dist/index.js.map +1 -1
- package/dist/utils/describe-error.cjs +16 -11
- package/dist/utils/describe-error.cjs.map +1 -1
- package/dist/utils/describe-error.d.cts +4 -4
- package/dist/utils/describe-error.d.ts +4 -4
- package/dist/utils/describe-error.js +16 -10
- package/dist/utils/describe-error.js.map +1 -1
- package/dist/utils/media-wallet/use-erc20-balance.d.cts +1 -1
- package/dist/utils/media-wallet/use-erc20-balance.d.ts +1 -1
- package/dist/utils/success-messages.cjs +54 -0
- package/dist/utils/success-messages.cjs.map +1 -0
- package/dist/utils/success-messages.d.cts +31 -0
- package/dist/utils/success-messages.d.ts +31 -0
- package/dist/utils/success-messages.js +30 -0
- package/dist/utils/success-messages.js.map +1 -0
- package/dist/utils/use-email-code.cjs +2 -2
- package/dist/utils/use-email-code.cjs.map +1 -1
- package/dist/utils/use-email-code.js +2 -2
- package/dist/utils/use-email-code.js.map +1 -1
- package/dist/utils/use-transaction.cjs +16 -2
- package/dist/utils/use-transaction.cjs.map +1 -1
- package/dist/utils/use-transaction.d.cts +1 -0
- package/dist/utils/use-transaction.d.ts +1 -0
- package/dist/utils/use-transaction.js +17 -3
- package/dist/utils/use-transaction.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/creation-success.cjs.map +0 -1
- package/dist/components/creation-success.d.cts +0 -20
- package/dist/components/creation-success.d.ts +0 -20
- package/dist/components/creation-success.js.map +0 -1
- package/dist/components/transaction-done.cjs +0 -46
- package/dist/components/transaction-done.cjs.map +0 -1
- package/dist/components/transaction-done.d.cts +0 -18
- package/dist/components/transaction-done.d.ts +0 -18
- package/dist/components/transaction-done.js +0 -22
- package/dist/components/transaction-done.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/comments-section.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { ExternalLink, Flag, Loader2, MessageCircle, Send, Zap } from \"lucide-react\";\nimport { normalizeAddress, profileHref, STARKNET_NFTCOMMENTS_CONTRACT } from \"@medialane/sdk\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { useMedialaneApp, type ReportTarget } from \"./medialane-app.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionDone } from \"./transaction-done.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { useComments } from \"../utils/use-comments.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nconst MAX_LEN = 1000;\n\nexport interface CommentsSectionProps {\n contract: string;\n tokenId: string;\n className?: string;\n}\n\nexport function CommentsSection({ contract, tokenId, className }: CommentsSectionProps) {\n const app = useMedialaneApp();\n const walletAddress = app.walletAddress;\n const hasWallet = !!walletAddress;\n const { ReportDialog } = app;\n const { comments, isLoading, mutate } = useComments(contract, tokenId);\n const tx = useTransaction();\n\n const [text, setText] = useState(\"\");\n const [reportTarget, setReportTarget] = useState<ReportTarget | null>(null);\n\n const messagesRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const composeRef = useRef<HTMLTextAreaElement>(null);\n\n const byteLen = new TextEncoder().encode(text).length;\n const canSubmit = text.trim().length > 0 && byteLen <= MAX_LEN && !!STARKNET_NFTCOMMENTS_CONTRACT;\n const isProcessing = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n const isOwn = (author: string) =>\n !!walletAddress && normalizeAddress(\"STARKNET\", author) === normalizeAddress(\"STARKNET\", walletAddress);\n\n const isNearBottom = () => {\n const el = messagesRef.current;\n if (!el) return true;\n return el.scrollHeight - el.scrollTop - el.clientHeight < 100;\n };\n\n useEffect(() => {\n if (isNearBottom()) {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }\n\n }, [comments.length]);\n\n const handleTextInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n e.target.style.height = \"auto\";\n e.target.style.height = Math.min(e.target.scrollHeight, 96) + \"px\";\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey && canSubmit && !isProcessing) {\n e.preventDefault();\n post();\n }\n };\n\n const post = () => {\n const body = text.trim();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().api.intents.create(\"comment\", { author: signer.address, nftContract: contract, tokenId, text: body }),\n );\n })\n .then((ok) => {\n if (!ok) return;\n setText(\"\");\n if (composeRef.current) composeRef.current.style.height = \"auto\";\n void mutate();\n });\n };\n\n const handleStartConversation = () => {\n if (hasWallet) composeRef.current?.focus();\n };\n\n return (\n <div className={cn(\"flex flex-col h-[480px] overflow-hidden\", className)}>\n\n <div ref={messagesRef} className=\"flex-1 overflow-y-auto px-4 py-4\">\n {isLoading ? (\n <div className=\"space-y-4\">\n {([\n { own: false, w: \"w-40\" },\n { own: true, w: \"w-56\" },\n { own: false, w: \"w-48\" },\n { own: true, w: \"w-32\" },\n ] as const).map((item, i) => (\n <div key={i} className={`flex ${item.own ? \"justify-end\" : \"justify-start\"} gap-2`}>\n {!item.own && <Skeleton className=\"h-8 w-8 rounded-full shrink-0\" />}\n <Skeleton\n className={`h-10 ${item.w} rounded-2xl ${item.own ? \"rounded-tr-sm\" : \"rounded-tl-sm\"}`}\n />\n </div>\n ))}\n </div>\n ) : comments.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-4 text-center px-4\">\n <div className=\"flex h-16 w-16 items-center justify-center rounded-full\" style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue) / 0.15), hsl(var(--brand-purple) / 0.15))\" }}>\n <MessageCircle className=\"h-7 w-7\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n </div>\n <div>\n <p className=\"text-sm font-semibold\">Nothing here yet</p>\n <p className=\"text-xs text-muted-foreground mt-1 leading-relaxed max-w-[220px]\">\n Your comment will be minted onchain — attached to this NFT forever.\n </p>\n </div>\n <Button\n size=\"sm\"\n onClick={handleStartConversation}\n className=\"rounded-full text-white px-5\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n Write the first comment\n </Button>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {comments.map((comment) => {\n const own = isOwn(comment.author);\n const avatarSeed = parseInt(comment.author.slice(2, 8), 16) % 360;\n const avatarBg = own\n ? \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\"\n : `linear-gradient(135deg, hsl(${avatarSeed}, 65%, 45%), hsl(${(avatarSeed + 60) % 360}, 65%, 55%))`;\n\n return (\n <div\n key={comment.id}\n className={`group flex gap-2.5 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}\n >\n\n <Link href={profileHref({ address: comment.author })} className=\"shrink-0 mt-0.5\">\n <div\n className=\"h-9 w-9 rounded-full flex items-center justify-center text-2xs font-bold text-white select-none ring-2 ring-background hover:ring-primary/40 transition-all\"\n style={{ background: avatarBg }}\n >\n {comment.author.slice(2, 5).toUpperCase()}\n </div>\n </Link>\n\n <div className={`flex flex-col max-w-[75%] gap-1 ${own ? \"items-end\" : \"items-start\"}`}>\n\n <div className={`flex items-center gap-2 px-1 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}>\n <Link\n href={profileHref({ address: comment.author })}\n className=\"text-xs font-semibold text-foreground hover:underline underline-offset-2\"\n >\n {own ? \"You\" : <AddressDisplay address={comment.author} chars={5} showCopy={false} />}\n </Link>\n <span className=\"text-2xs text-muted-foreground\" title={comment.postedAt}>\n {timeAgo(comment.postedAt)}\n </span>\n </div>\n\n <div className=\"relative\">\n {own ? (\n <div\n className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words rounded-2xl rounded-tr-sm text-white\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {comment.content}\n </div>\n ) : (\n <div className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words bg-muted rounded-2xl rounded-tl-sm border border-border/50\">\n {comment.content}\n </div>\n )}\n {!own && hasWallet && (\n <button\n className=\"absolute -top-1 -right-5 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground/40 hover:text-destructive/70\"\n title=\"Report comment\"\n aria-label=\"Report comment\"\n onClick={() => setReportTarget({ type: \"COMMENT\", commentId: comment.id })}\n >\n <Flag className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n\n {comment.txHash && (\n <a\n href={`${EXPLORER_URL}/tx/${comment.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 px-1 text-2xs font-medium transition-colors\"\n style={{ color: \"hsl(var(--brand-blue) / 0.55)\" }}\n onMouseEnter={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue))\")}\n onMouseLeave={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue) / 0.55)\")}\n >\n <span>⛓</span>\n <span>onchain proof</span>\n <ExternalLink className=\"h-2.5 w-2.5\" />\n </a>\n )}\n </div>\n </div>\n );\n })}\n <div ref={bottomRef} />\n </div>\n )}\n </div>\n\n <div className=\"border-t border-border/60 shrink-0\">\n {!hasWallet ? (\n <div className=\"flex items-center justify-center px-4 h-16\">\n <button type=\"button\" onClick={app.onRequireWallet} className=\"text-sm text-primary hover:underline\">\n {app.connectLabel ?? \"Connect\"} to comment\n </button>\n </div>\n ) : (\n <div className=\"px-3 pt-2 pb-3 space-y-2\">\n\n <div className=\"flex items-center gap-1.5\">\n <Zap className=\"h-3 w-3\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n <span className=\"text-2xs font-semibold\" style={{ color: \"hsl(var(--brand-blue))\" }}>\n Mint your message onchain\n </span>\n </div>\n\n <div\n className=\"rounded-xl border bg-background/60 transition-all focus-within:ring-2\"\n style={{\n borderColor: \"hsl(var(--border))\",\n }}\n onFocusCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--brand-blue) / 0.6)\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"0 0 0 3px hsl(var(--brand-blue) / 0.12)\";\n }}\n onBlurCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--border))\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"\";\n }}\n >\n <Textarea\n ref={composeRef}\n placeholder=\"Say something onchain… it's permanent.\"\n value={text}\n onChange={handleTextInput}\n onKeyDown={handleKeyDown}\n rows={2}\n className=\"resize-none min-h-[52px] max-h-[120px] w-full border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-3 pt-2.5 pb-1 text-sm rounded-xl\"\n disabled={isProcessing}\n />\n <div className=\"flex items-center justify-between px-3 pb-2.5\">\n <span className=\"text-2xs text-muted-foreground/40 flex items-center gap-1\">\n Enter ↵ to post\n </span>\n <div className=\"flex items-center gap-2\">\n {byteLen > 800 && (\n <span className={`text-2xs ${byteLen > MAX_LEN ? \"text-destructive\" : \"text-muted-foreground\"}`}>\n {byteLen}/{MAX_LEN}\n </span>\n )}\n <button\n onClick={post}\n disabled={!canSubmit || isProcessing}\n className=\"flex items-center gap-1.5 h-7 px-3 text-xs font-semibold rounded-full text-white transition-all hover:opacity-90 active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {isProcessing ? <Loader2 className=\"h-3 w-3 animate-spin\" /> : <Send className=\"h-3 w-3\" />}\n Post onchain\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {reportTarget && ReportDialog && (\n <ReportDialog\n target={reportTarget}\n open={!!reportTarget}\n onOpenChange={(open) => { if (!open) setReportTarget(null); }}\n />\n )}\n\n <TransactionDialog tx={tx} title=\"Comment\" workingLabel=\"Posting your comment…\" firstStepLabel=\"Prepare comment\">\n <TransactionDone\n tx={tx}\n name=\"Comment\"\n title=\"Comment posted!\"\n description=\"Your comment is onchain and will appear here once indexed (~30s).\"\n footer={<RewardEarned actionType=\"comment\" />}\n />\n </TransactionDialog>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/comments-section.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { ExternalLink, Flag, Loader2, MessageCircle, Send, Zap } from \"lucide-react\";\nimport { normalizeAddress, profileHref, STARKNET_NFTCOMMENTS_CONTRACT } from \"@medialane/sdk\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { useMedialaneApp, type ReportTarget } from \"./medialane-app.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { useComments } from \"../utils/use-comments.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nconst MAX_LEN = 1000;\n\nexport interface CommentsSectionProps {\n contract: string;\n tokenId: string;\n className?: string;\n}\n\nexport function CommentsSection({ contract, tokenId, className }: CommentsSectionProps) {\n const app = useMedialaneApp();\n const walletAddress = app.walletAddress;\n const hasWallet = !!walletAddress;\n const { ReportDialog } = app;\n const { comments, isLoading, mutate } = useComments(contract, tokenId);\n const tx = useTransaction();\n\n const [text, setText] = useState(\"\");\n const [reportTarget, setReportTarget] = useState<ReportTarget | null>(null);\n\n const messagesRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const composeRef = useRef<HTMLTextAreaElement>(null);\n\n const byteLen = new TextEncoder().encode(text).length;\n const canSubmit = text.trim().length > 0 && byteLen <= MAX_LEN && !!STARKNET_NFTCOMMENTS_CONTRACT;\n const isProcessing = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n const isOwn = (author: string) =>\n !!walletAddress && normalizeAddress(\"STARKNET\", author) === normalizeAddress(\"STARKNET\", walletAddress);\n\n const isNearBottom = () => {\n const el = messagesRef.current;\n if (!el) return true;\n return el.scrollHeight - el.scrollTop - el.clientHeight < 100;\n };\n\n useEffect(() => {\n if (isNearBottom()) {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }\n\n }, [comments.length]);\n\n const handleTextInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n e.target.style.height = \"auto\";\n e.target.style.height = Math.min(e.target.scrollHeight, 96) + \"px\";\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey && canSubmit && !isProcessing) {\n e.preventDefault();\n post();\n }\n };\n\n const post = () => {\n const body = text.trim();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().api.intents.create(\"comment\", { author: signer.address, nftContract: contract, tokenId, text: body }),\n );\n })\n .then((ok) => {\n if (!ok) return;\n setText(\"\");\n if (composeRef.current) composeRef.current.style.height = \"auto\";\n void mutate();\n });\n };\n\n const handleStartConversation = () => {\n if (hasWallet) composeRef.current?.focus();\n };\n\n return (\n <div className={cn(\"flex flex-col h-[480px] overflow-hidden\", className)}>\n\n <div ref={messagesRef} className=\"flex-1 overflow-y-auto px-4 py-4\">\n {isLoading ? (\n <div className=\"space-y-4\">\n {([\n { own: false, w: \"w-40\" },\n { own: true, w: \"w-56\" },\n { own: false, w: \"w-48\" },\n { own: true, w: \"w-32\" },\n ] as const).map((item, i) => (\n <div key={i} className={`flex ${item.own ? \"justify-end\" : \"justify-start\"} gap-2`}>\n {!item.own && <Skeleton className=\"h-8 w-8 rounded-full shrink-0\" />}\n <Skeleton\n className={`h-10 ${item.w} rounded-2xl ${item.own ? \"rounded-tr-sm\" : \"rounded-tl-sm\"}`}\n />\n </div>\n ))}\n </div>\n ) : comments.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-4 text-center px-4\">\n <div className=\"flex h-16 w-16 items-center justify-center rounded-full\" style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue) / 0.15), hsl(var(--brand-purple) / 0.15))\" }}>\n <MessageCircle className=\"h-7 w-7\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n </div>\n <div>\n <p className=\"text-sm font-semibold\">Nothing here yet</p>\n <p className=\"text-xs text-muted-foreground mt-1 leading-relaxed max-w-[220px]\">\n Your comment will be minted onchain — attached to this NFT forever.\n </p>\n </div>\n <Button\n size=\"sm\"\n onClick={handleStartConversation}\n className=\"rounded-full text-white px-5\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n Write the first comment\n </Button>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {comments.map((comment) => {\n const own = isOwn(comment.author);\n const avatarSeed = parseInt(comment.author.slice(2, 8), 16) % 360;\n const avatarBg = own\n ? \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\"\n : `linear-gradient(135deg, hsl(${avatarSeed}, 65%, 45%), hsl(${(avatarSeed + 60) % 360}, 65%, 55%))`;\n\n return (\n <div\n key={comment.id}\n className={`group flex gap-2.5 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}\n >\n\n <Link href={profileHref({ address: comment.author })} className=\"shrink-0 mt-0.5\">\n <div\n className=\"h-9 w-9 rounded-full flex items-center justify-center text-2xs font-bold text-white select-none ring-2 ring-background hover:ring-primary/40 transition-all\"\n style={{ background: avatarBg }}\n >\n {comment.author.slice(2, 5).toUpperCase()}\n </div>\n </Link>\n\n <div className={`flex flex-col max-w-[75%] gap-1 ${own ? \"items-end\" : \"items-start\"}`}>\n\n <div className={`flex items-center gap-2 px-1 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}>\n <Link\n href={profileHref({ address: comment.author })}\n className=\"text-xs font-semibold text-foreground hover:underline underline-offset-2\"\n >\n {own ? \"You\" : <AddressDisplay address={comment.author} chars={5} showCopy={false} />}\n </Link>\n <span className=\"text-2xs text-muted-foreground\" title={comment.postedAt}>\n {timeAgo(comment.postedAt)}\n </span>\n </div>\n\n <div className=\"relative\">\n {own ? (\n <div\n className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words rounded-2xl rounded-tr-sm text-white\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {comment.content}\n </div>\n ) : (\n <div className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words bg-muted rounded-2xl rounded-tl-sm border border-border/50\">\n {comment.content}\n </div>\n )}\n {!own && hasWallet && (\n <button\n className=\"absolute -top-1 -right-5 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground/40 hover:text-destructive/70\"\n title=\"Report comment\"\n aria-label=\"Report comment\"\n onClick={() => setReportTarget({ type: \"COMMENT\", commentId: comment.id })}\n >\n <Flag className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n\n {comment.txHash && (\n <a\n href={`${EXPLORER_URL}/tx/${comment.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 px-1 text-2xs font-medium transition-colors\"\n style={{ color: \"hsl(var(--brand-blue) / 0.55)\" }}\n onMouseEnter={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue))\")}\n onMouseLeave={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue) / 0.55)\")}\n >\n <span>⛓</span>\n <span>onchain proof</span>\n <ExternalLink className=\"h-2.5 w-2.5\" />\n </a>\n )}\n </div>\n </div>\n );\n })}\n <div ref={bottomRef} />\n </div>\n )}\n </div>\n\n <div className=\"border-t border-border/60 shrink-0\">\n {!hasWallet ? (\n <div className=\"flex items-center justify-center px-4 h-16\">\n <button type=\"button\" onClick={app.onRequireWallet} className=\"text-sm text-primary hover:underline\">\n {app.connectLabel ?? \"Connect\"} to comment\n </button>\n </div>\n ) : (\n <div className=\"px-3 pt-2 pb-3 space-y-2\">\n\n <div className=\"flex items-center gap-1.5\">\n <Zap className=\"h-3 w-3\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n <span className=\"text-2xs font-semibold\" style={{ color: \"hsl(var(--brand-blue))\" }}>\n Mint your message onchain\n </span>\n </div>\n\n <div\n className=\"rounded-xl border bg-background/60 transition-all focus-within:ring-2\"\n style={{\n borderColor: \"hsl(var(--border))\",\n }}\n onFocusCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--brand-blue) / 0.6)\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"0 0 0 3px hsl(var(--brand-blue) / 0.12)\";\n }}\n onBlurCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--border))\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"\";\n }}\n >\n <Textarea\n ref={composeRef}\n placeholder=\"Say something onchain… it's permanent.\"\n value={text}\n onChange={handleTextInput}\n onKeyDown={handleKeyDown}\n rows={2}\n className=\"resize-none min-h-[52px] max-h-[120px] w-full border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-3 pt-2.5 pb-1 text-sm rounded-xl\"\n disabled={isProcessing}\n />\n <div className=\"flex items-center justify-between px-3 pb-2.5\">\n <span className=\"text-2xs text-muted-foreground/40 flex items-center gap-1\">\n Enter ↵ to post\n </span>\n <div className=\"flex items-center gap-2\">\n {byteLen > 800 && (\n <span className={`text-2xs ${byteLen > MAX_LEN ? \"text-destructive\" : \"text-muted-foreground\"}`}>\n {byteLen}/{MAX_LEN}\n </span>\n )}\n <button\n onClick={post}\n disabled={!canSubmit || isProcessing}\n className=\"flex items-center gap-1.5 h-7 px-3 text-xs font-semibold rounded-full text-white transition-all hover:opacity-90 active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {isProcessing ? <Loader2 className=\"h-3 w-3 animate-spin\" /> : <Send className=\"h-3 w-3\" />}\n Post onchain\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {reportTarget && ReportDialog && (\n <ReportDialog\n target={reportTarget}\n open={!!reportTarget}\n onOpenChange={(open) => { if (!open) setReportTarget(null); }}\n />\n )}\n\n <TransactionDialog tx={tx} title=\"Comment\" workingLabel=\"Posting your comment…\" firstStepLabel=\"Prepare comment\">\n <TransactionSuccess\n name=\"Comment\"\n title=\"Comment posted!\"\n description=\"Your comment is onchain and will appear here once indexed (~30s).\"\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"comment\" />\n </TransactionSuccess>\n </TransactionDialog>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -108,7 +108,7 @@ function LaunchDialog({ open, onClose, draft }) {
|
|
|
108
108
|
}
|
|
109
109
|
setStep({ kind: "done", collection, links: list ? (0, import_starknet.dropClaimLinks)(window.location.origin, collection, list) : [], warning });
|
|
110
110
|
} catch (err) {
|
|
111
|
-
setStep({ kind: "error", message: (0, import_describe_error.describeError)(err
|
|
111
|
+
setStep({ kind: "error", message: (0, import_describe_error.describeError)(err).message });
|
|
112
112
|
}
|
|
113
113
|
};
|
|
114
114
|
const close = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/drop/create/launch-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { CheckCircle2, Loader2, RotateCcw, XCircle } from \"lucide-react\";\nimport { dropHref } from \"@medialane/sdk\";\nimport { buildPopAllowlist, dropClaimLinks, popClaimLinksCsv, type PopClaimLink } from \"@medialane/sdk/starknet\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { GradientButton } from \"../../gradient-button.js\";\nimport { Button } from \"../../button.js\";\nimport { ShareButton } from \"../../share-button.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\nimport { uploadDirectoryToIpfs, uploadFileToIpfs } from \"../../../utils/ipfs-upload.js\";\nimport { parseAllowlist } from \"../../../utils/drop/allowlist.js\";\nimport { buildDropMetadataFiles, metadataBytes, MAX_DROP_METADATA_BYTES } from \"../../../utils/drop/metadata.js\";\nimport { toDropTerms, priceLabel } from \"../../../utils/drop/sale.js\";\nimport { draftSupply, type DropDraft } from \"../../../utils/drop/draft.js\";\nimport { uploadAll, type UploadTask } from \"../../../utils/drop/upload.js\";\nimport { launchDrop, saveExclusiveContent } from \"../../../utils/drop/actions.js\";\nimport { useMedialaneApp } from \"../../medialane-app.js\";\n\ntype Step =\n | { kind: \"review\" }\n | { kind: \"uploading\" }\n | { kind: \"launching\" }\n | { kind: \"done\"; collection: string; links: PopClaimLink[]; warning: string | null }\n | { kind: \"error\"; message: string };\n\nexport function LaunchDialog({ open, onClose, draft }: { open: boolean; onClose: () => void; draft: DropDraft }) {\n const app = useMedialaneApp();\n const [step, setStep] = useState<Step>({ kind: \"review\" });\n const [tasks, setTasks] = useState<UploadTask[]>([]);\n const [baseUri, setBaseUri] = useState<string | null>(null);\n const client = app.getClient();\n const files = draft.kind === \"edition\" ? (draft.edition ? [draft.edition] : []) : draft.items.map((i) => i.file);\n const terms = toDropTerms(draft.sale);\n const list = useMemo(\n () => (draft.listOnly ? buildPopAllowlist(parseAllowlist(draft.allowlist).addresses) : null),\n [draft.listOnly, draft.allowlist],\n );\n\n const run = async () => {\n try {\n let uri = baseUri;\n if (!uri) {\n setStep({ kind: \"uploading\" });\n const initial = tasks.length > 0 ? tasks : [\n ...files.map((file, i) => ({ id: `art-${i}`, file, status: \"pending\" as const, uri: null, error: null })),\n ...(draft.cover ? [{ id: \"cover\", file: draft.cover, status: \"pending\" as const, uri: null, error: null }] : []),\n ];\n const done = await uploadAll(initial, async (f) => (await uploadFileToIpfs(client.api, f, \"image\")).uri, setTasks);\n setTasks(done);\n if (done.some((t) => t.status !== \"done\")) {\n setStep({ kind: \"error\", message: \"Some files didn't upload. Retry to send only those.\" });\n return;\n }\n const art = done.filter((t) => t.id.startsWith(\"art-\"));\n const metadata = buildDropMetadataFiles({\n kind: draft.kind,\n name: draft.name.trim(),\n description: draft.description.trim(),\n creator: app.walletAddress!,\n coverUri: done.find((t) => t.id === \"cover\")?.uri ?? null,\n license: draft.license,\n items: draft.kind === \"edition\"\n ? [{ name: \"\", description: \"\", imageUri: art[0]!.uri! }]\n : draft.items.map((it, i) => ({ name: it.name, description: it.description, imageUri: art[i]!.uri! })),\n supply: draftSupply(draft),\n });\n if (metadataBytes(metadata) > MAX_DROP_METADATA_BYTES) {\n setStep({ kind: \"error\", message: \"The descriptions are too long for this many tokens. Shorten them and try again.\" });\n return;\n }\n uri = (await uploadDirectoryToIpfs(client.api, metadata)).baseUri;\n setBaseUri(uri);\n }\n setStep({ kind: \"launching\" });\n const signer = await app.getSigner();\n const { collection } = await launchDrop({ client, signer }, {\n owner: app.walletAddress!,\n name: draft.name.trim(),\n symbol: draft.symbol,\n baseUri: uri!,\n maxSupply: draftSupply(draft),\n terms,\n allowlistRoot: list?.root,\n description: draft.description.trim() || undefined,\n });\n let warning: string | null = null;\n if (draft.gated.enabled) {\n try {\n await saveExclusiveContent(client, collection, draft.gated);\n } catch {\n warning = \"Your drop launched, but the exclusive content wasn't saved. You can add it from Manage.\";\n }\n }\n setStep({ kind: \"done\", collection, links: list ? dropClaimLinks(window.location.origin, collection, list) : [], warning });\n } catch (err) {\n setStep({ kind: \"error\", message: describeError(err, \"We couldn't launch your drop. Please try again.\").message });\n }\n };\n\n const close = () => {\n if (step.kind === \"uploading\" || step.kind === \"launching\") return;\n onClose();\n };\n\n return (\n <ActionDialog open={open} onClose={close}>\n <div className=\"space-y-5 p-6\">\n {step.kind === \"review\" && (\n <>\n <h2 className=\"text-lg font-semibold\">Review and launch</h2>\n <div className=\"space-y-2 rounded-xl border border-border p-4 text-sm\">\n <p className=\"font-semibold\">{draft.name}</p>\n <p className=\"text-xs font-semibold uppercase tracking-widest text-muted-foreground\">Fixed after launch</p>\n <Row label=\"Price\" value={priceLabel(terms.price, terms.paymentToken)} />\n <Row label=\"Supply\" value={`${draftSupply(draft).toLocaleString(\"en-US\")} ${draft.kind === \"edition\" ? (draftSupply(draft) === 1 ? \"copy\" : \"copies\") : draftSupply(draft) === 1 ? \"item\" : \"items\"}`} />\n <Row label=\"Starts\" value={terms.startTime === 0 ? \"At launch\" : new Date(terms.startTime * 1000).toLocaleString()} />\n <Row label=\"Ends\" value={terms.endTime === 0 ? \"No end date\" : new Date(terms.endTime * 1000).toLocaleString()} />\n <Row label=\"Per wallet\" value={terms.maxPerWallet === \"0\" ? \"No limit\" : terms.maxPerWallet} />\n <Row label=\"Who can mint\" value={list ? `${Object.keys(list.proofs).length} wallets on a list` : \"Everyone\"} />\n <p className=\"pt-1 text-xs text-muted-foreground\">The artwork and these terms can't be changed after launch. You can change the list later.</p>\n </div>\n <GradientButton big onClick={() => void run()}>Launch drop</GradientButton>\n </>\n )}\n {step.kind === \"uploading\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Uploading</h2>\n <p className=\"text-sm text-muted-foreground\">{tasks.filter((t) => t.status === \"done\").length} of {tasks.length} files</p>\n </>\n )}\n {step.kind === \"launching\" && (\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Launching your drop…</h2>\n )}\n {step.kind === \"error\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><XCircle className=\"h-4 w-4 text-destructive\" />Not launched</h2>\n <p className=\"text-sm text-muted-foreground\">{step.message}</p>\n {tasks.some((t) => t.status === \"failed\") && (\n <ul className=\"space-y-1 text-xs text-muted-foreground\">\n {tasks.filter((t) => t.status === \"failed\").map((t) => <li key={t.id}>{t.file.name}: {t.error}</li>)}\n </ul>\n )}\n <Button onClick={() => void run()} className=\"gap-1.5\"><RotateCcw className=\"h-3.5 w-3.5\" />Try again</Button>\n </>\n )}\n {step.kind === \"done\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><CheckCircle2 className=\"h-5 w-5 text-green-500\" />Your drop is live</h2>\n {step.warning && <p className=\"text-sm text-brand-orange\">{step.warning}</p>}\n <div className=\"flex flex-wrap gap-2\">\n <ShareButton title={draft.name} url={`${window.location.origin}${dropHref(step.collection)}`} variant=\"outline\" />\n <Button asChild variant=\"outline\"><a href={dropHref(step.collection)}>View drop</a></Button>\n {step.links.length > 0 && (\n <Button variant=\"outline\" onClick={() => downloadCsv(popClaimLinksCsv(step.links), \"claim-links.csv\")}>Download claim links</Button>\n )}\n </div>\n {step.links.length > 0 && <p className=\"text-xs text-muted-foreground\">Send each wallet its link — the link is what lets it mint.</p>}\n </>\n )}\n </div>\n </ActionDialog>\n );\n}\n\nfunction Row({ label, value }: { label: string; value: string }) {\n return <div className=\"flex justify-between gap-3\"><span className=\"text-muted-foreground\">{label}</span><span className=\"text-right font-medium\">{value}</span></div>;\n}\n\nexport function downloadCsv(csv: string, name: string) {\n const href = URL.createObjectURL(new Blob([csv], { type: \"text/csv\" }));\n Object.assign(document.createElement(\"a\"), { href, download: name }).click();\n URL.revokeObjectURL(href);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8GU;AA5GV,mBAAkC;AAClC,0BAA0D;AAC1D,iBAAyB;AACzB,sBAAuF;AACvF,2BAA6B;AAC7B,6BAA+B;AAC/B,oBAAuB;AACvB,0BAA4B;AAC5B,4BAA8B;AAC9B,yBAAwD;AACxD,uBAA+B;AAC/B,sBAA+E;AAC/E,kBAAwC;AACxC,mBAA4C;AAC5C,oBAA2C;AAC3C,qBAAiD;AACjD,2BAAgC;AASzB,SAAS,aAAa,EAAE,MAAM,SAAS,MAAM,GAA6D;AAC/G,QAAM,UAAM,sCAAgB;AAC5B,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAe,EAAE,MAAM,SAAS,CAAC;AACzD,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAuB,CAAC,CAAC;AACnD,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAwB,IAAI;AAC1D,QAAM,SAAS,IAAI,UAAU;AAC7B,QAAM,QAAQ,MAAM,SAAS,YAAa,MAAM,UAAU,CAAC,MAAM,OAAO,IAAI,CAAC,IAAK,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAC/G,QAAM,YAAQ,yBAAY,MAAM,IAAI;AACpC,QAAM,WAAO;AAAA,IACX,MAAO,MAAM,eAAW,uCAAkB,iCAAe,MAAM,SAAS,EAAE,SAAS,IAAI;AAAA,IACvF,CAAC,MAAM,UAAU,MAAM,SAAS;AAAA,EAClC;AAEA,QAAM,MAAM,YAAY;AACtB,QAAI;AACF,UAAI,MAAM;AACV,UAAI,CAAC,KAAK;AACR,gBAAQ,EAAE,MAAM,YAAY,CAAC;AAC7B,cAAM,UAAU,MAAM,SAAS,IAAI,QAAQ;AAAA,UACzC,GAAG,MAAM,IAAI,CAAC,MAAM,OAAO,EAAE,IAAI,OAAO,CAAC,IAAI,MAAM,QAAQ,WAAoB,KAAK,MAAM,OAAO,KAAK,EAAE;AAAA,UACxG,GAAI,MAAM,QAAQ,CAAC,EAAE,IAAI,SAAS,MAAM,MAAM,OAAO,QAAQ,WAAoB,KAAK,MAAM,OAAO,KAAK,CAAC,IAAI,CAAC;AAAA,QAChH;AACA,cAAM,OAAO,UAAM,yBAAU,SAAS,OAAO,OAAO,UAAM,qCAAiB,OAAO,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ;AACjH,iBAAS,IAAI;AACb,YAAI,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,GAAG;AACzC,kBAAQ,EAAE,MAAM,SAAS,SAAS,sDAAsD,CAAC;AACzF;AAAA,QACF;AACA,cAAM,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,GAAG,WAAW,MAAM,CAAC;AACtD,cAAM,eAAW,wCAAuB;AAAA,UACtC,MAAM,MAAM;AAAA,UACZ,MAAM,MAAM,KAAK,KAAK;AAAA,UACtB,aAAa,MAAM,YAAY,KAAK;AAAA,UACpC,SAAS,IAAI;AAAA,UACb,UAAU,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,GAAG,OAAO;AAAA,UACrD,SAAS,MAAM;AAAA,UACf,OAAO,MAAM,SAAS,YAClB,CAAC,EAAE,MAAM,IAAI,aAAa,IAAI,UAAU,IAAI,CAAC,EAAG,IAAK,CAAC,IACtD,MAAM,MAAM,IAAI,CAAC,IAAI,OAAO,EAAE,MAAM,GAAG,MAAM,aAAa,GAAG,aAAa,UAAU,IAAI,CAAC,EAAG,IAAK,EAAE;AAAA,UACvG,YAAQ,0BAAY,KAAK;AAAA,QAC3B,CAAC;AACD,gBAAI,+BAAc,QAAQ,IAAI,yCAAyB;AACrD,kBAAQ,EAAE,MAAM,SAAS,SAAS,kFAAkF,CAAC;AACrH;AAAA,QACF;AACA,eAAO,UAAM,0CAAsB,OAAO,KAAK,QAAQ,GAAG;AAC1D,mBAAW,GAAG;AAAA,MAChB;AACA,cAAQ,EAAE,MAAM,YAAY,CAAC;AAC7B,YAAM,SAAS,MAAM,IAAI,UAAU;AACnC,YAAM,EAAE,WAAW,IAAI,UAAM,2BAAW,EAAE,QAAQ,OAAO,GAAG;AAAA,QAC1D,OAAO,IAAI;AAAA,QACX,MAAM,MAAM,KAAK,KAAK;AAAA,QACtB,QAAQ,MAAM;AAAA,QACd,SAAS;AAAA,QACT,eAAW,0BAAY,KAAK;AAAA,QAC5B;AAAA,QACA,eAAe,MAAM;AAAA,QACrB,aAAa,MAAM,YAAY,KAAK,KAAK;AAAA,MAC3C,CAAC;AACD,UAAI,UAAyB;AAC7B,UAAI,MAAM,MAAM,SAAS;AACvB,YAAI;AACF,oBAAM,qCAAqB,QAAQ,YAAY,MAAM,KAAK;AAAA,QAC5D,QAAQ;AACN,oBAAU;AAAA,QACZ;AAAA,MACF;AACA,cAAQ,EAAE,MAAM,QAAQ,YAAY,OAAO,WAAO,gCAAe,OAAO,SAAS,QAAQ,YAAY,IAAI,IAAI,CAAC,GAAG,QAAQ,CAAC;AAAA,IAC5H,SAAS,KAAK;AACZ,cAAQ,EAAE,MAAM,SAAS,aAAS,qCAAc,KAAK,iDAAiD,EAAE,QAAQ,CAAC;AAAA,IACnH;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM;AAClB,QAAI,KAAK,SAAS,eAAe,KAAK,SAAS,YAAa;AAC5D,YAAQ;AAAA,EACV;AAEA,SACE,4CAAC,qCAAa,MAAY,SAAS,OACjC,uDAAC,SAAI,WAAU,iBACZ;AAAA,SAAK,SAAS,YACb,4EACE;AAAA,kDAAC,QAAG,WAAU,yBAAwB,+BAAiB;AAAA,MACvD,6CAAC,SAAI,WAAU,yDACb;AAAA,oDAAC,OAAE,WAAU,iBAAiB,gBAAM,MAAK;AAAA,QACzC,4CAAC,OAAE,WAAU,yEAAwE,gCAAkB;AAAA,QACvG,4CAAC,OAAI,OAAM,SAAQ,WAAO,wBAAW,MAAM,OAAO,MAAM,YAAY,GAAG;AAAA,QACvE,4CAAC,OAAI,OAAM,UAAS,OAAO,OAAG,0BAAY,KAAK,EAAE,eAAe,OAAO,CAAC,IAAI,MAAM,SAAS,gBAAa,0BAAY,KAAK,MAAM,IAAI,SAAS,eAAY,0BAAY,KAAK,MAAM,IAAI,SAAS,OAAO,IAAI;AAAA,QACvM,4CAAC,OAAI,OAAM,UAAS,OAAO,MAAM,cAAc,IAAI,cAAc,IAAI,KAAK,MAAM,YAAY,GAAI,EAAE,eAAe,GAAG;AAAA,QACpH,4CAAC,OAAI,OAAM,QAAO,OAAO,MAAM,YAAY,IAAI,gBAAgB,IAAI,KAAK,MAAM,UAAU,GAAI,EAAE,eAAe,GAAG;AAAA,QAChH,4CAAC,OAAI,OAAM,cAAa,OAAO,MAAM,iBAAiB,MAAM,aAAa,MAAM,cAAc;AAAA,QAC7F,4CAAC,OAAI,OAAM,gBAAe,OAAO,OAAO,GAAG,OAAO,KAAK,KAAK,MAAM,EAAE,MAAM,uBAAuB,YAAY;AAAA,QAC7G,4CAAC,OAAE,WAAU,sCAAqC,uGAAyF;AAAA,SAC7I;AAAA,MACA,4CAAC,yCAAe,KAAG,MAAC,SAAS,MAAM,KAAK,IAAI,GAAG,yBAAW;AAAA,OAC5D;AAAA,IAED,KAAK,SAAS,eACb,4EACE;AAAA,mDAAC,QAAG,WAAU,iDAAgD;AAAA,oDAAC,+BAAQ,WAAU,wBAAuB;AAAA,QAAE;AAAA,SAAS;AAAA,MACnH,6CAAC,OAAE,WAAU,iCAAiC;AAAA,cAAM,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE;AAAA,QAAO;AAAA,QAAK,MAAM;AAAA,QAAO;AAAA,SAAM;AAAA,OACxH;AAAA,IAED,KAAK,SAAS,eACb,6CAAC,QAAG,WAAU,iDAAgD;AAAA,kDAAC,+BAAQ,WAAU,wBAAuB;AAAA,MAAE;AAAA,OAAoB;AAAA,IAE/H,KAAK,SAAS,WACb,4EACE;AAAA,mDAAC,QAAG,WAAU,iDAAgD;AAAA,oDAAC,+BAAQ,WAAU,4BAA2B;AAAA,QAAE;AAAA,SAAY;AAAA,MAC1H,4CAAC,OAAE,WAAU,iCAAiC,eAAK,SAAQ;AAAA,MAC1D,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,KACtC,4CAAC,QAAG,WAAU,2CACX,gBAAM,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE,IAAI,CAAC,MAAM,6CAAC,QAAe;AAAA,UAAE,KAAK;AAAA,QAAK;AAAA,QAAG,EAAE;AAAA,WAAxB,EAAE,EAA4B,CAAK,GACrG;AAAA,MAEF,6CAAC,wBAAO,SAAS,MAAM,KAAK,IAAI,GAAG,WAAU,WAAU;AAAA,oDAAC,iCAAU,WAAU,eAAc;AAAA,QAAE;AAAA,SAAS;AAAA,OACvG;AAAA,IAED,KAAK,SAAS,UACb,4EACE;AAAA,mDAAC,QAAG,WAAU,iDAAgD;AAAA,oDAAC,oCAAa,WAAU,0BAAyB;AAAA,QAAE;AAAA,SAAiB;AAAA,MACjI,KAAK,WAAW,4CAAC,OAAE,WAAU,6BAA6B,eAAK,SAAQ;AAAA,MACxE,6CAAC,SAAI,WAAU,wBACb;AAAA,oDAAC,mCAAY,OAAO,MAAM,MAAM,KAAK,GAAG,OAAO,SAAS,MAAM,OAAG,qBAAS,KAAK,UAAU,CAAC,IAAI,SAAQ,WAAU;AAAA,QAChH,4CAAC,wBAAO,SAAO,MAAC,SAAQ,WAAU,sDAAC,OAAE,UAAM,qBAAS,KAAK,UAAU,GAAG,uBAAS,GAAI;AAAA,QAClF,KAAK,MAAM,SAAS,KACnB,4CAAC,wBAAO,SAAQ,WAAU,SAAS,MAAM,gBAAY,kCAAiB,KAAK,KAAK,GAAG,iBAAiB,GAAG,kCAAoB;AAAA,SAE/H;AAAA,MACC,KAAK,MAAM,SAAS,KAAK,4CAAC,OAAE,WAAU,iCAAgC,6EAA0D;AAAA,OACnI;AAAA,KAEJ,GACF;AAEJ;AAEA,SAAS,IAAI,EAAE,OAAO,MAAM,GAAqC;AAC/D,SAAO,6CAAC,SAAI,WAAU,8BAA6B;AAAA,gDAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA,IAAO,4CAAC,UAAK,WAAU,0BAA0B,iBAAM;AAAA,KAAO;AAClK;AAEO,SAAS,YAAY,KAAa,MAAc;AACrD,QAAM,OAAO,IAAI,gBAAgB,IAAI,KAAK,CAAC,GAAG,GAAG,EAAE,MAAM,WAAW,CAAC,CAAC;AACtE,SAAO,OAAO,SAAS,cAAc,GAAG,GAAG,EAAE,MAAM,UAAU,KAAK,CAAC,EAAE,MAAM;AAC3E,MAAI,gBAAgB,IAAI;AAC1B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/drop/create/launch-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { CheckCircle2, Loader2, RotateCcw, XCircle } from \"lucide-react\";\nimport { dropHref } from \"@medialane/sdk\";\nimport { buildPopAllowlist, dropClaimLinks, popClaimLinksCsv, type PopClaimLink } from \"@medialane/sdk/starknet\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { GradientButton } from \"../../gradient-button.js\";\nimport { Button } from \"../../button.js\";\nimport { ShareButton } from \"../../share-button.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\nimport { uploadDirectoryToIpfs, uploadFileToIpfs } from \"../../../utils/ipfs-upload.js\";\nimport { parseAllowlist } from \"../../../utils/drop/allowlist.js\";\nimport { buildDropMetadataFiles, metadataBytes, MAX_DROP_METADATA_BYTES } from \"../../../utils/drop/metadata.js\";\nimport { toDropTerms, priceLabel } from \"../../../utils/drop/sale.js\";\nimport { draftSupply, type DropDraft } from \"../../../utils/drop/draft.js\";\nimport { uploadAll, type UploadTask } from \"../../../utils/drop/upload.js\";\nimport { launchDrop, saveExclusiveContent } from \"../../../utils/drop/actions.js\";\nimport { useMedialaneApp } from \"../../medialane-app.js\";\n\ntype Step =\n | { kind: \"review\" }\n | { kind: \"uploading\" }\n | { kind: \"launching\" }\n | { kind: \"done\"; collection: string; links: PopClaimLink[]; warning: string | null }\n | { kind: \"error\"; message: string };\n\nexport function LaunchDialog({ open, onClose, draft }: { open: boolean; onClose: () => void; draft: DropDraft }) {\n const app = useMedialaneApp();\n const [step, setStep] = useState<Step>({ kind: \"review\" });\n const [tasks, setTasks] = useState<UploadTask[]>([]);\n const [baseUri, setBaseUri] = useState<string | null>(null);\n const client = app.getClient();\n const files = draft.kind === \"edition\" ? (draft.edition ? [draft.edition] : []) : draft.items.map((i) => i.file);\n const terms = toDropTerms(draft.sale);\n const list = useMemo(\n () => (draft.listOnly ? buildPopAllowlist(parseAllowlist(draft.allowlist).addresses) : null),\n [draft.listOnly, draft.allowlist],\n );\n\n const run = async () => {\n try {\n let uri = baseUri;\n if (!uri) {\n setStep({ kind: \"uploading\" });\n const initial = tasks.length > 0 ? tasks : [\n ...files.map((file, i) => ({ id: `art-${i}`, file, status: \"pending\" as const, uri: null, error: null })),\n ...(draft.cover ? [{ id: \"cover\", file: draft.cover, status: \"pending\" as const, uri: null, error: null }] : []),\n ];\n const done = await uploadAll(initial, async (f) => (await uploadFileToIpfs(client.api, f, \"image\")).uri, setTasks);\n setTasks(done);\n if (done.some((t) => t.status !== \"done\")) {\n setStep({ kind: \"error\", message: \"Some files didn't upload. Retry to send only those.\" });\n return;\n }\n const art = done.filter((t) => t.id.startsWith(\"art-\"));\n const metadata = buildDropMetadataFiles({\n kind: draft.kind,\n name: draft.name.trim(),\n description: draft.description.trim(),\n creator: app.walletAddress!,\n coverUri: done.find((t) => t.id === \"cover\")?.uri ?? null,\n license: draft.license,\n items: draft.kind === \"edition\"\n ? [{ name: \"\", description: \"\", imageUri: art[0]!.uri! }]\n : draft.items.map((it, i) => ({ name: it.name, description: it.description, imageUri: art[i]!.uri! })),\n supply: draftSupply(draft),\n });\n if (metadataBytes(metadata) > MAX_DROP_METADATA_BYTES) {\n setStep({ kind: \"error\", message: \"The descriptions are too long for this many tokens. Shorten them and try again.\" });\n return;\n }\n uri = (await uploadDirectoryToIpfs(client.api, metadata)).baseUri;\n setBaseUri(uri);\n }\n setStep({ kind: \"launching\" });\n const signer = await app.getSigner();\n const { collection } = await launchDrop({ client, signer }, {\n owner: app.walletAddress!,\n name: draft.name.trim(),\n symbol: draft.symbol,\n baseUri: uri!,\n maxSupply: draftSupply(draft),\n terms,\n allowlistRoot: list?.root,\n description: draft.description.trim() || undefined,\n });\n let warning: string | null = null;\n if (draft.gated.enabled) {\n try {\n await saveExclusiveContent(client, collection, draft.gated);\n } catch {\n warning = \"Your drop launched, but the exclusive content wasn't saved. You can add it from Manage.\";\n }\n }\n setStep({ kind: \"done\", collection, links: list ? dropClaimLinks(window.location.origin, collection, list) : [], warning });\n } catch (err) {\n setStep({ kind: \"error\", message: describeError(err).message });\n }\n };\n\n const close = () => {\n if (step.kind === \"uploading\" || step.kind === \"launching\") return;\n onClose();\n };\n\n return (\n <ActionDialog open={open} onClose={close}>\n <div className=\"space-y-5 p-6\">\n {step.kind === \"review\" && (\n <>\n <h2 className=\"text-lg font-semibold\">Review and launch</h2>\n <div className=\"space-y-2 rounded-xl border border-border p-4 text-sm\">\n <p className=\"font-semibold\">{draft.name}</p>\n <p className=\"text-xs font-semibold uppercase tracking-widest text-muted-foreground\">Fixed after launch</p>\n <Row label=\"Price\" value={priceLabel(terms.price, terms.paymentToken)} />\n <Row label=\"Supply\" value={`${draftSupply(draft).toLocaleString(\"en-US\")} ${draft.kind === \"edition\" ? (draftSupply(draft) === 1 ? \"copy\" : \"copies\") : draftSupply(draft) === 1 ? \"item\" : \"items\"}`} />\n <Row label=\"Starts\" value={terms.startTime === 0 ? \"At launch\" : new Date(terms.startTime * 1000).toLocaleString()} />\n <Row label=\"Ends\" value={terms.endTime === 0 ? \"No end date\" : new Date(terms.endTime * 1000).toLocaleString()} />\n <Row label=\"Per wallet\" value={terms.maxPerWallet === \"0\" ? \"No limit\" : terms.maxPerWallet} />\n <Row label=\"Who can mint\" value={list ? `${Object.keys(list.proofs).length} wallets on a list` : \"Everyone\"} />\n <p className=\"pt-1 text-xs text-muted-foreground\">The artwork and these terms can't be changed after launch. You can change the list later.</p>\n </div>\n <GradientButton big onClick={() => void run()}>Launch drop</GradientButton>\n </>\n )}\n {step.kind === \"uploading\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Uploading</h2>\n <p className=\"text-sm text-muted-foreground\">{tasks.filter((t) => t.status === \"done\").length} of {tasks.length} files</p>\n </>\n )}\n {step.kind === \"launching\" && (\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Launching your drop…</h2>\n )}\n {step.kind === \"error\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><XCircle className=\"h-4 w-4 text-destructive\" />Not launched</h2>\n <p className=\"text-sm text-muted-foreground\">{step.message}</p>\n {tasks.some((t) => t.status === \"failed\") && (\n <ul className=\"space-y-1 text-xs text-muted-foreground\">\n {tasks.filter((t) => t.status === \"failed\").map((t) => <li key={t.id}>{t.file.name}: {t.error}</li>)}\n </ul>\n )}\n <Button onClick={() => void run()} className=\"gap-1.5\"><RotateCcw className=\"h-3.5 w-3.5\" />Try again</Button>\n </>\n )}\n {step.kind === \"done\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><CheckCircle2 className=\"h-5 w-5 text-green-500\" />Your drop is live</h2>\n {step.warning && <p className=\"text-sm text-brand-orange\">{step.warning}</p>}\n <div className=\"flex flex-wrap gap-2\">\n <ShareButton title={draft.name} url={`${window.location.origin}${dropHref(step.collection)}`} variant=\"outline\" />\n <Button asChild variant=\"outline\"><a href={dropHref(step.collection)}>View drop</a></Button>\n {step.links.length > 0 && (\n <Button variant=\"outline\" onClick={() => downloadCsv(popClaimLinksCsv(step.links), \"claim-links.csv\")}>Download claim links</Button>\n )}\n </div>\n {step.links.length > 0 && <p className=\"text-xs text-muted-foreground\">Send each wallet its link — the link is what lets it mint.</p>}\n </>\n )}\n </div>\n </ActionDialog>\n );\n}\n\nfunction Row({ label, value }: { label: string; value: string }) {\n return <div className=\"flex justify-between gap-3\"><span className=\"text-muted-foreground\">{label}</span><span className=\"text-right font-medium\">{value}</span></div>;\n}\n\nexport function downloadCsv(csv: string, name: string) {\n const href = URL.createObjectURL(new Blob([csv], { type: \"text/csv\" }));\n Object.assign(document.createElement(\"a\"), { href, download: name }).click();\n URL.revokeObjectURL(href);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8GU;AA5GV,mBAAkC;AAClC,0BAA0D;AAC1D,iBAAyB;AACzB,sBAAuF;AACvF,2BAA6B;AAC7B,6BAA+B;AAC/B,oBAAuB;AACvB,0BAA4B;AAC5B,4BAA8B;AAC9B,yBAAwD;AACxD,uBAA+B;AAC/B,sBAA+E;AAC/E,kBAAwC;AACxC,mBAA4C;AAC5C,oBAA2C;AAC3C,qBAAiD;AACjD,2BAAgC;AASzB,SAAS,aAAa,EAAE,MAAM,SAAS,MAAM,GAA6D;AAC/G,QAAM,UAAM,sCAAgB;AAC5B,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAe,EAAE,MAAM,SAAS,CAAC;AACzD,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAuB,CAAC,CAAC;AACnD,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAwB,IAAI;AAC1D,QAAM,SAAS,IAAI,UAAU;AAC7B,QAAM,QAAQ,MAAM,SAAS,YAAa,MAAM,UAAU,CAAC,MAAM,OAAO,IAAI,CAAC,IAAK,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAC/G,QAAM,YAAQ,yBAAY,MAAM,IAAI;AACpC,QAAM,WAAO;AAAA,IACX,MAAO,MAAM,eAAW,uCAAkB,iCAAe,MAAM,SAAS,EAAE,SAAS,IAAI;AAAA,IACvF,CAAC,MAAM,UAAU,MAAM,SAAS;AAAA,EAClC;AAEA,QAAM,MAAM,YAAY;AACtB,QAAI;AACF,UAAI,MAAM;AACV,UAAI,CAAC,KAAK;AACR,gBAAQ,EAAE,MAAM,YAAY,CAAC;AAC7B,cAAM,UAAU,MAAM,SAAS,IAAI,QAAQ;AAAA,UACzC,GAAG,MAAM,IAAI,CAAC,MAAM,OAAO,EAAE,IAAI,OAAO,CAAC,IAAI,MAAM,QAAQ,WAAoB,KAAK,MAAM,OAAO,KAAK,EAAE;AAAA,UACxG,GAAI,MAAM,QAAQ,CAAC,EAAE,IAAI,SAAS,MAAM,MAAM,OAAO,QAAQ,WAAoB,KAAK,MAAM,OAAO,KAAK,CAAC,IAAI,CAAC;AAAA,QAChH;AACA,cAAM,OAAO,UAAM,yBAAU,SAAS,OAAO,OAAO,UAAM,qCAAiB,OAAO,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ;AACjH,iBAAS,IAAI;AACb,YAAI,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,GAAG;AACzC,kBAAQ,EAAE,MAAM,SAAS,SAAS,sDAAsD,CAAC;AACzF;AAAA,QACF;AACA,cAAM,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,GAAG,WAAW,MAAM,CAAC;AACtD,cAAM,eAAW,wCAAuB;AAAA,UACtC,MAAM,MAAM;AAAA,UACZ,MAAM,MAAM,KAAK,KAAK;AAAA,UACtB,aAAa,MAAM,YAAY,KAAK;AAAA,UACpC,SAAS,IAAI;AAAA,UACb,UAAU,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,GAAG,OAAO;AAAA,UACrD,SAAS,MAAM;AAAA,UACf,OAAO,MAAM,SAAS,YAClB,CAAC,EAAE,MAAM,IAAI,aAAa,IAAI,UAAU,IAAI,CAAC,EAAG,IAAK,CAAC,IACtD,MAAM,MAAM,IAAI,CAAC,IAAI,OAAO,EAAE,MAAM,GAAG,MAAM,aAAa,GAAG,aAAa,UAAU,IAAI,CAAC,EAAG,IAAK,EAAE;AAAA,UACvG,YAAQ,0BAAY,KAAK;AAAA,QAC3B,CAAC;AACD,gBAAI,+BAAc,QAAQ,IAAI,yCAAyB;AACrD,kBAAQ,EAAE,MAAM,SAAS,SAAS,kFAAkF,CAAC;AACrH;AAAA,QACF;AACA,eAAO,UAAM,0CAAsB,OAAO,KAAK,QAAQ,GAAG;AAC1D,mBAAW,GAAG;AAAA,MAChB;AACA,cAAQ,EAAE,MAAM,YAAY,CAAC;AAC7B,YAAM,SAAS,MAAM,IAAI,UAAU;AACnC,YAAM,EAAE,WAAW,IAAI,UAAM,2BAAW,EAAE,QAAQ,OAAO,GAAG;AAAA,QAC1D,OAAO,IAAI;AAAA,QACX,MAAM,MAAM,KAAK,KAAK;AAAA,QACtB,QAAQ,MAAM;AAAA,QACd,SAAS;AAAA,QACT,eAAW,0BAAY,KAAK;AAAA,QAC5B;AAAA,QACA,eAAe,MAAM;AAAA,QACrB,aAAa,MAAM,YAAY,KAAK,KAAK;AAAA,MAC3C,CAAC;AACD,UAAI,UAAyB;AAC7B,UAAI,MAAM,MAAM,SAAS;AACvB,YAAI;AACF,oBAAM,qCAAqB,QAAQ,YAAY,MAAM,KAAK;AAAA,QAC5D,QAAQ;AACN,oBAAU;AAAA,QACZ;AAAA,MACF;AACA,cAAQ,EAAE,MAAM,QAAQ,YAAY,OAAO,WAAO,gCAAe,OAAO,SAAS,QAAQ,YAAY,IAAI,IAAI,CAAC,GAAG,QAAQ,CAAC;AAAA,IAC5H,SAAS,KAAK;AACZ,cAAQ,EAAE,MAAM,SAAS,aAAS,qCAAc,GAAG,EAAE,QAAQ,CAAC;AAAA,IAChE;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM;AAClB,QAAI,KAAK,SAAS,eAAe,KAAK,SAAS,YAAa;AAC5D,YAAQ;AAAA,EACV;AAEA,SACE,4CAAC,qCAAa,MAAY,SAAS,OACjC,uDAAC,SAAI,WAAU,iBACZ;AAAA,SAAK,SAAS,YACb,4EACE;AAAA,kDAAC,QAAG,WAAU,yBAAwB,+BAAiB;AAAA,MACvD,6CAAC,SAAI,WAAU,yDACb;AAAA,oDAAC,OAAE,WAAU,iBAAiB,gBAAM,MAAK;AAAA,QACzC,4CAAC,OAAE,WAAU,yEAAwE,gCAAkB;AAAA,QACvG,4CAAC,OAAI,OAAM,SAAQ,WAAO,wBAAW,MAAM,OAAO,MAAM,YAAY,GAAG;AAAA,QACvE,4CAAC,OAAI,OAAM,UAAS,OAAO,OAAG,0BAAY,KAAK,EAAE,eAAe,OAAO,CAAC,IAAI,MAAM,SAAS,gBAAa,0BAAY,KAAK,MAAM,IAAI,SAAS,eAAY,0BAAY,KAAK,MAAM,IAAI,SAAS,OAAO,IAAI;AAAA,QACvM,4CAAC,OAAI,OAAM,UAAS,OAAO,MAAM,cAAc,IAAI,cAAc,IAAI,KAAK,MAAM,YAAY,GAAI,EAAE,eAAe,GAAG;AAAA,QACpH,4CAAC,OAAI,OAAM,QAAO,OAAO,MAAM,YAAY,IAAI,gBAAgB,IAAI,KAAK,MAAM,UAAU,GAAI,EAAE,eAAe,GAAG;AAAA,QAChH,4CAAC,OAAI,OAAM,cAAa,OAAO,MAAM,iBAAiB,MAAM,aAAa,MAAM,cAAc;AAAA,QAC7F,4CAAC,OAAI,OAAM,gBAAe,OAAO,OAAO,GAAG,OAAO,KAAK,KAAK,MAAM,EAAE,MAAM,uBAAuB,YAAY;AAAA,QAC7G,4CAAC,OAAE,WAAU,sCAAqC,uGAAyF;AAAA,SAC7I;AAAA,MACA,4CAAC,yCAAe,KAAG,MAAC,SAAS,MAAM,KAAK,IAAI,GAAG,yBAAW;AAAA,OAC5D;AAAA,IAED,KAAK,SAAS,eACb,4EACE;AAAA,mDAAC,QAAG,WAAU,iDAAgD;AAAA,oDAAC,+BAAQ,WAAU,wBAAuB;AAAA,QAAE;AAAA,SAAS;AAAA,MACnH,6CAAC,OAAE,WAAU,iCAAiC;AAAA,cAAM,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE;AAAA,QAAO;AAAA,QAAK,MAAM;AAAA,QAAO;AAAA,SAAM;AAAA,OACxH;AAAA,IAED,KAAK,SAAS,eACb,6CAAC,QAAG,WAAU,iDAAgD;AAAA,kDAAC,+BAAQ,WAAU,wBAAuB;AAAA,MAAE;AAAA,OAAoB;AAAA,IAE/H,KAAK,SAAS,WACb,4EACE;AAAA,mDAAC,QAAG,WAAU,iDAAgD;AAAA,oDAAC,+BAAQ,WAAU,4BAA2B;AAAA,QAAE;AAAA,SAAY;AAAA,MAC1H,4CAAC,OAAE,WAAU,iCAAiC,eAAK,SAAQ;AAAA,MAC1D,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,KACtC,4CAAC,QAAG,WAAU,2CACX,gBAAM,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE,IAAI,CAAC,MAAM,6CAAC,QAAe;AAAA,UAAE,KAAK;AAAA,QAAK;AAAA,QAAG,EAAE;AAAA,WAAxB,EAAE,EAA4B,CAAK,GACrG;AAAA,MAEF,6CAAC,wBAAO,SAAS,MAAM,KAAK,IAAI,GAAG,WAAU,WAAU;AAAA,oDAAC,iCAAU,WAAU,eAAc;AAAA,QAAE;AAAA,SAAS;AAAA,OACvG;AAAA,IAED,KAAK,SAAS,UACb,4EACE;AAAA,mDAAC,QAAG,WAAU,iDAAgD;AAAA,oDAAC,oCAAa,WAAU,0BAAyB;AAAA,QAAE;AAAA,SAAiB;AAAA,MACjI,KAAK,WAAW,4CAAC,OAAE,WAAU,6BAA6B,eAAK,SAAQ;AAAA,MACxE,6CAAC,SAAI,WAAU,wBACb;AAAA,oDAAC,mCAAY,OAAO,MAAM,MAAM,KAAK,GAAG,OAAO,SAAS,MAAM,OAAG,qBAAS,KAAK,UAAU,CAAC,IAAI,SAAQ,WAAU;AAAA,QAChH,4CAAC,wBAAO,SAAO,MAAC,SAAQ,WAAU,sDAAC,OAAE,UAAM,qBAAS,KAAK,UAAU,GAAG,uBAAS,GAAI;AAAA,QAClF,KAAK,MAAM,SAAS,KACnB,4CAAC,wBAAO,SAAQ,WAAU,SAAS,MAAM,gBAAY,kCAAiB,KAAK,KAAK,GAAG,iBAAiB,GAAG,kCAAoB;AAAA,SAE/H;AAAA,MACC,KAAK,MAAM,SAAS,KAAK,4CAAC,OAAE,WAAU,iCAAgC,6EAA0D;AAAA,OACnI;AAAA,KAEJ,GACF;AAEJ;AAEA,SAAS,IAAI,EAAE,OAAO,MAAM,GAAqC;AAC/D,SAAO,6CAAC,SAAI,WAAU,8BAA6B;AAAA,gDAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA,IAAO,4CAAC,UAAK,WAAU,0BAA0B,iBAAM;AAAA,KAAO;AAClK;AAEO,SAAS,YAAY,KAAa,MAAc;AACrD,QAAM,OAAO,IAAI,gBAAgB,IAAI,KAAK,CAAC,GAAG,GAAG,EAAE,MAAM,WAAW,CAAC,CAAC;AACtE,SAAO,OAAO,SAAS,cAAc,GAAG,GAAG,EAAE,MAAM,UAAU,KAAK,CAAC,EAAE,MAAM;AAC3E,MAAI,gBAAgB,IAAI;AAC1B;","names":[]}
|
|
@@ -84,7 +84,7 @@ function LaunchDialog({ open, onClose, draft }) {
|
|
|
84
84
|
}
|
|
85
85
|
setStep({ kind: "done", collection, links: list ? dropClaimLinks(window.location.origin, collection, list) : [], warning });
|
|
86
86
|
} catch (err) {
|
|
87
|
-
setStep({ kind: "error", message: describeError(err
|
|
87
|
+
setStep({ kind: "error", message: describeError(err).message });
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
const close = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/drop/create/launch-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { CheckCircle2, Loader2, RotateCcw, XCircle } from \"lucide-react\";\nimport { dropHref } from \"@medialane/sdk\";\nimport { buildPopAllowlist, dropClaimLinks, popClaimLinksCsv, type PopClaimLink } from \"@medialane/sdk/starknet\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { GradientButton } from \"../../gradient-button.js\";\nimport { Button } from \"../../button.js\";\nimport { ShareButton } from \"../../share-button.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\nimport { uploadDirectoryToIpfs, uploadFileToIpfs } from \"../../../utils/ipfs-upload.js\";\nimport { parseAllowlist } from \"../../../utils/drop/allowlist.js\";\nimport { buildDropMetadataFiles, metadataBytes, MAX_DROP_METADATA_BYTES } from \"../../../utils/drop/metadata.js\";\nimport { toDropTerms, priceLabel } from \"../../../utils/drop/sale.js\";\nimport { draftSupply, type DropDraft } from \"../../../utils/drop/draft.js\";\nimport { uploadAll, type UploadTask } from \"../../../utils/drop/upload.js\";\nimport { launchDrop, saveExclusiveContent } from \"../../../utils/drop/actions.js\";\nimport { useMedialaneApp } from \"../../medialane-app.js\";\n\ntype Step =\n | { kind: \"review\" }\n | { kind: \"uploading\" }\n | { kind: \"launching\" }\n | { kind: \"done\"; collection: string; links: PopClaimLink[]; warning: string | null }\n | { kind: \"error\"; message: string };\n\nexport function LaunchDialog({ open, onClose, draft }: { open: boolean; onClose: () => void; draft: DropDraft }) {\n const app = useMedialaneApp();\n const [step, setStep] = useState<Step>({ kind: \"review\" });\n const [tasks, setTasks] = useState<UploadTask[]>([]);\n const [baseUri, setBaseUri] = useState<string | null>(null);\n const client = app.getClient();\n const files = draft.kind === \"edition\" ? (draft.edition ? [draft.edition] : []) : draft.items.map((i) => i.file);\n const terms = toDropTerms(draft.sale);\n const list = useMemo(\n () => (draft.listOnly ? buildPopAllowlist(parseAllowlist(draft.allowlist).addresses) : null),\n [draft.listOnly, draft.allowlist],\n );\n\n const run = async () => {\n try {\n let uri = baseUri;\n if (!uri) {\n setStep({ kind: \"uploading\" });\n const initial = tasks.length > 0 ? tasks : [\n ...files.map((file, i) => ({ id: `art-${i}`, file, status: \"pending\" as const, uri: null, error: null })),\n ...(draft.cover ? [{ id: \"cover\", file: draft.cover, status: \"pending\" as const, uri: null, error: null }] : []),\n ];\n const done = await uploadAll(initial, async (f) => (await uploadFileToIpfs(client.api, f, \"image\")).uri, setTasks);\n setTasks(done);\n if (done.some((t) => t.status !== \"done\")) {\n setStep({ kind: \"error\", message: \"Some files didn't upload. Retry to send only those.\" });\n return;\n }\n const art = done.filter((t) => t.id.startsWith(\"art-\"));\n const metadata = buildDropMetadataFiles({\n kind: draft.kind,\n name: draft.name.trim(),\n description: draft.description.trim(),\n creator: app.walletAddress!,\n coverUri: done.find((t) => t.id === \"cover\")?.uri ?? null,\n license: draft.license,\n items: draft.kind === \"edition\"\n ? [{ name: \"\", description: \"\", imageUri: art[0]!.uri! }]\n : draft.items.map((it, i) => ({ name: it.name, description: it.description, imageUri: art[i]!.uri! })),\n supply: draftSupply(draft),\n });\n if (metadataBytes(metadata) > MAX_DROP_METADATA_BYTES) {\n setStep({ kind: \"error\", message: \"The descriptions are too long for this many tokens. Shorten them and try again.\" });\n return;\n }\n uri = (await uploadDirectoryToIpfs(client.api, metadata)).baseUri;\n setBaseUri(uri);\n }\n setStep({ kind: \"launching\" });\n const signer = await app.getSigner();\n const { collection } = await launchDrop({ client, signer }, {\n owner: app.walletAddress!,\n name: draft.name.trim(),\n symbol: draft.symbol,\n baseUri: uri!,\n maxSupply: draftSupply(draft),\n terms,\n allowlistRoot: list?.root,\n description: draft.description.trim() || undefined,\n });\n let warning: string | null = null;\n if (draft.gated.enabled) {\n try {\n await saveExclusiveContent(client, collection, draft.gated);\n } catch {\n warning = \"Your drop launched, but the exclusive content wasn't saved. You can add it from Manage.\";\n }\n }\n setStep({ kind: \"done\", collection, links: list ? dropClaimLinks(window.location.origin, collection, list) : [], warning });\n } catch (err) {\n setStep({ kind: \"error\", message: describeError(err, \"We couldn't launch your drop. Please try again.\").message });\n }\n };\n\n const close = () => {\n if (step.kind === \"uploading\" || step.kind === \"launching\") return;\n onClose();\n };\n\n return (\n <ActionDialog open={open} onClose={close}>\n <div className=\"space-y-5 p-6\">\n {step.kind === \"review\" && (\n <>\n <h2 className=\"text-lg font-semibold\">Review and launch</h2>\n <div className=\"space-y-2 rounded-xl border border-border p-4 text-sm\">\n <p className=\"font-semibold\">{draft.name}</p>\n <p className=\"text-xs font-semibold uppercase tracking-widest text-muted-foreground\">Fixed after launch</p>\n <Row label=\"Price\" value={priceLabel(terms.price, terms.paymentToken)} />\n <Row label=\"Supply\" value={`${draftSupply(draft).toLocaleString(\"en-US\")} ${draft.kind === \"edition\" ? (draftSupply(draft) === 1 ? \"copy\" : \"copies\") : draftSupply(draft) === 1 ? \"item\" : \"items\"}`} />\n <Row label=\"Starts\" value={terms.startTime === 0 ? \"At launch\" : new Date(terms.startTime * 1000).toLocaleString()} />\n <Row label=\"Ends\" value={terms.endTime === 0 ? \"No end date\" : new Date(terms.endTime * 1000).toLocaleString()} />\n <Row label=\"Per wallet\" value={terms.maxPerWallet === \"0\" ? \"No limit\" : terms.maxPerWallet} />\n <Row label=\"Who can mint\" value={list ? `${Object.keys(list.proofs).length} wallets on a list` : \"Everyone\"} />\n <p className=\"pt-1 text-xs text-muted-foreground\">The artwork and these terms can't be changed after launch. You can change the list later.</p>\n </div>\n <GradientButton big onClick={() => void run()}>Launch drop</GradientButton>\n </>\n )}\n {step.kind === \"uploading\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Uploading</h2>\n <p className=\"text-sm text-muted-foreground\">{tasks.filter((t) => t.status === \"done\").length} of {tasks.length} files</p>\n </>\n )}\n {step.kind === \"launching\" && (\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Launching your drop…</h2>\n )}\n {step.kind === \"error\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><XCircle className=\"h-4 w-4 text-destructive\" />Not launched</h2>\n <p className=\"text-sm text-muted-foreground\">{step.message}</p>\n {tasks.some((t) => t.status === \"failed\") && (\n <ul className=\"space-y-1 text-xs text-muted-foreground\">\n {tasks.filter((t) => t.status === \"failed\").map((t) => <li key={t.id}>{t.file.name}: {t.error}</li>)}\n </ul>\n )}\n <Button onClick={() => void run()} className=\"gap-1.5\"><RotateCcw className=\"h-3.5 w-3.5\" />Try again</Button>\n </>\n )}\n {step.kind === \"done\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><CheckCircle2 className=\"h-5 w-5 text-green-500\" />Your drop is live</h2>\n {step.warning && <p className=\"text-sm text-brand-orange\">{step.warning}</p>}\n <div className=\"flex flex-wrap gap-2\">\n <ShareButton title={draft.name} url={`${window.location.origin}${dropHref(step.collection)}`} variant=\"outline\" />\n <Button asChild variant=\"outline\"><a href={dropHref(step.collection)}>View drop</a></Button>\n {step.links.length > 0 && (\n <Button variant=\"outline\" onClick={() => downloadCsv(popClaimLinksCsv(step.links), \"claim-links.csv\")}>Download claim links</Button>\n )}\n </div>\n {step.links.length > 0 && <p className=\"text-xs text-muted-foreground\">Send each wallet its link — the link is what lets it mint.</p>}\n </>\n )}\n </div>\n </ActionDialog>\n );\n}\n\nfunction Row({ label, value }: { label: string; value: string }) {\n return <div className=\"flex justify-between gap-3\"><span className=\"text-muted-foreground\">{label}</span><span className=\"text-right font-medium\">{value}</span></div>;\n}\n\nexport function downloadCsv(csv: string, name: string) {\n const href = URL.createObjectURL(new Blob([csv], { type: \"text/csv\" }));\n Object.assign(document.createElement(\"a\"), { href, download: name }).click();\n URL.revokeObjectURL(href);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/drop/create/launch-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { CheckCircle2, Loader2, RotateCcw, XCircle } from \"lucide-react\";\nimport { dropHref } from \"@medialane/sdk\";\nimport { buildPopAllowlist, dropClaimLinks, popClaimLinksCsv, type PopClaimLink } from \"@medialane/sdk/starknet\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { GradientButton } from \"../../gradient-button.js\";\nimport { Button } from \"../../button.js\";\nimport { ShareButton } from \"../../share-button.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\nimport { uploadDirectoryToIpfs, uploadFileToIpfs } from \"../../../utils/ipfs-upload.js\";\nimport { parseAllowlist } from \"../../../utils/drop/allowlist.js\";\nimport { buildDropMetadataFiles, metadataBytes, MAX_DROP_METADATA_BYTES } from \"../../../utils/drop/metadata.js\";\nimport { toDropTerms, priceLabel } from \"../../../utils/drop/sale.js\";\nimport { draftSupply, type DropDraft } from \"../../../utils/drop/draft.js\";\nimport { uploadAll, type UploadTask } from \"../../../utils/drop/upload.js\";\nimport { launchDrop, saveExclusiveContent } from \"../../../utils/drop/actions.js\";\nimport { useMedialaneApp } from \"../../medialane-app.js\";\n\ntype Step =\n | { kind: \"review\" }\n | { kind: \"uploading\" }\n | { kind: \"launching\" }\n | { kind: \"done\"; collection: string; links: PopClaimLink[]; warning: string | null }\n | { kind: \"error\"; message: string };\n\nexport function LaunchDialog({ open, onClose, draft }: { open: boolean; onClose: () => void; draft: DropDraft }) {\n const app = useMedialaneApp();\n const [step, setStep] = useState<Step>({ kind: \"review\" });\n const [tasks, setTasks] = useState<UploadTask[]>([]);\n const [baseUri, setBaseUri] = useState<string | null>(null);\n const client = app.getClient();\n const files = draft.kind === \"edition\" ? (draft.edition ? [draft.edition] : []) : draft.items.map((i) => i.file);\n const terms = toDropTerms(draft.sale);\n const list = useMemo(\n () => (draft.listOnly ? buildPopAllowlist(parseAllowlist(draft.allowlist).addresses) : null),\n [draft.listOnly, draft.allowlist],\n );\n\n const run = async () => {\n try {\n let uri = baseUri;\n if (!uri) {\n setStep({ kind: \"uploading\" });\n const initial = tasks.length > 0 ? tasks : [\n ...files.map((file, i) => ({ id: `art-${i}`, file, status: \"pending\" as const, uri: null, error: null })),\n ...(draft.cover ? [{ id: \"cover\", file: draft.cover, status: \"pending\" as const, uri: null, error: null }] : []),\n ];\n const done = await uploadAll(initial, async (f) => (await uploadFileToIpfs(client.api, f, \"image\")).uri, setTasks);\n setTasks(done);\n if (done.some((t) => t.status !== \"done\")) {\n setStep({ kind: \"error\", message: \"Some files didn't upload. Retry to send only those.\" });\n return;\n }\n const art = done.filter((t) => t.id.startsWith(\"art-\"));\n const metadata = buildDropMetadataFiles({\n kind: draft.kind,\n name: draft.name.trim(),\n description: draft.description.trim(),\n creator: app.walletAddress!,\n coverUri: done.find((t) => t.id === \"cover\")?.uri ?? null,\n license: draft.license,\n items: draft.kind === \"edition\"\n ? [{ name: \"\", description: \"\", imageUri: art[0]!.uri! }]\n : draft.items.map((it, i) => ({ name: it.name, description: it.description, imageUri: art[i]!.uri! })),\n supply: draftSupply(draft),\n });\n if (metadataBytes(metadata) > MAX_DROP_METADATA_BYTES) {\n setStep({ kind: \"error\", message: \"The descriptions are too long for this many tokens. Shorten them and try again.\" });\n return;\n }\n uri = (await uploadDirectoryToIpfs(client.api, metadata)).baseUri;\n setBaseUri(uri);\n }\n setStep({ kind: \"launching\" });\n const signer = await app.getSigner();\n const { collection } = await launchDrop({ client, signer }, {\n owner: app.walletAddress!,\n name: draft.name.trim(),\n symbol: draft.symbol,\n baseUri: uri!,\n maxSupply: draftSupply(draft),\n terms,\n allowlistRoot: list?.root,\n description: draft.description.trim() || undefined,\n });\n let warning: string | null = null;\n if (draft.gated.enabled) {\n try {\n await saveExclusiveContent(client, collection, draft.gated);\n } catch {\n warning = \"Your drop launched, but the exclusive content wasn't saved. You can add it from Manage.\";\n }\n }\n setStep({ kind: \"done\", collection, links: list ? dropClaimLinks(window.location.origin, collection, list) : [], warning });\n } catch (err) {\n setStep({ kind: \"error\", message: describeError(err).message });\n }\n };\n\n const close = () => {\n if (step.kind === \"uploading\" || step.kind === \"launching\") return;\n onClose();\n };\n\n return (\n <ActionDialog open={open} onClose={close}>\n <div className=\"space-y-5 p-6\">\n {step.kind === \"review\" && (\n <>\n <h2 className=\"text-lg font-semibold\">Review and launch</h2>\n <div className=\"space-y-2 rounded-xl border border-border p-4 text-sm\">\n <p className=\"font-semibold\">{draft.name}</p>\n <p className=\"text-xs font-semibold uppercase tracking-widest text-muted-foreground\">Fixed after launch</p>\n <Row label=\"Price\" value={priceLabel(terms.price, terms.paymentToken)} />\n <Row label=\"Supply\" value={`${draftSupply(draft).toLocaleString(\"en-US\")} ${draft.kind === \"edition\" ? (draftSupply(draft) === 1 ? \"copy\" : \"copies\") : draftSupply(draft) === 1 ? \"item\" : \"items\"}`} />\n <Row label=\"Starts\" value={terms.startTime === 0 ? \"At launch\" : new Date(terms.startTime * 1000).toLocaleString()} />\n <Row label=\"Ends\" value={terms.endTime === 0 ? \"No end date\" : new Date(terms.endTime * 1000).toLocaleString()} />\n <Row label=\"Per wallet\" value={terms.maxPerWallet === \"0\" ? \"No limit\" : terms.maxPerWallet} />\n <Row label=\"Who can mint\" value={list ? `${Object.keys(list.proofs).length} wallets on a list` : \"Everyone\"} />\n <p className=\"pt-1 text-xs text-muted-foreground\">The artwork and these terms can't be changed after launch. You can change the list later.</p>\n </div>\n <GradientButton big onClick={() => void run()}>Launch drop</GradientButton>\n </>\n )}\n {step.kind === \"uploading\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Uploading</h2>\n <p className=\"text-sm text-muted-foreground\">{tasks.filter((t) => t.status === \"done\").length} of {tasks.length} files</p>\n </>\n )}\n {step.kind === \"launching\" && (\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Launching your drop…</h2>\n )}\n {step.kind === \"error\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><XCircle className=\"h-4 w-4 text-destructive\" />Not launched</h2>\n <p className=\"text-sm text-muted-foreground\">{step.message}</p>\n {tasks.some((t) => t.status === \"failed\") && (\n <ul className=\"space-y-1 text-xs text-muted-foreground\">\n {tasks.filter((t) => t.status === \"failed\").map((t) => <li key={t.id}>{t.file.name}: {t.error}</li>)}\n </ul>\n )}\n <Button onClick={() => void run()} className=\"gap-1.5\"><RotateCcw className=\"h-3.5 w-3.5\" />Try again</Button>\n </>\n )}\n {step.kind === \"done\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><CheckCircle2 className=\"h-5 w-5 text-green-500\" />Your drop is live</h2>\n {step.warning && <p className=\"text-sm text-brand-orange\">{step.warning}</p>}\n <div className=\"flex flex-wrap gap-2\">\n <ShareButton title={draft.name} url={`${window.location.origin}${dropHref(step.collection)}`} variant=\"outline\" />\n <Button asChild variant=\"outline\"><a href={dropHref(step.collection)}>View drop</a></Button>\n {step.links.length > 0 && (\n <Button variant=\"outline\" onClick={() => downloadCsv(popClaimLinksCsv(step.links), \"claim-links.csv\")}>Download claim links</Button>\n )}\n </div>\n {step.links.length > 0 && <p className=\"text-xs text-muted-foreground\">Send each wallet its link — the link is what lets it mint.</p>}\n </>\n )}\n </div>\n </ActionDialog>\n );\n}\n\nfunction Row({ label, value }: { label: string; value: string }) {\n return <div className=\"flex justify-between gap-3\"><span className=\"text-muted-foreground\">{label}</span><span className=\"text-right font-medium\">{value}</span></div>;\n}\n\nexport function downloadCsv(csv: string, name: string) {\n const href = URL.createObjectURL(new Blob([csv], { type: \"text/csv\" }));\n Object.assign(document.createElement(\"a\"), { href, download: name }).click();\n URL.revokeObjectURL(href);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -56,7 +56,7 @@ function DropManage({ contract, indexed, onchain, mints, run, saveExclusive }) {
|
|
|
56
56
|
await pending.act();
|
|
57
57
|
setMessage(`${pending.title} \u2014 done.`);
|
|
58
58
|
} catch (err) {
|
|
59
|
-
setMessage((0, import_describe_error.describeError)(err
|
|
59
|
+
setMessage((0, import_describe_error.describeError)(err).message);
|
|
60
60
|
} finally {
|
|
61
61
|
setBusy(false);
|
|
62
62
|
setPending(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/drop/page/drop-manage.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { buildPopAllowlist, dropClaimLinks, popClaimLinksCsv, type DropOnchain } from \"@medialane/sdk/starknet\";\nimport { dropHref, type ApiDrop, type ApiDropMint } from \"@medialane/sdk\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { Button } from \"../../button.js\";\nimport { Input } from \"../../input.js\";\nimport { Textarea } from \"../../textarea.js\";\nimport { ShareButton } from \"../../share-button.js\";\nimport { StatTile } from \"../../stat-tile.js\";\nimport { DropActivityList } from \"./drop-activity.js\";\nimport { ExclusiveFields, type ExclusiveValue } from \"../create/exclusive-fields.js\";\nimport { downloadCsv } from \"../create/launch-dialog.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\nimport { parseAllowlist } from \"../../../utils/drop/allowlist.js\";\nimport { priceLabel, supplyLabel } from \"../../../utils/drop/sale.js\";\n\nexport interface DropManageProps {\n contract: string;\n indexed: ApiDrop | null;\n onchain: DropOnchain;\n mints: ApiDropMint[];\n /** Runs a manage action as one transaction; resolves when confirmed. */\n run: (params: { action: \"issue\"; recipient: string; quantity: string } | { action: \"set_allowlist_root\"; root: string }) => Promise<void>;\n saveExclusive: (value: ExclusiveValue | null) => Promise<void>;\n}\n\ntype Pending = { title: string; body: string; act: () => Promise<void> } | null;\n\nexport function DropManage({ contract, indexed, onchain, mints, run, saveExclusive }: DropManageProps) {\n const [pending, setPending] = useState<Pending>(null);\n const [busy, setBusy] = useState(false);\n const [message, setMessage] = useState<string | null>(null);\n const [listText, setListText] = useState(\"\");\n const [links, setLinks] = useState<ReturnType<typeof dropClaimLinks>>([]);\n const [gift, setGift] = useState({ to: \"\", quantity: \"1\" });\n const [exclusive, setExclusive] = useState<ExclusiveValue>({ title: \"\", url: \"\", type: \"\" });\n const listed = BigInt(onchain.allowlistRoot) !== 0n;\n const left = onchain.maxSupply === 0n ? null : onchain.maxSupply - onchain.totalMinted;\n const shareUrl = typeof window === \"undefined\" ? dropHref(contract) : `${window.location.origin}${dropHref(contract)}`;\n\n const confirm = async () => {\n if (!pending) return;\n setBusy(true);\n try {\n await pending.act();\n setMessage(`${pending.title} — done.`);\n } catch (err) {\n setMessage(describeError(err, \"That didn't go through. Please try again.\").message);\n } finally {\n setBusy(false);\n setPending(null);\n }\n };\n\n const parsed = parseAllowlist(listText);\n const list = parsed.addresses.length > 0 ? buildPopAllowlist(parsed.addresses) : null;\n const sameList = list !== null && BigInt(list.root) === BigInt(onchain.allowlistRoot);\n\n return (\n <div className=\"space-y-8\">\n {message && <p className=\"rounded-lg bg-muted/50 px-3 py-2 text-sm\">{message}</p>}\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Overview</h3>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n <StatTile label=\"Minted\" value={supplyLabel(onchain.totalMinted.toString(), onchain.maxSupply.toString())} />\n <StatTile label=\"Revenue\" value={priceLabel(indexed?.revenue ?? \"0\", onchain.paymentToken)} />\n <StatTile label=\"Collectors\" value={indexed?.collectors ?? 0} />\n </div>\n <DropActivityList mints={mints} />\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Who can mint</h3>\n <p className=\"text-sm text-muted-foreground\">{listed ? \"Only wallets on your list can mint.\" : \"Everyone can mint.\"}</p>\n <Textarea rows={5} placeholder=\"Paste wallet addresses, one per line\" value={listText} onChange={(e) => { setListText(e.target.value); setLinks([]); }} />\n {parsed.invalid.length > 0 && <p className=\"text-xs text-destructive\">{parsed.invalid.length} line(s) aren't wallet addresses: {parsed.invalid.slice(0, 3).join(\", \")}</p>}\n <div className=\"flex flex-wrap gap-2\">\n {list && sameList && (\n <Button variant=\"outline\" onClick={() => setLinks(dropClaimLinks(window.location.origin, contract, list))}>This is your current list — get its claim links</Button>\n )}\n {list && !sameList && parsed.invalid.length === 0 && (\n <Button onClick={() => setPending({\n title: \"List published\",\n body: `Only these ${parsed.addresses.length} wallets will be able to mint. Claim links for your previous list stop working for wallets not on this one.`,\n act: async () => { await run({ action: \"set_allowlist_root\", root: list.root }); setLinks(dropClaimLinks(window.location.origin, contract, list)); },\n })}>Publish this list</Button>\n )}\n {listed && (\n <Button variant=\"outline\" onClick={() => setPending({\n title: \"Drop opened to everyone\",\n body: \"Anyone will be able to mint, with or without a claim link.\",\n act: () => run({ action: \"set_allowlist_root\", root: \"0x0\" }),\n })}>Open to everyone</Button>\n )}\n {links.length > 0 && <Button variant=\"outline\" onClick={() => downloadCsv(popClaimLinksCsv(links), \"claim-links.csv\")}>Download claim links</Button>}\n </div>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Gift</h3>\n <p className=\"text-sm text-muted-foreground\">\n Mint free tokens to a wallet{left !== null ? ` · ${left.toString()} left` : \"\"}. Gifts don't count toward that wallet's limit.\n </p>\n <div className=\"flex gap-2\">\n <Input placeholder=\"Wallet address\" value={gift.to} onChange={(e) => setGift({ ...gift, to: e.target.value.trim() })} />\n <Input className=\"w-20\" inputMode=\"numeric\" value={gift.quantity} onChange={(e) => setGift({ ...gift, quantity: e.target.value.trim() })} />\n </div>\n <Button\n disabled={parseAllowlist(gift.to).addresses.length !== 1 || !/^[1-9]\\d*$/.test(gift.quantity)}\n onClick={() => setPending({\n title: \"Gift sent\",\n body: `Mint ${gift.quantity} free token(s) to ${gift.to}.`,\n act: () => run({ action: \"issue\", recipient: gift.to, quantity: gift.quantity }),\n })}\n >Send gift</Button>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Share</h3>\n <div className=\"flex gap-2\">\n <Input readOnly value={shareUrl} />\n <ShareButton title={indexed?.name ?? \"Drop\"} url={shareUrl} variant=\"outline\" />\n </div>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Exclusive content</h3>\n <ExclusiveFields value={exclusive} onChange={setExclusive} />\n <div className=\"flex gap-2\">\n <Button disabled={!/^https:\\/\\//.test(exclusive.url)} onClick={() => setPending({ title: \"Exclusive content saved\", body: \"Holders will see this link.\", act: () => saveExclusive(exclusive) })}>Save</Button>\n <Button variant=\"outline\" onClick={() => setPending({ title: \"Exclusive content removed\", body: \"Holders will no longer see a link.\", act: () => saveExclusive(null) })}>Remove</Button>\n </div>\n </section>\n\n <ActionDialog open={pending !== null} onClose={() => !busy && setPending(null)} width={460}>\n <div className=\"space-y-4 p-6\">\n <p className=\"text-sm\">{pending?.body}</p>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={busy} onClick={() => setPending(null)}>Cancel</Button>\n <Button disabled={busy} onClick={() => void confirm()}>{busy ? \"Working…\" : \"Confirm\"}</Button>\n </div>\n </div>\n </ActionDialog>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8DkB;AA5DlB,mBAAyB;AACzB,sBAAsF;AACtF,iBAAyD;AACzD,2BAA6B;AAC7B,oBAAuB;AACvB,mBAAsB;AACtB,sBAAyB;AACzB,0BAA4B;AAC5B,uBAAyB;AACzB,2BAAiC;AACjC,8BAAqD;AACrD,2BAA4B;AAC5B,4BAA8B;AAC9B,uBAA+B;AAC/B,kBAAwC;AAcjC,SAAS,WAAW,EAAE,UAAU,SAAS,SAAS,OAAO,KAAK,cAAc,GAAoB;AACrG,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAkB,IAAI;AACpD,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,KAAK;AACtC,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAwB,IAAI;AAC1D,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAS,EAAE;AAC3C,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAA4C,CAAC,CAAC;AACxE,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,EAAE,IAAI,IAAI,UAAU,IAAI,CAAC;AAC1D,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAyB,EAAE,OAAO,IAAI,KAAK,IAAI,MAAM,GAAG,CAAC;AAC3F,QAAM,SAAS,OAAO,QAAQ,aAAa,MAAM;AACjD,QAAM,OAAO,QAAQ,cAAc,KAAK,OAAO,QAAQ,YAAY,QAAQ;AAC3E,QAAM,WAAW,OAAO,WAAW,kBAAc,qBAAS,QAAQ,IAAI,GAAG,OAAO,SAAS,MAAM,OAAG,qBAAS,QAAQ,CAAC;AAEpH,QAAM,UAAU,YAAY;AAC1B,QAAI,CAAC,QAAS;AACd,YAAQ,IAAI;AACZ,QAAI;AACF,YAAM,QAAQ,IAAI;AAClB,iBAAW,GAAG,QAAQ,KAAK,eAAU;AAAA,IACvC,SAAS,KAAK;AACZ,qBAAW,qCAAc,KAAK,2CAA2C,EAAE,OAAO;AAAA,IACpF,UAAE;AACA,cAAQ,KAAK;AACb,iBAAW,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,aAAS,iCAAe,QAAQ;AACtC,QAAM,OAAO,OAAO,UAAU,SAAS,QAAI,mCAAkB,OAAO,SAAS,IAAI;AACjF,QAAM,WAAW,SAAS,QAAQ,OAAO,KAAK,IAAI,MAAM,OAAO,QAAQ,aAAa;AAEpF,SACE,6CAAC,SAAI,WAAU,aACZ;AAAA,eAAW,4CAAC,OAAE,WAAU,4CAA4C,mBAAQ;AAAA,IAE7E,6CAAC,aAAQ,WAAU,aACjB;AAAA,kDAAC,QAAG,WAAU,yBAAwB,sBAAQ;AAAA,MAC9C,6CAAC,SAAI,WAAU,yCACb;AAAA,oDAAC,6BAAS,OAAM,UAAS,WAAO,yBAAY,QAAQ,YAAY,SAAS,GAAG,QAAQ,UAAU,SAAS,CAAC,GAAG;AAAA,QAC3G,4CAAC,6BAAS,OAAM,WAAU,WAAO,wBAAW,SAAS,WAAW,KAAK,QAAQ,YAAY,GAAG;AAAA,QAC5F,4CAAC,6BAAS,OAAM,cAAa,OAAO,SAAS,cAAc,GAAG;AAAA,SAChE;AAAA,MACA,4CAAC,yCAAiB,OAAc;AAAA,OAClC;AAAA,IAEA,6CAAC,aAAQ,WAAU,aACjB;AAAA,kDAAC,QAAG,WAAU,yBAAwB,0BAAY;AAAA,MAClD,4CAAC,OAAE,WAAU,iCAAiC,mBAAS,wCAAwC,sBAAqB;AAAA,MACpH,4CAAC,4BAAS,MAAM,GAAG,aAAY,wCAAuC,OAAO,UAAU,UAAU,CAAC,MAAM;AAAE,oBAAY,EAAE,OAAO,KAAK;AAAG,iBAAS,CAAC,CAAC;AAAA,MAAG,GAAG;AAAA,MACvJ,OAAO,QAAQ,SAAS,KAAK,6CAAC,OAAE,WAAU,4BAA4B;AAAA,eAAO,QAAQ;AAAA,QAAO;AAAA,QAAmC,OAAO,QAAQ,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AAAA,SAAE;AAAA,MACtK,6CAAC,SAAI,WAAU,wBACZ;AAAA,gBAAQ,YACP,4CAAC,wBAAO,SAAQ,WAAU,SAAS,MAAM,aAAS,gCAAe,OAAO,SAAS,QAAQ,UAAU,IAAI,CAAC,GAAG,kEAA+C;AAAA,QAE3J,QAAQ,CAAC,YAAY,OAAO,QAAQ,WAAW,KAC9C,4CAAC,wBAAO,SAAS,MAAM,WAAW;AAAA,UAChC,OAAO;AAAA,UACP,MAAM,cAAc,OAAO,UAAU,MAAM;AAAA,UAC3C,KAAK,YAAY;AAAE,kBAAM,IAAI,EAAE,QAAQ,sBAAsB,MAAM,KAAK,KAAK,CAAC;AAAG,yBAAS,gCAAe,OAAO,SAAS,QAAQ,UAAU,IAAI,CAAC;AAAA,UAAG;AAAA,QACrJ,CAAC,GAAG,+BAAiB;AAAA,QAEtB,UACC,4CAAC,wBAAO,SAAQ,WAAU,SAAS,MAAM,WAAW;AAAA,UAClD,OAAO;AAAA,UACP,MAAM;AAAA,UACN,KAAK,MAAM,IAAI,EAAE,QAAQ,sBAAsB,MAAM,MAAM,CAAC;AAAA,QAC9D,CAAC,GAAG,8BAAgB;AAAA,QAErB,MAAM,SAAS,KAAK,4CAAC,wBAAO,SAAQ,WAAU,SAAS,UAAM,sCAAY,kCAAiB,KAAK,GAAG,iBAAiB,GAAG,kCAAoB;AAAA,SAC7I;AAAA,OACF;AAAA,IAEA,6CAAC,aAAQ,WAAU,aACjB;AAAA,kDAAC,QAAG,WAAU,yBAAwB,kBAAI;AAAA,MAC1C,6CAAC,OAAE,WAAU,iCAAgC;AAAA;AAAA,QACd,SAAS,OAAO,SAAM,KAAK,SAAS,CAAC,UAAU;AAAA,QAAG;AAAA,SACjF;AAAA,MACA,6CAAC,SAAI,WAAU,cACb;AAAA,oDAAC,sBAAM,aAAY,kBAAiB,OAAO,KAAK,IAAI,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,IAAI,EAAE,OAAO,MAAM,KAAK,EAAE,CAAC,GAAG;AAAA,QACtH,4CAAC,sBAAM,WAAU,QAAO,WAAU,WAAU,OAAO,KAAK,UAAU,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,UAAU,EAAE,OAAO,MAAM,KAAK,EAAE,CAAC,GAAG;AAAA,SAC5I;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,cAAU,iCAAe,KAAK,EAAE,EAAE,UAAU,WAAW,KAAK,CAAC,aAAa,KAAK,KAAK,QAAQ;AAAA,UAC5F,SAAS,MAAM,WAAW;AAAA,YACxB,OAAO;AAAA,YACP,MAAM,QAAQ,KAAK,QAAQ,qBAAqB,KAAK,EAAE;AAAA,YACvD,KAAK,MAAM,IAAI,EAAE,QAAQ,SAAS,WAAW,KAAK,IAAI,UAAU,KAAK,SAAS,CAAC;AAAA,UACjF,CAAC;AAAA,UACF;AAAA;AAAA,MAAS;AAAA,OACZ;AAAA,IAEA,6CAAC,aAAQ,WAAU,aACjB;AAAA,kDAAC,QAAG,WAAU,yBAAwB,mBAAK;AAAA,MAC3C,6CAAC,SAAI,WAAU,cACb;AAAA,oDAAC,sBAAM,UAAQ,MAAC,OAAO,UAAU;AAAA,QACjC,4CAAC,mCAAY,OAAO,SAAS,QAAQ,QAAQ,KAAK,UAAU,SAAQ,WAAU;AAAA,SAChF;AAAA,OACF;AAAA,IAEA,6CAAC,aAAQ,WAAU,aACjB;AAAA,kDAAC,QAAG,WAAU,yBAAwB,+BAAiB;AAAA,MACvD,4CAAC,2CAAgB,OAAO,WAAW,UAAU,cAAc;AAAA,MAC3D,6CAAC,SAAI,WAAU,cACb;AAAA,oDAAC,wBAAO,UAAU,CAAC,cAAc,KAAK,UAAU,GAAG,GAAG,SAAS,MAAM,WAAW,EAAE,OAAO,2BAA2B,MAAM,+BAA+B,KAAK,MAAM,cAAc,SAAS,EAAE,CAAC,GAAG,kBAAI;AAAA,QACrM,4CAAC,wBAAO,SAAQ,WAAU,SAAS,MAAM,WAAW,EAAE,OAAO,6BAA6B,MAAM,sCAAsC,KAAK,MAAM,cAAc,IAAI,EAAE,CAAC,GAAG,oBAAM;AAAA,SACjL;AAAA,OACF;AAAA,IAEA,4CAAC,qCAAa,MAAM,YAAY,MAAM,SAAS,MAAM,CAAC,QAAQ,WAAW,IAAI,GAAG,OAAO,KACrF,uDAAC,SAAI,WAAU,iBACb;AAAA,kDAAC,OAAE,WAAU,WAAW,mBAAS,MAAK;AAAA,MACtC,6CAAC,SAAI,WAAU,0BACb;AAAA,oDAAC,wBAAO,SAAQ,WAAU,UAAU,MAAM,SAAS,MAAM,WAAW,IAAI,GAAG,oBAAM;AAAA,QACjF,4CAAC,wBAAO,UAAU,MAAM,SAAS,MAAM,KAAK,QAAQ,GAAI,iBAAO,kBAAa,WAAU;AAAA,SACxF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/drop/page/drop-manage.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { buildPopAllowlist, dropClaimLinks, popClaimLinksCsv, type DropOnchain } from \"@medialane/sdk/starknet\";\nimport { dropHref, type ApiDrop, type ApiDropMint } from \"@medialane/sdk\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { Button } from \"../../button.js\";\nimport { Input } from \"../../input.js\";\nimport { Textarea } from \"../../textarea.js\";\nimport { ShareButton } from \"../../share-button.js\";\nimport { StatTile } from \"../../stat-tile.js\";\nimport { DropActivityList } from \"./drop-activity.js\";\nimport { ExclusiveFields, type ExclusiveValue } from \"../create/exclusive-fields.js\";\nimport { downloadCsv } from \"../create/launch-dialog.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\nimport { parseAllowlist } from \"../../../utils/drop/allowlist.js\";\nimport { priceLabel, supplyLabel } from \"../../../utils/drop/sale.js\";\n\nexport interface DropManageProps {\n contract: string;\n indexed: ApiDrop | null;\n onchain: DropOnchain;\n mints: ApiDropMint[];\n /** Runs a manage action as one transaction; resolves when confirmed. */\n run: (params: { action: \"issue\"; recipient: string; quantity: string } | { action: \"set_allowlist_root\"; root: string }) => Promise<void>;\n saveExclusive: (value: ExclusiveValue | null) => Promise<void>;\n}\n\ntype Pending = { title: string; body: string; act: () => Promise<void> } | null;\n\nexport function DropManage({ contract, indexed, onchain, mints, run, saveExclusive }: DropManageProps) {\n const [pending, setPending] = useState<Pending>(null);\n const [busy, setBusy] = useState(false);\n const [message, setMessage] = useState<string | null>(null);\n const [listText, setListText] = useState(\"\");\n const [links, setLinks] = useState<ReturnType<typeof dropClaimLinks>>([]);\n const [gift, setGift] = useState({ to: \"\", quantity: \"1\" });\n const [exclusive, setExclusive] = useState<ExclusiveValue>({ title: \"\", url: \"\", type: \"\" });\n const listed = BigInt(onchain.allowlistRoot) !== 0n;\n const left = onchain.maxSupply === 0n ? null : onchain.maxSupply - onchain.totalMinted;\n const shareUrl = typeof window === \"undefined\" ? dropHref(contract) : `${window.location.origin}${dropHref(contract)}`;\n\n const confirm = async () => {\n if (!pending) return;\n setBusy(true);\n try {\n await pending.act();\n setMessage(`${pending.title} — done.`);\n } catch (err) {\n setMessage(describeError(err).message);\n } finally {\n setBusy(false);\n setPending(null);\n }\n };\n\n const parsed = parseAllowlist(listText);\n const list = parsed.addresses.length > 0 ? buildPopAllowlist(parsed.addresses) : null;\n const sameList = list !== null && BigInt(list.root) === BigInt(onchain.allowlistRoot);\n\n return (\n <div className=\"space-y-8\">\n {message && <p className=\"rounded-lg bg-muted/50 px-3 py-2 text-sm\">{message}</p>}\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Overview</h3>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n <StatTile label=\"Minted\" value={supplyLabel(onchain.totalMinted.toString(), onchain.maxSupply.toString())} />\n <StatTile label=\"Revenue\" value={priceLabel(indexed?.revenue ?? \"0\", onchain.paymentToken)} />\n <StatTile label=\"Collectors\" value={indexed?.collectors ?? 0} />\n </div>\n <DropActivityList mints={mints} />\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Who can mint</h3>\n <p className=\"text-sm text-muted-foreground\">{listed ? \"Only wallets on your list can mint.\" : \"Everyone can mint.\"}</p>\n <Textarea rows={5} placeholder=\"Paste wallet addresses, one per line\" value={listText} onChange={(e) => { setListText(e.target.value); setLinks([]); }} />\n {parsed.invalid.length > 0 && <p className=\"text-xs text-destructive\">{parsed.invalid.length} line(s) aren't wallet addresses: {parsed.invalid.slice(0, 3).join(\", \")}</p>}\n <div className=\"flex flex-wrap gap-2\">\n {list && sameList && (\n <Button variant=\"outline\" onClick={() => setLinks(dropClaimLinks(window.location.origin, contract, list))}>This is your current list — get its claim links</Button>\n )}\n {list && !sameList && parsed.invalid.length === 0 && (\n <Button onClick={() => setPending({\n title: \"List published\",\n body: `Only these ${parsed.addresses.length} wallets will be able to mint. Claim links for your previous list stop working for wallets not on this one.`,\n act: async () => { await run({ action: \"set_allowlist_root\", root: list.root }); setLinks(dropClaimLinks(window.location.origin, contract, list)); },\n })}>Publish this list</Button>\n )}\n {listed && (\n <Button variant=\"outline\" onClick={() => setPending({\n title: \"Drop opened to everyone\",\n body: \"Anyone will be able to mint, with or without a claim link.\",\n act: () => run({ action: \"set_allowlist_root\", root: \"0x0\" }),\n })}>Open to everyone</Button>\n )}\n {links.length > 0 && <Button variant=\"outline\" onClick={() => downloadCsv(popClaimLinksCsv(links), \"claim-links.csv\")}>Download claim links</Button>}\n </div>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Gift</h3>\n <p className=\"text-sm text-muted-foreground\">\n Mint free tokens to a wallet{left !== null ? ` · ${left.toString()} left` : \"\"}. Gifts don't count toward that wallet's limit.\n </p>\n <div className=\"flex gap-2\">\n <Input placeholder=\"Wallet address\" value={gift.to} onChange={(e) => setGift({ ...gift, to: e.target.value.trim() })} />\n <Input className=\"w-20\" inputMode=\"numeric\" value={gift.quantity} onChange={(e) => setGift({ ...gift, quantity: e.target.value.trim() })} />\n </div>\n <Button\n disabled={parseAllowlist(gift.to).addresses.length !== 1 || !/^[1-9]\\d*$/.test(gift.quantity)}\n onClick={() => setPending({\n title: \"Gift sent\",\n body: `Mint ${gift.quantity} free token(s) to ${gift.to}.`,\n act: () => run({ action: \"issue\", recipient: gift.to, quantity: gift.quantity }),\n })}\n >Send gift</Button>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Share</h3>\n <div className=\"flex gap-2\">\n <Input readOnly value={shareUrl} />\n <ShareButton title={indexed?.name ?? \"Drop\"} url={shareUrl} variant=\"outline\" />\n </div>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Exclusive content</h3>\n <ExclusiveFields value={exclusive} onChange={setExclusive} />\n <div className=\"flex gap-2\">\n <Button disabled={!/^https:\\/\\//.test(exclusive.url)} onClick={() => setPending({ title: \"Exclusive content saved\", body: \"Holders will see this link.\", act: () => saveExclusive(exclusive) })}>Save</Button>\n <Button variant=\"outline\" onClick={() => setPending({ title: \"Exclusive content removed\", body: \"Holders will no longer see a link.\", act: () => saveExclusive(null) })}>Remove</Button>\n </div>\n </section>\n\n <ActionDialog open={pending !== null} onClose={() => !busy && setPending(null)} width={460}>\n <div className=\"space-y-4 p-6\">\n <p className=\"text-sm\">{pending?.body}</p>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={busy} onClick={() => setPending(null)}>Cancel</Button>\n <Button disabled={busy} onClick={() => void confirm()}>{busy ? \"Working…\" : \"Confirm\"}</Button>\n </div>\n </div>\n </ActionDialog>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -33,7 +33,7 @@ function DropManage({ contract, indexed, onchain, mints, run, saveExclusive }) {
|
|
|
33
33
|
await pending.act();
|
|
34
34
|
setMessage(`${pending.title} \u2014 done.`);
|
|
35
35
|
} catch (err) {
|
|
36
|
-
setMessage(describeError(err
|
|
36
|
+
setMessage(describeError(err).message);
|
|
37
37
|
} finally {
|
|
38
38
|
setBusy(false);
|
|
39
39
|
setPending(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/drop/page/drop-manage.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { buildPopAllowlist, dropClaimLinks, popClaimLinksCsv, type DropOnchain } from \"@medialane/sdk/starknet\";\nimport { dropHref, type ApiDrop, type ApiDropMint } from \"@medialane/sdk\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { Button } from \"../../button.js\";\nimport { Input } from \"../../input.js\";\nimport { Textarea } from \"../../textarea.js\";\nimport { ShareButton } from \"../../share-button.js\";\nimport { StatTile } from \"../../stat-tile.js\";\nimport { DropActivityList } from \"./drop-activity.js\";\nimport { ExclusiveFields, type ExclusiveValue } from \"../create/exclusive-fields.js\";\nimport { downloadCsv } from \"../create/launch-dialog.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\nimport { parseAllowlist } from \"../../../utils/drop/allowlist.js\";\nimport { priceLabel, supplyLabel } from \"../../../utils/drop/sale.js\";\n\nexport interface DropManageProps {\n contract: string;\n indexed: ApiDrop | null;\n onchain: DropOnchain;\n mints: ApiDropMint[];\n /** Runs a manage action as one transaction; resolves when confirmed. */\n run: (params: { action: \"issue\"; recipient: string; quantity: string } | { action: \"set_allowlist_root\"; root: string }) => Promise<void>;\n saveExclusive: (value: ExclusiveValue | null) => Promise<void>;\n}\n\ntype Pending = { title: string; body: string; act: () => Promise<void> } | null;\n\nexport function DropManage({ contract, indexed, onchain, mints, run, saveExclusive }: DropManageProps) {\n const [pending, setPending] = useState<Pending>(null);\n const [busy, setBusy] = useState(false);\n const [message, setMessage] = useState<string | null>(null);\n const [listText, setListText] = useState(\"\");\n const [links, setLinks] = useState<ReturnType<typeof dropClaimLinks>>([]);\n const [gift, setGift] = useState({ to: \"\", quantity: \"1\" });\n const [exclusive, setExclusive] = useState<ExclusiveValue>({ title: \"\", url: \"\", type: \"\" });\n const listed = BigInt(onchain.allowlistRoot) !== 0n;\n const left = onchain.maxSupply === 0n ? null : onchain.maxSupply - onchain.totalMinted;\n const shareUrl = typeof window === \"undefined\" ? dropHref(contract) : `${window.location.origin}${dropHref(contract)}`;\n\n const confirm = async () => {\n if (!pending) return;\n setBusy(true);\n try {\n await pending.act();\n setMessage(`${pending.title} — done.`);\n } catch (err) {\n setMessage(describeError(err, \"That didn't go through. Please try again.\").message);\n } finally {\n setBusy(false);\n setPending(null);\n }\n };\n\n const parsed = parseAllowlist(listText);\n const list = parsed.addresses.length > 0 ? buildPopAllowlist(parsed.addresses) : null;\n const sameList = list !== null && BigInt(list.root) === BigInt(onchain.allowlistRoot);\n\n return (\n <div className=\"space-y-8\">\n {message && <p className=\"rounded-lg bg-muted/50 px-3 py-2 text-sm\">{message}</p>}\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Overview</h3>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n <StatTile label=\"Minted\" value={supplyLabel(onchain.totalMinted.toString(), onchain.maxSupply.toString())} />\n <StatTile label=\"Revenue\" value={priceLabel(indexed?.revenue ?? \"0\", onchain.paymentToken)} />\n <StatTile label=\"Collectors\" value={indexed?.collectors ?? 0} />\n </div>\n <DropActivityList mints={mints} />\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Who can mint</h3>\n <p className=\"text-sm text-muted-foreground\">{listed ? \"Only wallets on your list can mint.\" : \"Everyone can mint.\"}</p>\n <Textarea rows={5} placeholder=\"Paste wallet addresses, one per line\" value={listText} onChange={(e) => { setListText(e.target.value); setLinks([]); }} />\n {parsed.invalid.length > 0 && <p className=\"text-xs text-destructive\">{parsed.invalid.length} line(s) aren't wallet addresses: {parsed.invalid.slice(0, 3).join(\", \")}</p>}\n <div className=\"flex flex-wrap gap-2\">\n {list && sameList && (\n <Button variant=\"outline\" onClick={() => setLinks(dropClaimLinks(window.location.origin, contract, list))}>This is your current list — get its claim links</Button>\n )}\n {list && !sameList && parsed.invalid.length === 0 && (\n <Button onClick={() => setPending({\n title: \"List published\",\n body: `Only these ${parsed.addresses.length} wallets will be able to mint. Claim links for your previous list stop working for wallets not on this one.`,\n act: async () => { await run({ action: \"set_allowlist_root\", root: list.root }); setLinks(dropClaimLinks(window.location.origin, contract, list)); },\n })}>Publish this list</Button>\n )}\n {listed && (\n <Button variant=\"outline\" onClick={() => setPending({\n title: \"Drop opened to everyone\",\n body: \"Anyone will be able to mint, with or without a claim link.\",\n act: () => run({ action: \"set_allowlist_root\", root: \"0x0\" }),\n })}>Open to everyone</Button>\n )}\n {links.length > 0 && <Button variant=\"outline\" onClick={() => downloadCsv(popClaimLinksCsv(links), \"claim-links.csv\")}>Download claim links</Button>}\n </div>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Gift</h3>\n <p className=\"text-sm text-muted-foreground\">\n Mint free tokens to a wallet{left !== null ? ` · ${left.toString()} left` : \"\"}. Gifts don't count toward that wallet's limit.\n </p>\n <div className=\"flex gap-2\">\n <Input placeholder=\"Wallet address\" value={gift.to} onChange={(e) => setGift({ ...gift, to: e.target.value.trim() })} />\n <Input className=\"w-20\" inputMode=\"numeric\" value={gift.quantity} onChange={(e) => setGift({ ...gift, quantity: e.target.value.trim() })} />\n </div>\n <Button\n disabled={parseAllowlist(gift.to).addresses.length !== 1 || !/^[1-9]\\d*$/.test(gift.quantity)}\n onClick={() => setPending({\n title: \"Gift sent\",\n body: `Mint ${gift.quantity} free token(s) to ${gift.to}.`,\n act: () => run({ action: \"issue\", recipient: gift.to, quantity: gift.quantity }),\n })}\n >Send gift</Button>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Share</h3>\n <div className=\"flex gap-2\">\n <Input readOnly value={shareUrl} />\n <ShareButton title={indexed?.name ?? \"Drop\"} url={shareUrl} variant=\"outline\" />\n </div>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Exclusive content</h3>\n <ExclusiveFields value={exclusive} onChange={setExclusive} />\n <div className=\"flex gap-2\">\n <Button disabled={!/^https:\\/\\//.test(exclusive.url)} onClick={() => setPending({ title: \"Exclusive content saved\", body: \"Holders will see this link.\", act: () => saveExclusive(exclusive) })}>Save</Button>\n <Button variant=\"outline\" onClick={() => setPending({ title: \"Exclusive content removed\", body: \"Holders will no longer see a link.\", act: () => saveExclusive(null) })}>Remove</Button>\n </div>\n </section>\n\n <ActionDialog open={pending !== null} onClose={() => !busy && setPending(null)} width={460}>\n <div className=\"space-y-4 p-6\">\n <p className=\"text-sm\">{pending?.body}</p>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={busy} onClick={() => setPending(null)}>Cancel</Button>\n <Button disabled={busy} onClick={() => void confirm()}>{busy ? \"Working…\" : \"Confirm\"}</Button>\n </div>\n </div>\n </ActionDialog>\n </div>\n );\n}\n"],"mappings":";AA8DkB,cAIV,YAJU;AA5DlB,SAAS,gBAAgB;AACzB,SAAS,mBAAmB,gBAAgB,wBAA0C;AACtF,SAAS,gBAAgD;AACzD,SAAS,oBAAoB;AAC7B,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB;AACzB,SAAS,wBAAwB;AACjC,SAAS,uBAA4C;AACrD,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,YAAY,mBAAmB;AAcjC,SAAS,WAAW,EAAE,UAAU,SAAS,SAAS,OAAO,KAAK,cAAc,GAAoB;AACrG,QAAM,CAAC,SAAS,UAAU,IAAI,SAAkB,IAAI;AACpD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAwB,IAAI;AAC1D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,EAAE;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA4C,CAAC,CAAC;AACxE,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE,IAAI,IAAI,UAAU,IAAI,CAAC;AAC1D,QAAM,CAAC,WAAW,YAAY,IAAI,SAAyB,EAAE,OAAO,IAAI,KAAK,IAAI,MAAM,GAAG,CAAC;AAC3F,QAAM,SAAS,OAAO,QAAQ,aAAa,MAAM;AACjD,QAAM,OAAO,QAAQ,cAAc,KAAK,OAAO,QAAQ,YAAY,QAAQ;AAC3E,QAAM,WAAW,OAAO,WAAW,cAAc,SAAS,QAAQ,IAAI,GAAG,OAAO,SAAS,MAAM,GAAG,SAAS,QAAQ,CAAC;AAEpH,QAAM,UAAU,YAAY;AAC1B,QAAI,CAAC,QAAS;AACd,YAAQ,IAAI;AACZ,QAAI;AACF,YAAM,QAAQ,IAAI;AAClB,iBAAW,GAAG,QAAQ,KAAK,eAAU;AAAA,IACvC,SAAS,KAAK;AACZ,iBAAW,cAAc,KAAK,2CAA2C,EAAE,OAAO;AAAA,IACpF,UAAE;AACA,cAAQ,KAAK;AACb,iBAAW,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,SAAS,eAAe,QAAQ;AACtC,QAAM,OAAO,OAAO,UAAU,SAAS,IAAI,kBAAkB,OAAO,SAAS,IAAI;AACjF,QAAM,WAAW,SAAS,QAAQ,OAAO,KAAK,IAAI,MAAM,OAAO,QAAQ,aAAa;AAEpF,SACE,qBAAC,SAAI,WAAU,aACZ;AAAA,eAAW,oBAAC,OAAE,WAAU,4CAA4C,mBAAQ;AAAA,IAE7E,qBAAC,aAAQ,WAAU,aACjB;AAAA,0BAAC,QAAG,WAAU,yBAAwB,sBAAQ;AAAA,MAC9C,qBAAC,SAAI,WAAU,yCACb;AAAA,4BAAC,YAAS,OAAM,UAAS,OAAO,YAAY,QAAQ,YAAY,SAAS,GAAG,QAAQ,UAAU,SAAS,CAAC,GAAG;AAAA,QAC3G,oBAAC,YAAS,OAAM,WAAU,OAAO,WAAW,SAAS,WAAW,KAAK,QAAQ,YAAY,GAAG;AAAA,QAC5F,oBAAC,YAAS,OAAM,cAAa,OAAO,SAAS,cAAc,GAAG;AAAA,SAChE;AAAA,MACA,oBAAC,oBAAiB,OAAc;AAAA,OAClC;AAAA,IAEA,qBAAC,aAAQ,WAAU,aACjB;AAAA,0BAAC,QAAG,WAAU,yBAAwB,0BAAY;AAAA,MAClD,oBAAC,OAAE,WAAU,iCAAiC,mBAAS,wCAAwC,sBAAqB;AAAA,MACpH,oBAAC,YAAS,MAAM,GAAG,aAAY,wCAAuC,OAAO,UAAU,UAAU,CAAC,MAAM;AAAE,oBAAY,EAAE,OAAO,KAAK;AAAG,iBAAS,CAAC,CAAC;AAAA,MAAG,GAAG;AAAA,MACvJ,OAAO,QAAQ,SAAS,KAAK,qBAAC,OAAE,WAAU,4BAA4B;AAAA,eAAO,QAAQ;AAAA,QAAO;AAAA,QAAmC,OAAO,QAAQ,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AAAA,SAAE;AAAA,MACtK,qBAAC,SAAI,WAAU,wBACZ;AAAA,gBAAQ,YACP,oBAAC,UAAO,SAAQ,WAAU,SAAS,MAAM,SAAS,eAAe,OAAO,SAAS,QAAQ,UAAU,IAAI,CAAC,GAAG,kEAA+C;AAAA,QAE3J,QAAQ,CAAC,YAAY,OAAO,QAAQ,WAAW,KAC9C,oBAAC,UAAO,SAAS,MAAM,WAAW;AAAA,UAChC,OAAO;AAAA,UACP,MAAM,cAAc,OAAO,UAAU,MAAM;AAAA,UAC3C,KAAK,YAAY;AAAE,kBAAM,IAAI,EAAE,QAAQ,sBAAsB,MAAM,KAAK,KAAK,CAAC;AAAG,qBAAS,eAAe,OAAO,SAAS,QAAQ,UAAU,IAAI,CAAC;AAAA,UAAG;AAAA,QACrJ,CAAC,GAAG,+BAAiB;AAAA,QAEtB,UACC,oBAAC,UAAO,SAAQ,WAAU,SAAS,MAAM,WAAW;AAAA,UAClD,OAAO;AAAA,UACP,MAAM;AAAA,UACN,KAAK,MAAM,IAAI,EAAE,QAAQ,sBAAsB,MAAM,MAAM,CAAC;AAAA,QAC9D,CAAC,GAAG,8BAAgB;AAAA,QAErB,MAAM,SAAS,KAAK,oBAAC,UAAO,SAAQ,WAAU,SAAS,MAAM,YAAY,iBAAiB,KAAK,GAAG,iBAAiB,GAAG,kCAAoB;AAAA,SAC7I;AAAA,OACF;AAAA,IAEA,qBAAC,aAAQ,WAAU,aACjB;AAAA,0BAAC,QAAG,WAAU,yBAAwB,kBAAI;AAAA,MAC1C,qBAAC,OAAE,WAAU,iCAAgC;AAAA;AAAA,QACd,SAAS,OAAO,SAAM,KAAK,SAAS,CAAC,UAAU;AAAA,QAAG;AAAA,SACjF;AAAA,MACA,qBAAC,SAAI,WAAU,cACb;AAAA,4BAAC,SAAM,aAAY,kBAAiB,OAAO,KAAK,IAAI,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,IAAI,EAAE,OAAO,MAAM,KAAK,EAAE,CAAC,GAAG;AAAA,QACtH,oBAAC,SAAM,WAAU,QAAO,WAAU,WAAU,OAAO,KAAK,UAAU,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,UAAU,EAAE,OAAO,MAAM,KAAK,EAAE,CAAC,GAAG;AAAA,SAC5I;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,UAAU,eAAe,KAAK,EAAE,EAAE,UAAU,WAAW,KAAK,CAAC,aAAa,KAAK,KAAK,QAAQ;AAAA,UAC5F,SAAS,MAAM,WAAW;AAAA,YACxB,OAAO;AAAA,YACP,MAAM,QAAQ,KAAK,QAAQ,qBAAqB,KAAK,EAAE;AAAA,YACvD,KAAK,MAAM,IAAI,EAAE,QAAQ,SAAS,WAAW,KAAK,IAAI,UAAU,KAAK,SAAS,CAAC;AAAA,UACjF,CAAC;AAAA,UACF;AAAA;AAAA,MAAS;AAAA,OACZ;AAAA,IAEA,qBAAC,aAAQ,WAAU,aACjB;AAAA,0BAAC,QAAG,WAAU,yBAAwB,mBAAK;AAAA,MAC3C,qBAAC,SAAI,WAAU,cACb;AAAA,4BAAC,SAAM,UAAQ,MAAC,OAAO,UAAU;AAAA,QACjC,oBAAC,eAAY,OAAO,SAAS,QAAQ,QAAQ,KAAK,UAAU,SAAQ,WAAU;AAAA,SAChF;AAAA,OACF;AAAA,IAEA,qBAAC,aAAQ,WAAU,aACjB;AAAA,0BAAC,QAAG,WAAU,yBAAwB,+BAAiB;AAAA,MACvD,oBAAC,mBAAgB,OAAO,WAAW,UAAU,cAAc;AAAA,MAC3D,qBAAC,SAAI,WAAU,cACb;AAAA,4BAAC,UAAO,UAAU,CAAC,cAAc,KAAK,UAAU,GAAG,GAAG,SAAS,MAAM,WAAW,EAAE,OAAO,2BAA2B,MAAM,+BAA+B,KAAK,MAAM,cAAc,SAAS,EAAE,CAAC,GAAG,kBAAI;AAAA,QACrM,oBAAC,UAAO,SAAQ,WAAU,SAAS,MAAM,WAAW,EAAE,OAAO,6BAA6B,MAAM,sCAAsC,KAAK,MAAM,cAAc,IAAI,EAAE,CAAC,GAAG,oBAAM;AAAA,SACjL;AAAA,OACF;AAAA,IAEA,oBAAC,gBAAa,MAAM,YAAY,MAAM,SAAS,MAAM,CAAC,QAAQ,WAAW,IAAI,GAAG,OAAO,KACrF,+BAAC,SAAI,WAAU,iBACb;AAAA,0BAAC,OAAE,WAAU,WAAW,mBAAS,MAAK;AAAA,MACtC,qBAAC,SAAI,WAAU,0BACb;AAAA,4BAAC,UAAO,SAAQ,WAAU,UAAU,MAAM,SAAS,MAAM,WAAW,IAAI,GAAG,oBAAM;AAAA,QACjF,oBAAC,UAAO,UAAU,MAAM,SAAS,MAAM,KAAK,QAAQ,GAAI,iBAAO,kBAAa,WAAU;AAAA,SACxF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/drop/page/drop-manage.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { buildPopAllowlist, dropClaimLinks, popClaimLinksCsv, type DropOnchain } from \"@medialane/sdk/starknet\";\nimport { dropHref, type ApiDrop, type ApiDropMint } from \"@medialane/sdk\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { Button } from \"../../button.js\";\nimport { Input } from \"../../input.js\";\nimport { Textarea } from \"../../textarea.js\";\nimport { ShareButton } from \"../../share-button.js\";\nimport { StatTile } from \"../../stat-tile.js\";\nimport { DropActivityList } from \"./drop-activity.js\";\nimport { ExclusiveFields, type ExclusiveValue } from \"../create/exclusive-fields.js\";\nimport { downloadCsv } from \"../create/launch-dialog.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\nimport { parseAllowlist } from \"../../../utils/drop/allowlist.js\";\nimport { priceLabel, supplyLabel } from \"../../../utils/drop/sale.js\";\n\nexport interface DropManageProps {\n contract: string;\n indexed: ApiDrop | null;\n onchain: DropOnchain;\n mints: ApiDropMint[];\n /** Runs a manage action as one transaction; resolves when confirmed. */\n run: (params: { action: \"issue\"; recipient: string; quantity: string } | { action: \"set_allowlist_root\"; root: string }) => Promise<void>;\n saveExclusive: (value: ExclusiveValue | null) => Promise<void>;\n}\n\ntype Pending = { title: string; body: string; act: () => Promise<void> } | null;\n\nexport function DropManage({ contract, indexed, onchain, mints, run, saveExclusive }: DropManageProps) {\n const [pending, setPending] = useState<Pending>(null);\n const [busy, setBusy] = useState(false);\n const [message, setMessage] = useState<string | null>(null);\n const [listText, setListText] = useState(\"\");\n const [links, setLinks] = useState<ReturnType<typeof dropClaimLinks>>([]);\n const [gift, setGift] = useState({ to: \"\", quantity: \"1\" });\n const [exclusive, setExclusive] = useState<ExclusiveValue>({ title: \"\", url: \"\", type: \"\" });\n const listed = BigInt(onchain.allowlistRoot) !== 0n;\n const left = onchain.maxSupply === 0n ? null : onchain.maxSupply - onchain.totalMinted;\n const shareUrl = typeof window === \"undefined\" ? dropHref(contract) : `${window.location.origin}${dropHref(contract)}`;\n\n const confirm = async () => {\n if (!pending) return;\n setBusy(true);\n try {\n await pending.act();\n setMessage(`${pending.title} — done.`);\n } catch (err) {\n setMessage(describeError(err).message);\n } finally {\n setBusy(false);\n setPending(null);\n }\n };\n\n const parsed = parseAllowlist(listText);\n const list = parsed.addresses.length > 0 ? buildPopAllowlist(parsed.addresses) : null;\n const sameList = list !== null && BigInt(list.root) === BigInt(onchain.allowlistRoot);\n\n return (\n <div className=\"space-y-8\">\n {message && <p className=\"rounded-lg bg-muted/50 px-3 py-2 text-sm\">{message}</p>}\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Overview</h3>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n <StatTile label=\"Minted\" value={supplyLabel(onchain.totalMinted.toString(), onchain.maxSupply.toString())} />\n <StatTile label=\"Revenue\" value={priceLabel(indexed?.revenue ?? \"0\", onchain.paymentToken)} />\n <StatTile label=\"Collectors\" value={indexed?.collectors ?? 0} />\n </div>\n <DropActivityList mints={mints} />\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Who can mint</h3>\n <p className=\"text-sm text-muted-foreground\">{listed ? \"Only wallets on your list can mint.\" : \"Everyone can mint.\"}</p>\n <Textarea rows={5} placeholder=\"Paste wallet addresses, one per line\" value={listText} onChange={(e) => { setListText(e.target.value); setLinks([]); }} />\n {parsed.invalid.length > 0 && <p className=\"text-xs text-destructive\">{parsed.invalid.length} line(s) aren't wallet addresses: {parsed.invalid.slice(0, 3).join(\", \")}</p>}\n <div className=\"flex flex-wrap gap-2\">\n {list && sameList && (\n <Button variant=\"outline\" onClick={() => setLinks(dropClaimLinks(window.location.origin, contract, list))}>This is your current list — get its claim links</Button>\n )}\n {list && !sameList && parsed.invalid.length === 0 && (\n <Button onClick={() => setPending({\n title: \"List published\",\n body: `Only these ${parsed.addresses.length} wallets will be able to mint. Claim links for your previous list stop working for wallets not on this one.`,\n act: async () => { await run({ action: \"set_allowlist_root\", root: list.root }); setLinks(dropClaimLinks(window.location.origin, contract, list)); },\n })}>Publish this list</Button>\n )}\n {listed && (\n <Button variant=\"outline\" onClick={() => setPending({\n title: \"Drop opened to everyone\",\n body: \"Anyone will be able to mint, with or without a claim link.\",\n act: () => run({ action: \"set_allowlist_root\", root: \"0x0\" }),\n })}>Open to everyone</Button>\n )}\n {links.length > 0 && <Button variant=\"outline\" onClick={() => downloadCsv(popClaimLinksCsv(links), \"claim-links.csv\")}>Download claim links</Button>}\n </div>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Gift</h3>\n <p className=\"text-sm text-muted-foreground\">\n Mint free tokens to a wallet{left !== null ? ` · ${left.toString()} left` : \"\"}. Gifts don't count toward that wallet's limit.\n </p>\n <div className=\"flex gap-2\">\n <Input placeholder=\"Wallet address\" value={gift.to} onChange={(e) => setGift({ ...gift, to: e.target.value.trim() })} />\n <Input className=\"w-20\" inputMode=\"numeric\" value={gift.quantity} onChange={(e) => setGift({ ...gift, quantity: e.target.value.trim() })} />\n </div>\n <Button\n disabled={parseAllowlist(gift.to).addresses.length !== 1 || !/^[1-9]\\d*$/.test(gift.quantity)}\n onClick={() => setPending({\n title: \"Gift sent\",\n body: `Mint ${gift.quantity} free token(s) to ${gift.to}.`,\n act: () => run({ action: \"issue\", recipient: gift.to, quantity: gift.quantity }),\n })}\n >Send gift</Button>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Share</h3>\n <div className=\"flex gap-2\">\n <Input readOnly value={shareUrl} />\n <ShareButton title={indexed?.name ?? \"Drop\"} url={shareUrl} variant=\"outline\" />\n </div>\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">Exclusive content</h3>\n <ExclusiveFields value={exclusive} onChange={setExclusive} />\n <div className=\"flex gap-2\">\n <Button disabled={!/^https:\\/\\//.test(exclusive.url)} onClick={() => setPending({ title: \"Exclusive content saved\", body: \"Holders will see this link.\", act: () => saveExclusive(exclusive) })}>Save</Button>\n <Button variant=\"outline\" onClick={() => setPending({ title: \"Exclusive content removed\", body: \"Holders will no longer see a link.\", act: () => saveExclusive(null) })}>Remove</Button>\n </div>\n </section>\n\n <ActionDialog open={pending !== null} onClose={() => !busy && setPending(null)} width={460}>\n <div className=\"space-y-4 p-6\">\n <p className=\"text-sm\">{pending?.body}</p>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={busy} onClick={() => setPending(null)}>Cancel</Button>\n <Button disabled={busy} onClick={() => void confirm()}>{busy ? \"Working…\" : \"Confirm\"}</Button>\n </div>\n </div>\n </ActionDialog>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -44,7 +44,7 @@ function DropMintDialog({
|
|
|
44
44
|
try {
|
|
45
45
|
setStep({ kind: "done", tokenIds: (await onMint()).tokenIds });
|
|
46
46
|
} catch (err) {
|
|
47
|
-
setStep({ kind: "error", message: (0, import_describe_error.describeError)(err
|
|
47
|
+
setStep({ kind: "error", message: (0, import_describe_error.describeError)(err).message });
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
50
|
const close = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/drop/page/drop-mint-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { CheckCircle2, Loader2, XCircle } from \"lucide-react\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { GradientButton } from \"../../gradient-button.js\";\nimport { Button } from \"../../button.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\n\ntype Step = { kind: \"confirm\" } | { kind: \"minting\" } | { kind: \"done\"; tokenIds: string[] } | { kind: \"error\"; message: string };\n\nexport function DropMintDialog({\n open, onClose, name, quantity, totalText, onMint, portfolioHref,\n}: {\n open: boolean;\n onClose: () => void;\n name: string;\n quantity: bigint;\n totalText: string | null;\n onMint: () => Promise<{ tokenIds: string[] }>;\n portfolioHref: string;\n}) {\n const [step, setStep] = useState<Step>({ kind: \"confirm\" });\n const mint = async () => {\n setStep({ kind: \"minting\" });\n try {\n setStep({ kind: \"done\", tokenIds: (await onMint()).tokenIds });\n } catch (err) {\n setStep({ kind: \"error\", message: describeError(err
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/drop/page/drop-mint-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { CheckCircle2, Loader2, XCircle } from \"lucide-react\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { GradientButton } from \"../../gradient-button.js\";\nimport { Button } from \"../../button.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\n\ntype Step = { kind: \"confirm\" } | { kind: \"minting\" } | { kind: \"done\"; tokenIds: string[] } | { kind: \"error\"; message: string };\n\nexport function DropMintDialog({\n open, onClose, name, quantity, totalText, onMint, portfolioHref,\n}: {\n open: boolean;\n onClose: () => void;\n name: string;\n quantity: bigint;\n totalText: string | null;\n onMint: () => Promise<{ tokenIds: string[] }>;\n portfolioHref: string;\n}) {\n const [step, setStep] = useState<Step>({ kind: \"confirm\" });\n const mint = async () => {\n setStep({ kind: \"minting\" });\n try {\n setStep({ kind: \"done\", tokenIds: (await onMint()).tokenIds });\n } catch (err) {\n setStep({ kind: \"error\", message: describeError(err).message });\n }\n };\n const close = () => {\n if (step.kind === \"minting\") return;\n setStep({ kind: \"confirm\" });\n onClose();\n };\n return (\n <ActionDialog open={open} onClose={close} width={460}>\n <div className=\"space-y-5 p-6\">\n {step.kind === \"confirm\" && (\n <>\n <h2 className=\"text-lg font-semibold\">Mint {quantity.toString()} from {name}</h2>\n {totalText && <p className=\"text-sm text-muted-foreground\">{totalText}</p>}\n <GradientButton big onClick={() => void mint()}>Confirm mint</GradientButton>\n </>\n )}\n {step.kind === \"minting\" && <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Minting…</h2>}\n {step.kind === \"done\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><CheckCircle2 className=\"h-5 w-5 text-green-500\" />Minted</h2>\n <Button asChild><a href={portfolioHref}>View in portfolio</a></Button>\n </>\n )}\n {step.kind === \"error\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><XCircle className=\"h-4 w-4 text-destructive\" />Not minted</h2>\n <p className=\"text-sm text-muted-foreground\">{step.message}</p>\n <Button onClick={() => void mint()}>Try again</Button>\n </>\n )}\n </div>\n </ActionDialog>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwCU;AAtCV,mBAAyB;AACzB,0BAA+C;AAC/C,2BAA6B;AAC7B,6BAA+B;AAC/B,oBAAuB;AACvB,4BAA8B;AAIvB,SAAS,eAAe;AAAA,EAC7B;AAAA,EAAM;AAAA,EAAS;AAAA,EAAM;AAAA,EAAU;AAAA,EAAW;AAAA,EAAQ;AACpD,GAQG;AACD,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAe,EAAE,MAAM,UAAU,CAAC;AAC1D,QAAM,OAAO,YAAY;AACvB,YAAQ,EAAE,MAAM,UAAU,CAAC;AAC3B,QAAI;AACF,cAAQ,EAAE,MAAM,QAAQ,WAAW,MAAM,OAAO,GAAG,SAAS,CAAC;AAAA,IAC/D,SAAS,KAAK;AACZ,cAAQ,EAAE,MAAM,SAAS,aAAS,qCAAc,GAAG,EAAE,QAAQ,CAAC;AAAA,IAChE;AAAA,EACF;AACA,QAAM,QAAQ,MAAM;AAClB,QAAI,KAAK,SAAS,UAAW;AAC7B,YAAQ,EAAE,MAAM,UAAU,CAAC;AAC3B,YAAQ;AAAA,EACV;AACA,SACE,4CAAC,qCAAa,MAAY,SAAS,OAAO,OAAO,KAC/C,uDAAC,SAAI,WAAU,iBACZ;AAAA,SAAK,SAAS,aACb,4EACE;AAAA,mDAAC,QAAG,WAAU,yBAAwB;AAAA;AAAA,QAAM,SAAS,SAAS;AAAA,QAAE;AAAA,QAAO;AAAA,SAAK;AAAA,MAC3E,aAAa,4CAAC,OAAE,WAAU,iCAAiC,qBAAU;AAAA,MACtE,4CAAC,yCAAe,KAAG,MAAC,SAAS,MAAM,KAAK,KAAK,GAAG,0BAAY;AAAA,OAC9D;AAAA,IAED,KAAK,SAAS,aAAa,6CAAC,QAAG,WAAU,iDAAgD;AAAA,kDAAC,+BAAQ,WAAU,wBAAuB;AAAA,MAAE;AAAA,OAAQ;AAAA,IAC7I,KAAK,SAAS,UACb,4EACE;AAAA,mDAAC,QAAG,WAAU,iDAAgD;AAAA,oDAAC,oCAAa,WAAU,0BAAyB;AAAA,QAAE;AAAA,SAAM;AAAA,MACvH,4CAAC,wBAAO,SAAO,MAAC,sDAAC,OAAE,MAAM,eAAe,+BAAiB,GAAI;AAAA,OAC/D;AAAA,IAED,KAAK,SAAS,WACb,4EACE;AAAA,mDAAC,QAAG,WAAU,iDAAgD;AAAA,oDAAC,+BAAQ,WAAU,4BAA2B;AAAA,QAAE;AAAA,SAAU;AAAA,MACxH,4CAAC,OAAE,WAAU,iCAAiC,eAAK,SAAQ;AAAA,MAC3D,4CAAC,wBAAO,SAAS,MAAM,KAAK,KAAK,GAAG,uBAAS;AAAA,OAC/C;AAAA,KAEJ,GACF;AAEJ;","names":[]}
|
|
@@ -21,7 +21,7 @@ function DropMintDialog({
|
|
|
21
21
|
try {
|
|
22
22
|
setStep({ kind: "done", tokenIds: (await onMint()).tokenIds });
|
|
23
23
|
} catch (err) {
|
|
24
|
-
setStep({ kind: "error", message: describeError(err
|
|
24
|
+
setStep({ kind: "error", message: describeError(err).message });
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
const close = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/drop/page/drop-mint-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { CheckCircle2, Loader2, XCircle } from \"lucide-react\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { GradientButton } from \"../../gradient-button.js\";\nimport { Button } from \"../../button.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\n\ntype Step = { kind: \"confirm\" } | { kind: \"minting\" } | { kind: \"done\"; tokenIds: string[] } | { kind: \"error\"; message: string };\n\nexport function DropMintDialog({\n open, onClose, name, quantity, totalText, onMint, portfolioHref,\n}: {\n open: boolean;\n onClose: () => void;\n name: string;\n quantity: bigint;\n totalText: string | null;\n onMint: () => Promise<{ tokenIds: string[] }>;\n portfolioHref: string;\n}) {\n const [step, setStep] = useState<Step>({ kind: \"confirm\" });\n const mint = async () => {\n setStep({ kind: \"minting\" });\n try {\n setStep({ kind: \"done\", tokenIds: (await onMint()).tokenIds });\n } catch (err) {\n setStep({ kind: \"error\", message: describeError(err
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/drop/page/drop-mint-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { CheckCircle2, Loader2, XCircle } from \"lucide-react\";\nimport { ActionDialog } from \"../../action-dialog.js\";\nimport { GradientButton } from \"../../gradient-button.js\";\nimport { Button } from \"../../button.js\";\nimport { describeError } from \"../../../utils/describe-error.js\";\n\ntype Step = { kind: \"confirm\" } | { kind: \"minting\" } | { kind: \"done\"; tokenIds: string[] } | { kind: \"error\"; message: string };\n\nexport function DropMintDialog({\n open, onClose, name, quantity, totalText, onMint, portfolioHref,\n}: {\n open: boolean;\n onClose: () => void;\n name: string;\n quantity: bigint;\n totalText: string | null;\n onMint: () => Promise<{ tokenIds: string[] }>;\n portfolioHref: string;\n}) {\n const [step, setStep] = useState<Step>({ kind: \"confirm\" });\n const mint = async () => {\n setStep({ kind: \"minting\" });\n try {\n setStep({ kind: \"done\", tokenIds: (await onMint()).tokenIds });\n } catch (err) {\n setStep({ kind: \"error\", message: describeError(err).message });\n }\n };\n const close = () => {\n if (step.kind === \"minting\") return;\n setStep({ kind: \"confirm\" });\n onClose();\n };\n return (\n <ActionDialog open={open} onClose={close} width={460}>\n <div className=\"space-y-5 p-6\">\n {step.kind === \"confirm\" && (\n <>\n <h2 className=\"text-lg font-semibold\">Mint {quantity.toString()} from {name}</h2>\n {totalText && <p className=\"text-sm text-muted-foreground\">{totalText}</p>}\n <GradientButton big onClick={() => void mint()}>Confirm mint</GradientButton>\n </>\n )}\n {step.kind === \"minting\" && <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><Loader2 className=\"h-4 w-4 animate-spin\" />Minting…</h2>}\n {step.kind === \"done\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><CheckCircle2 className=\"h-5 w-5 text-green-500\" />Minted</h2>\n <Button asChild><a href={portfolioHref}>View in portfolio</a></Button>\n </>\n )}\n {step.kind === \"error\" && (\n <>\n <h2 className=\"flex items-center gap-2 text-lg font-semibold\"><XCircle className=\"h-4 w-4 text-destructive\" />Not minted</h2>\n <p className=\"text-sm text-muted-foreground\">{step.message}</p>\n <Button onClick={() => void mint()}>Try again</Button>\n </>\n )}\n </div>\n </ActionDialog>\n );\n}\n"],"mappings":";AAwCU,mBAEgB,KADd,YADF;AAtCV,SAAS,gBAAgB;AACzB,SAAS,cAAc,SAAS,eAAe;AAC/C,SAAS,oBAAoB;AAC7B,SAAS,sBAAsB;AAC/B,SAAS,cAAc;AACvB,SAAS,qBAAqB;AAIvB,SAAS,eAAe;AAAA,EAC7B;AAAA,EAAM;AAAA,EAAS;AAAA,EAAM;AAAA,EAAU;AAAA,EAAW;AAAA,EAAQ;AACpD,GAQG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAe,EAAE,MAAM,UAAU,CAAC;AAC1D,QAAM,OAAO,YAAY;AACvB,YAAQ,EAAE,MAAM,UAAU,CAAC;AAC3B,QAAI;AACF,cAAQ,EAAE,MAAM,QAAQ,WAAW,MAAM,OAAO,GAAG,SAAS,CAAC;AAAA,IAC/D,SAAS,KAAK;AACZ,cAAQ,EAAE,MAAM,SAAS,SAAS,cAAc,GAAG,EAAE,QAAQ,CAAC;AAAA,IAChE;AAAA,EACF;AACA,QAAM,QAAQ,MAAM;AAClB,QAAI,KAAK,SAAS,UAAW;AAC7B,YAAQ,EAAE,MAAM,UAAU,CAAC;AAC3B,YAAQ;AAAA,EACV;AACA,SACE,oBAAC,gBAAa,MAAY,SAAS,OAAO,OAAO,KAC/C,+BAAC,SAAI,WAAU,iBACZ;AAAA,SAAK,SAAS,aACb,iCACE;AAAA,2BAAC,QAAG,WAAU,yBAAwB;AAAA;AAAA,QAAM,SAAS,SAAS;AAAA,QAAE;AAAA,QAAO;AAAA,SAAK;AAAA,MAC3E,aAAa,oBAAC,OAAE,WAAU,iCAAiC,qBAAU;AAAA,MACtE,oBAAC,kBAAe,KAAG,MAAC,SAAS,MAAM,KAAK,KAAK,GAAG,0BAAY;AAAA,OAC9D;AAAA,IAED,KAAK,SAAS,aAAa,qBAAC,QAAG,WAAU,iDAAgD;AAAA,0BAAC,WAAQ,WAAU,wBAAuB;AAAA,MAAE;AAAA,OAAQ;AAAA,IAC7I,KAAK,SAAS,UACb,iCACE;AAAA,2BAAC,QAAG,WAAU,iDAAgD;AAAA,4BAAC,gBAAa,WAAU,0BAAyB;AAAA,QAAE;AAAA,SAAM;AAAA,MACvH,oBAAC,UAAO,SAAO,MAAC,8BAAC,OAAE,MAAM,eAAe,+BAAiB,GAAI;AAAA,OAC/D;AAAA,IAED,KAAK,SAAS,WACb,iCACE;AAAA,2BAAC,QAAG,WAAU,iDAAgD;AAAA,4BAAC,WAAQ,WAAU,4BAA2B;AAAA,QAAE;AAAA,SAAU;AAAA,MACxH,oBAAC,OAAE,WAAU,iCAAiC,eAAK,SAAQ;AAAA,MAC3D,oBAAC,UAAO,SAAS,MAAM,KAAK,KAAK,GAAG,uBAAS;AAAA,OAC/C;AAAA,KAEJ,GACF;AAEJ;","names":[]}
|
|
@@ -37,6 +37,7 @@ var import_skeleton = require("./skeleton.js");
|
|
|
37
37
|
var import_button = require("./button.js");
|
|
38
38
|
var import_link = __toESM(require("./link.js"), 1);
|
|
39
39
|
var import_lucide_react = require("lucide-react");
|
|
40
|
+
var import_describe_error = require("../utils/describe-error.js");
|
|
40
41
|
function EmptyOrError({
|
|
41
42
|
isLoading,
|
|
42
43
|
error,
|
|
@@ -58,8 +59,7 @@ function EmptyOrError({
|
|
|
58
59
|
if (error) {
|
|
59
60
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "py-16 text-center space-y-4", children: [
|
|
60
61
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-14 w-14 rounded-xl bg-destructive/10 flex items-center justify-center mx-auto", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.AlertCircle, { className: "h-7 w-7 text-destructive" }) }),
|
|
61
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "
|
|
62
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground max-w-xs mx-auto", children: error instanceof Error ? error.message : "Failed to load data. Please try again." }),
|
|
62
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground max-w-xs mx-auto", children: (0, import_describe_error.describeError)(error).message }),
|
|
63
63
|
onRetry && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_button.Button, { variant: "outline", size: "sm", onClick: onRetry, children: [
|
|
64
64
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.RefreshCw, { className: "h-3.5 w-3.5 mr-1.5" }),
|
|
65
65
|
"Try again"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/empty-or-error.tsx"],"sourcesContent":["\"use client\";\n\nimport { Skeleton } from \"./skeleton.js\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { RefreshCw, AlertCircle } from \"lucide-react\";\nimport { ReactNode } from \"react\";\n\ninterface EmptyOrErrorProps {\n isLoading: boolean;\n error?: unknown;\n isEmpty: boolean;\n onRetry?: () => void;\n emptyTitle: string;\n emptyDescription?: string;\n emptyCta?: { label: string; href: string };\n emptyActions?: ReactNode;\n emptyIcon?: ReactNode;\n skeletonCount?: number;\n\n skeletonNode?: ReactNode;\n children?: ReactNode;\n}\n\nexport function EmptyOrError({\n isLoading,\n error,\n isEmpty,\n onRetry,\n emptyTitle,\n emptyDescription,\n emptyCta,\n emptyActions,\n emptyIcon,\n skeletonCount = 4,\n skeletonNode,\n children,\n}: EmptyOrErrorProps) {\n if (isLoading) {\n if (skeletonNode) return <>{skeletonNode}</>;\n return (\n <div className=\"space-y-3\">\n {Array.from({ length: skeletonCount }).map((_, i) => (\n <Skeleton key={i} className=\"h-20 w-full rounded-xl\" />\n ))}\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"py-16 text-center space-y-4\">\n <div className=\"h-14 w-14 rounded-xl bg-destructive/10 flex items-center justify-center mx-auto\">\n <AlertCircle className=\"h-7 w-7 text-destructive\" />\n </div>\n <p className=\"
|
|
1
|
+
{"version":3,"sources":["../../src/components/empty-or-error.tsx"],"sourcesContent":["\"use client\";\n\nimport { Skeleton } from \"./skeleton.js\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { RefreshCw, AlertCircle } from \"lucide-react\";\nimport { ReactNode } from \"react\";\nimport { describeError } from \"../utils/describe-error.js\";\n\ninterface EmptyOrErrorProps {\n isLoading: boolean;\n error?: unknown;\n isEmpty: boolean;\n onRetry?: () => void;\n emptyTitle: string;\n emptyDescription?: string;\n emptyCta?: { label: string; href: string };\n emptyActions?: ReactNode;\n emptyIcon?: ReactNode;\n skeletonCount?: number;\n\n skeletonNode?: ReactNode;\n children?: ReactNode;\n}\n\nexport function EmptyOrError({\n isLoading,\n error,\n isEmpty,\n onRetry,\n emptyTitle,\n emptyDescription,\n emptyCta,\n emptyActions,\n emptyIcon,\n skeletonCount = 4,\n skeletonNode,\n children,\n}: EmptyOrErrorProps) {\n if (isLoading) {\n if (skeletonNode) return <>{skeletonNode}</>;\n return (\n <div className=\"space-y-3\">\n {Array.from({ length: skeletonCount }).map((_, i) => (\n <Skeleton key={i} className=\"h-20 w-full rounded-xl\" />\n ))}\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"py-16 text-center space-y-4\">\n <div className=\"h-14 w-14 rounded-xl bg-destructive/10 flex items-center justify-center mx-auto\">\n <AlertCircle className=\"h-7 w-7 text-destructive\" />\n </div>\n <p className=\"text-sm text-muted-foreground max-w-xs mx-auto\">\n {describeError(error).message}\n </p>\n {onRetry && (\n <Button variant=\"outline\" size=\"sm\" onClick={onRetry}>\n <RefreshCw className=\"h-3.5 w-3.5 mr-1.5\" />\n Try again\n </Button>\n )}\n </div>\n );\n }\n\n if (isEmpty) {\n return (\n <div className=\"py-16 text-center space-y-4\">\n {emptyIcon && (\n <div className=\"h-14 w-14 rounded-xl bg-muted flex items-center justify-center mx-auto\">\n {emptyIcon}\n </div>\n )}\n <p className=\"font-semibold text-lg\">{emptyTitle}</p>\n {emptyDescription && (\n <p className=\"text-sm text-muted-foreground max-w-xs mx-auto\">{emptyDescription}</p>\n )}\n <div className=\"flex items-center justify-center gap-3\">\n {onRetry && (\n <Button variant=\"outline\" size=\"sm\" onClick={onRetry}>\n <RefreshCw className=\"h-3.5 w-3.5 mr-1.5\" />\n Refresh\n </Button>\n )}\n {emptyCta && (\n <Button size=\"sm\" asChild>\n <Link href={emptyCta.href}>{emptyCta.label}</Link>\n </Button>\n )}\n </div>\n {emptyActions}\n </div>\n );\n }\n\n return <>{children}</>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwC6B;AAtC7B,sBAAyB;AACzB,oBAAuB;AACvB,kBAAiB;AACjB,0BAAuC;AAEvC,4BAA8B;AAkBvB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AACF,GAAsB;AACpB,MAAI,WAAW;AACb,QAAI,aAAc,QAAO,2EAAG,wBAAa;AACzC,WACE,4CAAC,SAAI,WAAU,aACZ,gBAAM,KAAK,EAAE,QAAQ,cAAc,CAAC,EAAE,IAAI,CAAC,GAAG,MAC7C,4CAAC,4BAAiB,WAAU,4BAAb,CAAsC,CACtD,GACH;AAAA,EAEJ;AAEA,MAAI,OAAO;AACT,WACE,6CAAC,SAAI,WAAU,+BACb;AAAA,kDAAC,SAAI,WAAU,mFACb,sDAAC,mCAAY,WAAU,4BAA2B,GACpD;AAAA,MACA,4CAAC,OAAE,WAAU,kDACV,mDAAc,KAAK,EAAE,SACxB;AAAA,MACC,WACC,6CAAC,wBAAO,SAAQ,WAAU,MAAK,MAAK,SAAS,SAC3C;AAAA,oDAAC,iCAAU,WAAU,sBAAqB;AAAA,QAAE;AAAA,SAE9C;AAAA,OAEJ;AAAA,EAEJ;AAEA,MAAI,SAAS;AACX,WACE,6CAAC,SAAI,WAAU,+BACZ;AAAA,mBACC,4CAAC,SAAI,WAAU,0EACZ,qBACH;AAAA,MAEF,4CAAC,OAAE,WAAU,yBAAyB,sBAAW;AAAA,MAChD,oBACC,4CAAC,OAAE,WAAU,kDAAkD,4BAAiB;AAAA,MAElF,6CAAC,SAAI,WAAU,0CACZ;AAAA,mBACC,6CAAC,wBAAO,SAAQ,WAAU,MAAK,MAAK,SAAS,SAC3C;AAAA,sDAAC,iCAAU,WAAU,sBAAqB;AAAA,UAAE;AAAA,WAE9C;AAAA,QAED,YACC,4CAAC,wBAAO,MAAK,MAAK,SAAO,MACvB,sDAAC,YAAAA,SAAA,EAAK,MAAM,SAAS,MAAO,mBAAS,OAAM,GAC7C;AAAA,SAEJ;AAAA,MACC;AAAA,OACH;AAAA,EAEJ;AAEA,SAAO,2EAAG,UAAS;AACrB;","names":["Link"]}
|