@medialane/ui 0.145.1 → 0.146.1

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 (67) hide show
  1. package/dist/components/collapsible-section.cjs +69 -0
  2. package/dist/components/collapsible-section.cjs.map +1 -0
  3. package/dist/components/collapsible-section.d.cts +15 -0
  4. package/dist/components/collapsible-section.d.ts +15 -0
  5. package/dist/components/collapsible-section.js +45 -0
  6. package/dist/components/collapsible-section.js.map +1 -0
  7. package/dist/components/drop-create-form.cjs +341 -0
  8. package/dist/components/drop-create-form.cjs.map +1 -0
  9. package/dist/components/drop-create-form.d.cts +39 -0
  10. package/dist/components/drop-create-form.d.ts +39 -0
  11. package/dist/components/drop-create-form.js +322 -0
  12. package/dist/components/drop-create-form.js.map +1 -0
  13. package/dist/components/drop-preview-card.cjs +106 -0
  14. package/dist/components/drop-preview-card.cjs.map +1 -0
  15. package/dist/components/drop-preview-card.d.cts +17 -0
  16. package/dist/components/drop-preview-card.d.ts +17 -0
  17. package/dist/components/drop-preview-card.js +82 -0
  18. package/dist/components/drop-preview-card.js.map +1 -0
  19. package/dist/components/drop-preview-card.test.cjs +84 -0
  20. package/dist/components/drop-preview-card.test.cjs.map +1 -0
  21. package/dist/components/drop-preview-card.test.d.cts +2 -0
  22. package/dist/components/drop-preview-card.test.d.ts +2 -0
  23. package/dist/components/drop-preview-card.test.js +83 -0
  24. package/dist/components/drop-preview-card.test.js.map +1 -0
  25. package/dist/components/drop-status-display.cjs +103 -0
  26. package/dist/components/drop-status-display.cjs.map +1 -0
  27. package/dist/components/drop-status-display.d.cts +15 -0
  28. package/dist/components/drop-status-display.d.ts +15 -0
  29. package/dist/components/drop-status-display.js +77 -0
  30. package/dist/components/drop-status-display.js.map +1 -0
  31. package/dist/components/drop-status-display.test.cjs +29 -0
  32. package/dist/components/drop-status-display.test.cjs.map +1 -0
  33. package/dist/components/drop-status-display.test.d.cts +2 -0
  34. package/dist/components/drop-status-display.test.d.ts +2 -0
  35. package/dist/components/drop-status-display.test.js +28 -0
  36. package/dist/components/drop-status-display.test.js.map +1 -0
  37. package/dist/components/exclusive-content-section.cjs +88 -0
  38. package/dist/components/exclusive-content-section.cjs.map +1 -0
  39. package/dist/components/exclusive-content-section.d.cts +10 -0
  40. package/dist/components/exclusive-content-section.d.ts +10 -0
  41. package/dist/components/exclusive-content-section.js +64 -0
  42. package/dist/components/exclusive-content-section.js.map +1 -0
  43. package/dist/data/drop-create-schema.cjs +8 -1
  44. package/dist/data/drop-create-schema.cjs.map +1 -1
  45. package/dist/data/drop-create-schema.d.cts +20 -0
  46. package/dist/data/drop-create-schema.d.ts +20 -0
  47. package/dist/data/drop-create-schema.js +8 -1
  48. package/dist/data/drop-create-schema.js.map +1 -1
  49. package/dist/data/gated-content-types.cjs +39 -0
  50. package/dist/data/gated-content-types.cjs.map +1 -0
  51. package/dist/data/gated-content-types.d.cts +12 -0
  52. package/dist/data/gated-content-types.d.ts +12 -0
  53. package/dist/data/gated-content-types.js +14 -0
  54. package/dist/data/gated-content-types.js.map +1 -0
  55. package/dist/index.cjs +27 -0
  56. package/dist/index.cjs.map +1 -1
  57. package/dist/index.d.cts +8 -1
  58. package/dist/index.d.ts +8 -1
  59. package/dist/index.js +17 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/utils/drop-status.cjs +37 -0
  62. package/dist/utils/drop-status.cjs.map +1 -0
  63. package/dist/utils/drop-status.d.cts +12 -0
  64. package/dist/utils/drop-status.d.ts +12 -0
  65. package/dist/utils/drop-status.js +13 -0
  66. package/dist/utils/drop-status.js.map +1 -0
  67. package/package.json +1 -1
