@medialane/ui 0.259.0 → 0.261.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 (139) hide show
  1. package/dist/components/action-button.cjs +7 -2
  2. package/dist/components/action-button.cjs.map +1 -1
  3. package/dist/components/action-button.d.cts +2 -1
  4. package/dist/components/action-button.d.ts +2 -1
  5. package/dist/components/action-button.js +7 -2
  6. package/dist/components/action-button.js.map +1 -1
  7. package/dist/components/activities-feed.cjs +5 -1
  8. package/dist/components/activities-feed.cjs.map +1 -1
  9. package/dist/components/activities-feed.js +5 -1
  10. package/dist/components/activities-feed.js.map +1 -1
  11. package/dist/components/activity-feed-shell.cjs +3 -1
  12. package/dist/components/activity-feed-shell.cjs.map +1 -1
  13. package/dist/components/activity-feed-shell.js +3 -1
  14. package/dist/components/activity-feed-shell.js.map +1 -1
  15. package/dist/components/asset-access-cards.cjs +21 -33
  16. package/dist/components/asset-access-cards.cjs.map +1 -1
  17. package/dist/components/asset-access-cards.d.cts +3 -3
  18. package/dist/components/asset-access-cards.d.ts +3 -3
  19. package/dist/components/asset-access-cards.js +20 -32
  20. package/dist/components/asset-access-cards.js.map +1 -1
  21. package/dist/components/asset-marketplace-panel.cjs +44 -41
  22. package/dist/components/asset-marketplace-panel.cjs.map +1 -1
  23. package/dist/components/asset-marketplace-panel.js +45 -42
  24. package/dist/components/asset-marketplace-panel.js.map +1 -1
  25. package/dist/components/asset-overview-content.cjs +12 -1
  26. package/dist/components/asset-overview-content.cjs.map +1 -1
  27. package/dist/components/asset-overview-content.d.cts +3 -1
  28. package/dist/components/asset-overview-content.d.ts +3 -1
  29. package/dist/components/asset-overview-content.js +13 -2
  30. package/dist/components/asset-overview-content.js.map +1 -1
  31. package/dist/components/asset-page.cjs +8 -6
  32. package/dist/components/asset-page.cjs.map +1 -1
  33. package/dist/components/asset-page.js +8 -6
  34. package/dist/components/asset-page.js.map +1 -1
  35. package/dist/components/asset-top-sections.cjs +1 -9
  36. package/dist/components/asset-top-sections.cjs.map +1 -1
  37. package/dist/components/asset-top-sections.d.cts +1 -2
  38. package/dist/components/asset-top-sections.d.ts +1 -2
  39. package/dist/components/asset-top-sections.js +1 -9
  40. package/dist/components/asset-top-sections.js.map +1 -1
  41. package/dist/components/coins-explorer.cjs +5 -1
  42. package/dist/components/coins-explorer.cjs.map +1 -1
  43. package/dist/components/coins-explorer.js +6 -2
  44. package/dist/components/coins-explorer.js.map +1 -1
  45. package/dist/components/comments-section.cjs +2 -2
  46. package/dist/components/comments-section.cjs.map +1 -1
  47. package/dist/components/comments-section.js +2 -2
  48. package/dist/components/comments-section.js.map +1 -1
  49. package/dist/components/discover-community-section.cjs +5 -1
  50. package/dist/components/discover-community-section.cjs.map +1 -1
  51. package/dist/components/discover-community-section.js +5 -1
  52. package/dist/components/discover-community-section.js.map +1 -1
  53. package/dist/components/discover-feed-section.cjs +5 -1
  54. package/dist/components/discover-feed-section.cjs.map +1 -1
  55. package/dist/components/discover-feed-section.js +5 -1
  56. package/dist/components/discover-feed-section.js.map +1 -1
  57. package/dist/components/fast-mint/success-view.cjs +2 -2
  58. package/dist/components/fast-mint/success-view.cjs.map +1 -1
  59. package/dist/components/fast-mint/success-view.js +2 -2
  60. package/dist/components/fast-mint/success-view.js.map +1 -1
  61. package/dist/components/ip-type-page.cjs +3 -2
  62. package/dist/components/ip-type-page.cjs.map +1 -1
  63. package/dist/components/ip-type-page.js +3 -2
  64. package/dist/components/ip-type-page.js.map +1 -1
  65. package/dist/components/markdown-text.cjs +53 -0
  66. package/dist/components/markdown-text.cjs.map +1 -0
  67. package/dist/components/markdown-text.d.cts +7 -0
  68. package/dist/components/markdown-text.d.ts +7 -0
  69. package/dist/components/markdown-text.js +19 -0
  70. package/dist/components/markdown-text.js.map +1 -0
  71. package/dist/components/marketplace-dialog-primitives.cjs +1 -1
  72. package/dist/components/marketplace-dialog-primitives.cjs.map +1 -1
  73. package/dist/components/marketplace-dialog-primitives.js +1 -1
  74. package/dist/components/marketplace-dialog-primitives.js.map +1 -1
  75. package/dist/components/media-wallet/media-wallet-activity.cjs +5 -1
  76. package/dist/components/media-wallet/media-wallet-activity.cjs.map +1 -1
  77. package/dist/components/media-wallet/media-wallet-activity.js +5 -1
  78. package/dist/components/media-wallet/media-wallet-activity.js.map +1 -1
  79. package/dist/components/media-wallet/media-wallet-home.cjs +3 -2
  80. package/dist/components/media-wallet/media-wallet-home.cjs.map +1 -1
  81. package/dist/components/media-wallet/media-wallet-home.js +3 -2
  82. package/dist/components/media-wallet/media-wallet-home.js.map +1 -1
  83. package/dist/components/media-wallet/media-wallet-send.cjs +5 -2
  84. package/dist/components/media-wallet/media-wallet-send.cjs.map +1 -1
  85. package/dist/components/media-wallet/media-wallet-send.js +5 -2
  86. package/dist/components/media-wallet/media-wallet-send.js.map +1 -1
  87. package/dist/components/media-wallet/success-dialog.cjs +5 -11
  88. package/dist/components/media-wallet/success-dialog.cjs.map +1 -1
  89. package/dist/components/media-wallet/success-dialog.js +5 -11
  90. package/dist/components/media-wallet/success-dialog.js.map +1 -1
  91. package/dist/components/pop-claim-button.cjs +2 -2
  92. package/dist/components/pop-claim-button.cjs.map +1 -1
  93. package/dist/components/pop-claim-button.js +2 -2
  94. package/dist/components/pop-claim-button.js.map +1 -1
  95. package/dist/components/pop-manage-page.cjs +3 -2
  96. package/dist/components/pop-manage-page.cjs.map +1 -1
  97. package/dist/components/pop-manage-page.js +3 -2
  98. package/dist/components/pop-manage-page.js.map +1 -1
  99. package/dist/components/portfolio-sponsorships.cjs +14 -7
  100. package/dist/components/portfolio-sponsorships.cjs.map +1 -1
  101. package/dist/components/portfolio-sponsorships.js +14 -7
  102. package/dist/components/portfolio-sponsorships.js.map +1 -1
  103. package/dist/components/service-collections-page.cjs +2 -2
  104. package/dist/components/service-collections-page.cjs.map +1 -1
  105. package/dist/components/service-collections-page.d.cts +2 -2
  106. package/dist/components/service-collections-page.d.ts +2 -2
  107. package/dist/components/service-collections-page.js +2 -2
  108. package/dist/components/service-collections-page.js.map +1 -1
  109. package/dist/components/sponsorship-offer-page.cjs +4 -4
  110. package/dist/components/sponsorship-offer-page.cjs.map +1 -1
  111. package/dist/components/sponsorship-offer-page.js +4 -4
  112. package/dist/components/sponsorship-offer-page.js.map +1 -1
  113. package/dist/components/transaction-success.cjs +2 -5
  114. package/dist/components/transaction-success.cjs.map +1 -1
  115. package/dist/components/transaction-success.js +3 -6
  116. package/dist/components/transaction-success.js.map +1 -1
  117. package/dist/components/transfer-collection-ownership.cjs +2 -5
  118. package/dist/components/transfer-collection-ownership.cjs.map +1 -1
  119. package/dist/components/transfer-collection-ownership.js +2 -5
  120. package/dist/components/transfer-collection-ownership.js.map +1 -1
  121. package/dist/index.cjs +3 -0
  122. package/dist/index.cjs.map +1 -1
  123. package/dist/index.d.cts +1 -0
  124. package/dist/index.d.ts +1 -0
  125. package/dist/index.js +2 -0
  126. package/dist/index.js.map +1 -1
  127. package/dist/utils/empty-messages.cjs +62 -0
  128. package/dist/utils/empty-messages.cjs.map +1 -0
  129. package/dist/utils/empty-messages.d.cts +40 -0
  130. package/dist/utils/empty-messages.d.ts +40 -0
  131. package/dist/utils/empty-messages.js +38 -0
  132. package/dist/utils/empty-messages.js.map +1 -0
  133. package/dist/utils/success-messages.cjs +52 -0
  134. package/dist/utils/success-messages.cjs.map +1 -1
  135. package/dist/utils/success-messages.d.cts +27 -0
  136. package/dist/utils/success-messages.d.ts +27 -0
  137. package/dist/utils/success-messages.js +52 -0
  138. package/dist/utils/success-messages.js.map +1 -1
  139. package/package.json +3 -1
