@medialane/ui 0.288.0 → 0.290.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/input-otp.d.cts +2 -2
- package/dist/components/account/input-otp.d.ts +2 -2
- package/dist/components/approve-mint-dialog.cjs +150 -0
- package/dist/components/approve-mint-dialog.cjs.map +1 -0
- package/dist/components/approve-mint-dialog.d.cts +27 -0
- package/dist/components/approve-mint-dialog.d.ts +27 -0
- package/dist/components/approve-mint-dialog.js +126 -0
- package/dist/components/approve-mint-dialog.js.map +1 -0
- package/dist/components/asset-page.cjs +3 -2
- package/dist/components/asset-page.cjs.map +1 -1
- package/dist/components/asset-page.js +3 -2
- package/dist/components/asset-page.js.map +1 -1
- package/dist/components/badge.d.cts +1 -1
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/button.d.cts +2 -2
- package/dist/components/button.d.ts +2 -2
- package/dist/components/collection-page.cjs +3 -2
- package/dist/components/collection-page.cjs.map +1 -1
- package/dist/components/collection-page.js +3 -2
- package/dist/components/collection-page.js.map +1 -1
- package/dist/components/comments-section.cjs +3 -3
- package/dist/components/comments-section.cjs.map +1 -1
- package/dist/components/comments-section.js +2 -2
- package/dist/components/comments-section.js.map +1 -1
- package/dist/components/creator-page.cjs +6 -5
- package/dist/components/creator-page.cjs.map +1 -1
- package/dist/components/creator-page.js +5 -4
- package/dist/components/creator-page.js.map +1 -1
- package/dist/components/fast-mint/fast-mint.d.cts +2 -2
- package/dist/components/fast-mint/fast-mint.d.ts +2 -2
- package/dist/components/listing-card-menu.cjs +10 -13
- package/dist/components/listing-card-menu.cjs.map +1 -1
- package/dist/components/listing-card-menu.js +10 -13
- package/dist/components/listing-card-menu.js.map +1 -1
- package/dist/components/medialane-app.cjs.map +1 -1
- package/dist/components/medialane-app.d.cts +2 -8
- package/dist/components/medialane-app.d.ts +2 -8
- package/dist/components/medialane-app.js.map +1 -1
- package/dist/components/portfolio-assets.cjs +4 -5
- package/dist/components/portfolio-assets.cjs.map +1 -1
- package/dist/components/portfolio-assets.js +3 -4
- package/dist/components/portfolio-assets.js.map +1 -1
- package/dist/components/report-dialog.cjs +191 -0
- package/dist/components/report-dialog.cjs.map +1 -0
- package/dist/components/report-dialog.d.cts +17 -0
- package/dist/components/report-dialog.d.ts +17 -0
- package/dist/components/report-dialog.js +167 -0
- package/dist/components/report-dialog.js.map +1 -0
- package/dist/components/sheet.d.cts +1 -1
- package/dist/components/sheet.d.ts +1 -1
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -40,6 +40,7 @@ var import_address_display = require("./address-display.js");
|
|
|
40
40
|
var import_button = require("./button.js");
|
|
41
41
|
var import_link = __toESM(require("./link.js"), 1);
|
|
42
42
|
var import_medialane_app = require("./medialane-app.js");
|
|
43
|
+
var import_report_dialog = require("./report-dialog.js");
|
|
43
44
|
var import_reward_earned = require("./rewards/reward-earned.js");
|
|
44
45
|
var import_skeleton = require("./skeleton.js");
|
|
45
46
|
var import_textarea = require("./textarea.js");
|
|
@@ -57,7 +58,6 @@ function CommentsSection({ contract, tokenId, className }) {
|
|
|
57
58
|
const app = (0, import_medialane_app.useMedialaneApp)();
|
|
58
59
|
const walletAddress = app.walletAddress;
|
|
59
60
|
const hasWallet = !!walletAddress;
|
|
60
|
-
const { ReportDialog } = app;
|
|
61
61
|
const { comments, isLoading, mutate } = (0, import_use_comments.useComments)(contract, tokenId);
|
|
62
62
|
const tx = (0, import_use_transaction.useTransaction)();
|
|
63
63
|
const [text, setText] = (0, import_react.useState)("");
|
|
@@ -276,8 +276,8 @@ function CommentsSection({ contract, tokenId, className }) {
|
|
|
276
276
|
}
|
|
277
277
|
)
|
|
278
278
|
] }) }),
|
|
279
|
-
reportTarget &&
|
|
280
|
-
ReportDialog,
|
|
279
|
+
reportTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
280
|
+
import_report_dialog.ReportDialog,
|
|
281
281
|
{
|
|
282
282
|
target: reportTarget,
|
|
283
283
|
open: !!reportTarget,
|
|
@@ -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 { 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 { successMessages } from \"../utils/success-messages.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 {...successMessages.commented()}\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":["Link"]}
|
|
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 { ReportDialog } from \"./report-dialog.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 { successMessages } from \"../utils/success-messages.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 { 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 && (\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 {...successMessages.commented()}\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":["Link"]}
|
|
@@ -7,6 +7,7 @@ import { AddressDisplay } from "./address-display.js";
|
|
|
7
7
|
import { Button } from "./button.js";
|
|
8
8
|
import Link from "./link.js";
|
|
9
9
|
import { useMedialaneApp } from "./medialane-app.js";
|
|
10
|
+
import { ReportDialog } from "./report-dialog.js";
|
|
10
11
|
import { RewardEarned } from "./rewards/reward-earned.js";
|
|
11
12
|
import { Skeleton } from "./skeleton.js";
|
|
12
13
|
import { Textarea } from "./textarea.js";
|
|
@@ -24,7 +25,6 @@ function CommentsSection({ contract, tokenId, className }) {
|
|
|
24
25
|
const app = useMedialaneApp();
|
|
25
26
|
const walletAddress = app.walletAddress;
|
|
26
27
|
const hasWallet = !!walletAddress;
|
|
27
|
-
const { ReportDialog } = app;
|
|
28
28
|
const { comments, isLoading, mutate } = useComments(contract, tokenId);
|
|
29
29
|
const tx = useTransaction();
|
|
30
30
|
const [text, setText] = useState("");
|
|
@@ -243,7 +243,7 @@ function CommentsSection({ contract, tokenId, className }) {
|
|
|
243
243
|
}
|
|
244
244
|
)
|
|
245
245
|
] }) }),
|
|
246
|
-
reportTarget &&
|
|
246
|
+
reportTarget && /* @__PURE__ */ jsx(
|
|
247
247
|
ReportDialog,
|
|
248
248
|
{
|
|
249
249
|
target: reportTarget,
|
|
@@ -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 { 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 { successMessages } from \"../utils/success-messages.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 {...successMessages.commented()}\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":[]}
|
|
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 { ReportDialog } from \"./report-dialog.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 { successMessages } from \"../utils/success-messages.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 { 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 && (\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 {...successMessages.commented()}\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":[]}
|
|
@@ -50,6 +50,7 @@ var import_listing_card_menu = require("./listing-card-menu.js");
|
|
|
50
50
|
var import_activity_timeline_row = require("./activity-timeline-row.js");
|
|
51
51
|
var import_more_menu = require("./more-menu.js");
|
|
52
52
|
var import_medialane_app = require("./medialane-app.js");
|
|
53
|
+
var import_report_dialog = require("./report-dialog.js");
|
|
53
54
|
var import_cn = require("../utils/cn.js");
|
|
54
55
|
var import_explorer_url = require("../utils/explorer-url.js");
|
|
55
56
|
var import_same_address = require("../utils/same-address.js");
|
|
@@ -72,7 +73,7 @@ const TABS = [
|
|
|
72
73
|
const GRID = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4";
|
|
73
74
|
const isNft = (itemType) => itemType === "ERC721" || itemType === "ERC1155";
|
|
74
75
|
function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }) {
|
|
75
|
-
const { walletAddress
|
|
76
|
+
const { walletAddress } = (0, import_medialane_app.useMedialaneApp)();
|
|
76
77
|
const client = (0, import_use_medialane_client.useMedialaneClient)();
|
|
77
78
|
const resolveImage = (0, import_use_image_url.useImageUrl)();
|
|
78
79
|
const prices = (0, import_use_usd_prices.useUsdPrices)();
|
|
@@ -168,7 +169,7 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
|
|
|
168
169
|
onCancel: isOwner ? actions.cancel : void 0,
|
|
169
170
|
onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
|
|
170
171
|
onOffer: isOwner ? void 0 : market.offer,
|
|
171
|
-
onReport:
|
|
172
|
+
onReport: setReportToken
|
|
172
173
|
},
|
|
173
174
|
`${t.contractAddress}-${t.tokenId}`
|
|
174
175
|
);
|
|
@@ -179,8 +180,8 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
|
|
|
179
180
|
] }),
|
|
180
181
|
actions.dialogs,
|
|
181
182
|
market.dialogs,
|
|
182
|
-
|
|
183
|
-
ReportDialog,
|
|
183
|
+
reportToken ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
184
|
+
import_report_dialog.ReportDialog,
|
|
184
185
|
{
|
|
185
186
|
open: !!reportToken,
|
|
186
187
|
onOpenChange: (open) => {
|
|
@@ -189,7 +190,7 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
|
|
|
189
190
|
target: { type: "TOKEN", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? void 0 }
|
|
190
191
|
}
|
|
191
192
|
) : null,
|
|
192
|
-
|
|
193
|
+
address ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_report_dialog.ReportDialog, { open: reportOpen, onOpenChange: setReportOpen, target: { type: "CREATOR", address, name: identity.name ?? identity.identity } }) : null
|
|
193
194
|
] });
|
|
194
195
|
}
|
|
195
196
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/creator-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\nimport { Activity, Image as ImageIcon, LayoutGrid, ShoppingBag } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Button } from \"./button.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CreatorHeader } from \"./creator-header.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { TabEmptyState } from \"./tab-empty-state.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { CollectionCard, CollectionCardSkeleton } from \"./collection-card.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { ActivityTimelineRow } from \"./activity-timeline-row.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport type { UsePortfolioAssetActions } from \"./portfolio-assets.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { profileIdentity } from \"../utils/profile-identity.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useTokensByOwner } from \"../utils/use-tokens.js\";\nimport { useCollectionsByOwner } from \"../utils/use-collections.js\";\nimport { useUserOrders } from \"../utils/use-orders.js\";\nimport { useActivitiesByAddress } from \"../utils/use-activities.js\";\nimport { useCreatorByUsername, useCreatorProfile } from \"../utils/use-profiles.js\";\n\nconst TABS = [\n { id: \"assets\", label: \"Assets\", Icon: ImageIcon },\n { id: \"collections\", label: \"Collections\", Icon: LayoutGrid },\n { id: \"listings\", label: \"Listings\", Icon: ShoppingBag },\n { id: \"activity\", label: \"Activity\", Icon: Activity },\n] as const;\n\ntype TabId = (typeof TABS)[number][\"id\"];\n\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4\";\nconst isNft = (itemType: string) => itemType === \"ERC721\" || itemType === \"ERC1155\";\n\nexport interface CreatorPageProps {\n address?: string;\n username?: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }: CreatorPageProps) {\n const { walletAddress, ReportDialog } = useMedialaneApp();\n const client = useMedialaneClient();\n const resolveImage = useImageUrl();\n const prices = useUsdPrices();\n const [activeTab, setActiveTab] = useState<TabId>(\"assets\");\n const [reportOpen, setReportOpen] = useState(false);\n const [reportToken, setReportToken] = useState<ApiToken | null>(null);\n\n const byName = useCreatorByUsername(username);\n const byAddress = useCreatorProfile(username ? undefined : addressProp);\n const creator = username ? byName.creator : byAddress.profile;\n const address = username ? creator?.walletAddress ?? null : addressProp ?? null;\n const isOwner = !!address && !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, meta, isLoading: tokensLoading, mutate: refreshTokens } = useTokensByOwner(address, 1, 20);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(activeTab === \"listings\" ? address : null);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(address ? `creator-hidden-${address}` : null, () => client.api.creators.isHidden(address!).catch(() => false));\n const actions = useAssetActions({ refresh: () => void refreshTokens() });\n const market = useMarketActions();\n\n const listings = orders.filter((o) => o.status === \"ACTIVE\" && isNft(o.offer.itemType));\n const identity = profileIdentity({ username: creator?.username, name: creator?.name, walletAddress: address });\n\n if (username && byName.isLoading) {\n return (\n <div className=\"min-h-screen pb-20\">\n <div className=\"px-6 pt-20 pb-6\"><CreatorHeader creator={null} image={null} stats={[]} loading /></div>\n <div className={cn(\"px-6\", GRID)}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n </div>\n );\n }\n\n if (username && !creator) {\n return (\n <div className=\"mx-auto max-w-lg space-y-4 px-4 py-24 text-center\">\n <h1 className=\"text-2xl font-bold\">Creator not found</h1>\n <p className=\"text-muted-foreground\"><span className=\"tabular-nums\">@{username}</span> isn't a profile yet.</p>\n <Button variant=\"outline\" asChild><Link href=\"/creators\">Browse creators</Link></Button>\n </div>\n );\n }\n\n const counts: Partial<Record<TabId, number>> = {\n assets: meta?.total ?? undefined,\n collections: collectionsLoading ? undefined : collections.length,\n ...(activeTab === \"listings\" && !ordersLoading ? { listings: listings.length } : {}),\n };\n\n return (\n <div className=\"min-h-screen overflow-x-hidden pb-20\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <div className=\"px-6 pt-20 pb-6\">\n {creator ? (\n <CreatorHeader\n creator={creator}\n image={resolveImage(creator.avatarImage || tokens[0]?.metadata?.image)}\n stats={[\n { label: \"Assets\", value: meta?.total ?? null },\n { label: \"Collections\", value: collectionsLoading ? null : collections.length },\n ]}\n />\n ) : (\n <div className=\"flex flex-wrap items-center gap-2\">\n <AddressDisplay address={address ?? \"\"} chars={10} className=\"text-base font-semibold tabular-nums\" />\n </div>\n )}\n </div>\n\n <div className=\"sticky top-0 z-20 mt-4 flex items-center gap-2 border-b border-border bg-background/95 px-6 backdrop-blur-sm\">\n <div className=\"-mb-px flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto scrollbar-none\">\n {TABS.map(({ id, label, Icon }) => {\n const count = counts[id];\n const active = activeTab === id;\n return (\n <button\n key={id}\n onClick={() => setActiveTab(id)}\n className={cn(\n \"relative flex shrink-0 items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium transition-colors duration-200\",\n active ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\"\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {label}\n {count ? (\n <span className={cn(\"min-w-[18px] rounded-full px-1.5 py-px text-center text-2xs font-bold tabular-nums\", active ? \"bg-primary/15 text-primary\" : \"bg-muted text-muted-foreground\")}>{count}</span>\n ) : null}\n {active ? <span className=\"absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-primary\" /> : null}\n </button>\n );\n })}\n </div>\n {address ? (\n <MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={identity.name ?? identity.identity} onReport={() => setReportOpen(true)} />\n ) : null}\n </div>\n\n <div className=\"mt-6 px-6\">\n {activeTab === \"assets\" && (\n tokensLoading ? (\n <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n ) : tokens.length === 0 ? (\n <TabEmptyState icon={ImageIcon} heading=\"No assets yet\" body=\"Works this creator makes on Medialane appear here.\" />\n ) : (\n <div className={GRID}>\n {tokens.map((t: ApiToken) => {\n const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));\n return (\n <TokenCard\n key={`${t.contractAddress}-${t.tokenId}`}\n token={t}\n isOwner={isOwner}\n usdValue={orderUsd(listing?.price, prices)}\n onList={isOwner ? actions.list : undefined}\n onTransfer={isOwner ? actions.transfer : undefined}\n onCancel={isOwner ? actions.cancel : undefined}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n onReport={ReportDialog ? setReportToken : undefined}\n />\n );\n })}\n </div>\n )\n )}\n\n {activeTab === \"collections\" && (\n collectionsLoading ? (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{Array.from({ length: 6 }).map((_, i) => <CollectionCardSkeleton key={i} />)}</div>\n ) : collections.length === 0 ? (\n <TabEmptyState icon={LayoutGrid} heading=\"No collections yet\" body=\"Collections this creator makes appear here.\" />\n ) : (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{collections.map((c) => <CollectionCard key={c.contractAddress} collection={c} />)}</div>\n )\n )}\n\n {activeTab === \"listings\" && (\n ordersLoading ? (\n <div className={GRID}>{Array.from({ length: 4 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>\n ) : listings.length === 0 ? (\n <TabEmptyState icon={ShoppingBag} heading=\"No active listings\" body=\"Works this creator lists for sale appear here.\" />\n ) : (\n <div className={GRID}>\n {listings.map((o) => <ListingCard key={o.orderHash} order={o} onBuy={isOwner ? undefined : market.buy} usdValue={orderUsd(o.price, prices)} overflowMenu={<ListingCardMenu order={o} />} />)}\n </div>\n )\n )}\n\n {activeTab === \"activity\" && (\n <div className=\"max-w-2xl\">\n {activitiesLoading ? (\n <div className=\"space-y-5\">{Array.from({ length: 6 }).map((_, i) => <Skeleton key={i} className=\"h-10 w-full rounded-xl\" />)}</div>\n ) : activities.length === 0 ? (\n <TabEmptyState icon={Activity} heading=\"No activity yet\" body=\"This creator's activity appears here as it happens.\" />\n ) : (\n <div>{activities.map((a, i) => <ActivityTimelineRow key={i} event={a} isLast={i === activities.length - 1} />)}</div>\n )}\n </div>\n )}\n </div>\n\n {actions.dialogs}\n {market.dialogs}\n {ReportDialog && reportToken ? (\n <ReportDialog\n open={!!reportToken}\n onOpenChange={(open) => { if (!open) setReportToken(null); }}\n target={{ type: \"TOKEN\", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? undefined }}\n />\n ) : null}\n {ReportDialog && address ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: identity.name ?? identity.identity }} />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":["ImageIcon","useSWR","Link"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/creator-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\nimport { Activity, Image as ImageIcon, LayoutGrid, ShoppingBag } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Button } from \"./button.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CreatorHeader } from \"./creator-header.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { TabEmptyState } from \"./tab-empty-state.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { CollectionCard, CollectionCardSkeleton } from \"./collection-card.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { ActivityTimelineRow } from \"./activity-timeline-row.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport type { UsePortfolioAssetActions } from \"./portfolio-assets.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { profileIdentity } from \"../utils/profile-identity.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useTokensByOwner } from \"../utils/use-tokens.js\";\nimport { useCollectionsByOwner } from \"../utils/use-collections.js\";\nimport { useUserOrders } from \"../utils/use-orders.js\";\nimport { useActivitiesByAddress } from \"../utils/use-activities.js\";\nimport { useCreatorByUsername, useCreatorProfile } from \"../utils/use-profiles.js\";\n\nconst TABS = [\n { id: \"assets\", label: \"Assets\", Icon: ImageIcon },\n { id: \"collections\", label: \"Collections\", Icon: LayoutGrid },\n { id: \"listings\", label: \"Listings\", Icon: ShoppingBag },\n { id: \"activity\", label: \"Activity\", Icon: Activity },\n] as const;\n\ntype TabId = (typeof TABS)[number][\"id\"];\n\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4\";\nconst isNft = (itemType: string) => itemType === \"ERC721\" || itemType === \"ERC1155\";\n\nexport interface CreatorPageProps {\n address?: string;\n username?: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }: CreatorPageProps) {\n const { walletAddress } = useMedialaneApp();\n const client = useMedialaneClient();\n const resolveImage = useImageUrl();\n const prices = useUsdPrices();\n const [activeTab, setActiveTab] = useState<TabId>(\"assets\");\n const [reportOpen, setReportOpen] = useState(false);\n const [reportToken, setReportToken] = useState<ApiToken | null>(null);\n\n const byName = useCreatorByUsername(username);\n const byAddress = useCreatorProfile(username ? undefined : addressProp);\n const creator = username ? byName.creator : byAddress.profile;\n const address = username ? creator?.walletAddress ?? null : addressProp ?? null;\n const isOwner = !!address && !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, meta, isLoading: tokensLoading, mutate: refreshTokens } = useTokensByOwner(address, 1, 20);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(activeTab === \"listings\" ? address : null);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(address ? `creator-hidden-${address}` : null, () => client.api.creators.isHidden(address!).catch(() => false));\n const actions = useAssetActions({ refresh: () => void refreshTokens() });\n const market = useMarketActions();\n\n const listings = orders.filter((o) => o.status === \"ACTIVE\" && isNft(o.offer.itemType));\n const identity = profileIdentity({ username: creator?.username, name: creator?.name, walletAddress: address });\n\n if (username && byName.isLoading) {\n return (\n <div className=\"min-h-screen pb-20\">\n <div className=\"px-6 pt-20 pb-6\"><CreatorHeader creator={null} image={null} stats={[]} loading /></div>\n <div className={cn(\"px-6\", GRID)}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n </div>\n );\n }\n\n if (username && !creator) {\n return (\n <div className=\"mx-auto max-w-lg space-y-4 px-4 py-24 text-center\">\n <h1 className=\"text-2xl font-bold\">Creator not found</h1>\n <p className=\"text-muted-foreground\"><span className=\"tabular-nums\">@{username}</span> isn't a profile yet.</p>\n <Button variant=\"outline\" asChild><Link href=\"/creators\">Browse creators</Link></Button>\n </div>\n );\n }\n\n const counts: Partial<Record<TabId, number>> = {\n assets: meta?.total ?? undefined,\n collections: collectionsLoading ? undefined : collections.length,\n ...(activeTab === \"listings\" && !ordersLoading ? { listings: listings.length } : {}),\n };\n\n return (\n <div className=\"min-h-screen overflow-x-hidden pb-20\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <div className=\"px-6 pt-20 pb-6\">\n {creator ? (\n <CreatorHeader\n creator={creator}\n image={resolveImage(creator.avatarImage || tokens[0]?.metadata?.image)}\n stats={[\n { label: \"Assets\", value: meta?.total ?? null },\n { label: \"Collections\", value: collectionsLoading ? null : collections.length },\n ]}\n />\n ) : (\n <div className=\"flex flex-wrap items-center gap-2\">\n <AddressDisplay address={address ?? \"\"} chars={10} className=\"text-base font-semibold tabular-nums\" />\n </div>\n )}\n </div>\n\n <div className=\"sticky top-0 z-20 mt-4 flex items-center gap-2 border-b border-border bg-background/95 px-6 backdrop-blur-sm\">\n <div className=\"-mb-px flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto scrollbar-none\">\n {TABS.map(({ id, label, Icon }) => {\n const count = counts[id];\n const active = activeTab === id;\n return (\n <button\n key={id}\n onClick={() => setActiveTab(id)}\n className={cn(\n \"relative flex shrink-0 items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium transition-colors duration-200\",\n active ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\"\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {label}\n {count ? (\n <span className={cn(\"min-w-[18px] rounded-full px-1.5 py-px text-center text-2xs font-bold tabular-nums\", active ? \"bg-primary/15 text-primary\" : \"bg-muted text-muted-foreground\")}>{count}</span>\n ) : null}\n {active ? <span className=\"absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-primary\" /> : null}\n </button>\n );\n })}\n </div>\n {address ? (\n <MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={identity.name ?? identity.identity} onReport={() => setReportOpen(true)} />\n ) : null}\n </div>\n\n <div className=\"mt-6 px-6\">\n {activeTab === \"assets\" && (\n tokensLoading ? (\n <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n ) : tokens.length === 0 ? (\n <TabEmptyState icon={ImageIcon} heading=\"No assets yet\" body=\"Works this creator makes on Medialane appear here.\" />\n ) : (\n <div className={GRID}>\n {tokens.map((t: ApiToken) => {\n const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));\n return (\n <TokenCard\n key={`${t.contractAddress}-${t.tokenId}`}\n token={t}\n isOwner={isOwner}\n usdValue={orderUsd(listing?.price, prices)}\n onList={isOwner ? actions.list : undefined}\n onTransfer={isOwner ? actions.transfer : undefined}\n onCancel={isOwner ? actions.cancel : undefined}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n onReport={setReportToken}\n />\n );\n })}\n </div>\n )\n )}\n\n {activeTab === \"collections\" && (\n collectionsLoading ? (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{Array.from({ length: 6 }).map((_, i) => <CollectionCardSkeleton key={i} />)}</div>\n ) : collections.length === 0 ? (\n <TabEmptyState icon={LayoutGrid} heading=\"No collections yet\" body=\"Collections this creator makes appear here.\" />\n ) : (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{collections.map((c) => <CollectionCard key={c.contractAddress} collection={c} />)}</div>\n )\n )}\n\n {activeTab === \"listings\" && (\n ordersLoading ? (\n <div className={GRID}>{Array.from({ length: 4 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>\n ) : listings.length === 0 ? (\n <TabEmptyState icon={ShoppingBag} heading=\"No active listings\" body=\"Works this creator lists for sale appear here.\" />\n ) : (\n <div className={GRID}>\n {listings.map((o) => <ListingCard key={o.orderHash} order={o} onBuy={isOwner ? undefined : market.buy} usdValue={orderUsd(o.price, prices)} overflowMenu={<ListingCardMenu order={o} />} />)}\n </div>\n )\n )}\n\n {activeTab === \"activity\" && (\n <div className=\"max-w-2xl\">\n {activitiesLoading ? (\n <div className=\"space-y-5\">{Array.from({ length: 6 }).map((_, i) => <Skeleton key={i} className=\"h-10 w-full rounded-xl\" />)}</div>\n ) : activities.length === 0 ? (\n <TabEmptyState icon={Activity} heading=\"No activity yet\" body=\"This creator's activity appears here as it happens.\" />\n ) : (\n <div>{activities.map((a, i) => <ActivityTimelineRow key={i} event={a} isLast={i === activities.length - 1} />)}</div>\n )}\n </div>\n )}\n </div>\n\n {actions.dialogs}\n {market.dialogs}\n {reportToken ? (\n <ReportDialog\n open={!!reportToken}\n onOpenChange={(open) => { if (!open) setReportToken(null); }}\n target={{ type: \"TOKEN\", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? undefined }}\n />\n ) : null}\n {address ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: identity.name ?? identity.identity }} />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":["ImageIcon","useSWR","Link"]}
|
|
@@ -17,6 +17,7 @@ import { ListingCardMenu } from "./listing-card-menu.js";
|
|
|
17
17
|
import { ActivityTimelineRow } from "./activity-timeline-row.js";
|
|
18
18
|
import { MoreMenu } from "./more-menu.js";
|
|
19
19
|
import { useMedialaneApp } from "./medialane-app.js";
|
|
20
|
+
import { ReportDialog } from "./report-dialog.js";
|
|
20
21
|
import { cn } from "../utils/cn.js";
|
|
21
22
|
import { EXPLORER_URL } from "../utils/explorer-url.js";
|
|
22
23
|
import { isSameAddress } from "../utils/same-address.js";
|
|
@@ -39,7 +40,7 @@ const TABS = [
|
|
|
39
40
|
const GRID = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4";
|
|
40
41
|
const isNft = (itemType) => itemType === "ERC721" || itemType === "ERC1155";
|
|
41
42
|
function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }) {
|
|
42
|
-
const { walletAddress
|
|
43
|
+
const { walletAddress } = useMedialaneApp();
|
|
43
44
|
const client = useMedialaneClient();
|
|
44
45
|
const resolveImage = useImageUrl();
|
|
45
46
|
const prices = useUsdPrices();
|
|
@@ -135,7 +136,7 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
|
|
|
135
136
|
onCancel: isOwner ? actions.cancel : void 0,
|
|
136
137
|
onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
|
|
137
138
|
onOffer: isOwner ? void 0 : market.offer,
|
|
138
|
-
onReport:
|
|
139
|
+
onReport: setReportToken
|
|
139
140
|
},
|
|
140
141
|
`${t.contractAddress}-${t.tokenId}`
|
|
141
142
|
);
|
|
@@ -146,7 +147,7 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
|
|
|
146
147
|
] }),
|
|
147
148
|
actions.dialogs,
|
|
148
149
|
market.dialogs,
|
|
149
|
-
|
|
150
|
+
reportToken ? /* @__PURE__ */ jsx(
|
|
150
151
|
ReportDialog,
|
|
151
152
|
{
|
|
152
153
|
open: !!reportToken,
|
|
@@ -156,7 +157,7 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
|
|
|
156
157
|
target: { type: "TOKEN", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? void 0 }
|
|
157
158
|
}
|
|
158
159
|
) : null,
|
|
159
|
-
|
|
160
|
+
address ? /* @__PURE__ */ jsx(ReportDialog, { open: reportOpen, onOpenChange: setReportOpen, target: { type: "CREATOR", address, name: identity.name ?? identity.identity } }) : null
|
|
160
161
|
] });
|
|
161
162
|
}
|
|
162
163
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/creator-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\nimport { Activity, Image as ImageIcon, LayoutGrid, ShoppingBag } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Button } from \"./button.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CreatorHeader } from \"./creator-header.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { TabEmptyState } from \"./tab-empty-state.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { CollectionCard, CollectionCardSkeleton } from \"./collection-card.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { ActivityTimelineRow } from \"./activity-timeline-row.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport type { UsePortfolioAssetActions } from \"./portfolio-assets.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { profileIdentity } from \"../utils/profile-identity.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useTokensByOwner } from \"../utils/use-tokens.js\";\nimport { useCollectionsByOwner } from \"../utils/use-collections.js\";\nimport { useUserOrders } from \"../utils/use-orders.js\";\nimport { useActivitiesByAddress } from \"../utils/use-activities.js\";\nimport { useCreatorByUsername, useCreatorProfile } from \"../utils/use-profiles.js\";\n\nconst TABS = [\n { id: \"assets\", label: \"Assets\", Icon: ImageIcon },\n { id: \"collections\", label: \"Collections\", Icon: LayoutGrid },\n { id: \"listings\", label: \"Listings\", Icon: ShoppingBag },\n { id: \"activity\", label: \"Activity\", Icon: Activity },\n] as const;\n\ntype TabId = (typeof TABS)[number][\"id\"];\n\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4\";\nconst isNft = (itemType: string) => itemType === \"ERC721\" || itemType === \"ERC1155\";\n\nexport interface CreatorPageProps {\n address?: string;\n username?: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }: CreatorPageProps) {\n const { walletAddress, ReportDialog } = useMedialaneApp();\n const client = useMedialaneClient();\n const resolveImage = useImageUrl();\n const prices = useUsdPrices();\n const [activeTab, setActiveTab] = useState<TabId>(\"assets\");\n const [reportOpen, setReportOpen] = useState(false);\n const [reportToken, setReportToken] = useState<ApiToken | null>(null);\n\n const byName = useCreatorByUsername(username);\n const byAddress = useCreatorProfile(username ? undefined : addressProp);\n const creator = username ? byName.creator : byAddress.profile;\n const address = username ? creator?.walletAddress ?? null : addressProp ?? null;\n const isOwner = !!address && !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, meta, isLoading: tokensLoading, mutate: refreshTokens } = useTokensByOwner(address, 1, 20);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(activeTab === \"listings\" ? address : null);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(address ? `creator-hidden-${address}` : null, () => client.api.creators.isHidden(address!).catch(() => false));\n const actions = useAssetActions({ refresh: () => void refreshTokens() });\n const market = useMarketActions();\n\n const listings = orders.filter((o) => o.status === \"ACTIVE\" && isNft(o.offer.itemType));\n const identity = profileIdentity({ username: creator?.username, name: creator?.name, walletAddress: address });\n\n if (username && byName.isLoading) {\n return (\n <div className=\"min-h-screen pb-20\">\n <div className=\"px-6 pt-20 pb-6\"><CreatorHeader creator={null} image={null} stats={[]} loading /></div>\n <div className={cn(\"px-6\", GRID)}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n </div>\n );\n }\n\n if (username && !creator) {\n return (\n <div className=\"mx-auto max-w-lg space-y-4 px-4 py-24 text-center\">\n <h1 className=\"text-2xl font-bold\">Creator not found</h1>\n <p className=\"text-muted-foreground\"><span className=\"tabular-nums\">@{username}</span> isn't a profile yet.</p>\n <Button variant=\"outline\" asChild><Link href=\"/creators\">Browse creators</Link></Button>\n </div>\n );\n }\n\n const counts: Partial<Record<TabId, number>> = {\n assets: meta?.total ?? undefined,\n collections: collectionsLoading ? undefined : collections.length,\n ...(activeTab === \"listings\" && !ordersLoading ? { listings: listings.length } : {}),\n };\n\n return (\n <div className=\"min-h-screen overflow-x-hidden pb-20\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <div className=\"px-6 pt-20 pb-6\">\n {creator ? (\n <CreatorHeader\n creator={creator}\n image={resolveImage(creator.avatarImage || tokens[0]?.metadata?.image)}\n stats={[\n { label: \"Assets\", value: meta?.total ?? null },\n { label: \"Collections\", value: collectionsLoading ? null : collections.length },\n ]}\n />\n ) : (\n <div className=\"flex flex-wrap items-center gap-2\">\n <AddressDisplay address={address ?? \"\"} chars={10} className=\"text-base font-semibold tabular-nums\" />\n </div>\n )}\n </div>\n\n <div className=\"sticky top-0 z-20 mt-4 flex items-center gap-2 border-b border-border bg-background/95 px-6 backdrop-blur-sm\">\n <div className=\"-mb-px flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto scrollbar-none\">\n {TABS.map(({ id, label, Icon }) => {\n const count = counts[id];\n const active = activeTab === id;\n return (\n <button\n key={id}\n onClick={() => setActiveTab(id)}\n className={cn(\n \"relative flex shrink-0 items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium transition-colors duration-200\",\n active ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\"\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {label}\n {count ? (\n <span className={cn(\"min-w-[18px] rounded-full px-1.5 py-px text-center text-2xs font-bold tabular-nums\", active ? \"bg-primary/15 text-primary\" : \"bg-muted text-muted-foreground\")}>{count}</span>\n ) : null}\n {active ? <span className=\"absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-primary\" /> : null}\n </button>\n );\n })}\n </div>\n {address ? (\n <MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={identity.name ?? identity.identity} onReport={() => setReportOpen(true)} />\n ) : null}\n </div>\n\n <div className=\"mt-6 px-6\">\n {activeTab === \"assets\" && (\n tokensLoading ? (\n <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n ) : tokens.length === 0 ? (\n <TabEmptyState icon={ImageIcon} heading=\"No assets yet\" body=\"Works this creator makes on Medialane appear here.\" />\n ) : (\n <div className={GRID}>\n {tokens.map((t: ApiToken) => {\n const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));\n return (\n <TokenCard\n key={`${t.contractAddress}-${t.tokenId}`}\n token={t}\n isOwner={isOwner}\n usdValue={orderUsd(listing?.price, prices)}\n onList={isOwner ? actions.list : undefined}\n onTransfer={isOwner ? actions.transfer : undefined}\n onCancel={isOwner ? actions.cancel : undefined}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n onReport={ReportDialog ? setReportToken : undefined}\n />\n );\n })}\n </div>\n )\n )}\n\n {activeTab === \"collections\" && (\n collectionsLoading ? (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{Array.from({ length: 6 }).map((_, i) => <CollectionCardSkeleton key={i} />)}</div>\n ) : collections.length === 0 ? (\n <TabEmptyState icon={LayoutGrid} heading=\"No collections yet\" body=\"Collections this creator makes appear here.\" />\n ) : (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{collections.map((c) => <CollectionCard key={c.contractAddress} collection={c} />)}</div>\n )\n )}\n\n {activeTab === \"listings\" && (\n ordersLoading ? (\n <div className={GRID}>{Array.from({ length: 4 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>\n ) : listings.length === 0 ? (\n <TabEmptyState icon={ShoppingBag} heading=\"No active listings\" body=\"Works this creator lists for sale appear here.\" />\n ) : (\n <div className={GRID}>\n {listings.map((o) => <ListingCard key={o.orderHash} order={o} onBuy={isOwner ? undefined : market.buy} usdValue={orderUsd(o.price, prices)} overflowMenu={<ListingCardMenu order={o} />} />)}\n </div>\n )\n )}\n\n {activeTab === \"activity\" && (\n <div className=\"max-w-2xl\">\n {activitiesLoading ? (\n <div className=\"space-y-5\">{Array.from({ length: 6 }).map((_, i) => <Skeleton key={i} className=\"h-10 w-full rounded-xl\" />)}</div>\n ) : activities.length === 0 ? (\n <TabEmptyState icon={Activity} heading=\"No activity yet\" body=\"This creator's activity appears here as it happens.\" />\n ) : (\n <div>{activities.map((a, i) => <ActivityTimelineRow key={i} event={a} isLast={i === activities.length - 1} />)}</div>\n )}\n </div>\n )}\n </div>\n\n {actions.dialogs}\n {market.dialogs}\n {ReportDialog && reportToken ? (\n <ReportDialog\n open={!!reportToken}\n onOpenChange={(open) => { if (!open) setReportToken(null); }}\n target={{ type: \"TOKEN\", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? undefined }}\n />\n ) : null}\n {ReportDialog && address ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: identity.name ?? identity.identity }} />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/creator-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\nimport { Activity, Image as ImageIcon, LayoutGrid, ShoppingBag } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Button } from \"./button.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CreatorHeader } from \"./creator-header.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { TabEmptyState } from \"./tab-empty-state.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { CollectionCard, CollectionCardSkeleton } from \"./collection-card.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { ActivityTimelineRow } from \"./activity-timeline-row.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport type { UsePortfolioAssetActions } from \"./portfolio-assets.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { profileIdentity } from \"../utils/profile-identity.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useTokensByOwner } from \"../utils/use-tokens.js\";\nimport { useCollectionsByOwner } from \"../utils/use-collections.js\";\nimport { useUserOrders } from \"../utils/use-orders.js\";\nimport { useActivitiesByAddress } from \"../utils/use-activities.js\";\nimport { useCreatorByUsername, useCreatorProfile } from \"../utils/use-profiles.js\";\n\nconst TABS = [\n { id: \"assets\", label: \"Assets\", Icon: ImageIcon },\n { id: \"collections\", label: \"Collections\", Icon: LayoutGrid },\n { id: \"listings\", label: \"Listings\", Icon: ShoppingBag },\n { id: \"activity\", label: \"Activity\", Icon: Activity },\n] as const;\n\ntype TabId = (typeof TABS)[number][\"id\"];\n\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4\";\nconst isNft = (itemType: string) => itemType === \"ERC721\" || itemType === \"ERC1155\";\n\nexport interface CreatorPageProps {\n address?: string;\n username?: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }: CreatorPageProps) {\n const { walletAddress } = useMedialaneApp();\n const client = useMedialaneClient();\n const resolveImage = useImageUrl();\n const prices = useUsdPrices();\n const [activeTab, setActiveTab] = useState<TabId>(\"assets\");\n const [reportOpen, setReportOpen] = useState(false);\n const [reportToken, setReportToken] = useState<ApiToken | null>(null);\n\n const byName = useCreatorByUsername(username);\n const byAddress = useCreatorProfile(username ? undefined : addressProp);\n const creator = username ? byName.creator : byAddress.profile;\n const address = username ? creator?.walletAddress ?? null : addressProp ?? null;\n const isOwner = !!address && !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, meta, isLoading: tokensLoading, mutate: refreshTokens } = useTokensByOwner(address, 1, 20);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(activeTab === \"listings\" ? address : null);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(address ? `creator-hidden-${address}` : null, () => client.api.creators.isHidden(address!).catch(() => false));\n const actions = useAssetActions({ refresh: () => void refreshTokens() });\n const market = useMarketActions();\n\n const listings = orders.filter((o) => o.status === \"ACTIVE\" && isNft(o.offer.itemType));\n const identity = profileIdentity({ username: creator?.username, name: creator?.name, walletAddress: address });\n\n if (username && byName.isLoading) {\n return (\n <div className=\"min-h-screen pb-20\">\n <div className=\"px-6 pt-20 pb-6\"><CreatorHeader creator={null} image={null} stats={[]} loading /></div>\n <div className={cn(\"px-6\", GRID)}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n </div>\n );\n }\n\n if (username && !creator) {\n return (\n <div className=\"mx-auto max-w-lg space-y-4 px-4 py-24 text-center\">\n <h1 className=\"text-2xl font-bold\">Creator not found</h1>\n <p className=\"text-muted-foreground\"><span className=\"tabular-nums\">@{username}</span> isn't a profile yet.</p>\n <Button variant=\"outline\" asChild><Link href=\"/creators\">Browse creators</Link></Button>\n </div>\n );\n }\n\n const counts: Partial<Record<TabId, number>> = {\n assets: meta?.total ?? undefined,\n collections: collectionsLoading ? undefined : collections.length,\n ...(activeTab === \"listings\" && !ordersLoading ? { listings: listings.length } : {}),\n };\n\n return (\n <div className=\"min-h-screen overflow-x-hidden pb-20\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <div className=\"px-6 pt-20 pb-6\">\n {creator ? (\n <CreatorHeader\n creator={creator}\n image={resolveImage(creator.avatarImage || tokens[0]?.metadata?.image)}\n stats={[\n { label: \"Assets\", value: meta?.total ?? null },\n { label: \"Collections\", value: collectionsLoading ? null : collections.length },\n ]}\n />\n ) : (\n <div className=\"flex flex-wrap items-center gap-2\">\n <AddressDisplay address={address ?? \"\"} chars={10} className=\"text-base font-semibold tabular-nums\" />\n </div>\n )}\n </div>\n\n <div className=\"sticky top-0 z-20 mt-4 flex items-center gap-2 border-b border-border bg-background/95 px-6 backdrop-blur-sm\">\n <div className=\"-mb-px flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto scrollbar-none\">\n {TABS.map(({ id, label, Icon }) => {\n const count = counts[id];\n const active = activeTab === id;\n return (\n <button\n key={id}\n onClick={() => setActiveTab(id)}\n className={cn(\n \"relative flex shrink-0 items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium transition-colors duration-200\",\n active ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\"\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {label}\n {count ? (\n <span className={cn(\"min-w-[18px] rounded-full px-1.5 py-px text-center text-2xs font-bold tabular-nums\", active ? \"bg-primary/15 text-primary\" : \"bg-muted text-muted-foreground\")}>{count}</span>\n ) : null}\n {active ? <span className=\"absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-primary\" /> : null}\n </button>\n );\n })}\n </div>\n {address ? (\n <MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={identity.name ?? identity.identity} onReport={() => setReportOpen(true)} />\n ) : null}\n </div>\n\n <div className=\"mt-6 px-6\">\n {activeTab === \"assets\" && (\n tokensLoading ? (\n <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n ) : tokens.length === 0 ? (\n <TabEmptyState icon={ImageIcon} heading=\"No assets yet\" body=\"Works this creator makes on Medialane appear here.\" />\n ) : (\n <div className={GRID}>\n {tokens.map((t: ApiToken) => {\n const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));\n return (\n <TokenCard\n key={`${t.contractAddress}-${t.tokenId}`}\n token={t}\n isOwner={isOwner}\n usdValue={orderUsd(listing?.price, prices)}\n onList={isOwner ? actions.list : undefined}\n onTransfer={isOwner ? actions.transfer : undefined}\n onCancel={isOwner ? actions.cancel : undefined}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n onReport={setReportToken}\n />\n );\n })}\n </div>\n )\n )}\n\n {activeTab === \"collections\" && (\n collectionsLoading ? (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{Array.from({ length: 6 }).map((_, i) => <CollectionCardSkeleton key={i} />)}</div>\n ) : collections.length === 0 ? (\n <TabEmptyState icon={LayoutGrid} heading=\"No collections yet\" body=\"Collections this creator makes appear here.\" />\n ) : (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{collections.map((c) => <CollectionCard key={c.contractAddress} collection={c} />)}</div>\n )\n )}\n\n {activeTab === \"listings\" && (\n ordersLoading ? (\n <div className={GRID}>{Array.from({ length: 4 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>\n ) : listings.length === 0 ? (\n <TabEmptyState icon={ShoppingBag} heading=\"No active listings\" body=\"Works this creator lists for sale appear here.\" />\n ) : (\n <div className={GRID}>\n {listings.map((o) => <ListingCard key={o.orderHash} order={o} onBuy={isOwner ? undefined : market.buy} usdValue={orderUsd(o.price, prices)} overflowMenu={<ListingCardMenu order={o} />} />)}\n </div>\n )\n )}\n\n {activeTab === \"activity\" && (\n <div className=\"max-w-2xl\">\n {activitiesLoading ? (\n <div className=\"space-y-5\">{Array.from({ length: 6 }).map((_, i) => <Skeleton key={i} className=\"h-10 w-full rounded-xl\" />)}</div>\n ) : activities.length === 0 ? (\n <TabEmptyState icon={Activity} heading=\"No activity yet\" body=\"This creator's activity appears here as it happens.\" />\n ) : (\n <div>{activities.map((a, i) => <ActivityTimelineRow key={i} event={a} isLast={i === activities.length - 1} />)}</div>\n )}\n </div>\n )}\n </div>\n\n {actions.dialogs}\n {market.dialogs}\n {reportToken ? (\n <ReportDialog\n open={!!reportToken}\n onOpenChange={(open) => { if (!open) setReportToken(null); }}\n target={{ type: \"TOKEN\", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? undefined }}\n />\n ) : null}\n {address ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: identity.name ?? identity.identity }} />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
3
|
import { FastMintProps } from './types.cjs';
|
|
4
4
|
import 'starknet';
|
|
5
5
|
import '@medialane/sdk';
|
|
6
6
|
import '@medialane/sdk/starknet';
|
|
7
7
|
|
|
8
|
-
declare function FastMint(props: FastMintProps): string | number | bigint | boolean |
|
|
8
|
+
declare function FastMint(props: FastMintProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
9
9
|
|
|
10
10
|
export { FastMint };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
3
|
import { FastMintProps } from './types.js';
|
|
4
4
|
import 'starknet';
|
|
5
5
|
import '@medialane/sdk';
|
|
6
6
|
import '@medialane/sdk/starknet';
|
|
7
7
|
|
|
8
|
-
declare function FastMint(props: FastMintProps): string | number | bigint | boolean |
|
|
8
|
+
declare function FastMint(props: FastMintProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
9
9
|
|
|
10
10
|
export { FastMint };
|