@@ -0,0 +1,82 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Calendar, Lock, ShieldCheck, Users } from "lucide-react";
4
+ import { MedialaneCollectionCard } from "./medialane-collection-card.js";
5
+ import { DropStatusBadge, DropSupplyProgress, DropPriceDisplay } from "./drop-status-display.js";
6
+ import { getDropStatus } from "../utils/drop-status.js";
7
+ function formatTs(ts) {
8
+ return new Date(ts * 1e3).toLocaleString(void 0, {
9
+ dateStyle: "medium",
10
+ timeStyle: "short"
11
+ });
12
+ }
13
+ function DropPreviewCard({
14
+ coverImage,
15
+ name,
16
+ symbol,
17
+ creatorAddress,
18
+ creatorHref,
19
+ itemCount,
20
+ conditions,
21
+ whitelistEnabled,
22
+ gatedContentEnabled
23
+ }) {
24
+ const status = getDropStatus(conditions, 0);
25
+ const maxPerWallet = conditions ? parseInt(conditions.maxPerWallet, 10) : 0;
26
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
27
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
28
+ /* @__PURE__ */ jsx(
29
+ MedialaneCollectionCard,
30
+ {
31
+ image: coverImage,
32
+ name,
33
+ collection: symbol || "Drop",
34
+ creator: creatorAddress,
35
+ creatorHref
36
+ }
37
+ ),
38
+ /* @__PURE__ */ jsx("span", { className: "absolute top-4 right-4 text-[9px] font-bold uppercase tracking-widest text-white bg-black/50 backdrop-blur-sm rounded-full px-2 py-0.5", children: "Drop" })
39
+ ] }),
40
+ /* @__PURE__ */ jsxs("div", { className: "bento-cell p-4 space-y-3", children: [
41
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
42
+ /* @__PURE__ */ jsx(DropStatusBadge, { status }),
43
+ whitelistEnabled && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-widest text-brand-orange bg-brand-orange/10 rounded-full px-2 py-0.5", children: [
44
+ /* @__PURE__ */ jsx(Users, { className: "h-3 w-3" }),
45
+ "Whitelist"
46
+ ] }),
47
+ gatedContentEnabled && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-widest text-primary bg-primary/10 rounded-full px-2 py-0.5", children: [
48
+ /* @__PURE__ */ jsx(Lock, { className: "h-3 w-3" }),
49
+ "Exclusive content"
50
+ ] })
51
+ ] }),
52
+ /* @__PURE__ */ jsx(DropSupplyProgress, { minted: 0, max: itemCount }),
53
+ conditions && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
54
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
55
+ /* @__PURE__ */ jsx(ShieldCheck, { className: "h-3.5 w-3.5 text-muted-foreground" }),
56
+ /* @__PURE__ */ jsx(DropPriceDisplay, { conditions })
57
+ ] }),
58
+ maxPerWallet > 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
59
+ "Max ",
60
+ maxPerWallet,
61
+ "/wallet"
62
+ ] })
63
+ ] }),
64
+ conditions && conditions.startTime > 0 && conditions.endTime > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-1 text-xs text-muted-foreground border-t border-border/60 pt-3", children: [
65
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
66
+ /* @__PURE__ */ jsx(Calendar, { className: "h-3 w-3 shrink-0" }),
67
+ "Opens: ",
68
+ formatTs(conditions.startTime)
69
+ ] }),
70
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
71
+ /* @__PURE__ */ jsx(Calendar, { className: "h-3 w-3 shrink-0" }),
72
+ "Closes: ",
73
+ formatTs(conditions.endTime)
74
+ ] })
75
+ ] })
76
+ ] })
77
+ ] });
78
+ }
79
+ export {
80
+ DropPreviewCard
81
+ };
82
+ //# sourceMappingURL=drop-preview-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/drop-preview-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { Calendar, Lock, ShieldCheck, Users } from \"lucide-react\";\nimport { MedialaneCollectionCard } from \"./medialane-collection-card.js\";\nimport { DropStatusBadge, DropSupplyProgress, DropPriceDisplay } from \"./drop-status-display.js\";\nimport { getDropStatus, type DropConditions } from \"../utils/drop-status.js\";\n\nexport interface DropPreviewCardProps {\n coverImage: string | null;\n name: string;\n symbol: string;\n creatorAddress?: string;\n creatorHref?: string;\n itemCount: number;\n conditions: DropConditions | null;\n whitelistEnabled: boolean;\n gatedContentEnabled: boolean;\n}\n\nfunction formatTs(ts: number): string {\n return new Date(ts * 1000).toLocaleString(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n });\n}\n\nexport function DropPreviewCard({\n coverImage, name, symbol, creatorAddress, creatorHref,\n itemCount, conditions, whitelistEnabled, gatedContentEnabled,\n}: DropPreviewCardProps) {\n const status = getDropStatus(conditions, 0);\n const maxPerWallet = conditions ? parseInt(conditions.maxPerWallet, 10) : 0;\n\n return (\n <div className=\"space-y-3\">\n <div className=\"relative\">\n <MedialaneCollectionCard\n image={coverImage}\n name={name}\n collection={symbol || \"Drop\"}\n creator={creatorAddress}\n creatorHref={creatorHref}\n />\n <span className=\"absolute top-4 right-4 text-[9px] font-bold uppercase tracking-widest text-white bg-black/50 backdrop-blur-sm rounded-full px-2 py-0.5\">\n Drop\n </span>\n </div>\n\n <div className=\"bento-cell p-4 space-y-3\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <DropStatusBadge status={status} />\n {whitelistEnabled && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-widest text-brand-orange bg-brand-orange/10 rounded-full px-2 py-0.5\">\n <Users className=\"h-3 w-3\" />\n Whitelist\n </span>\n )}\n {gatedContentEnabled && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-widest text-primary bg-primary/10 rounded-full px-2 py-0.5\">\n <Lock className=\"h-3 w-3\" />\n Exclusive content\n </span>\n )}\n </div>\n\n <DropSupplyProgress minted={0} max={itemCount} />\n\n {conditions && (\n <div className=\"flex items-center justify-between text-sm\">\n <div className=\"flex items-center gap-2\">\n <ShieldCheck className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <DropPriceDisplay conditions={conditions} />\n </div>\n {maxPerWallet > 0 && (\n <span className=\"text-xs text-muted-foreground\">Max {maxPerWallet}/wallet</span>\n )}\n </div>\n )}\n\n {conditions && conditions.startTime > 0 && conditions.endTime > 0 && (\n <div className=\"space-y-1 text-xs text-muted-foreground border-t border-border/60 pt-3\">\n <div className=\"flex items-center gap-1.5\">\n <Calendar className=\"h-3 w-3 shrink-0\" />\n Opens: {formatTs(conditions.startTime)}\n </div>\n <div className=\"flex items-center gap-1.5\">\n <Calendar className=\"h-3 w-3 shrink-0\" />\n Closes: {formatTs(conditions.endTime)}\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";AAmCM,SACE,KADF;AAjCN,SAAS,UAAU,MAAM,aAAa,aAAa;AACnD,SAAS,+BAA+B;AACxC,SAAS,iBAAiB,oBAAoB,wBAAwB;AACtE,SAAS,qBAA0C;AAcnD,SAAS,SAAS,IAAoB;AACpC,SAAO,IAAI,KAAK,KAAK,GAAI,EAAE,eAAe,QAAW;AAAA,IACnD,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AACH;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EAAY;AAAA,EAAM;AAAA,EAAQ;AAAA,EAAgB;AAAA,EAC1C;AAAA,EAAW;AAAA,EAAY;AAAA,EAAkB;AAC3C,GAAyB;AACvB,QAAM,SAAS,cAAc,YAAY,CAAC;AAC1C,QAAM,eAAe,aAAa,SAAS,WAAW,cAAc,EAAE,IAAI;AAE1E,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,yBAAC,SAAI,WAAU,YACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP;AAAA,UACA,YAAY,UAAU;AAAA,UACtB,SAAS;AAAA,UACT;AAAA;AAAA,MACF;AAAA,MACA,oBAAC,UAAK,WAAU,0IAAyI,kBAEzJ;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,4BACb;AAAA,2BAAC,SAAI,WAAU,qCACb;AAAA,4BAAC,mBAAgB,QAAgB;AAAA,QAChC,oBACC,qBAAC,UAAK,WAAU,gJACd;AAAA,8BAAC,SAAM,WAAU,WAAU;AAAA,UAAE;AAAA,WAE/B;AAAA,QAED,uBACC,qBAAC,UAAK,WAAU,sIACd;AAAA,8BAAC,QAAK,WAAU,WAAU;AAAA,UAAE;AAAA,WAE9B;AAAA,SAEJ;AAAA,MAEA,oBAAC,sBAAmB,QAAQ,GAAG,KAAK,WAAW;AAAA,MAE9C,cACC,qBAAC,SAAI,WAAU,6CACb;AAAA,6BAAC,SAAI,WAAU,2BACb;AAAA,8BAAC,eAAY,WAAU,qCAAoC;AAAA,UAC3D,oBAAC,oBAAiB,YAAwB;AAAA,WAC5C;AAAA,QACC,eAAe,KACd,qBAAC,UAAK,WAAU,iCAAgC;AAAA;AAAA,UAAK;AAAA,UAAa;AAAA,WAAO;AAAA,SAE7E;AAAA,MAGD,cAAc,WAAW,YAAY,KAAK,WAAW,UAAU,KAC9D,qBAAC,SAAI,WAAU,0EACb;AAAA,6BAAC,SAAI,WAAU,6BACb;AAAA,8BAAC,YAAS,WAAU,oBAAmB;AAAA,UAAE;AAAA,UACjC,SAAS,WAAW,SAAS;AAAA,WACvC;AAAA,QACA,qBAAC,SAAI,WAAU,6BACb;AAAA,8BAAC,YAAS,WAAU,oBAAmB;AAAA,UAAE;AAAA,UAChC,SAAS,WAAW,OAAO;AAAA,WACtC;AAAA,SACF;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var import_jsx_runtime = require("react/jsx-runtime");
3
+ var import_bun_test = require("bun:test");
4
+ var import_server = require("react-dom/server");
5
+ var import_drop_preview_card = require("./drop-preview-card.js");
6
+ (0, import_bun_test.test)("shows placeholder name and zero supply before anything is filled in", () => {
7
+ const html = (0, import_server.renderToStaticMarkup)(
8
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9
+ import_drop_preview_card.DropPreviewCard,
10
+ {
11
+ coverImage: null,
12
+ name: "",
13
+ symbol: "",
14
+ itemCount: 0,
15
+ conditions: null,
16
+ whitelistEnabled: false,
17
+ gatedContentEnabled: false
18
+ }
19
+ )
20
+ );
21
+ (0, import_bun_test.expect)(html).toContain("Untitled");
22
+ });
23
+ (0, import_bun_test.test)("shows the whitelist badge once enabled", () => {
24
+ const html = (0, import_server.renderToStaticMarkup)(
25
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26
+ import_drop_preview_card.DropPreviewCard,
27
+ {
28
+ coverImage: null,
29
+ name: "Genesis",
30
+ symbol: "GEN",
31
+ itemCount: 5,
32
+ conditions: null,
33
+ whitelistEnabled: true,
34
+ gatedContentEnabled: false
35
+ }
36
+ )
37
+ );
38
+ (0, import_bun_test.expect)(html).toContain("Whitelist");
39
+ });
40
+ (0, import_bun_test.test)("shows the exclusive content badge once enabled", () => {
41
+ const html = (0, import_server.renderToStaticMarkup)(
42
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43
+ import_drop_preview_card.DropPreviewCard,
44
+ {
45
+ coverImage: null,
46
+ name: "Genesis",
47
+ symbol: "GEN",
48
+ itemCount: 5,
49
+ conditions: null,
50
+ whitelistEnabled: false,
51
+ gatedContentEnabled: true
52
+ }
53
+ )
54
+ );
55
+ (0, import_bun_test.expect)(html).toContain("Exclusive content");
56
+ });
57
+ (0, import_bun_test.test)("shows mint window open/close dates and max-per-wallet instead of a countdown", () => {
58
+ const html = (0, import_server.renderToStaticMarkup)(
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
60
+ import_drop_preview_card.DropPreviewCard,
61
+ {
62
+ coverImage: null,
63
+ name: "Genesis",
64
+ symbol: "GEN",
65
+ itemCount: 5,
66
+ conditions: {
67
+ maxSupply: "5",
68
+ price: "0",
69
+ paymentToken: "0x0",
70
+ startTime: 1893456e3,
71
+ endTime: 1893542400,
72
+ maxPerWallet: "2"
73
+ },
74
+ whitelistEnabled: false,
75
+ gatedContentEnabled: false
76
+ }
77
+ )
78
+ );
79
+ (0, import_bun_test.expect)(html).toContain("Opens:");
80
+ (0, import_bun_test.expect)(html).toContain("Closes:");
81
+ (0, import_bun_test.expect)(html).toContain("Max 2/wallet");
82
+ (0, import_bun_test.expect)(html).not.toContain("HRS");
83
+ });
84
+ //# sourceMappingURL=drop-preview-card.test.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/drop-preview-card.test.tsx"],"sourcesContent":["import { test, expect } from \"bun:test\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { DropPreviewCard } from \"./drop-preview-card.js\";\n\ntest(\"shows placeholder name and zero supply before anything is filled in\", () => {\n const html = renderToStaticMarkup(\n <DropPreviewCard\n coverImage={null} name=\"\" symbol=\"\" itemCount={0}\n conditions={null} whitelistEnabled={false} gatedContentEnabled={false}\n />\n );\n expect(html).toContain(\"Untitled\");\n});\n\ntest(\"shows the whitelist badge once enabled\", () => {\n const html = renderToStaticMarkup(\n <DropPreviewCard\n coverImage={null} name=\"Genesis\" symbol=\"GEN\" itemCount={5}\n conditions={null} whitelistEnabled gatedContentEnabled={false}\n />\n );\n expect(html).toContain(\"Whitelist\");\n});\n\ntest(\"shows the exclusive content badge once enabled\", () => {\n const html = renderToStaticMarkup(\n <DropPreviewCard\n coverImage={null} name=\"Genesis\" symbol=\"GEN\" itemCount={5}\n conditions={null} whitelistEnabled={false} gatedContentEnabled\n />\n );\n expect(html).toContain(\"Exclusive content\");\n});\n\ntest(\"shows mint window open/close dates and max-per-wallet instead of a countdown\", () => {\n const html = renderToStaticMarkup(\n <DropPreviewCard\n coverImage={null} name=\"Genesis\" symbol=\"GEN\" itemCount={5}\n conditions={{\n maxSupply: \"5\", price: \"0\", paymentToken: \"0x0\",\n startTime: 1893456000, endTime: 1893542400, maxPerWallet: \"2\",\n }}\n whitelistEnabled={false} gatedContentEnabled={false}\n />\n );\n expect(html).toContain(\"Opens:\");\n expect(html).toContain(\"Closes:\");\n expect(html).toContain(\"Max 2/wallet\");\n expect(html).not.toContain(\"HRS\");\n});\n"],"mappings":";AAMI;AANJ,sBAA6B;AAC7B,oBAAqC;AACrC,+BAAgC;AAAA,IAEhC,sBAAK,uEAAuE,MAAM;AAChF,QAAM,WAAO;AAAA,IACX;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QAAM,MAAK;AAAA,QAAG,QAAO;AAAA,QAAG,WAAW;AAAA,QAC/C,YAAY;AAAA,QAAM,kBAAkB;AAAA,QAAO,qBAAqB;AAAA;AAAA,IAClE;AAAA,EACF;AACA,8BAAO,IAAI,EAAE,UAAU,UAAU;AACnC,CAAC;AAAA,IAED,sBAAK,0CAA0C,MAAM;AACnD,QAAM,WAAO;AAAA,IACX;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QAAM,MAAK;AAAA,QAAU,QAAO;AAAA,QAAM,WAAW;AAAA,QACzD,YAAY;AAAA,QAAM,kBAAgB;AAAA,QAAC,qBAAqB;AAAA;AAAA,IAC1D;AAAA,EACF;AACA,8BAAO,IAAI,EAAE,UAAU,WAAW;AACpC,CAAC;AAAA,IAED,sBAAK,kDAAkD,MAAM;AAC3D,QAAM,WAAO;AAAA,IACX;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QAAM,MAAK;AAAA,QAAU,QAAO;AAAA,QAAM,WAAW;AAAA,QACzD,YAAY;AAAA,QAAM,kBAAkB;AAAA,QAAO,qBAAmB;AAAA;AAAA,IAChE;AAAA,EACF;AACA,8BAAO,IAAI,EAAE,UAAU,mBAAmB;AAC5C,CAAC;AAAA,IAED,sBAAK,gFAAgF,MAAM;AACzF,QAAM,WAAO;AAAA,IACX;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QAAM,MAAK;AAAA,QAAU,QAAO;AAAA,QAAM,WAAW;AAAA,QACzD,YAAY;AAAA,UACV,WAAW;AAAA,UAAK,OAAO;AAAA,UAAK,cAAc;AAAA,UAC1C,WAAW;AAAA,UAAY,SAAS;AAAA,UAAY,cAAc;AAAA,QAC5D;AAAA,QACA,kBAAkB;AAAA,QAAO,qBAAqB;AAAA;AAAA,IAChD;AAAA,EACF;AACA,8BAAO,IAAI,EAAE,UAAU,QAAQ;AAC/B,8BAAO,IAAI,EAAE,UAAU,SAAS;AAChC,8BAAO,IAAI,EAAE,UAAU,cAAc;AACrC,8BAAO,IAAI,EAAE,IAAI,UAAU,KAAK;AAClC,CAAC;","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,83 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { test, expect } from "bun:test";
3
+ import { renderToStaticMarkup } from "react-dom/server";
4
+ import { DropPreviewCard } from "./drop-preview-card.js";
5
+ test("shows placeholder name and zero supply before anything is filled in", () => {
6
+ const html = renderToStaticMarkup(
7
+ /* @__PURE__ */ jsx(
8
+ DropPreviewCard,
9
+ {
10
+ coverImage: null,
11
+ name: "",
12
+ symbol: "",
13
+ itemCount: 0,
14
+ conditions: null,
15
+ whitelistEnabled: false,
16
+ gatedContentEnabled: false
17
+ }
18
+ )
19
+ );
20
+ expect(html).toContain("Untitled");
21
+ });
22
+ test("shows the whitelist badge once enabled", () => {
23
+ const html = renderToStaticMarkup(
24
+ /* @__PURE__ */ jsx(
25
+ DropPreviewCard,
26
+ {
27
+ coverImage: null,
28
+ name: "Genesis",
29
+ symbol: "GEN",
30
+ itemCount: 5,
31
+ conditions: null,
32
+ whitelistEnabled: true,
33
+ gatedContentEnabled: false
34
+ }
35
+ )
36
+ );
37
+ expect(html).toContain("Whitelist");
38
+ });
39
+ test("shows the exclusive content badge once enabled", () => {
40
+ const html = renderToStaticMarkup(
41
+ /* @__PURE__ */ jsx(
42
+ DropPreviewCard,
43
+ {
44
+ coverImage: null,
45
+ name: "Genesis",
46
+ symbol: "GEN",
47
+ itemCount: 5,
48
+ conditions: null,
49
+ whitelistEnabled: false,
50
+ gatedContentEnabled: true
51
+ }
52
+ )
53
+ );
54
+ expect(html).toContain("Exclusive content");
55
+ });
56
+ test("shows mint window open/close dates and max-per-wallet instead of a countdown", () => {
57
+ const html = renderToStaticMarkup(
58
+ /* @__PURE__ */ jsx(
59
+ DropPreviewCard,
60
+ {
61
+ coverImage: null,
62
+ name: "Genesis",
63
+ symbol: "GEN",
64
+ itemCount: 5,
65
+ conditions: {
66
+ maxSupply: "5",
67
+ price: "0",
68
+ paymentToken: "0x0",
69
+ startTime: 1893456e3,
70
+ endTime: 1893542400,
71
+ maxPerWallet: "2"
72
+ },
73
+ whitelistEnabled: false,
74
+ gatedContentEnabled: false
75
+ }
76
+ )
77
+ );
78
+ expect(html).toContain("Opens:");
79
+ expect(html).toContain("Closes:");
80
+ expect(html).toContain("Max 2/wallet");
81
+ expect(html).not.toContain("HRS");
82
+ });
83
+ //# sourceMappingURL=drop-preview-card.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/drop-preview-card.test.tsx"],"sourcesContent":["import { test, expect } from \"bun:test\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { DropPreviewCard } from \"./drop-preview-card.js\";\n\ntest(\"shows placeholder name and zero supply before anything is filled in\", () => {\n const html = renderToStaticMarkup(\n <DropPreviewCard\n coverImage={null} name=\"\" symbol=\"\" itemCount={0}\n conditions={null} whitelistEnabled={false} gatedContentEnabled={false}\n />\n );\n expect(html).toContain(\"Untitled\");\n});\n\ntest(\"shows the whitelist badge once enabled\", () => {\n const html = renderToStaticMarkup(\n <DropPreviewCard\n coverImage={null} name=\"Genesis\" symbol=\"GEN\" itemCount={5}\n conditions={null} whitelistEnabled gatedContentEnabled={false}\n />\n );\n expect(html).toContain(\"Whitelist\");\n});\n\ntest(\"shows the exclusive content badge once enabled\", () => {\n const html = renderToStaticMarkup(\n <DropPreviewCard\n coverImage={null} name=\"Genesis\" symbol=\"GEN\" itemCount={5}\n conditions={null} whitelistEnabled={false} gatedContentEnabled\n />\n );\n expect(html).toContain(\"Exclusive content\");\n});\n\ntest(\"shows mint window open/close dates and max-per-wallet instead of a countdown\", () => {\n const html = renderToStaticMarkup(\n <DropPreviewCard\n coverImage={null} name=\"Genesis\" symbol=\"GEN\" itemCount={5}\n conditions={{\n maxSupply: \"5\", price: \"0\", paymentToken: \"0x0\",\n startTime: 1893456000, endTime: 1893542400, maxPerWallet: \"2\",\n }}\n whitelistEnabled={false} gatedContentEnabled={false}\n />\n );\n expect(html).toContain(\"Opens:\");\n expect(html).toContain(\"Closes:\");\n expect(html).toContain(\"Max 2/wallet\");\n expect(html).not.toContain(\"HRS\");\n});\n"],"mappings":"AAMI;AANJ,SAAS,MAAM,cAAc;AAC7B,SAAS,4BAA4B;AACrC,SAAS,uBAAuB;AAEhC,KAAK,uEAAuE,MAAM;AAChF,QAAM,OAAO;AAAA,IACX;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QAAM,MAAK;AAAA,QAAG,QAAO;AAAA,QAAG,WAAW;AAAA,QAC/C,YAAY;AAAA,QAAM,kBAAkB;AAAA,QAAO,qBAAqB;AAAA;AAAA,IAClE;AAAA,EACF;AACA,SAAO,IAAI,EAAE,UAAU,UAAU;AACnC,CAAC;AAED,KAAK,0CAA0C,MAAM;AACnD,QAAM,OAAO;AAAA,IACX;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QAAM,MAAK;AAAA,QAAU,QAAO;AAAA,QAAM,WAAW;AAAA,QACzD,YAAY;AAAA,QAAM,kBAAgB;AAAA,QAAC,qBAAqB;AAAA;AAAA,IAC1D;AAAA,EACF;AACA,SAAO,IAAI,EAAE,UAAU,WAAW;AACpC,CAAC;AAED,KAAK,kDAAkD,MAAM;AAC3D,QAAM,OAAO;AAAA,IACX;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QAAM,MAAK;AAAA,QAAU,QAAO;AAAA,QAAM,WAAW;AAAA,QACzD,YAAY;AAAA,QAAM,kBAAkB;AAAA,QAAO,qBAAmB;AAAA;AAAA,IAChE;AAAA,EACF;AACA,SAAO,IAAI,EAAE,UAAU,mBAAmB;AAC5C,CAAC;AAED,KAAK,gFAAgF,MAAM;AACzF,QAAM,OAAO;AAAA,IACX;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QAAM,MAAK;AAAA,QAAU,QAAO;AAAA,QAAM,WAAW;AAAA,QACzD,YAAY;AAAA,UACV,WAAW;AAAA,UAAK,OAAO;AAAA,UAAK,cAAc;AAAA,UAC1C,WAAW;AAAA,UAAY,SAAS;AAAA,UAAY,cAAc;AAAA,QAC5D;AAAA,QACA,kBAAkB;AAAA,QAAO,qBAAqB;AAAA;AAAA,IAChD;AAAA,EACF;AACA,SAAO,IAAI,EAAE,UAAU,QAAQ;AAC/B,SAAO,IAAI,EAAE,UAAU,SAAS;AAChC,SAAO,IAAI,EAAE,UAAU,cAAc;AACrC,SAAO,IAAI,EAAE,IAAI,UAAU,KAAK;AAClC,CAAC;","names":[]}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var drop_status_display_exports = {};
21
+ __export(drop_status_display_exports, {
22
+ DropPriceDisplay: () => DropPriceDisplay,
23
+ DropStatusBadge: () => DropStatusBadge,
24
+ DropSupplyProgress: () => DropSupplyProgress
25
+ });
26
+ module.exports = __toCommonJS(drop_status_display_exports);
27
+ var import_jsx_runtime = require("react/jsx-runtime");
28
+ var import_sdk = require("@medialane/sdk");
29
+ var import_cn = require("../utils/cn.js");
30
+ function getTokenByAddress(address) {
31
+ return (0, import_sdk.getListableTokens)().find(
32
+ (t) => (0, import_sdk.normalizeAddress)("STARKNET", t.address) === (0, import_sdk.normalizeAddress)("STARKNET", address)
33
+ ) ?? null;
34
+ }
35
+ function DropStatusBadge({ status }) {
36
+ const map = {
37
+ live: { label: "Live", cls: "text-green-400 bg-green-500/10" },
38
+ upcoming: { label: "Upcoming", cls: "text-brand-blue bg-brand-blue/10" },
39
+ ended: { label: "Ended", cls: "text-muted-foreground bg-muted" },
40
+ sold_out: { label: "Sold out", cls: "text-brand-orange bg-brand-orange/10" }
41
+ };
42
+ const { label, cls } = map[status];
43
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
44
+ "span",
45
+ {
46
+ className: (0, import_cn.cn)(
47
+ "inline-flex items-center gap-1 text-xs font-bold uppercase tracking-widest rounded-full px-3 py-1",
48
+ cls
49
+ ),
50
+ children: [
51
+ status === "live" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-green-400 animate-pulse" }),
52
+ label
53
+ ]
54
+ }
55
+ );
56
+ }
57
+ function DropSupplyProgress({ minted, max }) {
58
+ const pct = max > 0 ? Math.min(100, minted / max * 100) : 0;
59
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-xs text-muted-foreground", children: [
61
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
62
+ minted.toLocaleString(),
63
+ " minted"
64
+ ] }),
65
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
66
+ "of ",
67
+ max.toLocaleString()
68
+ ] })
69
+ ] }),
70
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-2 rounded-full bg-muted overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
71
+ "div",
72
+ {
73
+ className: "h-full rounded-full bg-brand-orange transition-all duration-500",
74
+ style: { width: `${pct}%` }
75
+ }
76
+ ) }),
77
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
78
+ pct.toFixed(1),
79
+ "% claimed"
80
+ ] })
81
+ ] });
82
+ }
83
+ function DropPriceDisplay({ conditions }) {
84
+ if (conditions.price === "0" || conditions.paymentToken === "0x0") {
85
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex items-center gap-1.5 text-sm font-semibold text-green-500", children: "Free mint" });
86
+ }
87
+ const token = getTokenByAddress(conditions.paymentToken);
88
+ const decimals = token?.decimals ?? 18;
89
+ const priceNum = Number(BigInt(conditions.price) * 10000n / BigInt(10 ** decimals)) / 1e4;
90
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5 text-sm font-semibold", children: [
91
+ priceNum,
92
+ " ",
93
+ token?.symbol ?? "tokens",
94
+ " per token"
95
+ ] });
96
+ }
97
+ // Annotate the CommonJS export names for ESM import in node:
98
+ 0 && (module.exports = {
99
+ DropPriceDisplay,
100
+ DropStatusBadge,
101
+ DropSupplyProgress
102
+ });
103
+ //# sourceMappingURL=drop-status-display.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/drop-status-display.tsx"],"sourcesContent":["\"use client\";\n\nimport { getListableTokens, normalizeAddress } from \"@medialane/sdk\";\nimport { cn } from \"../utils/cn.js\";\nimport type { DropConditions, DropStatus } from \"../utils/drop-status.js\";\n\nfunction getTokenByAddress(address: string) {\n return (\n getListableTokens().find(\n (t) => normalizeAddress(\"STARKNET\", t.address) === normalizeAddress(\"STARKNET\", address)\n ) ?? null\n );\n}\n\nexport function DropStatusBadge({ status }: { status: DropStatus }) {\n const map = {\n live: { label: \"Live\", cls: \"text-green-400 bg-green-500/10\" },\n upcoming: { label: \"Upcoming\", cls: \"text-brand-blue bg-brand-blue/10\" },\n ended: { label: \"Ended\", cls: \"text-muted-foreground bg-muted\" },\n sold_out: { label: \"Sold out\", cls: \"text-brand-orange bg-brand-orange/10\" },\n } as const;\n const { label, cls } = map[status];\n return (\n <span\n className={cn(\n \"inline-flex items-center gap-1 text-xs font-bold uppercase tracking-widest rounded-full px-3 py-1\",\n cls\n )}\n >\n {status === \"live\" && <span className=\"h-1.5 w-1.5 rounded-full bg-green-400 animate-pulse\" />}\n {label}\n </span>\n );\n}\n\nexport function DropSupplyProgress({ minted, max }: { minted: number; max: number }) {\n const pct = max > 0 ? Math.min(100, (minted / max) * 100) : 0;\n return (\n <div className=\"space-y-1.5\">\n <div className=\"flex justify-between text-xs text-muted-foreground\">\n <span>{minted.toLocaleString()} minted</span>\n <span>of {max.toLocaleString()}</span>\n </div>\n <div className=\"h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-brand-orange transition-all duration-500\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <p className=\"text-xs text-muted-foreground\">{pct.toFixed(1)}% claimed</p>\n </div>\n );\n}\n\nexport function DropPriceDisplay({ conditions }: { conditions: DropConditions }) {\n if (conditions.price === \"0\" || conditions.paymentToken === \"0x0\") {\n return (\n <div className=\"flex items-center gap-1.5 text-sm font-semibold text-green-500\">\n Free mint\n </div>\n );\n }\n const token = getTokenByAddress(conditions.paymentToken);\n const decimals = token?.decimals ?? 18;\n const priceNum = Number(BigInt(conditions.price) * 10000n / BigInt(10 ** decimals)) / 10000;\n return (\n <div className=\"flex items-center gap-1.5 text-sm font-semibold\">\n {priceNum} {token?.symbol ?? \"tokens\"} per token\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBI;AArBJ,iBAAoD;AACpD,gBAAmB;AAGnB,SAAS,kBAAkB,SAAiB;AAC1C,aACE,8BAAkB,EAAE;AAAA,IAClB,CAAC,UAAM,6BAAiB,YAAY,EAAE,OAAO,UAAM,6BAAiB,YAAY,OAAO;AAAA,EACzF,KAAK;AAET;AAEO,SAAS,gBAAgB,EAAE,OAAO,GAA2B;AAClE,QAAM,MAAM;AAAA,IACV,MAAU,EAAE,OAAO,QAAY,KAAK,iCAAmC;AAAA,IACvE,UAAU,EAAE,OAAO,YAAY,KAAK,mCAAuC;AAAA,IAC3E,OAAU,EAAE,OAAO,SAAY,KAAK,iCAAmC;AAAA,IACvE,UAAU,EAAE,OAAO,YAAY,KAAK,uCAAuC;AAAA,EAC7E;AACA,QAAM,EAAE,OAAO,IAAI,IAAI,IAAI,MAAM;AACjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA,mBAAW,UAAU,4CAAC,UAAK,WAAU,uDAAsD;AAAA,QAC3F;AAAA;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,mBAAmB,EAAE,QAAQ,IAAI,GAAoC;AACnF,QAAM,MAAM,MAAM,IAAI,KAAK,IAAI,KAAM,SAAS,MAAO,GAAG,IAAI;AAC5D,SACE,6CAAC,SAAI,WAAU,eACb;AAAA,iDAAC,SAAI,WAAU,sDACb;AAAA,mDAAC,UAAM;AAAA,eAAO,eAAe;AAAA,QAAE;AAAA,SAAO;AAAA,MACtC,6CAAC,UAAK;AAAA;AAAA,QAAI,IAAI,eAAe;AAAA,SAAE;AAAA,OACjC;AAAA,IACA,4CAAC,SAAI,WAAU,6CACb;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,OAAO,GAAG,GAAG,IAAI;AAAA;AAAA,IAC5B,GACF;AAAA,IACA,6CAAC,OAAE,WAAU,iCAAiC;AAAA,UAAI,QAAQ,CAAC;AAAA,MAAE;AAAA,OAAS;AAAA,KACxE;AAEJ;AAEO,SAAS,iBAAiB,EAAE,WAAW,GAAmC;AAC/E,MAAI,WAAW,UAAU,OAAO,WAAW,iBAAiB,OAAO;AACjE,WACE,4CAAC,SAAI,WAAU,kEAAiE,uBAEhF;AAAA,EAEJ;AACA,QAAM,QAAQ,kBAAkB,WAAW,YAAY;AACvD,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,WAAW,OAAO,OAAO,WAAW,KAAK,IAAI,SAAS,OAAO,MAAM,QAAQ,CAAC,IAAI;AACtF,SACE,6CAAC,SAAI,WAAU,mDACZ;AAAA;AAAA,IAAS;AAAA,IAAE,OAAO,UAAU;AAAA,IAAS;AAAA,KACxC;AAEJ;","names":[]}
@@ -0,0 +1,15 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { DropConditions, DropStatus } from '../utils/drop-status.cjs';
3
+
4
+ declare function DropStatusBadge({ status }: {
5
+ status: DropStatus;
6
+ }): react_jsx_runtime.JSX.Element;
7
+ declare function DropSupplyProgress({ minted, max }: {
8
+ minted: number;
9
+ max: number;
10
+ }): react_jsx_runtime.JSX.Element;
11
+ declare function DropPriceDisplay({ conditions }: {
12
+ conditions: DropConditions;
13
+ }): react_jsx_runtime.JSX.Element;
14
+
15
+ export { DropPriceDisplay, DropStatusBadge, DropSupplyProgress };
@@ -0,0 +1,15 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { DropConditions, DropStatus } from '../utils/drop-status.js';
3
+
4
+ declare function DropStatusBadge({ status }: {
5
+ status: DropStatus;
6
+ }): react_jsx_runtime.JSX.Element;
7
+ declare function DropSupplyProgress({ minted, max }: {
8
+ minted: number;
9
+ max: number;
10
+ }): react_jsx_runtime.JSX.Element;
11
+ declare function DropPriceDisplay({ conditions }: {
12
+ conditions: DropConditions;
13
+ }): react_jsx_runtime.JSX.Element;
14
+
15
+ export { DropPriceDisplay, DropStatusBadge, DropSupplyProgress };
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { getListableTokens, normalizeAddress } from "@medialane/sdk";
4
+ import { cn } from "../utils/cn.js";
5
+ function getTokenByAddress(address) {
6
+ return getListableTokens().find(
7
+ (t) => normalizeAddress("STARKNET", t.address) === normalizeAddress("STARKNET", address)
8
+ ) ?? null;
9
+ }
10
+ function DropStatusBadge({ status }) {
11
+ const map = {
12
+ live: { label: "Live", cls: "text-green-400 bg-green-500/10" },
13
+ upcoming: { label: "Upcoming", cls: "text-brand-blue bg-brand-blue/10" },
14
+ ended: { label: "Ended", cls: "text-muted-foreground bg-muted" },
15
+ sold_out: { label: "Sold out", cls: "text-brand-orange bg-brand-orange/10" }
16
+ };
17
+ const { label, cls } = map[status];
18
+ return /* @__PURE__ */ jsxs(
19
+ "span",
20
+ {
21
+ className: cn(
22
+ "inline-flex items-center gap-1 text-xs font-bold uppercase tracking-widest rounded-full px-3 py-1",
23
+ cls
24
+ ),
25
+ children: [
26
+ status === "live" && /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-green-400 animate-pulse" }),
27
+ label
28
+ ]
29
+ }
30
+ );
31
+ }
32
+ function DropSupplyProgress({ minted, max }) {
33
+ const pct = max > 0 ? Math.min(100, minted / max * 100) : 0;
34
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
35
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-xs text-muted-foreground", children: [
36
+ /* @__PURE__ */ jsxs("span", { children: [
37
+ minted.toLocaleString(),
38
+ " minted"
39
+ ] }),
40
+ /* @__PURE__ */ jsxs("span", { children: [
41
+ "of ",
42
+ max.toLocaleString()
43
+ ] })
44
+ ] }),
45
+ /* @__PURE__ */ jsx("div", { className: "h-2 rounded-full bg-muted overflow-hidden", children: /* @__PURE__ */ jsx(
46
+ "div",
47
+ {
48
+ className: "h-full rounded-full bg-brand-orange transition-all duration-500",
49
+ style: { width: `${pct}%` }
50
+ }
51
+ ) }),
52
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
53
+ pct.toFixed(1),
54
+ "% claimed"
55
+ ] })
56
+ ] });
57
+ }
58
+ function DropPriceDisplay({ conditions }) {
59
+ if (conditions.price === "0" || conditions.paymentToken === "0x0") {
60
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 text-sm font-semibold text-green-500", children: "Free mint" });
61
+ }
62
+ const token = getTokenByAddress(conditions.paymentToken);
63
+ const decimals = token?.decimals ?? 18;
64
+ const priceNum = Number(BigInt(conditions.price) * 10000n / BigInt(10 ** decimals)) / 1e4;
65
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-sm font-semibold", children: [
66
+ priceNum,
67
+ " ",
68
+ token?.symbol ?? "tokens",
69
+ " per token"
70
+ ] });
71
+ }
72
+ export {
73
+ DropPriceDisplay,
74
+ DropStatusBadge,
75
+ DropSupplyProgress
76
+ };
77
+ //# sourceMappingURL=drop-status-display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/drop-status-display.tsx"],"sourcesContent":["\"use client\";\n\nimport { getListableTokens, normalizeAddress } from \"@medialane/sdk\";\nimport { cn } from \"../utils/cn.js\";\nimport type { DropConditions, DropStatus } from \"../utils/drop-status.js\";\n\nfunction getTokenByAddress(address: string) {\n return (\n getListableTokens().find(\n (t) => normalizeAddress(\"STARKNET\", t.address) === normalizeAddress(\"STARKNET\", address)\n ) ?? null\n );\n}\n\nexport function DropStatusBadge({ status }: { status: DropStatus }) {\n const map = {\n live: { label: \"Live\", cls: \"text-green-400 bg-green-500/10\" },\n upcoming: { label: \"Upcoming\", cls: \"text-brand-blue bg-brand-blue/10\" },\n ended: { label: \"Ended\", cls: \"text-muted-foreground bg-muted\" },\n sold_out: { label: \"Sold out\", cls: \"text-brand-orange bg-brand-orange/10\" },\n } as const;\n const { label, cls } = map[status];\n return (\n <span\n className={cn(\n \"inline-flex items-center gap-1 text-xs font-bold uppercase tracking-widest rounded-full px-3 py-1\",\n cls\n )}\n >\n {status === \"live\" && <span className=\"h-1.5 w-1.5 rounded-full bg-green-400 animate-pulse\" />}\n {label}\n </span>\n );\n}\n\nexport function DropSupplyProgress({ minted, max }: { minted: number; max: number }) {\n const pct = max > 0 ? Math.min(100, (minted / max) * 100) : 0;\n return (\n <div className=\"space-y-1.5\">\n <div className=\"flex justify-between text-xs text-muted-foreground\">\n <span>{minted.toLocaleString()} minted</span>\n <span>of {max.toLocaleString()}</span>\n </div>\n <div className=\"h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-brand-orange transition-all duration-500\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <p className=\"text-xs text-muted-foreground\">{pct.toFixed(1)}% claimed</p>\n </div>\n );\n}\n\nexport function DropPriceDisplay({ conditions }: { conditions: DropConditions }) {\n if (conditions.price === \"0\" || conditions.paymentToken === \"0x0\") {\n return (\n <div className=\"flex items-center gap-1.5 text-sm font-semibold text-green-500\">\n Free mint\n </div>\n );\n }\n const token = getTokenByAddress(conditions.paymentToken);\n const decimals = token?.decimals ?? 18;\n const priceNum = Number(BigInt(conditions.price) * 10000n / BigInt(10 ** decimals)) / 10000;\n return (\n <div className=\"flex items-center gap-1.5 text-sm font-semibold\">\n {priceNum} {token?.symbol ?? \"tokens\"} per token\n </div>\n );\n}\n"],"mappings":";AAuBI,SAMwB,KANxB;AArBJ,SAAS,mBAAmB,wBAAwB;AACpD,SAAS,UAAU;AAGnB,SAAS,kBAAkB,SAAiB;AAC1C,SACE,kBAAkB,EAAE;AAAA,IAClB,CAAC,MAAM,iBAAiB,YAAY,EAAE,OAAO,MAAM,iBAAiB,YAAY,OAAO;AAAA,EACzF,KAAK;AAET;AAEO,SAAS,gBAAgB,EAAE,OAAO,GAA2B;AAClE,QAAM,MAAM;AAAA,IACV,MAAU,EAAE,OAAO,QAAY,KAAK,iCAAmC;AAAA,IACvE,UAAU,EAAE,OAAO,YAAY,KAAK,mCAAuC;AAAA,IAC3E,OAAU,EAAE,OAAO,SAAY,KAAK,iCAAmC;AAAA,IACvE,UAAU,EAAE,OAAO,YAAY,KAAK,uCAAuC;AAAA,EAC7E;AACA,QAAM,EAAE,OAAO,IAAI,IAAI,IAAI,MAAM;AACjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA,mBAAW,UAAU,oBAAC,UAAK,WAAU,uDAAsD;AAAA,QAC3F;AAAA;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,mBAAmB,EAAE,QAAQ,IAAI,GAAoC;AACnF,QAAM,MAAM,MAAM,IAAI,KAAK,IAAI,KAAM,SAAS,MAAO,GAAG,IAAI;AAC5D,SACE,qBAAC,SAAI,WAAU,eACb;AAAA,yBAAC,SAAI,WAAU,sDACb;AAAA,2BAAC,UAAM;AAAA,eAAO,eAAe;AAAA,QAAE;AAAA,SAAO;AAAA,MACtC,qBAAC,UAAK;AAAA;AAAA,QAAI,IAAI,eAAe;AAAA,SAAE;AAAA,OACjC;AAAA,IACA,oBAAC,SAAI,WAAU,6CACb;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,OAAO,GAAG,GAAG,IAAI;AAAA;AAAA,IAC5B,GACF;AAAA,IACA,qBAAC,OAAE,WAAU,iCAAiC;AAAA,UAAI,QAAQ,CAAC;AAAA,MAAE;AAAA,OAAS;AAAA,KACxE;AAEJ;AAEO,SAAS,iBAAiB,EAAE,WAAW,GAAmC;AAC/E,MAAI,WAAW,UAAU,OAAO,WAAW,iBAAiB,OAAO;AACjE,WACE,oBAAC,SAAI,WAAU,kEAAiE,uBAEhF;AAAA,EAEJ;AACA,QAAM,QAAQ,kBAAkB,WAAW,YAAY;AACvD,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,WAAW,OAAO,OAAO,WAAW,KAAK,IAAI,SAAS,OAAO,MAAM,QAAQ,CAAC,IAAI;AACtF,SACE,qBAAC,SAAI,WAAU,mDACZ;AAAA;AAAA,IAAS;AAAA,IAAE,OAAO,UAAU;AAAA,IAAS;AAAA,KACxC;AAEJ;","names":[]}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var import_jsx_runtime = require("react/jsx-runtime");
3
+ var import_bun_test = require("bun:test");
4
+ var import_server = require("react-dom/server");
5
+ var import_drop_status_display = require("./drop-status-display.js");
6
+ (0, import_bun_test.test)("DropStatusBadge renders the live label with a pulse dot", () => {
7
+ const html = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_drop_status_display.DropStatusBadge, { status: "live" }));
8
+ (0, import_bun_test.expect)(html).toContain("Live");
9
+ (0, import_bun_test.expect)(html).toContain("animate-pulse");
10
+ });
11
+ (0, import_bun_test.test)("DropSupplyProgress shows minted-of-max and a percentage", () => {
12
+ const html = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_drop_status_display.DropSupplyProgress, { minted: 3, max: 10 }));
13
+ (0, import_bun_test.expect)(html).toContain("3");
14
+ (0, import_bun_test.expect)(html).toContain("of 10");
15
+ (0, import_bun_test.expect)(html).toContain("30.0%");
16
+ });
17
+ (0, import_bun_test.test)("DropPriceDisplay shows Free mint for a zero-price drop", () => {
18
+ const conditions = {
19
+ maxSupply: "10",
20
+ price: "0",
21
+ paymentToken: "0x0",
22
+ startTime: 0,
23
+ endTime: 0,
24
+ maxPerWallet: "1"
25
+ };
26
+ const html = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_drop_status_display.DropPriceDisplay, { conditions }));
27
+ (0, import_bun_test.expect)(html).toContain("Free mint");
28
+ });
29
+ //# sourceMappingURL=drop-status-display.test.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/drop-status-display.test.tsx"],"sourcesContent":["import { test, expect } from \"bun:test\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { DropStatusBadge, DropSupplyProgress, DropPriceDisplay } from \"./drop-status-display.js\";\nimport type { DropConditions } from \"../utils/drop-status.js\";\n\ntest(\"DropStatusBadge renders the live label with a pulse dot\", () => {\n const html = renderToStaticMarkup(<DropStatusBadge status=\"live\" />);\n expect(html).toContain(\"Live\");\n expect(html).toContain(\"animate-pulse\");\n});\n\ntest(\"DropSupplyProgress shows minted-of-max and a percentage\", () => {\n const html = renderToStaticMarkup(<DropSupplyProgress minted={3} max={10} />);\n expect(html).toContain(\"3\");\n expect(html).toContain(\"of 10\");\n expect(html).toContain(\"30.0%\");\n});\n\ntest(\"DropPriceDisplay shows Free mint for a zero-price drop\", () => {\n const conditions: DropConditions = {\n maxSupply: \"10\", price: \"0\", paymentToken: \"0x0\",\n startTime: 0, endTime: 0, maxPerWallet: \"1\",\n };\n const html = renderToStaticMarkup(<DropPriceDisplay conditions={conditions} />);\n expect(html).toContain(\"Free mint\");\n});\n"],"mappings":";AAMoC;AANpC,sBAA6B;AAC7B,oBAAqC;AACrC,iCAAsE;AAAA,IAGtE,sBAAK,2DAA2D,MAAM;AACpE,QAAM,WAAO,oCAAqB,4CAAC,8CAAgB,QAAO,QAAO,CAAE;AACnE,8BAAO,IAAI,EAAE,UAAU,MAAM;AAC7B,8BAAO,IAAI,EAAE,UAAU,eAAe;AACxC,CAAC;AAAA,IAED,sBAAK,2DAA2D,MAAM;AACpE,QAAM,WAAO,oCAAqB,4CAAC,iDAAmB,QAAQ,GAAG,KAAK,IAAI,CAAE;AAC5E,8BAAO,IAAI,EAAE,UAAU,GAAG;AAC1B,8BAAO,IAAI,EAAE,UAAU,OAAO;AAC9B,8BAAO,IAAI,EAAE,UAAU,OAAO;AAChC,CAAC;AAAA,IAED,sBAAK,0DAA0D,MAAM;AACnE,QAAM,aAA6B;AAAA,IACjC,WAAW;AAAA,IAAM,OAAO;AAAA,IAAK,cAAc;AAAA,IAC3C,WAAW;AAAA,IAAG,SAAS;AAAA,IAAG,cAAc;AAAA,EAC1C;AACA,QAAM,WAAO,oCAAqB,4CAAC,+CAAiB,YAAwB,CAAE;AAC9E,8BAAO,IAAI,EAAE,UAAU,WAAW;AACpC,CAAC;","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,28 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { test, expect } from "bun:test";
3
+ import { renderToStaticMarkup } from "react-dom/server";
4
+ import { DropStatusBadge, DropSupplyProgress, DropPriceDisplay } from "./drop-status-display.js";
5
+ test("DropStatusBadge renders the live label with a pulse dot", () => {
6
+ const html = renderToStaticMarkup(/* @__PURE__ */ jsx(DropStatusBadge, { status: "live" }));
7
+ expect(html).toContain("Live");
8
+ expect(html).toContain("animate-pulse");
9
+ });
10
+ test("DropSupplyProgress shows minted-of-max and a percentage", () => {
11
+ const html = renderToStaticMarkup(/* @__PURE__ */ jsx(DropSupplyProgress, { minted: 3, max: 10 }));
12
+ expect(html).toContain("3");
13
+ expect(html).toContain("of 10");
14
+ expect(html).toContain("30.0%");
15
+ });
16
+ test("DropPriceDisplay shows Free mint for a zero-price drop", () => {
17
+ const conditions = {
18
+ maxSupply: "10",
19
+ price: "0",
20
+ paymentToken: "0x0",
21
+ startTime: 0,
22
+ endTime: 0,
23
+ maxPerWallet: "1"
24
+ };
25
+ const html = renderToStaticMarkup(/* @__PURE__ */ jsx(DropPriceDisplay, { conditions }));
26
+ expect(html).toContain("Free mint");
27
+ });
28
+ //# sourceMappingURL=drop-status-display.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/drop-status-display.test.tsx"],"sourcesContent":["import { test, expect } from \"bun:test\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { DropStatusBadge, DropSupplyProgress, DropPriceDisplay } from \"./drop-status-display.js\";\nimport type { DropConditions } from \"../utils/drop-status.js\";\n\ntest(\"DropStatusBadge renders the live label with a pulse dot\", () => {\n const html = renderToStaticMarkup(<DropStatusBadge status=\"live\" />);\n expect(html).toContain(\"Live\");\n expect(html).toContain(\"animate-pulse\");\n});\n\ntest(\"DropSupplyProgress shows minted-of-max and a percentage\", () => {\n const html = renderToStaticMarkup(<DropSupplyProgress minted={3} max={10} />);\n expect(html).toContain(\"3\");\n expect(html).toContain(\"of 10\");\n expect(html).toContain(\"30.0%\");\n});\n\ntest(\"DropPriceDisplay shows Free mint for a zero-price drop\", () => {\n const conditions: DropConditions = {\n maxSupply: \"10\", price: \"0\", paymentToken: \"0x0\",\n startTime: 0, endTime: 0, maxPerWallet: \"1\",\n };\n const html = renderToStaticMarkup(<DropPriceDisplay conditions={conditions} />);\n expect(html).toContain(\"Free mint\");\n});\n"],"mappings":"AAMoC;AANpC,SAAS,MAAM,cAAc;AAC7B,SAAS,4BAA4B;AACrC,SAAS,iBAAiB,oBAAoB,wBAAwB;AAGtE,KAAK,2DAA2D,MAAM;AACpE,QAAM,OAAO,qBAAqB,oBAAC,mBAAgB,QAAO,QAAO,CAAE;AACnE,SAAO,IAAI,EAAE,UAAU,MAAM;AAC7B,SAAO,IAAI,EAAE,UAAU,eAAe;AACxC,CAAC;AAED,KAAK,2DAA2D,MAAM;AACpE,QAAM,OAAO,qBAAqB,oBAAC,sBAAmB,QAAQ,GAAG,KAAK,IAAI,CAAE;AAC5E,SAAO,IAAI,EAAE,UAAU,GAAG;AAC1B,SAAO,IAAI,EAAE,UAAU,OAAO;AAC9B,SAAO,IAAI,EAAE,UAAU,OAAO;AAChC,CAAC;AAED,KAAK,0DAA0D,MAAM;AACnE,QAAM,aAA6B;AAAA,IACjC,WAAW;AAAA,IAAM,OAAO;AAAA,IAAK,cAAc;AAAA,IAC3C,WAAW;AAAA,IAAG,SAAS;AAAA,IAAG,cAAc;AAAA,EAC1C;AACA,QAAM,OAAO,qBAAqB,oBAAC,oBAAiB,YAAwB,CAAE;AAC9E,SAAO,IAAI,EAAE,UAAU,WAAW;AACpC,CAAC;","names":[]}