@@ -59,6 +59,7 @@ function ActionButton({
59
59
  icon,
60
60
  big,
61
61
  ghost,
62
+ href,
62
63
  helpContent,
63
64
  disabled,
64
65
  children,
@@ -66,12 +67,15 @@ function ActionButton({
66
67
  style,
67
68
  ...rest
68
69
  }) {
70
+ const Tag = href ? "a" : "button";
71
+ const linkProps = href ? { href, target: "_blank", rel: "noopener noreferrer" } : {};
69
72
  const sizeClass = big ? "h-[54px] px-5 rounded-[13px] text-base" : "h-[46px] px-5 rounded-[13px] text-sm";
70
73
  if (ghost) {
71
74
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
72
- "button",
75
+ Tag,
73
76
  {
74
77
  ...rest,
78
+ ...linkProps,
75
79
  disabled,
76
80
  className: (0, import_cn.cn)(
77
81
  "inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap",
@@ -92,9 +96,10 @@ function ActionButton({
92
96
  const fg = action ? ACTION_FOREGROUNDS[action] : tone ? TONE_FOREGROUNDS[tone] : ACTION_FOREGROUNDS.buy;
93
97
  const grad = `linear-gradient(115deg, ${gradColors.join(",")})`;
94
98
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
95
- "button",
99
+ Tag,
96
100
  {
97
101
  ...rest,
102
+ ...linkProps,
98
103
  disabled,
99
104
  className: (0, import_cn.cn)(
100
105
  "ml-gbtn inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/action-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../utils/cn.js\";\nimport { HelpIcon } from \"./help-icon.js\";\n\nconst ACTION_GRADIENTS: Record<string, [string, string, string]> = {\n buy: ['#3b7bff', '#8a5cf6', '#3b7bff'],\n submit: ['#d6359a', '#5b4ce6', '#d6359a'],\n offer: ['#f6608f', '#fb8b46', '#f6608f'],\n remix: ['#8a5cf6', '#f6608f', '#8a5cf6'],\n license: ['#3b7bff', '#5b4ce6', '#3b7bff'],\n};\n\nconst ACTION_FOREGROUNDS: Record<string, string> = {\n buy: '#3b7bff',\n submit: '#5b4ce6',\n offer: '#fb7a32',\n remix: '#8a3ff0',\n license: '#3b7bff',\n};\n\nconst TONE_GRADIENTS: Record<string, [string, string, string]> = {\n blue: ['#3b7bff', '#5b4ce6', '#3b7bff'],\n purple: ['#8a5cf6', '#f6608f', '#8a5cf6'],\n orange: ['#fb8b46', '#f6608f', '#fb8b46'],\n red: ['#ef5a5a', '#f6608f', '#ef5a5a'],\n rose: ['#f6608f', '#fb8b46', '#f6608f'],\n};\n\nconst TONE_FOREGROUNDS: Record<string, string> = {\n blue: '#2f6bff',\n purple: '#8a3ff0',\n orange: '#fb7a32',\n red: '#ef5a5a',\n rose: '#f6608f',\n};\n\nexport type ActionKey = keyof typeof ACTION_GRADIENTS;\nexport type ToneKey = keyof typeof TONE_GRADIENTS;\n\nexport interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\n action?: ActionKey;\n\n tone?: ToneKey;\n icon?: React.ReactNode;\n\n big?: boolean;\n\n ghost?: boolean;\n\n helpContent?: string;\n}\n\nexport function ActionButton({\n action,\n tone,\n icon,\n big,\n ghost,\n helpContent,\n disabled,\n children,\n className,\n style,\n ...rest\n}: ActionButtonProps) {\n const sizeClass = big\n ? \"h-[54px] px-5 rounded-[13px] text-base\"\n : \"h-[46px] px-5 rounded-[13px] text-sm\";\n\n if (ghost) {\n return (\n <button\n {...rest}\n disabled={disabled}\n className={cn(\n \"inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap\",\n \"bg-muted text-foreground border-none disabled:opacity-50 disabled:pointer-events-none\",\n sizeClass,\n className,\n )}\n style={style}\n >\n {icon}{children}\n {helpContent ? <HelpIcon content={helpContent} /> : null}\n </button>\n );\n }\n\n const gradColors =\n action ? ACTION_GRADIENTS[action] :\n tone ? TONE_GRADIENTS[tone] :\n ACTION_GRADIENTS.buy;\n\n const fg =\n action ? ACTION_FOREGROUNDS[action] :\n tone ? TONE_FOREGROUNDS[tone] :\n ACTION_FOREGROUNDS.buy;\n\n const grad = `linear-gradient(115deg, ${gradColors.join(',')})`;\n\n return (\n <button\n {...rest}\n disabled={disabled}\n className={cn(\n \"ml-gbtn inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap\",\n \"bg-transparent text-foreground border-none relative disabled:opacity-40 disabled:pointer-events-none\",\n sizeClass,\n className,\n )}\n style={{ '--ml-grad': grad, ...style } as React.CSSProperties}\n >\n {icon && <span className=\"inline-flex\" style={{ color: fg }}>{icon}</span>}\n {children}\n {helpContent ? <HelpIcon content={helpContent} /> : null}\n </button>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyEM;AAvEN,gBAAmB;AACnB,uBAAyB;AAEzB,MAAM,mBAA6D;AAAA,EACjE,KAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,QAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,OAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,OAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,SAAS,CAAC,WAAW,WAAW,SAAS;AAC3C;AAEA,MAAM,qBAA6C;AAAA,EACjD,KAAS;AAAA,EACT,QAAS;AAAA,EACT,OAAS;AAAA,EACT,OAAS;AAAA,EACT,SAAS;AACX;AAEA,MAAM,iBAA2D;AAAA,EAC/D,MAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,KAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,MAAQ,CAAC,WAAW,WAAW,SAAS;AAC1C;AAEA,MAAM,mBAA2C;AAAA,EAC/C,MAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAQ;AAAA,EACR,MAAQ;AACV;AAmBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,YAAY,MACd,2CACA;AAEJ,MAAI,OAAO;AACT,WACE;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACJ;AAAA,QACA,eAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,UAAM;AAAA,UACN,cAAc,4CAAC,6BAAS,SAAS,aAAa,IAAK;AAAA;AAAA;AAAA,IACtD;AAAA,EAEJ;AAEA,QAAM,aACJ,SAAS,iBAAiB,MAAM,IAChC,OAAS,eAAe,IAAI,IAC5B,iBAAiB;AAEnB,QAAM,KACJ,SAAS,mBAAmB,MAAM,IAClC,OAAS,iBAAiB,IAAI,IAC9B,mBAAmB;AAErB,QAAM,OAAO,2BAA2B,WAAW,KAAK,GAAG,CAAC;AAE5D,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA,eAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,EAAE,aAAa,MAAM,GAAG,MAAM;AAAA,MAEpC;AAAA,gBAAQ,4CAAC,UAAK,WAAU,eAAc,OAAO,EAAE,OAAO,GAAG,GAAI,gBAAK;AAAA,QAClE;AAAA,QACA,cAAc,4CAAC,6BAAS,SAAS,aAAa,IAAK;AAAA;AAAA;AAAA,EACtD;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/action-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../utils/cn.js\";\nimport { HelpIcon } from \"./help-icon.js\";\n\nconst ACTION_GRADIENTS: Record<string, [string, string, string]> = {\n buy: ['#3b7bff', '#8a5cf6', '#3b7bff'],\n submit: ['#d6359a', '#5b4ce6', '#d6359a'],\n offer: ['#f6608f', '#fb8b46', '#f6608f'],\n remix: ['#8a5cf6', '#f6608f', '#8a5cf6'],\n license: ['#3b7bff', '#5b4ce6', '#3b7bff'],\n};\n\nconst ACTION_FOREGROUNDS: Record<string, string> = {\n buy: '#3b7bff',\n submit: '#5b4ce6',\n offer: '#fb7a32',\n remix: '#8a3ff0',\n license: '#3b7bff',\n};\n\nconst TONE_GRADIENTS: Record<string, [string, string, string]> = {\n blue: ['#3b7bff', '#5b4ce6', '#3b7bff'],\n purple: ['#8a5cf6', '#f6608f', '#8a5cf6'],\n orange: ['#fb8b46', '#f6608f', '#fb8b46'],\n red: ['#ef5a5a', '#f6608f', '#ef5a5a'],\n rose: ['#f6608f', '#fb8b46', '#f6608f'],\n};\n\nconst TONE_FOREGROUNDS: Record<string, string> = {\n blue: '#2f6bff',\n purple: '#8a3ff0',\n orange: '#fb7a32',\n red: '#ef5a5a',\n rose: '#f6608f',\n};\n\nexport type ActionKey = keyof typeof ACTION_GRADIENTS;\nexport type ToneKey = keyof typeof TONE_GRADIENTS;\n\nexport interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\n href?: string;\n\n action?: ActionKey;\n\n tone?: ToneKey;\n icon?: React.ReactNode;\n\n big?: boolean;\n\n ghost?: boolean;\n\n helpContent?: string;\n}\n\nexport function ActionButton({\n action,\n tone,\n icon,\n big,\n ghost,\n href,\n helpContent,\n disabled,\n children,\n className,\n style,\n ...rest\n}: ActionButtonProps) {\n const Tag = (href ? \"a\" : \"button\") as React.ElementType;\n const linkProps = href ? { href, target: \"_blank\", rel: \"noopener noreferrer\" } : {};\n\n const sizeClass = big\n ? \"h-[54px] px-5 rounded-[13px] text-base\"\n : \"h-[46px] px-5 rounded-[13px] text-sm\";\n\n if (ghost) {\n return (\n <Tag\n {...rest}\n {...linkProps}\n disabled={disabled}\n className={cn(\n \"inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap\",\n \"bg-muted text-foreground border-none disabled:opacity-50 disabled:pointer-events-none\",\n sizeClass,\n className,\n )}\n style={style}\n >\n {icon}{children}\n {helpContent ? <HelpIcon content={helpContent} /> : null}\n </Tag>\n );\n }\n\n const gradColors =\n action ? ACTION_GRADIENTS[action] :\n tone ? TONE_GRADIENTS[tone] :\n ACTION_GRADIENTS.buy;\n\n const fg =\n action ? ACTION_FOREGROUNDS[action] :\n tone ? TONE_FOREGROUNDS[tone] :\n ACTION_FOREGROUNDS.buy;\n\n const grad = `linear-gradient(115deg, ${gradColors.join(',')})`;\n\n return (\n <Tag\n {...rest}\n {...linkProps}\n disabled={disabled}\n className={cn(\n \"ml-gbtn inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap\",\n \"bg-transparent text-foreground border-none relative disabled:opacity-40 disabled:pointer-events-none\",\n sizeClass,\n className,\n )}\n style={{ '--ml-grad': grad, ...style } as React.CSSProperties}\n >\n {icon && <span className=\"inline-flex\" style={{ color: fg }}>{icon}</span>}\n {children}\n {helpContent ? <HelpIcon content={helpContent} /> : null}\n </Tag>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+EM;AA7EN,gBAAmB;AACnB,uBAAyB;AAEzB,MAAM,mBAA6D;AAAA,EACjE,KAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,QAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,OAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,OAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,SAAS,CAAC,WAAW,WAAW,SAAS;AAC3C;AAEA,MAAM,qBAA6C;AAAA,EACjD,KAAS;AAAA,EACT,QAAS;AAAA,EACT,OAAS;AAAA,EACT,OAAS;AAAA,EACT,SAAS;AACX;AAEA,MAAM,iBAA2D;AAAA,EAC/D,MAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,KAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,MAAQ,CAAC,WAAW,WAAW,SAAS;AAC1C;AAEA,MAAM,mBAA2C;AAAA,EAC/C,MAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAQ;AAAA,EACR,MAAQ;AACV;AAqBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,MAAO,OAAO,MAAM;AAC1B,QAAM,YAAY,OAAO,EAAE,MAAM,QAAQ,UAAU,KAAK,sBAAsB,IAAI,CAAC;AAEnF,QAAM,YAAY,MACd,2CACA;AAEJ,MAAI,OAAO;AACT,WACE;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACH,GAAG;AAAA,QACJ;AAAA,QACA,eAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,UAAM;AAAA,UACN,cAAc,4CAAC,6BAAS,SAAS,aAAa,IAAK;AAAA;AAAA;AAAA,IACtD;AAAA,EAEJ;AAEA,QAAM,aACJ,SAAS,iBAAiB,MAAM,IAChC,OAAS,eAAe,IAAI,IAC5B,iBAAiB;AAEnB,QAAM,KACJ,SAAS,mBAAmB,MAAM,IAClC,OAAS,iBAAiB,IAAI,IAC9B,mBAAmB;AAErB,QAAM,OAAO,2BAA2B,WAAW,KAAK,GAAG,CAAC;AAE5D,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACH,GAAG;AAAA,MACJ;AAAA,MACA,eAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,EAAE,aAAa,MAAM,GAAG,MAAM;AAAA,MAEpC;AAAA,gBAAQ,4CAAC,UAAK,WAAU,eAAc,OAAO,EAAE,OAAO,GAAG,GAAI,gBAAK;AAAA,QAClE;AAAA,QACA,cAAc,4CAAC,6BAAS,SAAS,aAAa,IAAK;AAAA;AAAA;AAAA,EACtD;AAEJ;","names":[]}
@@ -5,6 +5,7 @@ declare const TONE_GRADIENTS: Record<string, [string, string, string]>;
5
5
  type ActionKey = keyof typeof ACTION_GRADIENTS;
6
6
  type ToneKey = keyof typeof TONE_GRADIENTS;
7
7
  interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
8
+ href?: string;
8
9
  action?: ActionKey;
9
10
  tone?: ToneKey;
10
11
  icon?: React.ReactNode;
@@ -12,6 +13,6 @@ interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement
12
13
  ghost?: boolean;
13
14
  helpContent?: string;
14
15
  }
15
- declare function ActionButton({ action, tone, icon, big, ghost, helpContent, disabled, children, className, style, ...rest }: ActionButtonProps): react_jsx_runtime.JSX.Element;
16
+ declare function ActionButton({ action, tone, icon, big, ghost, href, helpContent, disabled, children, className, style, ...rest }: ActionButtonProps): react_jsx_runtime.JSX.Element;
16
17
 
17
18
  export { ActionButton, type ActionButtonProps, type ActionKey, type ToneKey };
@@ -5,6 +5,7 @@ declare const TONE_GRADIENTS: Record<string, [string, string, string]>;
5
5
  type ActionKey = keyof typeof ACTION_GRADIENTS;
6
6
  type ToneKey = keyof typeof TONE_GRADIENTS;
7
7
  interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
8
+ href?: string;
8
9
  action?: ActionKey;
9
10
  tone?: ToneKey;
10
11
  icon?: React.ReactNode;
@@ -12,6 +13,6 @@ interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement
12
13
  ghost?: boolean;
13
14
  helpContent?: string;
14
15
  }
15
- declare function ActionButton({ action, tone, icon, big, ghost, helpContent, disabled, children, className, style, ...rest }: ActionButtonProps): react_jsx_runtime.JSX.Element;
16
+ declare function ActionButton({ action, tone, icon, big, ghost, href, helpContent, disabled, children, className, style, ...rest }: ActionButtonProps): react_jsx_runtime.JSX.Element;
16
17
 
17
18
  export { ActionButton, type ActionButtonProps, type ActionKey, type ToneKey };
@@ -36,6 +36,7 @@ function ActionButton({
36
36
  icon,
37
37
  big,
38
38
  ghost,
39
+ href,
39
40
  helpContent,
40
41
  disabled,
41
42
  children,
@@ -43,12 +44,15 @@ function ActionButton({
43
44
  style,
44
45
  ...rest
45
46
  }) {
47
+ const Tag = href ? "a" : "button";
48
+ const linkProps = href ? { href, target: "_blank", rel: "noopener noreferrer" } : {};
46
49
  const sizeClass = big ? "h-[54px] px-5 rounded-[13px] text-base" : "h-[46px] px-5 rounded-[13px] text-sm";
47
50
  if (ghost) {
48
51
  return /* @__PURE__ */ jsxs(
49
- "button",
52
+ Tag,
50
53
  {
51
54
  ...rest,
55
+ ...linkProps,
52
56
  disabled,
53
57
  className: cn(
54
58
  "inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap",
@@ -69,9 +73,10 @@ function ActionButton({
69
73
  const fg = action ? ACTION_FOREGROUNDS[action] : tone ? TONE_FOREGROUNDS[tone] : ACTION_FOREGROUNDS.buy;
70
74
  const grad = `linear-gradient(115deg, ${gradColors.join(",")})`;
71
75
  return /* @__PURE__ */ jsxs(
72
- "button",
76
+ Tag,
73
77
  {
74
78
  ...rest,
79
+ ...linkProps,
75
80
  disabled,
76
81
  className: cn(
77
82
  "ml-gbtn inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/action-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../utils/cn.js\";\nimport { HelpIcon } from \"./help-icon.js\";\n\nconst ACTION_GRADIENTS: Record<string, [string, string, string]> = {\n buy: ['#3b7bff', '#8a5cf6', '#3b7bff'],\n submit: ['#d6359a', '#5b4ce6', '#d6359a'],\n offer: ['#f6608f', '#fb8b46', '#f6608f'],\n remix: ['#8a5cf6', '#f6608f', '#8a5cf6'],\n license: ['#3b7bff', '#5b4ce6', '#3b7bff'],\n};\n\nconst ACTION_FOREGROUNDS: Record<string, string> = {\n buy: '#3b7bff',\n submit: '#5b4ce6',\n offer: '#fb7a32',\n remix: '#8a3ff0',\n license: '#3b7bff',\n};\n\nconst TONE_GRADIENTS: Record<string, [string, string, string]> = {\n blue: ['#3b7bff', '#5b4ce6', '#3b7bff'],\n purple: ['#8a5cf6', '#f6608f', '#8a5cf6'],\n orange: ['#fb8b46', '#f6608f', '#fb8b46'],\n red: ['#ef5a5a', '#f6608f', '#ef5a5a'],\n rose: ['#f6608f', '#fb8b46', '#f6608f'],\n};\n\nconst TONE_FOREGROUNDS: Record<string, string> = {\n blue: '#2f6bff',\n purple: '#8a3ff0',\n orange: '#fb7a32',\n red: '#ef5a5a',\n rose: '#f6608f',\n};\n\nexport type ActionKey = keyof typeof ACTION_GRADIENTS;\nexport type ToneKey = keyof typeof TONE_GRADIENTS;\n\nexport interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\n action?: ActionKey;\n\n tone?: ToneKey;\n icon?: React.ReactNode;\n\n big?: boolean;\n\n ghost?: boolean;\n\n helpContent?: string;\n}\n\nexport function ActionButton({\n action,\n tone,\n icon,\n big,\n ghost,\n helpContent,\n disabled,\n children,\n className,\n style,\n ...rest\n}: ActionButtonProps) {\n const sizeClass = big\n ? \"h-[54px] px-5 rounded-[13px] text-base\"\n : \"h-[46px] px-5 rounded-[13px] text-sm\";\n\n if (ghost) {\n return (\n <button\n {...rest}\n disabled={disabled}\n className={cn(\n \"inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap\",\n \"bg-muted text-foreground border-none disabled:opacity-50 disabled:pointer-events-none\",\n sizeClass,\n className,\n )}\n style={style}\n >\n {icon}{children}\n {helpContent ? <HelpIcon content={helpContent} /> : null}\n </button>\n );\n }\n\n const gradColors =\n action ? ACTION_GRADIENTS[action] :\n tone ? TONE_GRADIENTS[tone] :\n ACTION_GRADIENTS.buy;\n\n const fg =\n action ? ACTION_FOREGROUNDS[action] :\n tone ? TONE_FOREGROUNDS[tone] :\n ACTION_FOREGROUNDS.buy;\n\n const grad = `linear-gradient(115deg, ${gradColors.join(',')})`;\n\n return (\n <button\n {...rest}\n disabled={disabled}\n className={cn(\n \"ml-gbtn inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap\",\n \"bg-transparent text-foreground border-none relative disabled:opacity-40 disabled:pointer-events-none\",\n sizeClass,\n className,\n )}\n style={{ '--ml-grad': grad, ...style } as React.CSSProperties}\n >\n {icon && <span className=\"inline-flex\" style={{ color: fg }}>{icon}</span>}\n {children}\n {helpContent ? <HelpIcon content={helpContent} /> : null}\n </button>\n );\n}\n"],"mappings":";AAyEM,SAYiB,KAZjB;AAvEN,SAAS,UAAU;AACnB,SAAS,gBAAgB;AAEzB,MAAM,mBAA6D;AAAA,EACjE,KAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,QAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,OAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,OAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,SAAS,CAAC,WAAW,WAAW,SAAS;AAC3C;AAEA,MAAM,qBAA6C;AAAA,EACjD,KAAS;AAAA,EACT,QAAS;AAAA,EACT,OAAS;AAAA,EACT,OAAS;AAAA,EACT,SAAS;AACX;AAEA,MAAM,iBAA2D;AAAA,EAC/D,MAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,KAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,MAAQ,CAAC,WAAW,WAAW,SAAS;AAC1C;AAEA,MAAM,mBAA2C;AAAA,EAC/C,MAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAQ;AAAA,EACR,MAAQ;AACV;AAmBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,YAAY,MACd,2CACA;AAEJ,MAAI,OAAO;AACT,WACE;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACJ;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,UAAM;AAAA,UACN,cAAc,oBAAC,YAAS,SAAS,aAAa,IAAK;AAAA;AAAA;AAAA,IACtD;AAAA,EAEJ;AAEA,QAAM,aACJ,SAAS,iBAAiB,MAAM,IAChC,OAAS,eAAe,IAAI,IAC5B,iBAAiB;AAEnB,QAAM,KACJ,SAAS,mBAAmB,MAAM,IAClC,OAAS,iBAAiB,IAAI,IAC9B,mBAAmB;AAErB,QAAM,OAAO,2BAA2B,WAAW,KAAK,GAAG,CAAC;AAE5D,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,EAAE,aAAa,MAAM,GAAG,MAAM;AAAA,MAEpC;AAAA,gBAAQ,oBAAC,UAAK,WAAU,eAAc,OAAO,EAAE,OAAO,GAAG,GAAI,gBAAK;AAAA,QAClE;AAAA,QACA,cAAc,oBAAC,YAAS,SAAS,aAAa,IAAK;AAAA;AAAA;AAAA,EACtD;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/action-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../utils/cn.js\";\nimport { HelpIcon } from \"./help-icon.js\";\n\nconst ACTION_GRADIENTS: Record<string, [string, string, string]> = {\n buy: ['#3b7bff', '#8a5cf6', '#3b7bff'],\n submit: ['#d6359a', '#5b4ce6', '#d6359a'],\n offer: ['#f6608f', '#fb8b46', '#f6608f'],\n remix: ['#8a5cf6', '#f6608f', '#8a5cf6'],\n license: ['#3b7bff', '#5b4ce6', '#3b7bff'],\n};\n\nconst ACTION_FOREGROUNDS: Record<string, string> = {\n buy: '#3b7bff',\n submit: '#5b4ce6',\n offer: '#fb7a32',\n remix: '#8a3ff0',\n license: '#3b7bff',\n};\n\nconst TONE_GRADIENTS: Record<string, [string, string, string]> = {\n blue: ['#3b7bff', '#5b4ce6', '#3b7bff'],\n purple: ['#8a5cf6', '#f6608f', '#8a5cf6'],\n orange: ['#fb8b46', '#f6608f', '#fb8b46'],\n red: ['#ef5a5a', '#f6608f', '#ef5a5a'],\n rose: ['#f6608f', '#fb8b46', '#f6608f'],\n};\n\nconst TONE_FOREGROUNDS: Record<string, string> = {\n blue: '#2f6bff',\n purple: '#8a3ff0',\n orange: '#fb7a32',\n red: '#ef5a5a',\n rose: '#f6608f',\n};\n\nexport type ActionKey = keyof typeof ACTION_GRADIENTS;\nexport type ToneKey = keyof typeof TONE_GRADIENTS;\n\nexport interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\n href?: string;\n\n action?: ActionKey;\n\n tone?: ToneKey;\n icon?: React.ReactNode;\n\n big?: boolean;\n\n ghost?: boolean;\n\n helpContent?: string;\n}\n\nexport function ActionButton({\n action,\n tone,\n icon,\n big,\n ghost,\n href,\n helpContent,\n disabled,\n children,\n className,\n style,\n ...rest\n}: ActionButtonProps) {\n const Tag = (href ? \"a\" : \"button\") as React.ElementType;\n const linkProps = href ? { href, target: \"_blank\", rel: \"noopener noreferrer\" } : {};\n\n const sizeClass = big\n ? \"h-[54px] px-5 rounded-[13px] text-base\"\n : \"h-[46px] px-5 rounded-[13px] text-sm\";\n\n if (ghost) {\n return (\n <Tag\n {...rest}\n {...linkProps}\n disabled={disabled}\n className={cn(\n \"inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap\",\n \"bg-muted text-foreground border-none disabled:opacity-50 disabled:pointer-events-none\",\n sizeClass,\n className,\n )}\n style={style}\n >\n {icon}{children}\n {helpContent ? <HelpIcon content={helpContent} /> : null}\n </Tag>\n );\n }\n\n const gradColors =\n action ? ACTION_GRADIENTS[action] :\n tone ? TONE_GRADIENTS[tone] :\n ACTION_GRADIENTS.buy;\n\n const fg =\n action ? ACTION_FOREGROUNDS[action] :\n tone ? TONE_FOREGROUNDS[tone] :\n ACTION_FOREGROUNDS.buy;\n\n const grad = `linear-gradient(115deg, ${gradColors.join(',')})`;\n\n return (\n <Tag\n {...rest}\n {...linkProps}\n disabled={disabled}\n className={cn(\n \"ml-gbtn inline-flex items-center justify-center gap-2 font-semibold cursor-pointer whitespace-nowrap\",\n \"bg-transparent text-foreground border-none relative disabled:opacity-40 disabled:pointer-events-none\",\n sizeClass,\n className,\n )}\n style={{ '--ml-grad': grad, ...style } as React.CSSProperties}\n >\n {icon && <span className=\"inline-flex\" style={{ color: fg }}>{icon}</span>}\n {children}\n {helpContent ? <HelpIcon content={helpContent} /> : null}\n </Tag>\n );\n}\n"],"mappings":";AA+EM,SAaiB,KAbjB;AA7EN,SAAS,UAAU;AACnB,SAAS,gBAAgB;AAEzB,MAAM,mBAA6D;AAAA,EACjE,KAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,QAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,OAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,OAAS,CAAC,WAAW,WAAW,SAAS;AAAA,EACzC,SAAS,CAAC,WAAW,WAAW,SAAS;AAC3C;AAEA,MAAM,qBAA6C;AAAA,EACjD,KAAS;AAAA,EACT,QAAS;AAAA,EACT,OAAS;AAAA,EACT,OAAS;AAAA,EACT,SAAS;AACX;AAEA,MAAM,iBAA2D;AAAA,EAC/D,MAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,KAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,EACxC,MAAQ,CAAC,WAAW,WAAW,SAAS;AAC1C;AAEA,MAAM,mBAA2C;AAAA,EAC/C,MAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAQ;AAAA,EACR,MAAQ;AACV;AAqBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,MAAO,OAAO,MAAM;AAC1B,QAAM,YAAY,OAAO,EAAE,MAAM,QAAQ,UAAU,KAAK,sBAAsB,IAAI,CAAC;AAEnF,QAAM,YAAY,MACd,2CACA;AAEJ,MAAI,OAAO;AACT,WACE;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACH,GAAG;AAAA,QACJ;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,UAAM;AAAA,UACN,cAAc,oBAAC,YAAS,SAAS,aAAa,IAAK;AAAA;AAAA;AAAA,IACtD;AAAA,EAEJ;AAEA,QAAM,aACJ,SAAS,iBAAiB,MAAM,IAChC,OAAS,eAAe,IAAI,IAC5B,iBAAiB;AAEnB,QAAM,KACJ,SAAS,mBAAmB,MAAM,IAClC,OAAS,iBAAiB,IAAI,IAC9B,mBAAmB;AAErB,QAAM,OAAO,2BAA2B,WAAW,KAAK,GAAG,CAAC;AAE5D,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACH,GAAG;AAAA,MACJ;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,EAAE,aAAa,MAAM,GAAG,MAAM;AAAA,MAEpC;AAAA,gBAAQ,oBAAC,UAAK,WAAU,eAAc,OAAO,EAAE,OAAO,GAAG,GAAI,gBAAK;AAAA,QAClE;AAAA,QACA,cAAc,oBAAC,YAAS,SAAS,aAAa,IAAK;AAAA;AAAA;AAAA,EACtD;AAEJ;","names":[]}
@@ -43,6 +43,7 @@ var import_lucide_react = require("lucide-react");
43
43
  var import_activity = require("../data/activity.js");
44
44
  var import_activity_row = require("./activity-row.js");
45
45
  var import_cn = require("../utils/cn.js");
46
+ var import_empty_messages = require("../utils/empty-messages.js");
46
47
  async function fetchAnnouncements() {
47
48
  const res = await fetch("/api/announcements");
48
49
  if (!res.ok) return [];
@@ -175,7 +176,10 @@ function ActivitiesFeed() {
175
176
  ] })
176
177
  ] }, i)) }) : allActivities.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "py-20 flex flex-col items-center gap-3 text-center", children: [
177
178
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-12 w-12 rounded-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Zap, { className: "h-5 w-5 text-muted-foreground" }) }),
178
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground", children: typeFilter ? `No ${typeFilter} events yet.` : "No activity yet." })
179
+ typeFilter ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground", children: `No ${typeFilter} events yet.` }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
180
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "font-medium", children: import_empty_messages.emptyMessages.activity.title }),
181
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground", children: import_empty_messages.emptyMessages.activity.description })
182
+ ] })
179
183
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-4", children: [
180
184
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "divide-y divide-border/50 rounded-xl border border-border overflow-hidden", children: allActivities.map((activity, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
181
185
  import_activity_row.ActivityRow,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/activities-feed.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport useSWR from \"swr\";\nimport Link from \"next/link\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport type { ApiActivitiesQuery, ApiActivity } from \"@medialane/sdk\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Zap, Megaphone, ArrowRight, Pin } from \"lucide-react\";\nimport { ACTIVITY_TYPE_CONFIG, TYPE_FILTERS } from \"../data/activity.js\";\nimport { ActivityRow } from \"./activity-row.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { Announcement } from \"../data/notification.js\";\n\nasync function fetchAnnouncements(): Promise<Announcement[]> {\n const res = await fetch(\"/api/announcements\");\n if (!res.ok) return [];\n return res.json();\n}\n\nfunction AnnouncementsBanner({ announcements }: { announcements: Announcement[] }) {\n const pinned = announcements.filter((a) => a.pinned);\n if (pinned.length === 0) return null;\n return (\n <div className=\"space-y-2\">\n {pinned.map((ann) => (\n <Link\n key={ann.id}\n href={ann.href}\n className=\"flex items-start gap-3 rounded-xl border border-brand-purple/20 bg-brand-purple/5 px-4 py-3 hover:bg-brand-purple/10 transition-colors group\"\n >\n <div className=\"h-8 w-8 rounded-lg bg-brand-purple/10 flex items-center justify-center shrink-0 mt-0.5\">\n <Megaphone className=\"h-3.5 w-3.5 text-brand-purple\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 mb-0.5\">\n <Pin className=\"h-2.5 w-2.5 text-brand-purple/60\" />\n <span className=\"text-2xs font-bold uppercase tracking-widest text-brand-purple/60\">Announcement</span>\n </div>\n <p className=\"text-sm font-semibold leading-snug\">{ann.title}</p>\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">{ann.body}</p>\n </div>\n <ArrowRight className=\"h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors shrink-0 mt-1\" />\n </Link>\n ))}\n </div>\n );\n}\n\nconst PAGE_SIZE = 30;\n\nexport function ActivitiesFeed() {\n const [page, setPage] = useState(1);\n const [typeFilter, setTypeFilter] = useState(\"\");\n const [allActivities, setAllActivities] = useState<ApiActivity[]>([]);\n const { data: announcements = [] } = useSWR<Announcement[]>(\n \"announcements\",\n fetchAnnouncements,\n { revalidateOnFocus: false }\n );\n\n const prevType = useRef(typeFilter);\n useEffect(() => {\n if (prevType.current !== typeFilter) {\n prevType.current = typeFilter;\n setPage(1);\n setAllActivities([]);\n }\n }, [typeFilter]);\n\n const { activities, meta, isLoading } = useActivities({\n limit: PAGE_SIZE,\n page,\n type: (typeFilter as ApiActivitiesQuery[\"type\"]) || undefined,\n });\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllActivities(activities);\n } else {\n setAllActivities((prev) => {\n const existing = new Set(\n prev.map((a) => `${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n const newItems = activities.filter(\n (a) => !existing.has(`${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n return newItems.length > 0 ? [...prev, ...newItems] : prev;\n });\n }\n }, [activities, isLoading, page]);\n\n const isInitialLoading = isLoading && allActivities.length === 0;\n const isLoadingMore = isLoading && allActivities.length > 0;\n const hasMore = meta?.total != null ? allActivities.length < meta.total : false;\n const total = meta?.total ?? null;\n\n return (\n <div className=\"space-y-5\">\n <AnnouncementsBanner announcements={announcements} />\n\n {total != null && (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse\" />\n <span className=\"font-semibold text-foreground tabular-nums\">\n {total.toLocaleString()}\n </span>\n {typeFilter ? `${typeFilter} events` : \"total events\"}\n </span>\n {typeFilter && allActivities.length > 0 && (\n <>\n <span className=\"text-muted-foreground/40\">·</span>\n <span>{allActivities.length.toLocaleString()} loaded</span>\n </>\n )}\n </div>\n )}\n\n <div className=\"flex flex-wrap gap-2\">\n {TYPE_FILTERS.map((f) => {\n const typeConfig = f.value ? ACTIVITY_TYPE_CONFIG[f.value] : null;\n const Icon = typeConfig?.icon;\n const isActive = typeFilter === f.value;\n return (\n <button\n key={f.value}\n onClick={() => setTypeFilter(f.value)}\n className={cn(\n \"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-all font-medium\",\n isActive\n ? \"border-primary bg-primary/10 text-primary shadow-sm\"\n : \"border-border text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-muted/50\"\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"h-3 w-3\",\n isActive ? typeConfig?.colorClass : \"\"\n )}\n />\n )}\n {f.label}\n </button>\n );\n })}\n </div>\n\n {isInitialLoading ? (\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {Array.from({ length: 10 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-3.5 bg-card\">\n <Skeleton className=\"h-8 w-8 rounded-lg shrink-0\" />\n <Skeleton className=\"h-9 w-9 rounded-md shrink-0\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-3.5 w-40\" />\n <Skeleton className=\"h-2.5 w-24\" />\n </div>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"space-y-1 text-right\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-2.5 w-8\" />\n </div>\n <Skeleton className=\"h-2.5 w-12 hidden sm:block\" />\n </div>\n </div>\n ))}\n </div>\n ) : allActivities.length === 0 ? (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <div className=\"h-12 w-12 rounded-full bg-muted flex items-center justify-center\">\n <Zap className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"text-muted-foreground\">\n {typeFilter ? `No ${typeFilter} events yet.` : \"No activity yet.\"}\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {allActivities.map((activity, i) => (\n <ActivityRow\n key={`${activity.txHash}-${activity.type}-${activity.nftTokenId ?? i}`}\n activity={activity}\n showActor\n showExplorer\n />\n ))}\n </div>\n\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["Link","useSWR"]}
1
+ {"version":3,"sources":["../../src/components/activities-feed.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport useSWR from \"swr\";\nimport Link from \"next/link\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport type { ApiActivitiesQuery, ApiActivity } from \"@medialane/sdk\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Zap, Megaphone, ArrowRight, Pin } from \"lucide-react\";\nimport { ACTIVITY_TYPE_CONFIG, TYPE_FILTERS } from \"../data/activity.js\";\nimport { ActivityRow } from \"./activity-row.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { Announcement } from \"../data/notification.js\";\nimport { emptyMessages } from \"../utils/empty-messages.js\";\n\nasync function fetchAnnouncements(): Promise<Announcement[]> {\n const res = await fetch(\"/api/announcements\");\n if (!res.ok) return [];\n return res.json();\n}\n\nfunction AnnouncementsBanner({ announcements }: { announcements: Announcement[] }) {\n const pinned = announcements.filter((a) => a.pinned);\n if (pinned.length === 0) return null;\n return (\n <div className=\"space-y-2\">\n {pinned.map((ann) => (\n <Link\n key={ann.id}\n href={ann.href}\n className=\"flex items-start gap-3 rounded-xl border border-brand-purple/20 bg-brand-purple/5 px-4 py-3 hover:bg-brand-purple/10 transition-colors group\"\n >\n <div className=\"h-8 w-8 rounded-lg bg-brand-purple/10 flex items-center justify-center shrink-0 mt-0.5\">\n <Megaphone className=\"h-3.5 w-3.5 text-brand-purple\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 mb-0.5\">\n <Pin className=\"h-2.5 w-2.5 text-brand-purple/60\" />\n <span className=\"text-2xs font-bold uppercase tracking-widest text-brand-purple/60\">Announcement</span>\n </div>\n <p className=\"text-sm font-semibold leading-snug\">{ann.title}</p>\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">{ann.body}</p>\n </div>\n <ArrowRight className=\"h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors shrink-0 mt-1\" />\n </Link>\n ))}\n </div>\n );\n}\n\nconst PAGE_SIZE = 30;\n\nexport function ActivitiesFeed() {\n const [page, setPage] = useState(1);\n const [typeFilter, setTypeFilter] = useState(\"\");\n const [allActivities, setAllActivities] = useState<ApiActivity[]>([]);\n const { data: announcements = [] } = useSWR<Announcement[]>(\n \"announcements\",\n fetchAnnouncements,\n { revalidateOnFocus: false }\n );\n\n const prevType = useRef(typeFilter);\n useEffect(() => {\n if (prevType.current !== typeFilter) {\n prevType.current = typeFilter;\n setPage(1);\n setAllActivities([]);\n }\n }, [typeFilter]);\n\n const { activities, meta, isLoading } = useActivities({\n limit: PAGE_SIZE,\n page,\n type: (typeFilter as ApiActivitiesQuery[\"type\"]) || undefined,\n });\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllActivities(activities);\n } else {\n setAllActivities((prev) => {\n const existing = new Set(\n prev.map((a) => `${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n const newItems = activities.filter(\n (a) => !existing.has(`${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n return newItems.length > 0 ? [...prev, ...newItems] : prev;\n });\n }\n }, [activities, isLoading, page]);\n\n const isInitialLoading = isLoading && allActivities.length === 0;\n const isLoadingMore = isLoading && allActivities.length > 0;\n const hasMore = meta?.total != null ? allActivities.length < meta.total : false;\n const total = meta?.total ?? null;\n\n return (\n <div className=\"space-y-5\">\n <AnnouncementsBanner announcements={announcements} />\n\n {total != null && (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse\" />\n <span className=\"font-semibold text-foreground tabular-nums\">\n {total.toLocaleString()}\n </span>\n {typeFilter ? `${typeFilter} events` : \"total events\"}\n </span>\n {typeFilter && allActivities.length > 0 && (\n <>\n <span className=\"text-muted-foreground/40\">·</span>\n <span>{allActivities.length.toLocaleString()} loaded</span>\n </>\n )}\n </div>\n )}\n\n <div className=\"flex flex-wrap gap-2\">\n {TYPE_FILTERS.map((f) => {\n const typeConfig = f.value ? ACTIVITY_TYPE_CONFIG[f.value] : null;\n const Icon = typeConfig?.icon;\n const isActive = typeFilter === f.value;\n return (\n <button\n key={f.value}\n onClick={() => setTypeFilter(f.value)}\n className={cn(\n \"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-all font-medium\",\n isActive\n ? \"border-primary bg-primary/10 text-primary shadow-sm\"\n : \"border-border text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-muted/50\"\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"h-3 w-3\",\n isActive ? typeConfig?.colorClass : \"\"\n )}\n />\n )}\n {f.label}\n </button>\n );\n })}\n </div>\n\n {isInitialLoading ? (\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {Array.from({ length: 10 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-3.5 bg-card\">\n <Skeleton className=\"h-8 w-8 rounded-lg shrink-0\" />\n <Skeleton className=\"h-9 w-9 rounded-md shrink-0\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-3.5 w-40\" />\n <Skeleton className=\"h-2.5 w-24\" />\n </div>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"space-y-1 text-right\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-2.5 w-8\" />\n </div>\n <Skeleton className=\"h-2.5 w-12 hidden sm:block\" />\n </div>\n </div>\n ))}\n </div>\n ) : allActivities.length === 0 ? (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <div className=\"h-12 w-12 rounded-full bg-muted flex items-center justify-center\">\n <Zap className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n {typeFilter ? (\n <p className=\"text-muted-foreground\">{`No ${typeFilter} events yet.`}</p>\n ) : (\n <div>\n <p className=\"font-medium\">{emptyMessages.activity.title}</p>\n <p className=\"text-sm text-muted-foreground\">{emptyMessages.activity.description}</p>\n </div>\n )}\n </div>\n ) : (\n <div className=\"space-y-4\">\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {allActivities.map((activity, i) => (\n <ActivityRow\n key={`${activity.txHash}-${activity.type}-${activity.nftTokenId ?? i}`}\n activity={activity}\n showActor\n showExplorer\n />\n ))}\n </div>\n\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["Link","useSWR"]}
@@ -10,6 +10,7 @@ import { Zap, Megaphone, ArrowRight, Pin } from "lucide-react";
10
10
  import { ACTIVITY_TYPE_CONFIG, TYPE_FILTERS } from "../data/activity.js";
11
11
  import { ActivityRow } from "./activity-row.js";
12
12
  import { cn } from "../utils/cn.js";
13
+ import { emptyMessages } from "../utils/empty-messages.js";
13
14
  async function fetchAnnouncements() {
14
15
  const res = await fetch("/api/announcements");
15
16
  if (!res.ok) return [];
@@ -142,7 +143,10 @@ function ActivitiesFeed() {
142
143
  ] })
143
144
  ] }, i)) }) : allActivities.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "py-20 flex flex-col items-center gap-3 text-center", children: [
144
145
  /* @__PURE__ */ jsx("div", { className: "h-12 w-12 rounded-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx(Zap, { className: "h-5 w-5 text-muted-foreground" }) }),
145
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: typeFilter ? `No ${typeFilter} events yet.` : "No activity yet." })
146
+ typeFilter ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: `No ${typeFilter} events yet.` }) : /* @__PURE__ */ jsxs("div", { children: [
147
+ /* @__PURE__ */ jsx("p", { className: "font-medium", children: emptyMessages.activity.title }),
148
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessages.activity.description })
149
+ ] })
146
150
  ] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
