@medialane/ui 0.10.2 → 0.11.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.
Files changed (87) hide show
  1. package/dist/components/activity-card.cjs +136 -0
  2. package/dist/components/activity-card.cjs.map +1 -0
  3. package/dist/components/activity-card.js +100 -0
  4. package/dist/components/activity-card.js.map +1 -0
  5. package/dist/components/discover-feed-section.cjs +72 -44
  6. package/dist/components/discover-feed-section.cjs.map +1 -1
  7. package/dist/components/discover-feed-section.js +73 -45
  8. package/dist/components/discover-feed-section.js.map +1 -1
  9. package/dist/index.cjs +7 -0
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +4 -0
  12. package/dist/index.js.map +1 -1
  13. package/package.json +1 -1
  14. package/dist/components/activity-feed-shell.d.cts +0 -13
  15. package/dist/components/activity-feed-shell.d.ts +0 -13
  16. package/dist/components/activity-row.d.cts +0 -20
  17. package/dist/components/activity-row.d.ts +0 -20
  18. package/dist/components/activity-ticker.d.cts +0 -13
  19. package/dist/components/activity-ticker.d.ts +0 -13
  20. package/dist/components/address-display.d.cts +0 -12
  21. package/dist/components/address-display.d.ts +0 -12
  22. package/dist/components/brand-icon.d.cts +0 -10
  23. package/dist/components/brand-icon.d.ts +0 -10
  24. package/dist/components/brand-logo.d.cts +0 -11
  25. package/dist/components/brand-logo.d.ts +0 -11
  26. package/dist/components/collection-card.d.cts +0 -13
  27. package/dist/components/collection-card.d.ts +0 -13
  28. package/dist/components/cta-card-grid.d.cts +0 -23
  29. package/dist/components/cta-card-grid.d.ts +0 -23
  30. package/dist/components/currency-icon.d.cts +0 -25
  31. package/dist/components/currency-icon.d.ts +0 -25
  32. package/dist/components/discover-collections-strip.d.cts +0 -14
  33. package/dist/components/discover-collections-strip.d.ts +0 -14
  34. package/dist/components/discover-creators-strip.d.cts +0 -14
  35. package/dist/components/discover-creators-strip.d.ts +0 -14
  36. package/dist/components/discover-feed-section.d.cts +0 -18
  37. package/dist/components/discover-feed-section.d.ts +0 -18
  38. package/dist/components/discover-hero.d.cts +0 -17
  39. package/dist/components/discover-hero.d.ts +0 -17
  40. package/dist/components/featured-carousel.d.cts +0 -13
  41. package/dist/components/featured-carousel.d.ts +0 -13
  42. package/dist/components/hero-slider.d.cts +0 -17
  43. package/dist/components/hero-slider.d.ts +0 -17
  44. package/dist/components/ip-type-badge.d.cts +0 -21
  45. package/dist/components/ip-type-badge.d.ts +0 -21
  46. package/dist/components/launchpad-services.d.cts +0 -43
  47. package/dist/components/launchpad-services.d.ts +0 -43
  48. package/dist/components/listing-card.d.cts +0 -16
  49. package/dist/components/listing-card.d.ts +0 -16
  50. package/dist/components/motion-primitives.d.cts +0 -36
  51. package/dist/components/motion-primitives.d.ts +0 -36
  52. package/dist/components/nav-command-menu.d.cts +0 -51
  53. package/dist/components/nav-command-menu.d.ts +0 -51
  54. package/dist/components/page-container.d.cts +0 -15
  55. package/dist/components/page-container.d.ts +0 -15
  56. package/dist/components/portfolio-subnav.d.cts +0 -27
  57. package/dist/components/portfolio-subnav.d.ts +0 -27
  58. package/dist/components/scroll-section.d.cts +0 -18
  59. package/dist/components/scroll-section.d.ts +0 -18
  60. package/dist/components/share-button.d.cts +0 -12
  61. package/dist/components/share-button.d.ts +0 -12
  62. package/dist/components/token-card.d.cts +0 -31
  63. package/dist/components/token-card.d.ts +0 -31
  64. package/dist/data/activity.d.cts +0 -16
  65. package/dist/data/activity.d.ts +0 -16
  66. package/dist/data/brand.d.cts +0 -44
  67. package/dist/data/brand.d.ts +0 -44
  68. package/dist/data/ip-types.d.cts +0 -13
  69. package/dist/data/ip-types.d.ts +0 -13
  70. package/dist/data/launchpad-services.d.cts +0 -42
  71. package/dist/data/launchpad-services.d.ts +0 -42
  72. package/dist/index.d.cts +0 -41
  73. package/dist/index.d.ts +0 -41
  74. package/dist/preset/tailwind.d.cts +0 -5
  75. package/dist/preset/tailwind.d.ts +0 -5
  76. package/dist/utils/address.d.cts +0 -7
  77. package/dist/utils/address.d.ts +0 -7
  78. package/dist/utils/cn.d.cts +0 -5
  79. package/dist/utils/cn.d.ts +0 -5
  80. package/dist/utils/format.d.cts +0 -7
  81. package/dist/utils/format.d.ts +0 -7
  82. package/dist/utils/ipfs.d.cts +0 -11
  83. package/dist/utils/ipfs.d.ts +0 -11
  84. package/dist/utils/portfolio-counts.d.cts +0 -33
  85. package/dist/utils/portfolio-counts.d.ts +0 -33
  86. package/dist/utils/time.d.cts +0 -7
  87. package/dist/utils/time.d.ts +0 -7
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var activity_card_exports = {};
31
+ __export(activity_card_exports, {
32
+ ACTIVITY_MESSAGES: () => ACTIVITY_MESSAGES,
33
+ ActivityCard: () => ActivityCard,
34
+ ActivityCardSkeleton: () => ActivityCardSkeleton
35
+ });
36
+ module.exports = __toCommonJS(activity_card_exports);
37
+ var import_jsx_runtime = require("react/jsx-runtime");
38
+ var import_image = __toESM(require("next/image"), 1);
39
+ var import_link = __toESM(require("next/link"), 1);
40
+ var import_lucide_react = require("lucide-react");
41
+ var import_currency_icon = require("./currency-icon.js");
42
+ var import_activity = require("../data/activity.js");
43
+ var import_ipfs = require("../utils/ipfs.js");
44
+ var import_time = require("../utils/time.js");
45
+ var import_format = require("../utils/format.js");
46
+ var import_cn = require("../utils/cn.js");
47
+ const ACTIVITY_MESSAGES = {
48
+ mint: (actor) => actor ? `Minted by ${actor}` : "Newly minted",
49
+ listing: (actor) => actor ? `Listed by ${actor}` : "Listed for sale",
50
+ sale: (actor) => actor ? `Purchased by ${actor}` : "Sold",
51
+ offer: (actor) => actor ? `Offer by ${actor}` : "Offer placed",
52
+ transfer: (actor) => actor ? `Transferred by ${actor}` : "Transferred",
53
+ cancelled: (actor) => actor ? `Cancelled by ${actor}` : "Listing cancelled"
54
+ };
55
+ function ActivityCardSkeleton() {
56
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "card-base", children: [
57
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "aspect-square w-full bg-muted animate-pulse" }),
58
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "p-4 space-y-2", children: [
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-32 bg-muted animate-pulse rounded" }),
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-24 bg-muted animate-pulse rounded" })
61
+ ] })
62
+ ] });
63
+ }
64
+ function ActivityCard({
65
+ activity,
66
+ getAssetHref = (c, t) => `/asset/${c}/${t}`
67
+ }) {
68
+ const config = import_activity.ACTIVITY_TYPE_CONFIG[activity.type] ?? {
69
+ label: activity.type,
70
+ variant: "outline",
71
+ icon: import_lucide_react.ExternalLink,
72
+ colorClass: "text-muted-foreground",
73
+ bgClass: "bg-muted"
74
+ };
75
+ const Icon = config.icon;
76
+ const contract = activity.nftContract ?? activity.contractAddress ?? null;
77
+ const tokenId = activity.nftTokenId ?? activity.tokenId ?? null;
78
+ const actor = activity.offerer ?? activity.fulfiller ?? (activity.type === "mint" ? activity.to : activity.from) ?? null;
79
+ const tokenName = activity.token?.name ?? (tokenId ? `#${tokenId}` : "\u2014");
80
+ const rawImage = activity.token?.image ?? null;
81
+ const tokenImage = rawImage ? (0, import_ipfs.ipfsToHttp)(rawImage) : null;
82
+ const amount = activity.amount && Number(activity.amount) > 1 ? activity.amount : null;
83
+ const shortActor = actor ? actor.length > 10 ? `${actor.slice(0, 6)}\u2026${actor.slice(-4)}` : actor : null;
84
+ const message = ACTIVITY_MESSAGES[activity.type]?.(shortActor) ?? config.label;
85
+ const body = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
86
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "aspect-square relative bg-muted", children: [
87
+ tokenImage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
88
+ import_image.default,
89
+ {
90
+ src: tokenImage,
91
+ alt: tokenName,
92
+ fill: true,
93
+ sizes: "256px",
94
+ className: "object-cover",
95
+ unoptimized: true
96
+ }
97
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 bg-gradient-to-br from-muted-foreground/10 to-muted-foreground/5", "aria-hidden": true }),
98
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "absolute top-2.5 left-2.5 inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[11px] font-semibold bg-background/75 backdrop-blur-md border border-border/40", children: [
99
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: (0, import_cn.cn)("h-3 w-3", config.colorClass), "aria-hidden": true }),
100
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: config.colorClass, children: config.label })
101
+ ] }),
102
+ amount && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "absolute bottom-2.5 right-2.5 px-2 py-0.5 rounded-full text-[10px] font-bold bg-violet-500 text-white", children: [
103
+ "\xD7",
104
+ amount
105
+ ] })
106
+ ] }),
107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "p-4 space-y-1.5", children: [
108
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-[15px] font-semibold truncate", children: tokenName }),
109
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
110
+ "p",
111
+ {
112
+ className: "text-xs text-muted-foreground truncate",
113
+ title: new Date(activity.timestamp).toLocaleString(),
114
+ children: [
115
+ message,
116
+ " \xB7 ",
117
+ (0, import_time.timeAgo)(activity.timestamp)
118
+ ]
119
+ }
120
+ ),
121
+ activity.price?.formatted && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-sm font-bold tabular-nums flex items-center gap-1.5 pt-0.5", children: [
122
+ activity.price.currency && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_currency_icon.CurrencyIcon, { symbol: activity.price.currency, size: 13, "aria-hidden": true }),
123
+ (0, import_format.formatDisplayPrice)(activity.price.formatted)
124
+ ] })
125
+ ] })
126
+ ] });
127
+ const className = "card-base block active:scale-[0.99] transition-all";
128
+ return contract && tokenId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: getAssetHref(contract, tokenId), className, children: body }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, children: body });
129
+ }
130
+ // Annotate the CommonJS export names for ESM import in node:
131
+ 0 && (module.exports = {
132
+ ACTIVITY_MESSAGES,
133
+ ActivityCard,
134
+ ActivityCardSkeleton
135
+ });
136
+ //# sourceMappingURL=activity-card.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/activity-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { ExternalLink } from \"lucide-react\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { ACTIVITY_TYPE_CONFIG } from \"../data/activity.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { ApiActivity } from \"@medialane/sdk\";\n\nexport const ACTIVITY_MESSAGES: Record<string, (actor: string | null) => string> = {\n mint: (actor) => actor ? `Minted by ${actor}` : \"Newly minted\",\n listing: (actor) => actor ? `Listed by ${actor}` : \"Listed for sale\",\n sale: (actor) => actor ? `Purchased by ${actor}` : \"Sold\",\n offer: (actor) => actor ? `Offer by ${actor}` : \"Offer placed\",\n transfer: (actor) => actor ? `Transferred by ${actor}` : \"Transferred\",\n cancelled: (actor) => actor ? `Cancelled by ${actor}` : \"Listing cancelled\",\n};\n\nexport function ActivityCardSkeleton() {\n return (\n <div className=\"card-base\">\n <div className=\"aspect-square w-full bg-muted animate-pulse\" />\n <div className=\"p-4 space-y-2\">\n <div className=\"h-4 w-32 bg-muted animate-pulse rounded\" />\n <div className=\"h-3 w-24 bg-muted animate-pulse rounded\" />\n </div>\n </div>\n );\n}\n\nexport interface ActivityCardProps {\n activity: ApiActivity;\n /** Builds the asset link; card is unlinked when the activity has no token ref */\n getAssetHref?: (contract: string, tokenId: string) => string;\n}\n\n/** Card-shaped activity item for horizontal carousels (Discover Community strip).\n * Same data as ActivityRow, presented like a collection/listing card. */\nexport function ActivityCard({\n activity,\n getAssetHref = (c, t) => `/asset/${c}/${t}`,\n}: ActivityCardProps) {\n const config = ACTIVITY_TYPE_CONFIG[activity.type] ?? {\n label: activity.type,\n variant: \"outline\" as const,\n icon: ExternalLink,\n colorClass: \"text-muted-foreground\",\n bgClass: \"bg-muted\",\n };\n const Icon = config.icon;\n\n const contract = activity.nftContract ?? activity.contractAddress ?? null;\n const tokenId = activity.nftTokenId ?? activity.tokenId ?? null;\n const actor =\n activity.offerer ??\n activity.fulfiller ??\n ((activity.type as string) === \"mint\" ? activity.to : activity.from) ??\n null;\n\n const tokenName = activity.token?.name ?? (tokenId ? `#${tokenId}` : \"—\");\n const rawImage = activity.token?.image ?? null;\n const tokenImage = rawImage ? ipfsToHttp(rawImage) : null;\n const amount = activity.amount && Number(activity.amount) > 1 ? activity.amount : null;\n\n const shortActor = actor\n ? actor.length > 10\n ? `${actor.slice(0, 6)}…${actor.slice(-4)}`\n : actor\n : null;\n const message = ACTIVITY_MESSAGES[activity.type]?.(shortActor) ?? config.label;\n\n const body = (\n <>\n <div className=\"aspect-square relative bg-muted\">\n {tokenImage ? (\n <Image\n src={tokenImage}\n alt={tokenName}\n fill\n sizes=\"256px\"\n className=\"object-cover\"\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-muted-foreground/10 to-muted-foreground/5\" aria-hidden />\n )}\n {/* Activity type chip — vivid label on glass */}\n <span className=\"absolute top-2.5 left-2.5 inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[11px] font-semibold bg-background/75 backdrop-blur-md border border-border/40\">\n <Icon className={cn(\"h-3 w-3\", config.colorClass)} aria-hidden />\n <span className={config.colorClass}>{config.label}</span>\n </span>\n {amount && (\n <span className=\"absolute bottom-2.5 right-2.5 px-2 py-0.5 rounded-full text-[10px] font-bold bg-violet-500 text-white\">\n ×{amount}\n </span>\n )}\n </div>\n <div className=\"p-4 space-y-1.5\">\n <p className=\"text-[15px] font-semibold truncate\">{tokenName}</p>\n <p\n className=\"text-xs text-muted-foreground truncate\"\n title={new Date(activity.timestamp).toLocaleString()}\n >\n {message} · {timeAgo(activity.timestamp)}\n </p>\n {activity.price?.formatted && (\n <p className=\"text-sm font-bold tabular-nums flex items-center gap-1.5 pt-0.5\">\n {activity.price.currency && <CurrencyIcon symbol={activity.price.currency} size={13} aria-hidden />}\n {formatDisplayPrice(activity.price.formatted)}\n </p>\n )}\n </div>\n </>\n );\n\n const className = \"card-base block active:scale-[0.99] transition-all\";\n\n return contract && tokenId ? (\n <Link href={getAssetHref(contract, tokenId)} className={className}>\n {body}\n </Link>\n ) : (\n <div className={className}>{body}</div>\n );\n}\n"],"mappings":"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","names":["Image","Link"]}
@@ -0,0 +1,100 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import Image from "next/image";
4
+ import Link from "next/link";
5
+ import { ExternalLink } from "lucide-react";
6
+ import { CurrencyIcon } from "./currency-icon.js";
7
+ import { ACTIVITY_TYPE_CONFIG } from "../data/activity.js";
8
+ import { ipfsToHttp } from "../utils/ipfs.js";
9
+ import { timeAgo } from "../utils/time.js";
10
+ import { formatDisplayPrice } from "../utils/format.js";
11
+ import { cn } from "../utils/cn.js";
12
+ const ACTIVITY_MESSAGES = {
13
+ mint: (actor) => actor ? `Minted by ${actor}` : "Newly minted",
14
+ listing: (actor) => actor ? `Listed by ${actor}` : "Listed for sale",
15
+ sale: (actor) => actor ? `Purchased by ${actor}` : "Sold",
16
+ offer: (actor) => actor ? `Offer by ${actor}` : "Offer placed",
17
+ transfer: (actor) => actor ? `Transferred by ${actor}` : "Transferred",
18
+ cancelled: (actor) => actor ? `Cancelled by ${actor}` : "Listing cancelled"
19
+ };
20
+ function ActivityCardSkeleton() {
21
+ return /* @__PURE__ */ jsxs("div", { className: "card-base", children: [
22
+ /* @__PURE__ */ jsx("div", { className: "aspect-square w-full bg-muted animate-pulse" }),
23
+ /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-2", children: [
24
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-32 bg-muted animate-pulse rounded" }),
25
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-24 bg-muted animate-pulse rounded" })
26
+ ] })
27
+ ] });
28
+ }
29
+ function ActivityCard({
30
+ activity,
31
+ getAssetHref = (c, t) => `/asset/${c}/${t}`
32
+ }) {
33
+ const config = ACTIVITY_TYPE_CONFIG[activity.type] ?? {
34
+ label: activity.type,
35
+ variant: "outline",
36
+ icon: ExternalLink,
37
+ colorClass: "text-muted-foreground",
38
+ bgClass: "bg-muted"
39
+ };
40
+ const Icon = config.icon;
41
+ const contract = activity.nftContract ?? activity.contractAddress ?? null;
42
+ const tokenId = activity.nftTokenId ?? activity.tokenId ?? null;
43
+ const actor = activity.offerer ?? activity.fulfiller ?? (activity.type === "mint" ? activity.to : activity.from) ?? null;
44
+ const tokenName = activity.token?.name ?? (tokenId ? `#${tokenId}` : "\u2014");
45
+ const rawImage = activity.token?.image ?? null;
46
+ const tokenImage = rawImage ? ipfsToHttp(rawImage) : null;
47
+ const amount = activity.amount && Number(activity.amount) > 1 ? activity.amount : null;
48
+ const shortActor = actor ? actor.length > 10 ? `${actor.slice(0, 6)}\u2026${actor.slice(-4)}` : actor : null;
49
+ const message = ACTIVITY_MESSAGES[activity.type]?.(shortActor) ?? config.label;
50
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
51
+ /* @__PURE__ */ jsxs("div", { className: "aspect-square relative bg-muted", children: [
52
+ tokenImage ? /* @__PURE__ */ jsx(
53
+ Image,
54
+ {
55
+ src: tokenImage,
56
+ alt: tokenName,
57
+ fill: true,
58
+ sizes: "256px",
59
+ className: "object-cover",
60
+ unoptimized: true
61
+ }
62
+ ) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-muted-foreground/10 to-muted-foreground/5", "aria-hidden": true }),
63
+ /* @__PURE__ */ jsxs("span", { className: "absolute top-2.5 left-2.5 inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[11px] font-semibold bg-background/75 backdrop-blur-md border border-border/40", children: [
64
+ /* @__PURE__ */ jsx(Icon, { className: cn("h-3 w-3", config.colorClass), "aria-hidden": true }),
65
+ /* @__PURE__ */ jsx("span", { className: config.colorClass, children: config.label })
66
+ ] }),
67
+ amount && /* @__PURE__ */ jsxs("span", { className: "absolute bottom-2.5 right-2.5 px-2 py-0.5 rounded-full text-[10px] font-bold bg-violet-500 text-white", children: [
68
+ "\xD7",
69
+ amount
70
+ ] })
71
+ ] }),
72
+ /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-1.5", children: [
73
+ /* @__PURE__ */ jsx("p", { className: "text-[15px] font-semibold truncate", children: tokenName }),
74
+ /* @__PURE__ */ jsxs(
75
+ "p",
76
+ {
77
+ className: "text-xs text-muted-foreground truncate",
78
+ title: new Date(activity.timestamp).toLocaleString(),
79
+ children: [
80
+ message,
81
+ " \xB7 ",
82
+ timeAgo(activity.timestamp)
83
+ ]
84
+ }
85
+ ),
86
+ activity.price?.formatted && /* @__PURE__ */ jsxs("p", { className: "text-sm font-bold tabular-nums flex items-center gap-1.5 pt-0.5", children: [
87
+ activity.price.currency && /* @__PURE__ */ jsx(CurrencyIcon, { symbol: activity.price.currency, size: 13, "aria-hidden": true }),
88
+ formatDisplayPrice(activity.price.formatted)
89
+ ] })
90
+ ] })
91
+ ] });
92
+ const className = "card-base block active:scale-[0.99] transition-all";
93
+ return contract && tokenId ? /* @__PURE__ */ jsx(Link, { href: getAssetHref(contract, tokenId), className, children: body }) : /* @__PURE__ */ jsx("div", { className, children: body });
94
+ }
95
+ export {
96
+ ACTIVITY_MESSAGES,
97
+ ActivityCard,
98
+ ActivityCardSkeleton
99
+ };
100
+ //# sourceMappingURL=activity-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/activity-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { ExternalLink } from \"lucide-react\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { ACTIVITY_TYPE_CONFIG } from \"../data/activity.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { ApiActivity } from \"@medialane/sdk\";\n\nexport const ACTIVITY_MESSAGES: Record<string, (actor: string | null) => string> = {\n mint: (actor) => actor ? `Minted by ${actor}` : \"Newly minted\",\n listing: (actor) => actor ? `Listed by ${actor}` : \"Listed for sale\",\n sale: (actor) => actor ? `Purchased by ${actor}` : \"Sold\",\n offer: (actor) => actor ? `Offer by ${actor}` : \"Offer placed\",\n transfer: (actor) => actor ? `Transferred by ${actor}` : \"Transferred\",\n cancelled: (actor) => actor ? `Cancelled by ${actor}` : \"Listing cancelled\",\n};\n\nexport function ActivityCardSkeleton() {\n return (\n <div className=\"card-base\">\n <div className=\"aspect-square w-full bg-muted animate-pulse\" />\n <div className=\"p-4 space-y-2\">\n <div className=\"h-4 w-32 bg-muted animate-pulse rounded\" />\n <div className=\"h-3 w-24 bg-muted animate-pulse rounded\" />\n </div>\n </div>\n );\n}\n\nexport interface ActivityCardProps {\n activity: ApiActivity;\n /** Builds the asset link; card is unlinked when the activity has no token ref */\n getAssetHref?: (contract: string, tokenId: string) => string;\n}\n\n/** Card-shaped activity item for horizontal carousels (Discover Community strip).\n * Same data as ActivityRow, presented like a collection/listing card. */\nexport function ActivityCard({\n activity,\n getAssetHref = (c, t) => `/asset/${c}/${t}`,\n}: ActivityCardProps) {\n const config = ACTIVITY_TYPE_CONFIG[activity.type] ?? {\n label: activity.type,\n variant: \"outline\" as const,\n icon: ExternalLink,\n colorClass: \"text-muted-foreground\",\n bgClass: \"bg-muted\",\n };\n const Icon = config.icon;\n\n const contract = activity.nftContract ?? activity.contractAddress ?? null;\n const tokenId = activity.nftTokenId ?? activity.tokenId ?? null;\n const actor =\n activity.offerer ??\n activity.fulfiller ??\n ((activity.type as string) === \"mint\" ? activity.to : activity.from) ??\n null;\n\n const tokenName = activity.token?.name ?? (tokenId ? `#${tokenId}` : \"—\");\n const rawImage = activity.token?.image ?? null;\n const tokenImage = rawImage ? ipfsToHttp(rawImage) : null;\n const amount = activity.amount && Number(activity.amount) > 1 ? activity.amount : null;\n\n const shortActor = actor\n ? actor.length > 10\n ? `${actor.slice(0, 6)}…${actor.slice(-4)}`\n : actor\n : null;\n const message = ACTIVITY_MESSAGES[activity.type]?.(shortActor) ?? config.label;\n\n const body = (\n <>\n <div className=\"aspect-square relative bg-muted\">\n {tokenImage ? (\n <Image\n src={tokenImage}\n alt={tokenName}\n fill\n sizes=\"256px\"\n className=\"object-cover\"\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-muted-foreground/10 to-muted-foreground/5\" aria-hidden />\n )}\n {/* Activity type chip — vivid label on glass */}\n <span className=\"absolute top-2.5 left-2.5 inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[11px] font-semibold bg-background/75 backdrop-blur-md border border-border/40\">\n <Icon className={cn(\"h-3 w-3\", config.colorClass)} aria-hidden />\n <span className={config.colorClass}>{config.label}</span>\n </span>\n {amount && (\n <span className=\"absolute bottom-2.5 right-2.5 px-2 py-0.5 rounded-full text-[10px] font-bold bg-violet-500 text-white\">\n ×{amount}\n </span>\n )}\n </div>\n <div className=\"p-4 space-y-1.5\">\n <p className=\"text-[15px] font-semibold truncate\">{tokenName}</p>\n <p\n className=\"text-xs text-muted-foreground truncate\"\n title={new Date(activity.timestamp).toLocaleString()}\n >\n {message} · {timeAgo(activity.timestamp)}\n </p>\n {activity.price?.formatted && (\n <p className=\"text-sm font-bold tabular-nums flex items-center gap-1.5 pt-0.5\">\n {activity.price.currency && <CurrencyIcon symbol={activity.price.currency} size={13} aria-hidden />}\n {formatDisplayPrice(activity.price.formatted)}\n </p>\n )}\n </div>\n </>\n );\n\n const className = \"card-base block active:scale-[0.99] transition-all\";\n\n return contract && tokenId ? (\n <Link href={getAssetHref(contract, tokenId)} className={className}>\n {body}\n </Link>\n ) : (\n <div className={className}>{body}</div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -26,8 +26,43 @@ var import_jsx_runtime = require("react/jsx-runtime");
26
26
  var import_lucide_react = require("lucide-react");
