@medialane/ui 0.145.1 → 0.146.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 (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 +79 -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 +55 -0
  18. package/dist/components/drop-preview-card.js.map +1 -0
  19. package/dist/components/drop-preview-card.test.cjs +57 -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 +56 -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,57 @@
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
+ //# 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"],"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;","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,56 @@
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
+ //# 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"],"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;","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":[]}
@@ -0,0 +1,88 @@
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 exclusive_content_section_exports = {};
21
+ __export(exclusive_content_section_exports, {
22
+ ExclusiveContentSection: () => ExclusiveContentSection
23
+ });
24
+ module.exports = __toCommonJS(exclusive_content_section_exports);
25
+ var import_jsx_runtime = require("react/jsx-runtime");
26
+ var import_lucide_react = require("lucide-react");
27
+ var import_form = require("./form.js");
28
+ var import_input = require("./input.js");
29
+ var import_select = require("./select.js");
30
+ var import_switch = require("./switch.js");
31
+ var import_collapsible_section = require("./collapsible-section.js");
32
+ var import_gated_content_types = require("../data/gated-content-types.js");
33
+ const CONTENT_TYPES = Object.keys(import_gated_content_types.GATED_CONTENT_TYPES).map((value) => ({
34
+ value,
35
+ label: value.charAt(0) + value.slice(1).toLowerCase()
36
+ }));
37
+ function ExclusiveContentSection({ form }) {
38
+ const gatedEnabled = form.watch("gatedEnabled");
39
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
40
+ import_collapsible_section.CollapsibleSection,
41
+ {
42
+ open: gatedEnabled,
43
+ onOpenChange: (o) => form.setValue("gatedEnabled", o),
44
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Lock, { className: "h-4 w-4 text-primary" }),
45
+ label: "Exclusive Content",
46
+ hint: gatedEnabled ? "Holders get a locked tab with this content" : "Optional \xB7 reward holders with gated content",
47
+ children: [
48
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground", children: "Reward your holders with exclusive access \u2014 video, audio, documents, or any link. Only verified token holders can access this content." }),
49
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between", children: [
50
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium", children: "Enable exclusive content" }),
51
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
52
+ import_switch.Switch,
53
+ {
54
+ checked: gatedEnabled,
55
+ onCheckedChange: (checked) => form.setValue("gatedEnabled", checked)
56
+ }
57
+ )
58
+ ] }),
59
+ gatedEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormField, { control: form.control, name: "gatedContentTitle", render: ({ field }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_form.FormItem, { children: [
61
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormLabel, { children: "Content title" }),
62
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormControl, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_input.Input, { placeholder: "e.g. Behind-the-scenes footage", ...field }) }),
63
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormMessage, {})
64
+ ] }) }),
65
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormField, { control: form.control, name: "gatedContentUrl", render: ({ field }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_form.FormItem, { children: [
66
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormLabel, { children: "Content URL" }),
67
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormControl, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_input.Input, { placeholder: "https://\u2026", ...field }) }),
68
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormDescription, { children: "Only holders will see this URL. Use a private or unlisted link." }),
69
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormMessage, {})
70
+ ] }) }),
71
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormField, { control: form.control, name: "gatedContentType", render: ({ field }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_form.FormItem, { children: [
72
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormLabel, { children: "Content type" }),
73
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_select.Select, { value: field.value, onValueChange: field.onChange, children: [
74
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormControl, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectValue, { placeholder: "Select type" }) }) }),
75
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectContent, { children: CONTENT_TYPES.map(({ value, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectItem, { value, children: label }, value)) })
76
+ ] }),
77
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form.FormMessage, {})
78
+ ] }) })
79
+ ] })
80
+ ]
81
+ }
82
+ );
83
+ }
84
+ // Annotate the CommonJS export names for ESM import in node:
85
+ 0 && (module.exports = {
86
+ ExclusiveContentSection
87
+ });
88
+ //# sourceMappingURL=exclusive-content-section.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/exclusive-content-section.tsx"],"sourcesContent":["\"use client\";\n\nimport type { UseFormReturn } from \"react-hook-form\";\nimport { Lock } from \"lucide-react\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, FormDescription } from \"./form.js\";\nimport { Input } from \"./input.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"./select.js\";\nimport { Switch } from \"./switch.js\";\nimport { CollapsibleSection } from \"./collapsible-section.js\";\nimport { GATED_CONTENT_TYPES } from \"../data/gated-content-types.js\";\nimport type { DropCreateFormValues } from \"../data/drop-create-schema.js\";\n\nconst CONTENT_TYPES = Object.keys(GATED_CONTENT_TYPES).map((value) => ({\n value,\n label: value.charAt(0) + value.slice(1).toLowerCase(),\n}));\n\nexport function ExclusiveContentSection({ form }: { form: UseFormReturn<DropCreateFormValues> }) {\n const gatedEnabled = form.watch(\"gatedEnabled\");\n\n return (\n <CollapsibleSection\n open={gatedEnabled}\n onOpenChange={(o) => form.setValue(\"gatedEnabled\", o)}\n icon={<Lock className=\"h-4 w-4 text-primary\" />}\n label=\"Exclusive Content\"\n hint={gatedEnabled ? \"Holders get a locked tab with this content\" : \"Optional · reward holders with gated content\"}\n >\n <p className=\"text-xs text-muted-foreground\">\n Reward your holders with exclusive access — video, audio, documents, or any link.\n Only verified token holders can access this content.\n </p>\n\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm font-medium\">Enable exclusive content</p>\n <Switch\n checked={gatedEnabled}\n onCheckedChange={(checked) => form.setValue(\"gatedEnabled\", checked)}\n />\n </div>\n\n {gatedEnabled && (\n <>\n <FormField control={form.control} name=\"gatedContentTitle\" render={({ field }) => (\n <FormItem>\n <FormLabel>Content title</FormLabel>\n <FormControl><Input placeholder=\"e.g. Behind-the-scenes footage\" {...field} /></FormControl>\n <FormMessage />\n </FormItem>\n )} />\n\n <FormField control={form.control} name=\"gatedContentUrl\" render={({ field }) => (\n <FormItem>\n <FormLabel>Content URL</FormLabel>\n <FormControl><Input placeholder=\"https://…\" {...field} /></FormControl>\n <FormDescription>Only holders will see this URL. Use a private or unlisted link.</FormDescription>\n <FormMessage />\n </FormItem>\n )} />\n\n <FormField control={form.control} name=\"gatedContentType\" render={({ field }) => (\n <FormItem>\n <FormLabel>Content type</FormLabel>\n <Select value={field.value} onValueChange={field.onChange}>\n <FormControl><SelectTrigger><SelectValue placeholder=\"Select type\" /></SelectTrigger></FormControl>\n <SelectContent>\n {CONTENT_TYPES.map(({ value, label }) => <SelectItem key={value} value={value}>{label}</SelectItem>)}\n </SelectContent>\n </Select>\n <FormMessage />\n </FormItem>\n )} />\n </>\n )}\n </CollapsibleSection>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBY;AArBZ,0BAAqB;AACrB,kBAA0F;AAC1F,mBAAsB;AACtB,oBAA8E;AAC9E,oBAAuB;AACvB,iCAAmC;AACnC,iCAAoC;AAGpC,MAAM,gBAAgB,OAAO,KAAK,8CAAmB,EAAE,IAAI,CAAC,WAAW;AAAA,EACrE;AAAA,EACA,OAAO,MAAM,OAAO,CAAC,IAAI,MAAM,MAAM,CAAC,EAAE,YAAY;AACtD,EAAE;AAEK,SAAS,wBAAwB,EAAE,KAAK,GAAkD;AAC/F,QAAM,eAAe,KAAK,MAAM,cAAc;AAE9C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,cAAc,CAAC,MAAM,KAAK,SAAS,gBAAgB,CAAC;AAAA,MACpD,MAAM,4CAAC,4BAAK,WAAU,wBAAuB;AAAA,MAC7C,OAAM;AAAA,MACN,MAAM,eAAe,+CAA+C;AAAA,MAEpE;AAAA,oDAAC,OAAE,WAAU,iCAAgC,yJAG7C;AAAA,QAEA,6CAAC,SAAI,WAAU,qCACb;AAAA,sDAAC,OAAE,WAAU,uBAAsB,sCAAwB;AAAA,UAC3D;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,iBAAiB,CAAC,YAAY,KAAK,SAAS,gBAAgB,OAAO;AAAA;AAAA,UACrE;AAAA,WACF;AAAA,QAEC,gBACC,4EACE;AAAA,sDAAC,yBAAU,SAAS,KAAK,SAAS,MAAK,qBAAoB,QAAQ,CAAC,EAAE,MAAM,MAC1E,6CAAC,wBACC;AAAA,wDAAC,yBAAU,2BAAa;AAAA,YACxB,4CAAC,2BAAY,sDAAC,sBAAM,aAAY,kCAAkC,GAAG,OAAO,GAAE;AAAA,YAC9E,4CAAC,2BAAY;AAAA,aACf,GACC;AAAA,UAEH,4CAAC,yBAAU,SAAS,KAAK,SAAS,MAAK,mBAAkB,QAAQ,CAAC,EAAE,MAAM,MACxE,6CAAC,wBACC;AAAA,wDAAC,yBAAU,yBAAW;AAAA,YACtB,4CAAC,2BAAY,sDAAC,sBAAM,aAAY,kBAAa,GAAG,OAAO,GAAE;AAAA,YACzD,4CAAC,+BAAgB,6EAA+D;AAAA,YAChF,4CAAC,2BAAY;AAAA,aACf,GACC;AAAA,UAEH,4CAAC,yBAAU,SAAS,KAAK,SAAS,MAAK,oBAAmB,QAAQ,CAAC,EAAE,MAAM,MACzE,6CAAC,wBACC;AAAA,wDAAC,yBAAU,0BAAY;AAAA,YACvB,6CAAC,wBAAO,OAAO,MAAM,OAAO,eAAe,MAAM,UAC/C;AAAA,0DAAC,2BAAY,sDAAC,+BAAc,sDAAC,6BAAY,aAAY,eAAc,GAAE,GAAgB;AAAA,cACrF,4CAAC,+BACE,wBAAc,IAAI,CAAC,EAAE,OAAO,MAAM,MAAM,4CAAC,4BAAuB,OAAe,mBAAtB,KAA4B,CAAa,GACrG;AAAA,eACF;AAAA,YACA,4CAAC,2BAAY;AAAA,aACf,GACC;AAAA,WACL;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":[]}
@@ -0,0 +1,10 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { UseFormReturn } from 'react-hook-form';
3
+ import { DropCreateFormValues } from '../data/drop-create-schema.cjs';
4
+ import 'zod';
5
+
6
+ declare function ExclusiveContentSection({ form }: {
7
+ form: UseFormReturn<DropCreateFormValues>;
8
+ }): react_jsx_runtime.JSX.Element;
9
+
10
+ export { ExclusiveContentSection };
@@ -0,0 +1,10 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { UseFormReturn } from 'react-hook-form';
3
+ import { DropCreateFormValues } from '../data/drop-create-schema.js';
4
+ import 'zod';
5
+
6
+ declare function ExclusiveContentSection({ form }: {
7
+ form: UseFormReturn<DropCreateFormValues>;
8
+ }): react_jsx_runtime.JSX.Element;
9
+
10
+ export { ExclusiveContentSection };