147
151
  /* @__PURE__ */ jsx("div", { className: "divide-y divide-border/50 rounded-xl border border-border overflow-hidden", children: allActivities.map((activity, i) => /* @__PURE__ */ jsx(
148
152
  ActivityRow,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/activities-feed.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport useSWR from \"swr\";\nimport Link from \"next/link\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport type { ApiActivitiesQuery, ApiActivity } from \"@medialane/sdk\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Zap, Megaphone, ArrowRight, Pin } from \"lucide-react\";\nimport { ACTIVITY_TYPE_CONFIG, TYPE_FILTERS } from \"../data/activity.js\";\nimport { ActivityRow } from \"./activity-row.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { Announcement } from \"../data/notification.js\";\n\nasync function fetchAnnouncements(): Promise<Announcement[]> {\n const res = await fetch(\"/api/announcements\");\n if (!res.ok) return [];\n return res.json();\n}\n\nfunction AnnouncementsBanner({ announcements }: { announcements: Announcement[] }) {\n const pinned = announcements.filter((a) => a.pinned);\n if (pinned.length === 0) return null;\n return (\n <div className=\"space-y-2\">\n {pinned.map((ann) => (\n <Link\n key={ann.id}\n href={ann.href}\n className=\"flex items-start gap-3 rounded-xl border border-brand-purple/20 bg-brand-purple/5 px-4 py-3 hover:bg-brand-purple/10 transition-colors group\"\n >\n <div className=\"h-8 w-8 rounded-lg bg-brand-purple/10 flex items-center justify-center shrink-0 mt-0.5\">\n <Megaphone className=\"h-3.5 w-3.5 text-brand-purple\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 mb-0.5\">\n <Pin className=\"h-2.5 w-2.5 text-brand-purple/60\" />\n <span className=\"text-2xs font-bold uppercase tracking-widest text-brand-purple/60\">Announcement</span>\n </div>\n <p className=\"text-sm font-semibold leading-snug\">{ann.title}</p>\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">{ann.body}</p>\n </div>\n <ArrowRight className=\"h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors shrink-0 mt-1\" />\n </Link>\n ))}\n </div>\n );\n}\n\nconst PAGE_SIZE = 30;\n\nexport function ActivitiesFeed() {\n const [page, setPage] = useState(1);\n const [typeFilter, setTypeFilter] = useState(\"\");\n const [allActivities, setAllActivities] = useState<ApiActivity[]>([]);\n const { data: announcements = [] } = useSWR<Announcement[]>(\n \"announcements\",\n fetchAnnouncements,\n { revalidateOnFocus: false }\n );\n\n const prevType = useRef(typeFilter);\n useEffect(() => {\n if (prevType.current !== typeFilter) {\n prevType.current = typeFilter;\n setPage(1);\n setAllActivities([]);\n }\n }, [typeFilter]);\n\n const { activities, meta, isLoading } = useActivities({\n limit: PAGE_SIZE,\n page,\n type: (typeFilter as ApiActivitiesQuery[\"type\"]) || undefined,\n });\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllActivities(activities);\n } else {\n setAllActivities((prev) => {\n const existing = new Set(\n prev.map((a) => `${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n const newItems = activities.filter(\n (a) => !existing.has(`${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n return newItems.length > 0 ? [...prev, ...newItems] : prev;\n });\n }\n }, [activities, isLoading, page]);\n\n const isInitialLoading = isLoading && allActivities.length === 0;\n const isLoadingMore = isLoading && allActivities.length > 0;\n const hasMore = meta?.total != null ? allActivities.length < meta.total : false;\n const total = meta?.total ?? null;\n\n return (\n <div className=\"space-y-5\">\n <AnnouncementsBanner announcements={announcements} />\n\n {total != null && (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse\" />\n <span className=\"font-semibold text-foreground tabular-nums\">\n {total.toLocaleString()}\n </span>\n {typeFilter ? `${typeFilter} events` : \"total events\"}\n </span>\n {typeFilter && allActivities.length > 0 && (\n <>\n <span className=\"text-muted-foreground/40\">·</span>\n <span>{allActivities.length.toLocaleString()} loaded</span>\n </>\n )}\n </div>\n )}\n\n <div className=\"flex flex-wrap gap-2\">\n {TYPE_FILTERS.map((f) => {\n const typeConfig = f.value ? ACTIVITY_TYPE_CONFIG[f.value] : null;\n const Icon = typeConfig?.icon;\n const isActive = typeFilter === f.value;\n return (\n <button\n key={f.value}\n onClick={() => setTypeFilter(f.value)}\n className={cn(\n \"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-all font-medium\",\n isActive\n ? \"border-primary bg-primary/10 text-primary shadow-sm\"\n : \"border-border text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-muted/50\"\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"h-3 w-3\",\n isActive ? typeConfig?.colorClass : \"\"\n )}\n />\n )}\n {f.label}\n </button>\n );\n })}\n </div>\n\n {isInitialLoading ? (\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {Array.from({ length: 10 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-3.5 bg-card\">\n <Skeleton className=\"h-8 w-8 rounded-lg shrink-0\" />\n <Skeleton className=\"h-9 w-9 rounded-md shrink-0\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-3.5 w-40\" />\n <Skeleton className=\"h-2.5 w-24\" />\n </div>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"space-y-1 text-right\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-2.5 w-8\" />\n </div>\n <Skeleton className=\"h-2.5 w-12 hidden sm:block\" />\n </div>\n </div>\n ))}\n </div>\n ) : allActivities.length === 0 ? (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <div className=\"h-12 w-12 rounded-full bg-muted flex items-center justify-center\">\n <Zap className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"text-muted-foreground\">\n {typeFilter ? `No ${typeFilter} events yet.` : \"No activity yet.\"}\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {allActivities.map((activity, i) => (\n <ActivityRow\n key={`${activity.txHash}-${activity.type}-${activity.nftTokenId ?? i}`}\n activity={activity}\n showActor\n showExplorer\n />\n ))}\n </div>\n\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/activities-feed.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport useSWR from \"swr\";\nimport Link from \"next/link\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport type { ApiActivitiesQuery, ApiActivity } from \"@medialane/sdk\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Zap, Megaphone, ArrowRight, Pin } from \"lucide-react\";\nimport { ACTIVITY_TYPE_CONFIG, TYPE_FILTERS } from \"../data/activity.js\";\nimport { ActivityRow } from \"./activity-row.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { Announcement } from \"../data/notification.js\";\nimport { emptyMessages } from \"../utils/empty-messages.js\";\n\nasync function fetchAnnouncements(): Promise<Announcement[]> {\n const res = await fetch(\"/api/announcements\");\n if (!res.ok) return [];\n return res.json();\n}\n\nfunction AnnouncementsBanner({ announcements }: { announcements: Announcement[] }) {\n const pinned = announcements.filter((a) => a.pinned);\n if (pinned.length === 0) return null;\n return (\n <div className=\"space-y-2\">\n {pinned.map((ann) => (\n <Link\n key={ann.id}\n href={ann.href}\n className=\"flex items-start gap-3 rounded-xl border border-brand-purple/20 bg-brand-purple/5 px-4 py-3 hover:bg-brand-purple/10 transition-colors group\"\n >\n <div className=\"h-8 w-8 rounded-lg bg-brand-purple/10 flex items-center justify-center shrink-0 mt-0.5\">\n <Megaphone className=\"h-3.5 w-3.5 text-brand-purple\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 mb-0.5\">\n <Pin className=\"h-2.5 w-2.5 text-brand-purple/60\" />\n <span className=\"text-2xs font-bold uppercase tracking-widest text-brand-purple/60\">Announcement</span>\n </div>\n <p className=\"text-sm font-semibold leading-snug\">{ann.title}</p>\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">{ann.body}</p>\n </div>\n <ArrowRight className=\"h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors shrink-0 mt-1\" />\n </Link>\n ))}\n </div>\n );\n}\n\nconst PAGE_SIZE = 30;\n\nexport function ActivitiesFeed() {\n const [page, setPage] = useState(1);\n const [typeFilter, setTypeFilter] = useState(\"\");\n const [allActivities, setAllActivities] = useState<ApiActivity[]>([]);\n const { data: announcements = [] } = useSWR<Announcement[]>(\n \"announcements\",\n fetchAnnouncements,\n { revalidateOnFocus: false }\n );\n\n const prevType = useRef(typeFilter);\n useEffect(() => {\n if (prevType.current !== typeFilter) {\n prevType.current = typeFilter;\n setPage(1);\n setAllActivities([]);\n }\n }, [typeFilter]);\n\n const { activities, meta, isLoading } = useActivities({\n limit: PAGE_SIZE,\n page,\n type: (typeFilter as ApiActivitiesQuery[\"type\"]) || undefined,\n });\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllActivities(activities);\n } else {\n setAllActivities((prev) => {\n const existing = new Set(\n prev.map((a) => `${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n const newItems = activities.filter(\n (a) => !existing.has(`${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n return newItems.length > 0 ? [...prev, ...newItems] : prev;\n });\n }\n }, [activities, isLoading, page]);\n\n const isInitialLoading = isLoading && allActivities.length === 0;\n const isLoadingMore = isLoading && allActivities.length > 0;\n const hasMore = meta?.total != null ? allActivities.length < meta.total : false;\n const total = meta?.total ?? null;\n\n return (\n <div className=\"space-y-5\">\n <AnnouncementsBanner announcements={announcements} />\n\n {total != null && (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse\" />\n <span className=\"font-semibold text-foreground tabular-nums\">\n {total.toLocaleString()}\n </span>\n {typeFilter ? `${typeFilter} events` : \"total events\"}\n </span>\n {typeFilter && allActivities.length > 0 && (\n <>\n <span className=\"text-muted-foreground/40\">·</span>\n <span>{allActivities.length.toLocaleString()} loaded</span>\n </>\n )}\n </div>\n )}\n\n <div className=\"flex flex-wrap gap-2\">\n {TYPE_FILTERS.map((f) => {\n const typeConfig = f.value ? ACTIVITY_TYPE_CONFIG[f.value] : null;\n const Icon = typeConfig?.icon;\n const isActive = typeFilter === f.value;\n return (\n <button\n key={f.value}\n onClick={() => setTypeFilter(f.value)}\n className={cn(\n \"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-all font-medium\",\n isActive\n ? \"border-primary bg-primary/10 text-primary shadow-sm\"\n : \"border-border text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-muted/50\"\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"h-3 w-3\",\n isActive ? typeConfig?.colorClass : \"\"\n )}\n />\n )}\n {f.label}\n </button>\n );\n })}\n </div>\n\n {isInitialLoading ? (\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {Array.from({ length: 10 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-3.5 bg-card\">\n <Skeleton className=\"h-8 w-8 rounded-lg shrink-0\" />\n <Skeleton className=\"h-9 w-9 rounded-md shrink-0\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-3.5 w-40\" />\n <Skeleton className=\"h-2.5 w-24\" />\n </div>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"space-y-1 text-right\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-2.5 w-8\" />\n </div>\n <Skeleton className=\"h-2.5 w-12 hidden sm:block\" />\n </div>\n </div>\n ))}\n </div>\n ) : allActivities.length === 0 ? (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <div className=\"h-12 w-12 rounded-full bg-muted flex items-center justify-center\">\n <Zap className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n {typeFilter ? (\n <p className=\"text-muted-foreground\">{`No ${typeFilter} events yet.`}</p>\n ) : (\n <div>\n <p className=\"font-medium\">{emptyMessages.activity.title}</p>\n <p className=\"text-sm text-muted-foreground\">{emptyMessages.activity.description}</p>\n </div>\n )}\n </div>\n ) : (\n <div className=\"space-y-4\">\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {allActivities.map((activity, i) => (\n <ActivityRow\n key={`${activity.txHash}-${activity.type}-${activity.nftTokenId ?? i}`}\n activity={activity}\n showActor\n showExplorer\n />\n ))}\n </div>\n\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -36,6 +36,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
36
36
  var import_link = __toESM(require("./link.js"), 1);
37
37
  var import_lucide_react = require("lucide-react");
38
38
  var import_time = require("../utils/time.js");
39
+ var import_empty_messages = require("../utils/empty-messages.js");
39
40
  function SkeletonRow() {
40
41
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 px-4 py-2.5", children: [
41
42
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-7 w-7 rounded-lg bg-muted animate-pulse shrink-0" }),
@@ -79,7 +80,8 @@ function ActivityFeedShell({ title, href, hrefLabel = "Activities", lastUpdated,
79
80
  ] }),
80
81
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "bento-cell overflow-hidden divide-y divide-border/40", children: isLoading ? Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonRow, {}, i)) : !children || Array.isArray(children) && children.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-center gap-2 py-10 text-center", children: [
81
82
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Activity, { className: "h-8 w-8 text-muted-foreground/30" }),
82
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground", children: "No activity yet." })
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium", children: import_empty_messages.emptyMessages.activity.title }),
84
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground", children: import_empty_messages.emptyMessages.activity.description })
83
85
  ] }) : children })