27
27
  var import_motion_primitives = require("./motion-primitives.js");
28
28
  var import_listing_card = require("./listing-card.js");
29
- var import_activity_feed_shell = require("./activity-feed-shell.js");
30
- var import_activity_row = require("./activity-row.js");
29
+ var import_activity_card = require("./activity-card.js");
30
+ var import_time = require("../utils/time.js");
31
+ var import_cn = require("../utils/cn.js");
32
+ function StripShell({
33
+ icon,
34
+ iconBg,
35
+ title,
36
+ subtitle,
37
+ href,
38
+ linkLabel,
39
+ children
40
+ }) {
41
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "space-y-4", children: [
42
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between", children: [
43
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2.5", children: [
44
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("h-7 w-7 rounded-lg flex items-center justify-center", iconBg), children: icon }),
45
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
46
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-lg sm:text-xl font-semibold leading-none", children: title }),
47
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-[10px] text-muted-foreground mt-1", children: subtitle })
48
+ ] })
49
+ ] }),
50
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
51
+ "a",
52
+ {
53
+ href,
54
+ className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-accent transition-colors",
55
+ children: [
56
+ linkLabel,
57
+ " ",
58
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRight, { className: "h-3.5 w-3.5" })
59
+ ]
60
+ }
61
+ )
62
+ ] }),
63
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full overflow-x-auto scrollbar-hide", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex gap-5 sm:gap-6 snap-x snap-mandatory pb-2", style: { width: "max-content" }, children }) })
64
+ ] });
65
+ }
31
66
  function DiscoverFeedSection({
32
67
  orders,
33
68
  isLoading,
@@ -35,55 +70,48 @@ function DiscoverFeedSection({
35
70
  activitiesLoading,
36
71
  lastUpdated,
37
72
  getAssetHref = (c, t) => `/asset/${c}/${t}`,
38
- getActorHref = (a) => `/creator/${a}`,
39
- explorerUrl = "https://voyager.online",
40
73
  marketplaceHref = "/marketplace",
41
- activitiesHref = "/activities"
74
+ activitiesHref = "/activities",
75
+ onBuyOrder,
76
+ isOwnOrder
42
77
  }) {
43
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-8", children: [
44
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_motion_primitives.FadeIn, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-3", children: [
45
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between", children: [
46
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
47
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "section-label", children: "Markets" }),
48
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 mt-0.5", children: [
49
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Tag, { className: "h-4 w-4 text-brand-rose" }),
50
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-lg font-bold", children: "Activity" })
51
- ] })
52
- ] }),
53
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
54
- "a",
55
- {
56
- href: marketplaceHref,
57
- className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-accent transition-colors",
58
- children: "View all"
59
- }
60
- )
61
- ] }),
62
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-3 gap-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card.ListingCardSkeleton, {}, i)) }) : orders.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rounded-xl border border-border py-12 text-center text-sm text-muted-foreground", children: "No active listings yet." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-3 gap-3", children: orders.map((o) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card.ListingCard, { order: o, compact: true }, o.orderHash)) })
63
- ] }) }),
78
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-14 sm:space-y-20", children: [
79
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_motion_primitives.FadeIn, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
80
+ StripShell,
81
+ {
82
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Tag, { className: "h-3.5 w-3.5 text-white" }),
83
+ iconBg: "bg-gradient-to-br from-rose-500 to-pink-600 shadow-md shadow-rose-500/20",
84
+ title: "Activity",
85
+ href: marketplaceHref,
86
+ linkLabel: "View all",
87
+ children: isLoading ? Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-72 snap-start shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card.ListingCardSkeleton, {}) }, i)) : orders.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground py-4", children: "No active listings yet." }) : orders.map((order) => {
88
+ const own = isOwnOrder?.(order) ?? false;
89
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-72 snap-start shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
90
+ import_listing_card.ListingCard,
91
+ {
92
+ order,
93
+ onBuy: onBuyOrder && !own ? () => onBuyOrder(order) : void 0
94
+ }
95
+ ) }, order.orderHash);
96
+ })
97
+ }
98
+ ) }),
64
99
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_motion_primitives.FadeIn, { delay: 0.08, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
65
- import_activity_feed_shell.ActivityFeedShell,
100
+ StripShell,
66
101
  {
102
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Activity, { className: "h-3.5 w-3.5 text-white" }),
103
+ iconBg: "bg-gradient-to-br from-indigo-500 to-blue-600 shadow-md shadow-indigo-500/20",
67
104
  title: "Community",
105
+ subtitle: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1", children: [
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.RefreshCw, { className: "h-2.5 w-2.5" }),
107
+ "Updated ",
108
+ (0, import_time.timeAgo)(lastUpdated)
109
+ ] }),
68
110
  href: activitiesHref,