84
86
  ] });
85
87
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/activity-feed-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { ArrowRight, Activity, RefreshCw } from \"lucide-react\";\nimport { timeAgo } from \"../utils/time.js\";\n\nexport interface ActivityFeedShellProps {\n title: string;\n href: string;\n hrefLabel?: string;\n lastUpdated: string;\n isLoading: boolean;\n children: React.ReactNode;\n}\n\nfunction SkeletonRow() {\n return (\n <div className=\"flex items-center gap-3 px-4 py-2.5\">\n <div className=\"h-7 w-7 rounded-lg bg-muted animate-pulse shrink-0\" />\n <div className=\"h-7 w-7 rounded-md bg-muted animate-pulse shrink-0\" />\n <div className=\"flex-1 space-y-1.5\">\n <div className=\"h-3 w-32 bg-muted animate-pulse rounded\" />\n <div className=\"h-2.5 w-20 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"space-y-1 text-right\">\n <div className=\"h-3.5 w-14 bg-muted animate-pulse rounded\" />\n <div className=\"h-2.5 w-8 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"h-3 w-10 bg-muted animate-pulse rounded hidden sm:block\" />\n </div>\n );\n}\n\nexport function ActivityFeedShell({ title, href, hrefLabel = \"Activities\", lastUpdated, isLoading, children }: ActivityFeedShellProps) {\n return (\n <section className=\"space-y-5\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"relative h-8 w-8 rounded-xl bg-gradient-to-br from-indigo-500 to-blue-600 flex items-center justify-center shadow-lg shadow-indigo-500/20 shrink-0\">\n <Activity className=\"h-4 w-4 text-white\" />\n <span className=\"absolute -top-1 -right-1 flex h-2.5 w-2.5\">\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75\" />\n <span className=\"relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500\" />\n </span>\n </div>\n <div>\n <h2 className=\"text-xl sm:text-2xl font-black leading-none\">{title}</h2>\n <p className=\"text-2xs text-muted-foreground mt-0.5 flex items-center gap-1\">\n <RefreshCw className=\"h-2.5 w-2.5\" />\n Updated {timeAgo(lastUpdated)}\n </p>\n </div>\n </div>\n <Link href={href} 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 {hrefLabel} <ArrowRight className=\"h-3.5 w-3.5\" />\n </Link>\n </div>\n\n <div className=\"bento-cell overflow-hidden divide-y divide-border/40\">\n {isLoading ? (\n Array.from({ length: 6 }).map((_, i) => <SkeletonRow key={i} />)\n ) : !children || (Array.isArray(children) && children.length === 0) ? (\n <div className=\"flex flex-col items-center gap-2 py-10 text-center\">\n <Activity className=\"h-8 w-8 text-muted-foreground/30\" />\n <p className=\"text-sm text-muted-foreground\">No activity yet.</p>\n </div>\n ) : (\n children\n )}\n </div>\n </section>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBM;AAhBN,kBAAiB;AACjB,0BAAgD;AAChD,kBAAwB;AAWxB,SAAS,cAAc;AACrB,SACE,6CAAC,SAAI,WAAU,uCACb;AAAA,gDAAC,SAAI,WAAU,sDAAqD;AAAA,IACpE,4CAAC,SAAI,WAAU,sDAAqD;AAAA,IACpE,6CAAC,SAAI,WAAU,sBACb;AAAA,kDAAC,SAAI,WAAU,2CAA0C;AAAA,MACzD,4CAAC,SAAI,WAAU,6CAA4C;AAAA,OAC7D;AAAA,IACA,6CAAC,SAAI,WAAU,wBACb;AAAA,kDAAC,SAAI,WAAU,6CAA4C;AAAA,MAC3D,4CAAC,SAAI,WAAU,4CAA2C;AAAA,OAC5D;AAAA,IACA,4CAAC,SAAI,WAAU,2DAA0D;AAAA,KAC3E;AAEJ;AAEO,SAAS,kBAAkB,EAAE,OAAO,MAAM,YAAY,cAAc,aAAa,WAAW,SAAS,GAA2B;AACrI,SACE,6CAAC,aAAQ,WAAU,aACjB;AAAA,iDAAC,SAAI,WAAU,qCACb;AAAA,mDAAC,SAAI,WAAU,6BACb;AAAA,qDAAC,SAAI,WAAU,sJACb;AAAA,sDAAC,gCAAS,WAAU,sBAAqB;AAAA,UACzC,6CAAC,UAAK,WAAU,6CACd;AAAA,wDAAC,UAAK,WAAU,0FAAyF;AAAA,YACzG,4CAAC,UAAK,WAAU,gEAA+D;AAAA,aACjF;AAAA,WACF;AAAA,QACA,6CAAC,SACC;AAAA,sDAAC,QAAG,WAAU,+CAA+C,iBAAM;AAAA,UACnE,6CAAC,OAAE,WAAU,iEACX;AAAA,wDAAC,iCAAU,WAAU,eAAc;AAAA,YAAE;AAAA,gBAC5B,qBAAQ,WAAW;AAAA,aAC9B;AAAA,WACF;AAAA,SACF;AAAA,MACA,6CAAC,YAAAA,SAAA,EAAK,MAAY,WAAU,+IACzB;AAAA;AAAA,QAAU;AAAA,QAAC,4CAAC,kCAAW,WAAU,eAAc;AAAA,SAClD;AAAA,OACF;AAAA,IAEA,4CAAC,SAAI,WAAU,wDACZ,sBACC,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,4CAAC,iBAAiB,CAAG,CAAE,IAC7D,CAAC,YAAa,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW,IAC/D,6CAAC,SAAI,WAAU,sDACb;AAAA,kDAAC,gCAAS,WAAU,oCAAmC;AAAA,MACvD,4CAAC,OAAE,WAAU,iCAAgC,8BAAgB;AAAA,OAC/D,IAEA,UAEJ;AAAA,KACF;AAEJ;","names":["Link"]}
1
+ {"version":3,"sources":["../../src/components/activity-feed-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { ArrowRight, Activity, RefreshCw } from \"lucide-react\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { emptyMessages } from \"../utils/empty-messages.js\";\n\nexport interface ActivityFeedShellProps {\n title: string;\n href: string;\n hrefLabel?: string;\n lastUpdated: string;\n isLoading: boolean;\n children: React.ReactNode;\n}\n\nfunction SkeletonRow() {\n return (\n <div className=\"flex items-center gap-3 px-4 py-2.5\">\n <div className=\"h-7 w-7 rounded-lg bg-muted animate-pulse shrink-0\" />\n <div className=\"h-7 w-7 rounded-md bg-muted animate-pulse shrink-0\" />\n <div className=\"flex-1 space-y-1.5\">\n <div className=\"h-3 w-32 bg-muted animate-pulse rounded\" />\n <div className=\"h-2.5 w-20 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"space-y-1 text-right\">\n <div className=\"h-3.5 w-14 bg-muted animate-pulse rounded\" />\n <div className=\"h-2.5 w-8 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"h-3 w-10 bg-muted animate-pulse rounded hidden sm:block\" />\n </div>\n );\n}\n\nexport function ActivityFeedShell({ title, href, hrefLabel = \"Activities\", lastUpdated, isLoading, children }: ActivityFeedShellProps) {\n return (\n <section className=\"space-y-5\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"relative h-8 w-8 rounded-xl bg-gradient-to-br from-indigo-500 to-blue-600 flex items-center justify-center shadow-lg shadow-indigo-500/20 shrink-0\">\n <Activity className=\"h-4 w-4 text-white\" />\n <span className=\"absolute -top-1 -right-1 flex h-2.5 w-2.5\">\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75\" />\n <span className=\"relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500\" />\n </span>\n </div>\n <div>\n <h2 className=\"text-xl sm:text-2xl font-black leading-none\">{title}</h2>\n <p className=\"text-2xs text-muted-foreground mt-0.5 flex items-center gap-1\">\n <RefreshCw className=\"h-2.5 w-2.5\" />\n Updated {timeAgo(lastUpdated)}\n </p>\n </div>\n </div>\n <Link href={href} 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 {hrefLabel} <ArrowRight className=\"h-3.5 w-3.5\" />\n </Link>\n </div>\n\n <div className=\"bento-cell overflow-hidden divide-y divide-border/40\">\n {isLoading ? (\n Array.from({ length: 6 }).map((_, i) => <SkeletonRow key={i} />)\n ) : !children || (Array.isArray(children) && children.length === 0) ? (\n <div className=\"flex flex-col items-center gap-2 py-10 text-center\">\n <Activity className=\"h-8 w-8 text-muted-foreground/30\" />\n <p className=\"text-sm font-medium\">{emptyMessages.activity.title}</p>\n <p className=\"text-sm text-muted-foreground\">{emptyMessages.activity.description}</p>\n </div>\n ) : (\n children\n )}\n </div>\n </section>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBM;AAjBN,kBAAiB;AACjB,0BAAgD;AAChD,kBAAwB;AACxB,4BAA8B;AAW9B,SAAS,cAAc;AACrB,SACE,6CAAC,SAAI,WAAU,uCACb;AAAA,gDAAC,SAAI,WAAU,sDAAqD;AAAA,IACpE,4CAAC,SAAI,WAAU,sDAAqD;AAAA,IACpE,6CAAC,SAAI,WAAU,sBACb;AAAA,kDAAC,SAAI,WAAU,2CAA0C;AAAA,MACzD,4CAAC,SAAI,WAAU,6CAA4C;AAAA,OAC7D;AAAA,IACA,6CAAC,SAAI,WAAU,wBACb;AAAA,kDAAC,SAAI,WAAU,6CAA4C;AAAA,MAC3D,4CAAC,SAAI,WAAU,4CAA2C;AAAA,OAC5D;AAAA,IACA,4CAAC,SAAI,WAAU,2DAA0D;AAAA,KAC3E;AAEJ;AAEO,SAAS,kBAAkB,EAAE,OAAO,MAAM,YAAY,cAAc,aAAa,WAAW,SAAS,GAA2B;AACrI,SACE,6CAAC,aAAQ,WAAU,aACjB;AAAA,iDAAC,SAAI,WAAU,qCACb;AAAA,mDAAC,SAAI,WAAU,6BACb;AAAA,qDAAC,SAAI,WAAU,sJACb;AAAA,sDAAC,gCAAS,WAAU,sBAAqB;AAAA,UACzC,6CAAC,UAAK,WAAU,6CACd;AAAA,wDAAC,UAAK,WAAU,0FAAyF;AAAA,YACzG,4CAAC,UAAK,WAAU,gEAA+D;AAAA,aACjF;AAAA,WACF;AAAA,QACA,6CAAC,SACC;AAAA,sDAAC,QAAG,WAAU,+CAA+C,iBAAM;AAAA,UACnE,6CAAC,OAAE,WAAU,iEACX;AAAA,wDAAC,iCAAU,WAAU,eAAc;AAAA,YAAE;AAAA,gBAC5B,qBAAQ,WAAW;AAAA,aAC9B;AAAA,WACF;AAAA,SACF;AAAA,MACA,6CAAC,YAAAA,SAAA,EAAK,MAAY,WAAU,+IACzB;AAAA;AAAA,QAAU;AAAA,QAAC,4CAAC,kCAAW,WAAU,eAAc;AAAA,SAClD;AAAA,OACF;AAAA,IAEA,4CAAC,SAAI,WAAU,wDACZ,sBACC,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,4CAAC,iBAAiB,CAAG,CAAE,IAC7D,CAAC,YAAa,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW,IAC/D,6CAAC,SAAI,WAAU,sDACb;AAAA,kDAAC,gCAAS,WAAU,oCAAmC;AAAA,MACvD,4CAAC,OAAE,WAAU,uBAAuB,8CAAc,SAAS,OAAM;AAAA,MACjE,4CAAC,OAAE,WAAU,iCAAiC,8CAAc,SAAS,aAAY;AAAA,OACnF,IAEA,UAEJ;AAAA,KACF;AAEJ;","names":["Link"]}
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import Link from "./link.js";
4
4
  import { ArrowRight, Activity, RefreshCw } from "lucide-react";
5
5
  import { timeAgo } from "../utils/time.js";
6
+ import { emptyMessages } from "../utils/empty-messages.js";
6
7
  function SkeletonRow() {
7
8
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 px-4 py-2.5", children: [
8
9
  /* @__PURE__ */ jsx("div", { className: "h-7 w-7 rounded-lg bg-muted animate-pulse shrink-0" }),
@@ -46,7 +47,8 @@ function ActivityFeedShell({ title, href, hrefLabel = "Activities", lastUpdated,
46
47
  ] }),
47
48
  /* @__PURE__ */ jsx("div", { className: "bento-cell overflow-hidden divide-y divide-border/40", children: isLoading ? Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(SkeletonRow, {}, i)) : !children || Array.isArray(children) && children.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 py-10 text-center", children: [
48
49
  /* @__PURE__ */ jsx(Activity, { className: "h-8 w-8 text-muted-foreground/30" }),
49
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No activity yet." })
50
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: emptyMessages.activity.title }),
51
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessages.activity.description })
50
52
  ] }) : children })
51
53
  ] });
52
54
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/activity-feed-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { ArrowRight, Activity, RefreshCw } from \"lucide-react\";\nimport { timeAgo } from \"../utils/time.js\";\n\nexport interface ActivityFeedShellProps {\n title: string;\n href: string;\n hrefLabel?: string;\n lastUpdated: string;\n isLoading: boolean;\n children: React.ReactNode;\n}\n\nfunction SkeletonRow() {\n return (\n <div className=\"flex items-center gap-3 px-4 py-2.5\">\n <div className=\"h-7 w-7 rounded-lg bg-muted animate-pulse shrink-0\" />\n <div className=\"h-7 w-7 rounded-md bg-muted animate-pulse shrink-0\" />\n <div className=\"flex-1 space-y-1.5\">\n <div className=\"h-3 w-32 bg-muted animate-pulse rounded\" />\n <div className=\"h-2.5 w-20 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"space-y-1 text-right\">\n <div className=\"h-3.5 w-14 bg-muted animate-pulse rounded\" />\n <div className=\"h-2.5 w-8 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"h-3 w-10 bg-muted animate-pulse rounded hidden sm:block\" />\n </div>\n );\n}\n\nexport function ActivityFeedShell({ title, href, hrefLabel = \"Activities\", lastUpdated, isLoading, children }: ActivityFeedShellProps) {\n return (\n <section className=\"space-y-5\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"relative h-8 w-8 rounded-xl bg-gradient-to-br from-indigo-500 to-blue-600 flex items-center justify-center shadow-lg shadow-indigo-500/20 shrink-0\">\n <Activity className=\"h-4 w-4 text-white\" />\n <span className=\"absolute -top-1 -right-1 flex h-2.5 w-2.5\">\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75\" />\n <span className=\"relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500\" />\n </span>\n </div>\n <div>\n <h2 className=\"text-xl sm:text-2xl font-black leading-none\">{title}</h2>\n <p className=\"text-2xs text-muted-foreground mt-0.5 flex items-center gap-1\">\n <RefreshCw className=\"h-2.5 w-2.5\" />\n Updated {timeAgo(lastUpdated)}\n </p>\n </div>\n </div>\n <Link href={href} 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 {hrefLabel} <ArrowRight className=\"h-3.5 w-3.5\" />\n </Link>\n </div>\n\n <div className=\"bento-cell overflow-hidden divide-y divide-border/40\">\n {isLoading ? (\n Array.from({ length: 6 }).map((_, i) => <SkeletonRow key={i} />)\n ) : !children || (Array.isArray(children) && children.length === 0) ? (\n <div className=\"flex flex-col items-center gap-2 py-10 text-center\">\n <Activity className=\"h-8 w-8 text-muted-foreground/30\" />\n <p className=\"text-sm text-muted-foreground\">No activity yet.</p>\n </div>\n ) : (\n children\n )}\n </div>\n </section>\n );\n}\n"],"mappings":";AAkBM,cAEA,YAFA;AAhBN,OAAO,UAAU;AACjB,SAAS,YAAY,UAAU,iBAAiB;AAChD,SAAS,eAAe;AAWxB,SAAS,cAAc;AACrB,SACE,qBAAC,SAAI,WAAU,uCACb;AAAA,wBAAC,SAAI,WAAU,sDAAqD;AAAA,IACpE,oBAAC,SAAI,WAAU,sDAAqD;AAAA,IACpE,qBAAC,SAAI,WAAU,sBACb;AAAA,0BAAC,SAAI,WAAU,2CAA0C;AAAA,MACzD,oBAAC,SAAI,WAAU,6CAA4C;AAAA,OAC7D;AAAA,IACA,qBAAC,SAAI,WAAU,wBACb;AAAA,0BAAC,SAAI,WAAU,6CAA4C;AAAA,MAC3D,oBAAC,SAAI,WAAU,4CAA2C;AAAA,OAC5D;AAAA,IACA,oBAAC,SAAI,WAAU,2DAA0D;AAAA,KAC3E;AAEJ;AAEO,SAAS,kBAAkB,EAAE,OAAO,MAAM,YAAY,cAAc,aAAa,WAAW,SAAS,GAA2B;AACrI,SACE,qBAAC,aAAQ,WAAU,aACjB;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,SAAI,WAAU,6BACb;AAAA,6BAAC,SAAI,WAAU,sJACb;AAAA,8BAAC,YAAS,WAAU,sBAAqB;AAAA,UACzC,qBAAC,UAAK,WAAU,6CACd;AAAA,gCAAC,UAAK,WAAU,0FAAyF;AAAA,YACzG,oBAAC,UAAK,WAAU,gEAA+D;AAAA,aACjF;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,QAAG,WAAU,+CAA+C,iBAAM;AAAA,UACnE,qBAAC,OAAE,WAAU,iEACX;AAAA,gCAAC,aAAU,WAAU,eAAc;AAAA,YAAE;AAAA,YAC5B,QAAQ,WAAW;AAAA,aAC9B;AAAA,WACF;AAAA,SACF;AAAA,MACA,qBAAC,QAAK,MAAY,WAAU,+IACzB;AAAA;AAAA,QAAU;AAAA,QAAC,oBAAC,cAAW,WAAU,eAAc;AAAA,SAClD;AAAA,OACF;AAAA,IAEA,oBAAC,SAAI,WAAU,wDACZ,sBACC,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,oBAAC,iBAAiB,CAAG,CAAE,IAC7D,CAAC,YAAa,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW,IAC/D,qBAAC,SAAI,WAAU,sDACb;AAAA,0BAAC,YAAS,WAAU,oCAAmC;AAAA,MACvD,oBAAC,OAAE,WAAU,iCAAgC,8BAAgB;AAAA,OAC/D,IAEA,UAEJ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/activity-feed-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { ArrowRight, Activity, RefreshCw } from \"lucide-react\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { emptyMessages } from \"../utils/empty-messages.js\";\n\nexport interface ActivityFeedShellProps {\n title: string;\n href: string;\n hrefLabel?: string;\n lastUpdated: string;\n isLoading: boolean;\n children: React.ReactNode;\n}\n\nfunction SkeletonRow() {\n return (\n <div className=\"flex items-center gap-3 px-4 py-2.5\">\n <div className=\"h-7 w-7 rounded-lg bg-muted animate-pulse shrink-0\" />\n <div className=\"h-7 w-7 rounded-md bg-muted animate-pulse shrink-0\" />\n <div className=\"flex-1 space-y-1.5\">\n <div className=\"h-3 w-32 bg-muted animate-pulse rounded\" />\n <div className=\"h-2.5 w-20 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"space-y-1 text-right\">\n <div className=\"h-3.5 w-14 bg-muted animate-pulse rounded\" />\n <div className=\"h-2.5 w-8 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"h-3 w-10 bg-muted animate-pulse rounded hidden sm:block\" />\n </div>\n );\n}\n\nexport function ActivityFeedShell({ title, href, hrefLabel = \"Activities\", lastUpdated, isLoading, children }: ActivityFeedShellProps) {\n return (\n <section className=\"space-y-5\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"relative h-8 w-8 rounded-xl bg-gradient-to-br from-indigo-500 to-blue-600 flex items-center justify-center shadow-lg shadow-indigo-500/20 shrink-0\">\n <Activity className=\"h-4 w-4 text-white\" />\n <span className=\"absolute -top-1 -right-1 flex h-2.5 w-2.5\">\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75\" />\n <span className=\"relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500\" />\n </span>\n </div>\n <div>\n <h2 className=\"text-xl sm:text-2xl font-black leading-none\">{title}</h2>\n <p className=\"text-2xs text-muted-foreground mt-0.5 flex items-center gap-1\">\n <RefreshCw className=\"h-2.5 w-2.5\" />\n Updated {timeAgo(lastUpdated)}\n </p>\n </div>\n </div>\n <Link href={href} 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 {hrefLabel} <ArrowRight className=\"h-3.5 w-3.5\" />\n </Link>\n </div>\n\n <div className=\"bento-cell overflow-hidden divide-y divide-border/40\">\n {isLoading ? (\n Array.from({ length: 6 }).map((_, i) => <SkeletonRow key={i} />)\n ) : !children || (Array.isArray(children) && children.length === 0) ? (\n <div className=\"flex flex-col items-center gap-2 py-10 text-center\">\n <Activity className=\"h-8 w-8 text-muted-foreground/30\" />\n <p className=\"text-sm font-medium\">{emptyMessages.activity.title}</p>\n <p className=\"text-sm text-muted-foreground\">{emptyMessages.activity.description}</p>\n </div>\n ) : (\n children\n )}\n </div>\n </section>\n );\n}\n"],"mappings":";AAmBM,cAEA,YAFA;AAjBN,OAAO,UAAU;AACjB,SAAS,YAAY,UAAU,iBAAiB;AAChD,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAW9B,SAAS,cAAc;AACrB,SACE,qBAAC,SAAI,WAAU,uCACb;AAAA,wBAAC,SAAI,WAAU,sDAAqD;AAAA,IACpE,oBAAC,SAAI,WAAU,sDAAqD;AAAA,IACpE,qBAAC,SAAI,WAAU,sBACb;AAAA,0BAAC,SAAI,WAAU,2CAA0C;AAAA,MACzD,oBAAC,SAAI,WAAU,6CAA4C;AAAA,OAC7D;AAAA,IACA,qBAAC,SAAI,WAAU,wBACb;AAAA,0BAAC,SAAI,WAAU,6CAA4C;AAAA,MAC3D,oBAAC,SAAI,WAAU,4CAA2C;AAAA,OAC5D;AAAA,IACA,oBAAC,SAAI,WAAU,2DAA0D;AAAA,KAC3E;AAEJ;AAEO,SAAS,kBAAkB,EAAE,OAAO,MAAM,YAAY,cAAc,aAAa,WAAW,SAAS,GAA2B;AACrI,SACE,qBAAC,aAAQ,WAAU,aACjB;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,SAAI,WAAU,6BACb;AAAA,6BAAC,SAAI,WAAU,sJACb;AAAA,8BAAC,YAAS,WAAU,sBAAqB;AAAA,UACzC,qBAAC,UAAK,WAAU,6CACd;AAAA,gCAAC,UAAK,WAAU,0FAAyF;AAAA,YACzG,oBAAC,UAAK,WAAU,gEAA+D;AAAA,aACjF;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,QAAG,WAAU,+CAA+C,iBAAM;AAAA,UACnE,qBAAC,OAAE,WAAU,iEACX;AAAA,gCAAC,aAAU,WAAU,eAAc;AAAA,YAAE;AAAA,YAC5B,QAAQ,WAAW;AAAA,aAC9B;AAAA,WACF;AAAA,SACF;AAAA,MACA,qBAAC,QAAK,MAAY,WAAU,+IACzB;AAAA;AAAA,QAAU;AAAA,QAAC,oBAAC,cAAW,WAAU,eAAc;AAAA,SAClD;AAAA,OACF;AAAA,IAEA,oBAAC,SAAI,WAAU,wDACZ,sBACC,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,oBAAC,iBAAiB,CAAG,CAAE,IAC7D,CAAC,YAAa,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW,IAC/D,qBAAC,SAAI,WAAU,sDACb;AAAA,0BAAC,YAAS,WAAU,oCAAmC;AAAA,MACvD,oBAAC,OAAE,WAAU,uBAAuB,wBAAc,SAAS,OAAM;AAAA,MACjE,oBAAC,OAAE,WAAU,iCAAiC,wBAAc,SAAS,aAAY;AAAA,OACnF,IAEA,UAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -19,57 +19,45 @@ var __copyProps = (to, from, except, desc) => {
19
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
20
  var asset_access_cards_exports = {};