69
- hrefLabel: "Activities",
70
- lastUpdated,
71
- isLoading: activitiesLoading,
72
- children: activities.map((act, i) => {
111
+ linkLabel: "Activities",
112
+ children: activitiesLoading ? Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-56 sm:w-64 snap-start shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_activity_card.ActivityCardSkeleton, {}) }, i)) : activities.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground py-4", children: "No activity yet. Be the first to trade on Medialane!" }) : activities.map((act, i) => {
73
113
  const key = act.txHash ? `${act.txHash}-${act.type}-${act.nftTokenId ?? ""}` : `activity-${i}`;
74
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
75
- import_activity_row.ActivityRow,
76
- {
77
- activity: act,
78
- showActor: true,
79
- showExplorer: false,
80
- compact: true,
81
- getAssetHref,
82
- getActorHref,
83
- explorerUrl
84
- },
85
- key
86
- );
114
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-56 sm:w-64 snap-start shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_activity_card.ActivityCard, { activity: act, getAssetHref }) }, key);
87
115
  })
88
116
  }
89
117
  ) })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/discover-feed-section.tsx"],"sourcesContent":["\"use client\";\n\nimport { Tag } from \"lucide-react\";\nimport { FadeIn } from \"./motion-primitives.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ActivityFeedShell } from \"./activity-feed-shell.js\";\nimport { ActivityRow } from \"./activity-row.js\";\nimport type { ApiOrder, ApiActivity } from \"@medialane/sdk\";\n\nexport interface DiscoverFeedSectionProps {\n orders: ApiOrder[];\n isLoading: boolean;\n activities: ApiActivity[];\n activitiesLoading: boolean;\n lastUpdated: string;\n getAssetHref?: (contract: string, tokenId: string) => string;\n getActorHref?: (address: string) => string;\n explorerUrl?: string;\n marketplaceHref?: string;\n activitiesHref?: string;\n}\n\nexport function DiscoverFeedSection({\n orders,\n isLoading,\n activities,\n activitiesLoading,\n lastUpdated,\n getAssetHref = (c, t) => `/asset/${c}/${t}`,\n getActorHref = (a) => `/creator/${a}`,\n explorerUrl = \"https://voyager.online\",\n marketplaceHref = \"/marketplace\",\n activitiesHref = \"/activities\",\n}: DiscoverFeedSectionProps) {\n return (\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-8\">\n {/* New Listings */}\n <FadeIn>\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"section-label\">Markets</p>\n <div className=\"flex items-center gap-2 mt-0.5\">\n <Tag className=\"h-4 w-4 text-brand-rose\" />\n <h2 className=\"text-lg font-bold\">Activity</h2>\n </div>\n </div>\n <a\n href={marketplaceHref}\n className=\"inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-accent transition-colors\"\n >\n View all\n </a>\n </div>\n\n {isLoading ? (\n <div className=\"grid grid-cols-3 gap-3\">\n {Array.from({ length: 6 }).map((_, i) => <ListingCardSkeleton key={i} />)}\n </div>\n ) : orders.length === 0 ? (\n <div className=\"rounded-xl border border-border py-12 text-center text-sm text-muted-foreground\">\n No active listings yet.\n </div>\n ) : (\n <div className=\"grid grid-cols-3 gap-3\">\n {orders.map((o) => (\n <ListingCard key={o.orderHash} order={o} compact />\n ))}\n </div>\n )}\n </div>\n </FadeIn>\n\n {/* Recent Activity */}\n <FadeIn delay={0.08}>\n <ActivityFeedShell\n title=\"Community\"\n href={activitiesHref}\n hrefLabel=\"Activities\"\n lastUpdated={lastUpdated}\n isLoading={activitiesLoading}\n >\n {activities.map((act, i) => {\n const key = act.txHash\n ? `${act.txHash}-${act.type}-${act.nftTokenId ?? \"\"}`\n : `activity-${i}`;\n return (\n <ActivityRow\n key={key}\n activity={act}\n showActor\n showExplorer={false}\n compact\n getAssetHref={getAssetHref}\n getActorHref={getActorHref}\n explorerUrl={explorerUrl}\n />\n );\n })}\n </ActivityFeedShell>\n </FadeIn>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyCc;AAvCd,0BAAoB;AACpB,+BAAuB;AACvB,0BAAiD;AACjD,iCAAkC;AAClC,0BAA4B;AAgBrB,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe,CAAC,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC;AAAA,EACzC,eAAe,CAAC,MAAM,YAAY,CAAC;AAAA,EACnC,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,iBAAiB;AACnB,GAA6B;AAC3B,SACE,6CAAC,SAAI,WAAU,yCAEb;AAAA,gDAAC,mCACC,uDAAC,SAAI,WAAU,aACb;AAAA,mDAAC,SAAI,WAAU,qCACb;AAAA,qDAAC,SACC;AAAA,sDAAC,OAAE,WAAU,iBAAgB,qBAAO;AAAA,UACpC,6CAAC,SAAI,WAAU,kCACb;AAAA,wDAAC,2BAAI,WAAU,2BAA0B;AAAA,YACzC,4CAAC,QAAG,WAAU,qBAAoB,sBAAQ;AAAA,aAC5C;AAAA,WACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,WAAU;AAAA,YACX;AAAA;AAAA,QAED;AAAA,SACF;AAAA,MAEC,YACC,4CAAC,SAAI,WAAU,0BACZ,gBAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,4CAAC,6CAAyB,CAAG,CAAE,GAC1E,IACE,OAAO,WAAW,IACpB,4CAAC,SAAI,WAAU,mFAAkF,qCAEjG,IAEA,4CAAC,SAAI,WAAU,0BACZ,iBAAO,IAAI,CAAC,MACX,4CAAC,mCAA8B,OAAO,GAAG,SAAO,QAA9B,EAAE,SAA6B,CAClD,GACH;AAAA,OAEJ,GACF;AAAA,IAGA,4CAAC,mCAAO,OAAO,MACb;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,MAAM;AAAA,QACN,WAAU;AAAA,QACV;AAAA,QACA,WAAW;AAAA,QAEV,qBAAW,IAAI,CAAC,KAAK,MAAM;AAC1B,gBAAM,MAAM,IAAI,SACZ,GAAG,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,IAAI,cAAc,EAAE,KACjD,YAAY,CAAC;AACjB,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,UAAU;AAAA,cACV,WAAS;AAAA,cACT,cAAc;AAAA,cACd,SAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA;AAAA;AAAA,YAPK;AAAA,UAQP;AAAA,QAEJ,CAAC;AAAA;AAAA,IACH,GACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/discover-feed-section.tsx"],"sourcesContent":["\"use client\";\n\nimport { Tag, Activity, RefreshCw, ArrowRight } from \"lucide-react\";\nimport { FadeIn } from \"./motion-primitives.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ActivityCard, ActivityCardSkeleton } from \"./activity-card.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { ApiOrder, ApiActivity } from \"@medialane/sdk\";\n\nexport interface DiscoverFeedSectionProps {\n orders: ApiOrder[];\n isLoading: boolean;\n activities: ApiActivity[];\n activitiesLoading: boolean;\n lastUpdated: string;\n getAssetHref?: (contract: string, tokenId: string) => string;\n getActorHref?: (address: string) => string;\n explorerUrl?: string;\n marketplaceHref?: string;\n activitiesHref?: string;\n /** Optional buy hook — when provided, listing cards show their Buy action */\n onBuyOrder?: (order: ApiOrder) => void;\n /** Hide the buy action for orders the viewer owns */\n isOwnOrder?: (order: ApiOrder) => boolean;\n}\n\n// ── Shared strip shell: icon-badge header + snap-scroll row ─────────────────\nfunction StripShell({\n icon,\n iconBg,\n title,\n subtitle,\n href,\n linkLabel,\n children,\n}: {\n icon: React.ReactNode;\n iconBg: string;\n title: string;\n subtitle?: React.ReactNode;\n href: string;\n linkLabel: string;\n children: React.ReactNode;\n}) {\n return (\n <section className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2.5\">\n <div className={cn(\"h-7 w-7 rounded-lg flex items-center justify-center\", iconBg)}>\n {icon}\n </div>\n <div>\n <h2 className=\"text-lg sm:text-xl font-semibold leading-none\">{title}</h2>\n {subtitle && <p className=\"text-[10px] text-muted-foreground mt-1\">{subtitle}</p>}\n </div>\n </div>\n <a\n href={href}\n className=\"inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-accent transition-colors\"\n >\n {linkLabel} <ArrowRight className=\"h-3.5 w-3.5\" />\n </a>\n </div>\n\n <div className=\"w-full overflow-x-auto scrollbar-hide\">\n <div className=\"flex gap-5 sm:gap-6 snap-x snap-mandatory pb-2\" style={{ width: \"max-content\" }}>\n {children}\n </div>\n </div>\n </section>\n );\n}\n\n/** Discover feed — Markets activity + Community as horizontal carousels,\n * matching the Collections/Creators explore-by-scrolling model. */\nexport function DiscoverFeedSection({\n orders,\n isLoading,\n activities,\n activitiesLoading,\n lastUpdated,\n getAssetHref = (c, t) => `/asset/${c}/${t}`,\n marketplaceHref = \"/marketplace\",\n activitiesHref = \"/activities\",\n onBuyOrder,\n isOwnOrder,\n}: DiscoverFeedSectionProps) {\n return (\n <div className=\"space-y-14 sm:space-y-20\">\n {/* Markets — recent listings carousel */}\n <FadeIn>\n <StripShell\n icon={<Tag className=\"h-3.5 w-3.5 text-white\" />}\n iconBg=\"bg-gradient-to-br from-rose-500 to-pink-600 shadow-md shadow-rose-500/20\"\n title=\"Activity\"\n href={marketplaceHref}\n linkLabel=\"View all\"\n >\n {isLoading\n ? Array.from({ length: 8 }).map((_, i) => (\n <div key={i} className=\"w-72 snap-start shrink-0\">\n <ListingCardSkeleton />\n </div>\n ))\n : orders.length === 0\n ? (\n <p className=\"text-sm text-muted-foreground py-4\">No active listings yet.</p>\n )\n : orders.map((order) => {\n const own = isOwnOrder?.(order) ?? false;\n return (\n <div key={order.orderHash} className=\"w-72 snap-start shrink-0\">\n <ListingCard\n order={order}\n onBuy={onBuyOrder && !own ? () => onBuyOrder(order) : undefined}\n />\n </div>\n );\n })}\n </StripShell>\n </FadeIn>\n\n {/* Community recent on-chain activity carousel */}\n <FadeIn delay={0.08}>\n <StripShell\n icon={<Activity className=\"h-3.5 w-3.5 text-white\" />}\n iconBg=\"bg-gradient-to-br from-indigo-500 to-blue-600 shadow-md shadow-indigo-500/20\"\n title=\"Community\"\n subtitle={\n <span className=\"flex items-center gap-1\">\n <RefreshCw className=\"h-2.5 w-2.5\" />\n Updated {timeAgo(lastUpdated)}\n </span>\n }\n href={activitiesHref}\n linkLabel=\"Activities\"\n >\n {activitiesLoading\n ? Array.from({ length: 8 }).map((_, i) => (\n <div key={i} className=\"w-56 sm:w-64 snap-start shrink-0\">\n <ActivityCardSkeleton />\n </div>\n ))\n : activities.length === 0\n ? (\n <p className=\"text-sm text-muted-foreground py-4\">\n No activity yet. Be the first to trade on Medialane!\n </p>\n )\n : activities.map((act, i) => {\n const key = act.txHash\n ? `${act.txHash}-${act.type}-${act.nftTokenId ?? \"\"}`\n : `activity-${i}`;\n return (\n <div key={key} className=\"w-56 sm:w-64 snap-start shrink-0\">\n <ActivityCard activity={act} getAssetHref={getAssetHref} />\n </div>\n );\n })}\n </StripShell>\n </FadeIn>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,10 +1,45 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { Tag } from "lucide-react";
3
+ import { Tag, Activity, RefreshCw, ArrowRight } from "lucide-react";
4
4
  import { FadeIn } from "./motion-primitives.js";
5
5
  import { ListingCard, ListingCardSkeleton } from "./listing-card.js";
6
- import { ActivityFeedShell } from "./activity-feed-shell.js";
7
- import { ActivityRow } from "./activity-row.js";
6
+ import { ActivityCard, ActivityCardSkeleton } from "./activity-card.js";
7
+ import { timeAgo } from "../utils/time.js";
8
+ import { cn } from "../utils/cn.js";
9
+ function StripShell({
10
+ icon,
11
+ iconBg,
12
+ title,
13
+ subtitle,
14
+ href,
15
+ linkLabel,
16
+ children
17
+ }) {
18
+ return /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
19
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
20
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
21
+ /* @__PURE__ */ jsx("div", { className: cn("h-7 w-7 rounded-lg flex items-center justify-center", iconBg), children: icon }),
22
+ /* @__PURE__ */ jsxs("div", { children: [
23
+ /* @__PURE__ */ jsx("h2", { className: "text-lg sm:text-xl font-semibold leading-none", children: title }),
24
+ subtitle && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground mt-1", children: subtitle })
25
+ ] })
26
+ ] }),
27
+ /* @__PURE__ */ jsxs(
28
+ "a",
29
+ {
30
+ href,
31
+ className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-accent transition-colors",
32
+ children: [
33
+ linkLabel,
34
+ " ",
35
+ /* @__PURE__ */ jsx(ArrowRight, { className: "h-3.5 w-3.5" })
36
+ ]
37
+ }
38
+ )
39
+ ] }),
40
+ /* @__PURE__ */ jsx("div", { className: "w-full overflow-x-auto scrollbar-hide", children: /* @__PURE__ */ jsx("div", { className: "flex gap-5 sm:gap-6 snap-x snap-mandatory pb-2", style: { width: "max-content" }, children }) })
41
+ ] });
42
+ }
8
43
  function DiscoverFeedSection({
9
44
  orders,
10
45
  isLoading,
@@ -12,55 +47,48 @@ function DiscoverFeedSection({
12
47
  activitiesLoading,
13
48
  lastUpdated,
14
49
  getAssetHref = (c, t) => `/asset/${c}/${t}`,
15
- getActorHref = (a) => `/creator/${a}`,
16
- explorerUrl = "https://voyager.online",
17
50
  marketplaceHref = "/marketplace",
18
- activitiesHref = "/activities"
51
+ activitiesHref = "/activities",
52
+ onBuyOrder,
53
+ isOwnOrder
19
54
  }) {
20
- return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-8", children: [
21
- /* @__PURE__ */ jsx(FadeIn, { children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
22
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
23
- /* @__PURE__ */ jsxs("div", { children: [
24
- /* @__PURE__ */ jsx("p", { className: "section-label", children: "Markets" }),
25
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-0.5", children: [
26
- /* @__PURE__ */ jsx(Tag, { className: "h-4 w-4 text-brand-rose" }),
27
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold", children: "Activity" })
28
- ] })
29
- ] }),
30
- /* @__PURE__ */ jsx(
31
- "a",
32
- {
33
- href: marketplaceHref,
34
- className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-accent transition-colors",
35
- children: "View all"
36
- }
37
- )
38
- ] }),
39
- isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(ListingCardSkeleton, {}, i)) }) : orders.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-border py-12 text-center text-sm text-muted-foreground", children: "No active listings yet." }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-3", children: orders.map((o) => /* @__PURE__ */ jsx(ListingCard, { order: o, compact: true }, o.orderHash)) })
40
- ] }) }),
55
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-14 sm:space-y-20", children: [
56
+ /* @__PURE__ */ jsx(FadeIn, { children: /* @__PURE__ */ jsx(
57
+ StripShell,
58
+ {
59
+ icon: /* @__PURE__ */ jsx(Tag, { className: "h-3.5 w-3.5 text-white" }),
60
+ iconBg: "bg-gradient-to-br from-rose-500 to-pink-600 shadow-md shadow-rose-500/20",
61
+ title: "Activity",
62
+ href: marketplaceHref,
63
+ linkLabel: "View all",
64
+ children: isLoading ? Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsx("div", { className: "w-72 snap-start shrink-0", children: /* @__PURE__ */ jsx(ListingCardSkeleton, {}) }, i)) : orders.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground py-4", children: "No active listings yet." }) : orders.map((order) => {
65
+ const own = isOwnOrder?.(order) ?? false;
66
+ return /* @__PURE__ */ jsx("div", { className: "w-72 snap-start shrink-0", children: /* @__PURE__ */ jsx(
67
+ ListingCard,
68
+ {
69
+ order,
70
+ onBuy: onBuyOrder && !own ? () => onBuyOrder(order) : void 0
71
+ }
72
+ ) }, order.orderHash);
73
+ })
74
+ }
75
+ ) }),
41
76
  /* @__PURE__ */ jsx(FadeIn, { delay: 0.08, children: /* @__PURE__ */ jsx(
42
- ActivityFeedShell,
77
+ StripShell,
43
78
  {
79
+ icon: /* @__PURE__ */ jsx(Activity, { className: "h-3.5 w-3.5 text-white" }),
80
+ iconBg: "bg-gradient-to-br from-indigo-500 to-blue-600 shadow-md shadow-indigo-500/20",
44
81
  title: "Community",
82
+ subtitle: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
83
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-2.5 w-2.5" }),
84
+ "Updated ",
85
+ timeAgo(lastUpdated)
86
+ ] }),
45
87
  href: activitiesHref,
46
- hrefLabel: "Activities",
47
- lastUpdated,
48
- isLoading: activitiesLoading,
49
- children: activities.map((act, i) => {
88
+ linkLabel: "Activities",
89
+ children: activitiesLoading ? Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsx("div", { className: "w-56 sm:w-64 snap-start shrink-0", children: /* @__PURE__ */ jsx(ActivityCardSkeleton, {}) }, i)) : activities.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground py-4", children: "No activity yet. Be the first to trade on Medialane!" }) : activities.map((act, i) => {
50
90
  const key = act.txHash ? `${act.txHash}-${act.type}-${act.nftTokenId ?? ""}` : `activity-${i}`;
51
- return /* @__PURE__ */ jsx(
52
- ActivityRow,
53
- {
54
- activity: act,
55
- showActor: true,
56
- showExplorer: false,
57
- compact: true,
58
- getAssetHref,
59
- getActorHref,
60
- explorerUrl
61
- },
62
- key
63
- );
91
+ return /* @__PURE__ */ jsx("div", { className: "w-56 sm:w-64 snap-start shrink-0", children: /* @__PURE__ */ jsx(ActivityCard, { activity: act, getAssetHref }) }, key);
64
92
  })
65
93
  }
66
94
  ) })