21
21
  __export(asset_access_cards_exports, {
22
- AssetAccessCards: () => AssetAccessCards,
23
- CompanionAppCard: () => CompanionAppCard
22
+ AssetAccessButtons: () => AssetAccessButtons,
23
+ CompanionAppButton: () => CompanionAppButton
24
24
  });
25
25
  module.exports = __toCommonJS(asset_access_cards_exports);
26
26
  var import_jsx_runtime = require("react/jsx-runtime");
27
- var import_lucide_react = require("lucide-react");
28
27
  var import_sdk = require("@medialane/sdk");
28
+ var import_lucide_react = require("lucide-react");
29
29
  var import_medialane_app = require("./medialane-app.js");
30
+ var import_action_button = require("./action-button.js");
30
31
  var import_cn = require("../utils/cn.js");
31
- const CARD = "group flex h-full w-full items-start gap-3 rounded-2xl border border-transparent p-4 text-left transition-colors";
32
- function CardBody({ icon: Icon, iconClassName, title, description }) {
33
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
34
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("mt-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br text-white", iconClassName), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "h-[18px] w-[18px]" }) }),
35
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-w-0 flex-1", children: [
36
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-bold leading-snug", children: title }),
37
- description ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-0.5 text-xs leading-relaxed text-muted-foreground", children: description }) : null
38
- ] })
39
- ] });
40
- }
41
- function CompanionAppCard({ asset }) {
32
+ function CompanionAppButton({ asset }) {
42
33
  const { companion } = (0, import_medialane_app.useMedialaneApp)();
43
34
  if (!companion) return null;
35
+ const Icon = companion.icon;
44
36
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
45
- "a",
37
+ import_action_button.ActionButton,
46
38
  {
39
+ action: "offer",
40
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "h-4 w-4" }),
47
41
  href: `${companion.origin}${(0, import_sdk.assetHref)(asset.chain.toUpperCase(), asset.contractAddress, asset.tokenId)}`,
48
- target: "_blank",
49
- rel: "noopener noreferrer",
50
- className: (0, import_cn.cn)(CARD, "bg-gradient-to-br from-brand-rose/15 via-brand-orange/10 to-transparent hover:border-brand-orange/30"),
51
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardBody, { icon: companion.icon, iconClassName: "from-brand-rose to-brand-orange", title: companion.title, description: companion.description })
42
+ title: companion.description,
43
+ className: "w-full",
44
+ children: companion.title
52
45
  }
53
46
  );
54
47
  }
55
- function AssetAccessCards({ asset, stacked = false }) {
48
+ function AssetAccessButtons({ asset, stacked = false }) {
56
49
  const { onRequireWallet, connectLabel = "Sign in", connectDescription, companion } = (0, import_medialane_app.useMedialaneApp)();
57
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_cn.cn)("grid grid-cols-1 gap-3 items-stretch", companion && !stacked && "sm:grid-cols-2"), children: [
58
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
59
- "button",
60
- {
61
- type: "button",
62
- onClick: onRequireWallet,
63
- className: (0, import_cn.cn)(CARD, "bg-gradient-to-br from-brand-blue/15 via-brand-purple/10 to-transparent hover:border-brand-purple/30"),
64
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardBody, { icon: import_lucide_react.Wallet, iconClassName: "from-brand-blue to-brand-purple", title: connectLabel, description: connectDescription })
65
- }
66
- ),
67
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompanionAppCard, { asset })
50
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
51
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_cn.cn)("grid grid-cols-1 gap-2", companion && !stacked && "sm:grid-cols-2"), children: [
52
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_action_button.ActionButton, { action: "buy", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Wallet, { className: "h-4 w-4" }), onClick: onRequireWallet, className: "w-full", children: connectLabel }),
53
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompanionAppButton, { asset })
54
+ ] }),
55
+ connectDescription ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground", children: connectDescription }) : null
68
56
  ] });
69
57
  }
70
58
  // Annotate the CommonJS export names for ESM import in node:
71
59
  0 && (module.exports = {
72
- AssetAccessCards,
73
- CompanionAppCard
60
+ AssetAccessButtons,
61
+ CompanionAppButton
74
62
  });
75
63
  //# sourceMappingURL=asset-access-cards.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/asset-access-cards.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ElementType } from \"react\";\nimport { Wallet } from \"lucide-react\";\nimport { assetHref, type Chain } from \"@medialane/sdk\";\nimport { useMedialaneApp, type AssetRef } from \"./medialane-app.js\";\nimport { cn } from \"../utils/cn.js\";\n\nconst CARD = \"group flex h-full w-full items-start gap-3 rounded-2xl border border-transparent p-4 text-left transition-colors\";\n\nfunction CardBody({ icon: Icon, iconClassName, title, description }: { icon: ElementType; iconClassName: string; title: string; description?: string }) {\n return (\n <>\n <div className={cn(\"mt-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br text-white\", iconClassName)}>\n <Icon className=\"h-[18px] w-[18px]\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-bold leading-snug\">{title}</p>\n {description ? <p className=\"mt-0.5 text-xs leading-relaxed text-muted-foreground\">{description}</p> : null}\n </div>\n </>\n );\n}\n\nexport function CompanionAppCard({ asset }: { asset: AssetRef }) {\n const { companion } = useMedialaneApp();\n if (!companion) return null;\n return (\n <a\n href={`${companion.origin}${assetHref(asset.chain.toUpperCase() as Chain, asset.contractAddress, asset.tokenId)}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(CARD, \"bg-gradient-to-br from-brand-rose/15 via-brand-orange/10 to-transparent hover:border-brand-orange/30\")}\n >\n <CardBody icon={companion.icon} iconClassName=\"from-brand-rose to-brand-orange\" title={companion.title} description={companion.description} />\n </a>\n );\n}\n\nexport function AssetAccessCards({ asset, stacked = false }: { asset: AssetRef; stacked?: boolean }) {\n const { onRequireWallet, connectLabel = \"Sign in\", connectDescription, companion } = useMedialaneApp();\n return (\n <div className={cn(\"grid grid-cols-1 gap-3 items-stretch\", companion && !stacked && \"sm:grid-cols-2\")}>\n <button\n type=\"button\"\n onClick={onRequireWallet}\n className={cn(CARD, \"bg-gradient-to-br from-brand-blue/15 via-brand-purple/10 to-transparent hover:border-brand-purple/30\")}\n >\n <CardBody icon={Wallet} iconClassName=\"from-brand-blue to-brand-purple\" title={connectLabel} description={connectDescription} />\n </button>\n <CompanionAppCard asset={asset} />\n </div>\n );\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYI;AATJ,0BAAuB;AACvB,iBAAsC;AACtC,2BAA+C;AAC/C,gBAAmB;AAEnB,MAAM,OAAO;AAEb,SAAS,SAAS,EAAE,MAAM,MAAM,eAAe,OAAO,YAAY,GAAsF;AACtJ,SACE,4EACE;AAAA,gDAAC,SAAI,eAAW,cAAG,oGAAoG,aAAa,GAClI,sDAAC,QAAK,WAAU,qBAAoB,GACtC;AAAA,IACA,6CAAC,SAAI,WAAU,kBACb;AAAA,kDAAC,OAAE,WAAU,kCAAkC,iBAAM;AAAA,MACpD,cAAc,4CAAC,OAAE,WAAU,wDAAwD,uBAAY,IAAO;AAAA,OACzG;AAAA,KACF;AAEJ;AAEO,SAAS,iBAAiB,EAAE,MAAM,GAAwB;AAC/D,QAAM,EAAE,UAAU,QAAI,sCAAgB;AACtC,MAAI,CAAC,UAAW,QAAO;AACvB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,GAAG,UAAU,MAAM,OAAG,sBAAU,MAAM,MAAM,YAAY,GAAY,MAAM,iBAAiB,MAAM,OAAO,CAAC;AAAA,MAC/G,QAAO;AAAA,MACP,KAAI;AAAA,MACJ,eAAW,cAAG,MAAM,sGAAsG;AAAA,MAE1H,sDAAC,YAAS,MAAM,UAAU,MAAM,eAAc,mCAAkC,OAAO,UAAU,OAAO,aAAa,UAAU,aAAa;AAAA;AAAA,EAC9I;AAEJ;AAEO,SAAS,iBAAiB,EAAE,OAAO,UAAU,MAAM,GAA2C;AACnG,QAAM,EAAE,iBAAiB,eAAe,WAAW,oBAAoB,UAAU,QAAI,sCAAgB;AACrG,SACE,6CAAC,SAAI,eAAW,cAAG,wCAAwC,aAAa,CAAC,WAAW,gBAAgB,GAClG;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS;AAAA,QACT,eAAW,cAAG,MAAM,sGAAsG;AAAA,QAE1H,sDAAC,YAAS,MAAM,4BAAQ,eAAc,mCAAkC,OAAO,cAAc,aAAa,oBAAoB;AAAA;AAAA,IAChI;AAAA,IACA,4CAAC,oBAAiB,OAAc;AAAA,KAClC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/asset-access-cards.tsx"],"sourcesContent":["\"use client\";\n\nimport { assetHref, type Chain } from \"@medialane/sdk\";\nimport { Wallet } from \"lucide-react\";\nimport { useMedialaneApp, type AssetRef } from \"./medialane-app.js\";\nimport { ActionButton } from \"./action-button.js\";\nimport { cn } from \"../utils/cn.js\";\n\nexport function CompanionAppButton({ asset }: { asset: AssetRef }) {\n const { companion } = useMedialaneApp();\n if (!companion) return null;\n const Icon = companion.icon;\n return (\n <ActionButton\n action=\"offer\"\n icon={<Icon className=\"h-4 w-4\" />}\n href={`${companion.origin}${assetHref(asset.chain.toUpperCase() as Chain, asset.contractAddress, asset.tokenId)}`}\n title={companion.description}\n className=\"w-full\"\n >\n {companion.title}\n </ActionButton>\n );\n}\n\nexport function AssetAccessButtons({ asset, stacked = false }: { asset: AssetRef; stacked?: boolean }) {\n const { onRequireWallet, connectLabel = \"Sign in\", connectDescription, companion } = useMedialaneApp();\n return (\n <div className=\"space-y-2\">\n <div className={cn(\"grid grid-cols-1 gap-2\", companion && !stacked && \"sm:grid-cols-2\")}>\n <ActionButton action=\"buy\" icon={<Wallet className=\"h-4 w-4\" />} onClick={onRequireWallet} className=\"w-full\">\n {connectLabel}\n </ActionButton>\n <CompanionAppButton asset={asset} />\n </div>\n {connectDescription ? <p className=\"text-xs text-muted-foreground\">{connectDescription}</p> : null}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeY;AAbZ,iBAAsC;AACtC,0BAAuB;AACvB,2BAA+C;AAC/C,2BAA6B;AAC7B,gBAAmB;AAEZ,SAAS,mBAAmB,EAAE,MAAM,GAAwB;AACjE,QAAM,EAAE,UAAU,QAAI,sCAAgB;AACtC,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,OAAO,UAAU;AACvB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QAAO;AAAA,MACP,MAAM,4CAAC,QAAK,WAAU,WAAU;AAAA,MAChC,MAAM,GAAG,UAAU,MAAM,OAAG,sBAAU,MAAM,MAAM,YAAY,GAAY,MAAM,iBAAiB,MAAM,OAAO,CAAC;AAAA,MAC/G,OAAO,UAAU;AAAA,MACjB,WAAU;AAAA,MAET,oBAAU;AAAA;AAAA,EACb;AAEJ;AAEO,SAAS,mBAAmB,EAAE,OAAO,UAAU,MAAM,GAA2C;AACrG,QAAM,EAAE,iBAAiB,eAAe,WAAW,oBAAoB,UAAU,QAAI,sCAAgB;AACrG,SACE,6CAAC,SAAI,WAAU,aACb;AAAA,iDAAC,SAAI,eAAW,cAAG,0BAA0B,aAAa,CAAC,WAAW,gBAAgB,GACpF;AAAA,kDAAC,qCAAa,QAAO,OAAM,MAAM,4CAAC,8BAAO,WAAU,WAAU,GAAI,SAAS,iBAAiB,WAAU,UAClG,wBACH;AAAA,MACA,4CAAC,sBAAmB,OAAc;AAAA,OACpC;AAAA,IACC,qBAAqB,4CAAC,OAAE,WAAU,iCAAiC,8BAAmB,IAAO;AAAA,KAChG;AAEJ;","names":[]}
@@ -7,12 +7,12 @@ import 'starknet';
7
7
  import '@medialane/sdk';
8
8
  import '../utils/ipfs.cjs';
9
9
 
10
- declare function CompanionAppCard({ asset }: {
10
+ declare function CompanionAppButton({ asset }: {
11
11
  asset: AssetRef;
12
12
  }): react_jsx_runtime.JSX.Element | null;
13
- declare function AssetAccessCards({ asset, stacked }: {
13
+ declare function AssetAccessButtons({ asset, stacked }: {
14
14
  asset: AssetRef;
15
15
  stacked?: boolean;
16
16
  }): react_jsx_runtime.JSX.Element;
17
17
 
18
- export { AssetAccessCards, CompanionAppCard };
18
+ export { AssetAccessButtons, CompanionAppButton };
@@ -7,12 +7,12 @@ import 'starknet';
7
7
  import '@medialane/sdk';
8
8
  import '../utils/ipfs.js';
9
9
 
10
- declare function CompanionAppCard({ asset }: {
10
+ declare function CompanionAppButton({ asset }: {
11
11
  asset: AssetRef;
12
12
  }): react_jsx_runtime.JSX.Element | null;
13
- declare function AssetAccessCards({ asset, stacked }: {
13
+ declare function AssetAccessButtons({ asset, stacked }: {
14
14
  asset: AssetRef;
15
15
  stacked?: boolean;
16
16
  }): react_jsx_runtime.JSX.Element;
17
17
 
18
- export { AssetAccessCards, CompanionAppCard };
18
+ export { AssetAccessButtons, CompanionAppButton };