@medialane/ui 0.174.0 → 0.176.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 (93) hide show
  1. package/dist/components/account/account-section.cjs +50 -0
  2. package/dist/components/account/account-section.cjs.map +1 -0
  3. package/dist/components/account/account-section.d.cts +14 -0
  4. package/dist/components/account/account-section.d.ts +14 -0
  5. package/dist/components/account/account-section.js +26 -0
  6. package/dist/components/account/account-section.js.map +1 -0
  7. package/dist/components/account/account.test.cjs +86 -0
  8. package/dist/components/account/account.test.cjs.map +1 -0
  9. package/dist/components/account/account.test.d.cts +2 -0
  10. package/dist/components/account/account.test.d.ts +2 -0
  11. package/dist/components/account/account.test.js +85 -0
  12. package/dist/components/account/account.test.js.map +1 -0
  13. package/dist/components/account/add-guardian-dialog.cjs +90 -0
  14. package/dist/components/account/add-guardian-dialog.cjs.map +1 -0
  15. package/dist/components/account/add-guardian-dialog.d.cts +14 -0
  16. package/dist/components/account/add-guardian-dialog.d.ts +14 -0
  17. package/dist/components/account/add-guardian-dialog.js +66 -0
  18. package/dist/components/account/add-guardian-dialog.js.map +1 -0
  19. package/dist/components/account/device-approval-dialog.cjs +120 -0
  20. package/dist/components/account/device-approval-dialog.cjs.map +1 -0
  21. package/dist/components/account/device-approval-dialog.d.cts +14 -0
  22. package/dist/components/account/device-approval-dialog.d.ts +14 -0
  23. package/dist/components/account/device-approval-dialog.js +96 -0
  24. package/dist/components/account/device-approval-dialog.js.map +1 -0
  25. package/dist/components/account/devices-section.cjs +117 -0
  26. package/dist/components/account/devices-section.cjs.map +1 -0
  27. package/dist/components/account/devices-section.d.cts +12 -0
  28. package/dist/components/account/devices-section.d.ts +12 -0
  29. package/dist/components/account/devices-section.js +93 -0
  30. package/dist/components/account/devices-section.js.map +1 -0
  31. package/dist/components/account/email-code-entry.cjs +85 -0
  32. package/dist/components/account/email-code-entry.cjs.map +1 -0
  33. package/dist/components/account/email-code-entry.d.cts +11 -0
  34. package/dist/components/account/email-code-entry.d.ts +11 -0
  35. package/dist/components/account/email-code-entry.js +61 -0
  36. package/dist/components/account/email-code-entry.js.map +1 -0
  37. package/dist/components/account/guardian-recovery-section.cjs +161 -0
  38. package/dist/components/account/guardian-recovery-section.cjs.map +1 -0
  39. package/dist/components/account/guardian-recovery-section.d.cts +14 -0
  40. package/dist/components/account/guardian-recovery-section.d.ts +14 -0
  41. package/dist/components/account/guardian-recovery-section.js +130 -0
  42. package/dist/components/account/guardian-recovery-section.js.map +1 -0
  43. package/dist/components/account/input-otp.cjs +89 -0
  44. package/dist/components/account/input-otp.cjs.map +1 -0
  45. package/dist/components/account/input-otp.d.cts +37 -0
  46. package/dist/components/account/input-otp.d.ts +37 -0
  47. package/dist/components/account/input-otp.js +52 -0
  48. package/dist/components/account/input-otp.js.map +1 -0
  49. package/dist/components/account/wallet-types.cjs +17 -0
  50. package/dist/components/account/wallet-types.cjs.map +1 -0
  51. package/dist/components/account/wallet-types.d.cts +7 -0
  52. package/dist/components/account/wallet-types.d.ts +7 -0
  53. package/dist/components/account/wallet-types.js +1 -0
  54. package/dist/components/account/wallet-types.js.map +1 -0
  55. package/dist/components/button.d.cts +1 -1
  56. package/dist/components/button.d.ts +1 -1
  57. package/dist/index.cjs +56 -0
  58. package/dist/index.cjs.map +1 -1
  59. package/dist/index.d.cts +15 -1
  60. package/dist/index.d.ts +15 -1
  61. package/dist/index.js +40 -0
  62. package/dist/index.js.map +1 -1
  63. package/dist/utils/app-wallet.cjs +84 -0
  64. package/dist/utils/app-wallet.cjs.map +1 -0
  65. package/dist/utils/app-wallet.d.cts +26 -0
  66. package/dist/utils/app-wallet.d.ts +26 -0
  67. package/dist/utils/app-wallet.js +65 -0
  68. package/dist/utils/app-wallet.js.map +1 -0
  69. package/dist/utils/email-code.cjs +58 -0
  70. package/dist/utils/email-code.cjs.map +1 -0
  71. package/dist/utils/email-code.d.cts +32 -0
  72. package/dist/utils/email-code.d.ts +32 -0
  73. package/dist/utils/email-code.js +30 -0
  74. package/dist/utils/email-code.js.map +1 -0
  75. package/dist/utils/passkey-support.cjs +37 -0
  76. package/dist/utils/passkey-support.cjs.map +1 -0
  77. package/dist/utils/passkey-support.d.cts +7 -0
  78. package/dist/utils/passkey-support.d.ts +7 -0
  79. package/dist/utils/passkey-support.js +13 -0
  80. package/dist/utils/passkey-support.js.map +1 -0
  81. package/dist/utils/use-email-code.cjs +75 -0
  82. package/dist/utils/use-email-code.cjs.map +1 -0
  83. package/dist/utils/use-email-code.d.cts +20 -0
  84. package/dist/utils/use-email-code.d.ts +20 -0
  85. package/dist/utils/use-email-code.js +51 -0
  86. package/dist/utils/use-email-code.js.map +1 -0
  87. package/dist/utils/wallet-failure.cjs +63 -0
  88. package/dist/utils/wallet-failure.cjs.map +1 -0
  89. package/dist/utils/wallet-failure.d.cts +12 -0
  90. package/dist/utils/wallet-failure.d.ts +12 -0
  91. package/dist/utils/wallet-failure.js +38 -0
  92. package/dist/utils/wallet-failure.js.map +1 -0
  93. package/package.json +3 -1
@@ -0,0 +1,50 @@
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 account_section_exports = {};
21
+ __export(account_section_exports, {
22
+ AccountSection: () => AccountSection
23
+ });
24
+ module.exports = __toCommonJS(account_section_exports);
25
+ var import_jsx_runtime = require("react/jsx-runtime");
26
+ var import_cn = require("../../utils/cn.js");
27
+ function AccountSection({
28
+ icon: Icon,
29
+ iconColor = "text-primary",
30
+ iconBg = "bg-primary/10",
31
+ title,
32
+ description,
33
+ children
34
+ }) {
35
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-2xl border border-border/60 bg-card p-5 sm:p-6 space-y-5", children: [
36
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start gap-3", children: [
37
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("h-10 w-10 shrink-0 rounded-full flex items-center justify-center", iconBg), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: (0, import_cn.cn)("h-5 w-5", iconColor) }) }),
38
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
39
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "text-base font-bold text-foreground", children: title }),
40
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground mt-0.5", children: description })
41
+ ] })
42
+ ] }),
43
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-4", children })
44
+ ] });
45
+ }
46
+ // Annotate the CommonJS export names for ESM import in node:
47
+ 0 && (module.exports = {
48
+ AccountSection
49
+ });
50
+ //# sourceMappingURL=account-section.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/account/account-section.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ElementType, ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn.js\";\n\nexport interface AccountSectionProps {\n icon: ElementType;\n iconColor?: string;\n iconBg?: string;\n title: string;\n description: string;\n children: ReactNode;\n}\n\nexport function AccountSection({\n icon: Icon,\n iconColor = \"text-primary\",\n iconBg = \"bg-primary/10\",\n title,\n description,\n children,\n}: AccountSectionProps) {\n return (\n <div className=\"rounded-2xl border border-border/60 bg-card p-5 sm:p-6 space-y-5\">\n <div className=\"flex items-start gap-3\">\n <div className={cn(\"h-10 w-10 shrink-0 rounded-full flex items-center justify-center\", iconBg)}>\n <Icon className={cn(\"h-5 w-5\", iconColor)} />\n </div>\n <div>\n <h3 className=\"text-base font-bold text-foreground\">{title}</h3>\n <p className=\"text-sm text-muted-foreground mt-0.5\">{description}</p>\n </div>\n </div>\n <div className=\"space-y-4\">{children}</div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BU;AAvBV,gBAAmB;AAWZ,SAAS,eAAe;AAAA,EAC7B,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,SACE,6CAAC,SAAI,WAAU,oEACb;AAAA,iDAAC,SAAI,WAAU,0BACb;AAAA,kDAAC,SAAI,eAAW,cAAG,oEAAoE,MAAM,GAC3F,sDAAC,QAAK,eAAW,cAAG,WAAW,SAAS,GAAG,GAC7C;AAAA,MACA,6CAAC,SACC;AAAA,oDAAC,QAAG,WAAU,uCAAuC,iBAAM;AAAA,QAC3D,4CAAC,OAAE,WAAU,wCAAwC,uBAAY;AAAA,SACnE;AAAA,OACF;AAAA,IACA,4CAAC,SAAI,WAAU,aAAa,UAAS;AAAA,KACvC;AAEJ;","names":[]}
@@ -0,0 +1,14 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ElementType, ReactNode } from 'react';
3
+
4
+ interface AccountSectionProps {
5
+ icon: ElementType;
6
+ iconColor?: string;
7
+ iconBg?: string;
8
+ title: string;
9
+ description: string;
10
+ children: ReactNode;
11
+ }
12
+ declare function AccountSection({ icon: Icon, iconColor, iconBg, title, description, children, }: AccountSectionProps): react_jsx_runtime.JSX.Element;
13
+
14
+ export { AccountSection, type AccountSectionProps };
@@ -0,0 +1,14 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ElementType, ReactNode } from 'react';
3
+
4
+ interface AccountSectionProps {
5
+ icon: ElementType;
6
+ iconColor?: string;
7
+ iconBg?: string;
8
+ title: string;
9
+ description: string;
10
+ children: ReactNode;
11
+ }
12
+ declare function AccountSection({ icon: Icon, iconColor, iconBg, title, description, children, }: AccountSectionProps): react_jsx_runtime.JSX.Element;
13
+
14
+ export { AccountSection, type AccountSectionProps };
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { cn } from "../../utils/cn.js";
4
+ function AccountSection({
5
+ icon: Icon,
6
+ iconColor = "text-primary",
7
+ iconBg = "bg-primary/10",
8
+ title,
9
+ description,
10
+ children
11
+ }) {
12
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border/60 bg-card p-5 sm:p-6 space-y-5", children: [
13
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
14
+ /* @__PURE__ */ jsx("div", { className: cn("h-10 w-10 shrink-0 rounded-full flex items-center justify-center", iconBg), children: /* @__PURE__ */ jsx(Icon, { className: cn("h-5 w-5", iconColor) }) }),
15
+ /* @__PURE__ */ jsxs("div", { children: [
16
+ /* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-foreground", children: title }),
17
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-0.5", children: description })
18
+ ] })
19
+ ] }),
20
+ /* @__PURE__ */ jsx("div", { className: "space-y-4", children })
21
+ ] });
22
+ }
23
+ export {
24
+ AccountSection
25
+ };
26
+ //# sourceMappingURL=account-section.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/account/account-section.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ElementType, ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn.js\";\n\nexport interface AccountSectionProps {\n icon: ElementType;\n iconColor?: string;\n iconBg?: string;\n title: string;\n description: string;\n children: ReactNode;\n}\n\nexport function AccountSection({\n icon: Icon,\n iconColor = \"text-primary\",\n iconBg = \"bg-primary/10\",\n title,\n description,\n children,\n}: AccountSectionProps) {\n return (\n <div className=\"rounded-2xl border border-border/60 bg-card p-5 sm:p-6 space-y-5\">\n <div className=\"flex items-start gap-3\">\n <div className={cn(\"h-10 w-10 shrink-0 rounded-full flex items-center justify-center\", iconBg)}>\n <Icon className={cn(\"h-5 w-5\", iconColor)} />\n </div>\n <div>\n <h3 className=\"text-base font-bold text-foreground\">{title}</h3>\n <p className=\"text-sm text-muted-foreground mt-0.5\">{description}</p>\n </div>\n </div>\n <div className=\"space-y-4\">{children}</div>\n </div>\n );\n}\n"],"mappings":";AA0BU,cAEF,YAFE;AAvBV,SAAS,UAAU;AAWZ,SAAS,eAAe;AAAA,EAC7B,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,SACE,qBAAC,SAAI,WAAU,oEACb;AAAA,yBAAC,SAAI,WAAU,0BACb;AAAA,0BAAC,SAAI,WAAW,GAAG,oEAAoE,MAAM,GAC3F,8BAAC,QAAK,WAAW,GAAG,WAAW,SAAS,GAAG,GAC7C;AAAA,MACA,qBAAC,SACC;AAAA,4BAAC,QAAG,WAAU,uCAAuC,iBAAM;AAAA,QAC3D,oBAAC,OAAE,WAAU,wCAAwC,uBAAY;AAAA,SACnE;AAAA,OACF;AAAA,IACA,oBAAC,SAAI,WAAU,aAAa,UAAS;AAAA,KACvC;AAEJ;","names":[]}
@@ -0,0 +1,86 @@
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_lucide_react = require("lucide-react");
6
+ var import_account_section = require("./account-section.js");
7
+ var import_email_code_entry = require("./email-code-entry.js");
8
+ var import_devices_section = require("./devices-section.js");
9
+ var import_guardian_recovery_section = require("./guardian-recovery-section.js");
10
+ var import_email_code = require("../../utils/email-code.js");
11
+ const emailCode = (state) => ({
12
+ state: { ...import_email_code.initialEmailCodeState, ...state },
13
+ setCode: () => {
14
+ },
15
+ send: async () => true,
16
+ fail: () => {
17
+ },
18
+ verify: async () => true,
19
+ markReady: () => {
20
+ }
21
+ });
22
+ const wallet = {
23
+ getOwners: async () => [],
24
+ addDevice: async () => "",
25
+ removeDevice: async () => "",
26
+ getGuardians: async () => [],
27
+ getEscape: async () => ({ escapeType: "None", status: "None", readyAt: 0 }),
28
+ setFirstGuardian: async () => "",
29
+ cancelEscape: async () => ""
30
+ };
31
+ (0, import_bun_test.describe)("an account section", () => {
32
+ (0, import_bun_test.test)("shows its title, description and content", () => {
33
+ const html = (0, import_server.renderToStaticMarkup)(
34
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_account_section.AccountSection, { icon: import_lucide_react.Shield, title: "Devices", description: "Who can sign", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "content" }) })
35
+ );
36
+ (0, import_bun_test.expect)(html).toContain("Devices");
37
+ (0, import_bun_test.expect)(html).toContain("Who can sign");
38
+ (0, import_bun_test.expect)(html).toContain("content");
39
+ });
40
+ });
41
+ (0, import_bun_test.describe)("the email code entry", () => {
42
+ (0, import_bun_test.test)("says the code is being sent", () => {
43
+ (0, import_bun_test.expect)((0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_email_code_entry.EmailCodeEntry, { emailCode: emailCode({ status: "sending" }), onVerify: () => {
44
+ } }))).toContain("Sending code");
45
+ });
46
+ (0, import_bun_test.test)("shows an error", () => {
47
+ const html = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_email_code_entry.EmailCodeEntry, { emailCode: emailCode({ status: "ready", error: "Incorrect code" }), onVerify: () => {
48
+ } }));
49
+ (0, import_bun_test.expect)(html).toContain("Incorrect code");
50
+ });
51
+ (0, import_bun_test.test)("counts down before the code can be sent again", () => {
52
+ const html = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_email_code_entry.EmailCodeEntry, { emailCode: emailCode({ status: "ready", cooldown: 30 }), onVerify: () => {
53
+ } }));
54
+ (0, import_bun_test.expect)(html).toContain("resend in 30s");
55
+ (0, import_bun_test.expect)(html).not.toContain("resend the code");
56
+ });
57
+ (0, import_bun_test.test)("offers a resend once the cooldown is over, and keeps verify off until six digits", () => {
58
+ const html = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_email_code_entry.EmailCodeEntry, { emailCode: emailCode({ status: "ready", cooldown: 0, code: "123" }), onVerify: () => {
59
+ } }));
60
+ (0, import_bun_test.expect)(html).toContain("resend the code");
61
+ (0, import_bun_test.expect)(html).toMatch(/<button[^>]*disabled[^>]*>[^<]*Verify/);
62
+ });
63
+ });
64
+ (0, import_bun_test.describe)("the devices section", () => {
65
+ (0, import_bun_test.test)("starts with its heading and the add button while devices load", () => {
66
+ const html = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_devices_section.DevicesSection, { walletAddress: "0x1", wallet, loadSealed: () => null }));
67
+ (0, import_bun_test.expect)(html).toContain("Your devices");
68
+ (0, import_bun_test.expect)(html).toContain("Add");
69
+ });
70
+ });
71
+ (0, import_bun_test.describe)("the guardian recovery section", () => {
72
+ (0, import_bun_test.test)("links to the app's recovery page", () => {
73
+ const html = (0, import_server.renderToStaticMarkup)(
74
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_guardian_recovery_section.GuardianRecoverySection, { walletAddress: "0x1", wallet, loadSealed: () => null, guardianRecoveryAvailable: true, recoverHref: "/settings/recovery" })
75
+ );
76
+ (0, import_bun_test.expect)(html).toContain("Guardian recovery");
77
+ (0, import_bun_test.expect)(html).toContain('href="/settings/recovery"');
78
+ });
79
+ (0, import_bun_test.test)("defaults the recovery link to /recover", () => {
80
+ const html = (0, import_server.renderToStaticMarkup)(
81
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_guardian_recovery_section.GuardianRecoverySection, { walletAddress: "0x1", wallet, loadSealed: () => null, guardianRecoveryAvailable: false })
82
+ );
83
+ (0, import_bun_test.expect)(html).toContain('href="/recover"');
84
+ });
85
+ });
86
+ //# sourceMappingURL=account.test.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/account/account.test.tsx"],"sourcesContent":["import { describe, expect, test } from \"bun:test\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { Shield } from \"lucide-react\";\nimport { AccountSection } from \"./account-section.js\";\nimport { EmailCodeEntry } from \"./email-code-entry.js\";\nimport { DevicesSection } from \"./devices-section.js\";\nimport { GuardianRecoverySection } from \"./guardian-recovery-section.js\";\nimport { initialEmailCodeState, type EmailCodeState } from \"../../utils/email-code.js\";\nimport type { EmailCode } from \"../../utils/use-email-code.js\";\n\nconst emailCode = (state: Partial<EmailCodeState>): EmailCode => ({\n state: { ...initialEmailCodeState, ...state },\n setCode: () => {},\n send: async () => true,\n fail: () => {},\n verify: async () => true,\n markReady: () => {},\n});\n\nconst wallet = {\n getOwners: async () => [],\n addDevice: async () => \"\",\n removeDevice: async () => \"\",\n getGuardians: async () => [],\n getEscape: async () => ({ escapeType: \"None\", status: \"None\", readyAt: 0 }),\n setFirstGuardian: async () => \"\",\n cancelEscape: async () => \"\",\n} as never;\n\ndescribe(\"an account section\", () => {\n test(\"shows its title, description and content\", () => {\n const html = renderToStaticMarkup(\n <AccountSection icon={Shield} title=\"Devices\" description=\"Who can sign\">\n <p>content</p>\n </AccountSection>,\n );\n expect(html).toContain(\"Devices\");\n expect(html).toContain(\"Who can sign\");\n expect(html).toContain(\"content\");\n });\n});\n\ndescribe(\"the email code entry\", () => {\n test(\"says the code is being sent\", () => {\n expect(renderToStaticMarkup(<EmailCodeEntry emailCode={emailCode({ status: \"sending\" })} onVerify={() => {}} />)).toContain(\"Sending code\");\n });\n\n test(\"shows an error\", () => {\n const html = renderToStaticMarkup(<EmailCodeEntry emailCode={emailCode({ status: \"ready\", error: \"Incorrect code\" })} onVerify={() => {}} />);\n expect(html).toContain(\"Incorrect code\");\n });\n\n test(\"counts down before the code can be sent again\", () => {\n const html = renderToStaticMarkup(<EmailCodeEntry emailCode={emailCode({ status: \"ready\", cooldown: 30 })} onVerify={() => {}} />);\n expect(html).toContain(\"resend in 30s\");\n expect(html).not.toContain(\"resend the code\");\n });\n\n test(\"offers a resend once the cooldown is over, and keeps verify off until six digits\", () => {\n const html = renderToStaticMarkup(<EmailCodeEntry emailCode={emailCode({ status: \"ready\", cooldown: 0, code: \"123\" })} onVerify={() => {}} />);\n expect(html).toContain(\"resend the code\");\n expect(html).toMatch(/<button[^>]*disabled[^>]*>[^<]*Verify/);\n });\n});\n\ndescribe(\"the devices section\", () => {\n test(\"starts with its heading and the add button while devices load\", () => {\n const html = renderToStaticMarkup(<DevicesSection walletAddress=\"0x1\" wallet={wallet} loadSealed={() => null} />);\n expect(html).toContain(\"Your devices\");\n expect(html).toContain(\"Add\");\n });\n});\n\ndescribe(\"the guardian recovery section\", () => {\n test(\"links to the app's recovery page\", () => {\n const html = renderToStaticMarkup(\n <GuardianRecoverySection walletAddress=\"0x1\" wallet={wallet} loadSealed={() => null} guardianRecoveryAvailable recoverHref=\"/settings/recovery\" />,\n );\n expect(html).toContain(\"Guardian recovery\");\n expect(html).toContain('href=\"/settings/recovery\"');\n });\n\n test(\"defaults the recovery link to /recover\", () => {\n const html = renderToStaticMarkup(\n <GuardianRecoverySection walletAddress=\"0x1\" wallet={wallet} loadSealed={() => null} guardianRecoveryAvailable={false} />,\n );\n expect(html).toContain('href=\"/recover\"');\n });\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,85 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { describe, expect, test } from "bun:test";
3
+ import { renderToStaticMarkup } from "react-dom/server";
4
+ import { Shield } from "lucide-react";
5
+ import { AccountSection } from "./account-section.js";
6
+ import { EmailCodeEntry } from "./email-code-entry.js";
7
+ import { DevicesSection } from "./devices-section.js";
8
+ import { GuardianRecoverySection } from "./guardian-recovery-section.js";
9
+ import { initialEmailCodeState } from "../../utils/email-code.js";
10
+ const emailCode = (state) => ({
11
+ state: { ...initialEmailCodeState, ...state },
12
+ setCode: () => {
13
+ },
14
+ send: async () => true,
15
+ fail: () => {
16
+ },
17
+ verify: async () => true,
18
+ markReady: () => {
19
+ }
20
+ });
21
+ const wallet = {
22
+ getOwners: async () => [],
23
+ addDevice: async () => "",
24
+ removeDevice: async () => "",
25
+ getGuardians: async () => [],
26
+ getEscape: async () => ({ escapeType: "None", status: "None", readyAt: 0 }),
27
+ setFirstGuardian: async () => "",
28
+ cancelEscape: async () => ""
29
+ };
30
+ describe("an account section", () => {
31
+ test("shows its title, description and content", () => {
32
+ const html = renderToStaticMarkup(
33
+ /* @__PURE__ */ jsx(AccountSection, { icon: Shield, title: "Devices", description: "Who can sign", children: /* @__PURE__ */ jsx("p", { children: "content" }) })
34
+ );
35
+ expect(html).toContain("Devices");
36
+ expect(html).toContain("Who can sign");
37
+ expect(html).toContain("content");
38
+ });
39
+ });
40
+ describe("the email code entry", () => {
41
+ test("says the code is being sent", () => {
42
+ expect(renderToStaticMarkup(/* @__PURE__ */ jsx(EmailCodeEntry, { emailCode: emailCode({ status: "sending" }), onVerify: () => {
43
+ } }))).toContain("Sending code");
44
+ });
45
+ test("shows an error", () => {
46
+ const html = renderToStaticMarkup(/* @__PURE__ */ jsx(EmailCodeEntry, { emailCode: emailCode({ status: "ready", error: "Incorrect code" }), onVerify: () => {
47
+ } }));
48
+ expect(html).toContain("Incorrect code");
49
+ });
50
+ test("counts down before the code can be sent again", () => {
51
+ const html = renderToStaticMarkup(/* @__PURE__ */ jsx(EmailCodeEntry, { emailCode: emailCode({ status: "ready", cooldown: 30 }), onVerify: () => {
52
+ } }));
53
+ expect(html).toContain("resend in 30s");
54
+ expect(html).not.toContain("resend the code");
55
+ });
56
+ test("offers a resend once the cooldown is over, and keeps verify off until six digits", () => {
57
+ const html = renderToStaticMarkup(/* @__PURE__ */ jsx(EmailCodeEntry, { emailCode: emailCode({ status: "ready", cooldown: 0, code: "123" }), onVerify: () => {
58
+ } }));
59
+ expect(html).toContain("resend the code");
60
+ expect(html).toMatch(/<button[^>]*disabled[^>]*>[^<]*Verify/);
61
+ });
62
+ });
63
+ describe("the devices section", () => {
64
+ test("starts with its heading and the add button while devices load", () => {
65
+ const html = renderToStaticMarkup(/* @__PURE__ */ jsx(DevicesSection, { walletAddress: "0x1", wallet, loadSealed: () => null }));
66
+ expect(html).toContain("Your devices");
67
+ expect(html).toContain("Add");
68
+ });
69
+ });
70
+ describe("the guardian recovery section", () => {
71
+ test("links to the app's recovery page", () => {
72
+ const html = renderToStaticMarkup(
73
+ /* @__PURE__ */ jsx(GuardianRecoverySection, { walletAddress: "0x1", wallet, loadSealed: () => null, guardianRecoveryAvailable: true, recoverHref: "/settings/recovery" })
74
+ );
75
+ expect(html).toContain("Guardian recovery");
76
+ expect(html).toContain('href="/settings/recovery"');
77
+ });
78
+ test("defaults the recovery link to /recover", () => {
79
+ const html = renderToStaticMarkup(
80
+ /* @__PURE__ */ jsx(GuardianRecoverySection, { walletAddress: "0x1", wallet, loadSealed: () => null, guardianRecoveryAvailable: false })
81
+ );
82
+ expect(html).toContain('href="/recover"');
83
+ });
84
+ });
85
+ //# sourceMappingURL=account.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/account/account.test.tsx"],"sourcesContent":["import { describe, expect, test } from \"bun:test\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { Shield } from \"lucide-react\";\nimport { AccountSection } from \"./account-section.js\";\nimport { EmailCodeEntry } from \"./email-code-entry.js\";\nimport { DevicesSection } from \"./devices-section.js\";\nimport { GuardianRecoverySection } from \"./guardian-recovery-section.js\";\nimport { initialEmailCodeState, type EmailCodeState } from \"../../utils/email-code.js\";\nimport type { EmailCode } from \"../../utils/use-email-code.js\";\n\nconst emailCode = (state: Partial<EmailCodeState>): EmailCode => ({\n state: { ...initialEmailCodeState, ...state },\n setCode: () => {},\n send: async () => true,\n fail: () => {},\n verify: async () => true,\n markReady: () => {},\n});\n\nconst wallet = {\n getOwners: async () => [],\n addDevice: async () => \"\",\n removeDevice: async () => \"\",\n getGuardians: async () => [],\n getEscape: async () => ({ escapeType: \"None\", status: \"None\", readyAt: 0 }),\n setFirstGuardian: async () => \"\",\n cancelEscape: async () => \"\",\n} as never;\n\ndescribe(\"an account section\", () => {\n test(\"shows its title, description and content\", () => {\n const html = renderToStaticMarkup(\n <AccountSection icon={Shield} title=\"Devices\" description=\"Who can sign\">\n <p>content</p>\n </AccountSection>,\n );\n expect(html).toContain(\"Devices\");\n expect(html).toContain(\"Who can sign\");\n expect(html).toContain(\"content\");\n });\n});\n\ndescribe(\"the email code entry\", () => {\n test(\"says the code is being sent\", () => {\n expect(renderToStaticMarkup(<EmailCodeEntry emailCode={emailCode({ status: \"sending\" })} onVerify={() => {}} />)).toContain(\"Sending code\");\n });\n\n test(\"shows an error\", () => {\n const html = renderToStaticMarkup(<EmailCodeEntry emailCode={emailCode({ status: \"ready\", error: \"Incorrect code\" })} onVerify={() => {}} />);\n expect(html).toContain(\"Incorrect code\");\n });\n\n test(\"counts down before the code can be sent again\", () => {\n const html = renderToStaticMarkup(<EmailCodeEntry emailCode={emailCode({ status: \"ready\", cooldown: 30 })} onVerify={() => {}} />);\n expect(html).toContain(\"resend in 30s\");\n expect(html).not.toContain(\"resend the code\");\n });\n\n test(\"offers a resend once the cooldown is over, and keeps verify off until six digits\", () => {\n const html = renderToStaticMarkup(<EmailCodeEntry emailCode={emailCode({ status: \"ready\", cooldown: 0, code: \"123\" })} onVerify={() => {}} />);\n expect(html).toContain(\"resend the code\");\n expect(html).toMatch(/<button[^>]*disabled[^>]*>[^<]*Verify/);\n });\n});\n\ndescribe(\"the devices section\", () => {\n test(\"starts with its heading and the add button while devices load\", () => {\n const html = renderToStaticMarkup(<DevicesSection walletAddress=\"0x1\" wallet={wallet} loadSealed={() => null} />);\n expect(html).toContain(\"Your devices\");\n expect(html).toContain(\"Add\");\n });\n});\n\ndescribe(\"the guardian recovery section\", () => {\n test(\"links to the app's recovery page\", () => {\n const html = renderToStaticMarkup(\n <GuardianRecoverySection walletAddress=\"0x1\" wallet={wallet} loadSealed={() => null} guardianRecoveryAvailable recoverHref=\"/settings/recovery\" />,\n );\n expect(html).toContain(\"Guardian recovery\");\n expect(html).toContain('href=\"/settings/recovery\"');\n });\n\n test(\"defaults the recovery link to /recover\", () => {\n const html = renderToStaticMarkup(\n <GuardianRecoverySection walletAddress=\"0x1\" wallet={wallet} loadSealed={() => null} guardianRecoveryAvailable={false} />,\n );\n expect(html).toContain('href=\"/recover\"');\n });\n});\n"],"mappings":"AAiCQ;AAjCR,SAAS,UAAU,QAAQ,YAAY;AACvC,SAAS,4BAA4B;AACrC,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,+BAA+B;AACxC,SAAS,6BAAkD;AAG3D,MAAM,YAAY,CAAC,WAA+C;AAAA,EAChE,OAAO,EAAE,GAAG,uBAAuB,GAAG,MAAM;AAAA,EAC5C,SAAS,MAAM;AAAA,EAAC;AAAA,EAChB,MAAM,YAAY;AAAA,EAClB,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,QAAQ,YAAY;AAAA,EACpB,WAAW,MAAM;AAAA,EAAC;AACpB;AAEA,MAAM,SAAS;AAAA,EACb,WAAW,YAAY,CAAC;AAAA,EACxB,WAAW,YAAY;AAAA,EACvB,cAAc,YAAY;AAAA,EAC1B,cAAc,YAAY,CAAC;AAAA,EAC3B,WAAW,aAAa,EAAE,YAAY,QAAQ,QAAQ,QAAQ,SAAS,EAAE;AAAA,EACzE,kBAAkB,YAAY;AAAA,EAC9B,cAAc,YAAY;AAC5B;AAEA,SAAS,sBAAsB,MAAM;AACnC,OAAK,4CAA4C,MAAM;AACrD,UAAM,OAAO;AAAA,MACX,oBAAC,kBAAe,MAAM,QAAQ,OAAM,WAAU,aAAY,gBACxD,8BAAC,OAAE,qBAAO,GACZ;AAAA,IACF;AACA,WAAO,IAAI,EAAE,UAAU,SAAS;AAChC,WAAO,IAAI,EAAE,UAAU,cAAc;AACrC,WAAO,IAAI,EAAE,UAAU,SAAS;AAAA,EAClC,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,MAAM;AACrC,OAAK,+BAA+B,MAAM;AACxC,WAAO,qBAAqB,oBAAC,kBAAe,WAAW,UAAU,EAAE,QAAQ,UAAU,CAAC,GAAG,UAAU,MAAM;AAAA,IAAC,GAAG,CAAE,CAAC,EAAE,UAAU,cAAc;AAAA,EAC5I,CAAC;AAED,OAAK,kBAAkB,MAAM;AAC3B,UAAM,OAAO,qBAAqB,oBAAC,kBAAe,WAAW,UAAU,EAAE,QAAQ,SAAS,OAAO,iBAAiB,CAAC,GAAG,UAAU,MAAM;AAAA,IAAC,GAAG,CAAE;AAC5I,WAAO,IAAI,EAAE,UAAU,gBAAgB;AAAA,EACzC,CAAC;AAED,OAAK,iDAAiD,MAAM;AAC1D,UAAM,OAAO,qBAAqB,oBAAC,kBAAe,WAAW,UAAU,EAAE,QAAQ,SAAS,UAAU,GAAG,CAAC,GAAG,UAAU,MAAM;AAAA,IAAC,GAAG,CAAE;AACjI,WAAO,IAAI,EAAE,UAAU,eAAe;AACtC,WAAO,IAAI,EAAE,IAAI,UAAU,iBAAiB;AAAA,EAC9C,CAAC;AAED,OAAK,oFAAoF,MAAM;AAC7F,UAAM,OAAO,qBAAqB,oBAAC,kBAAe,WAAW,UAAU,EAAE,QAAQ,SAAS,UAAU,GAAG,MAAM,MAAM,CAAC,GAAG,UAAU,MAAM;AAAA,IAAC,GAAG,CAAE;AAC7I,WAAO,IAAI,EAAE,UAAU,iBAAiB;AACxC,WAAO,IAAI,EAAE,QAAQ,uCAAuC;AAAA,EAC9D,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,MAAM;AACpC,OAAK,iEAAiE,MAAM;AAC1E,UAAM,OAAO,qBAAqB,oBAAC,kBAAe,eAAc,OAAM,QAAgB,YAAY,MAAM,MAAM,CAAE;AAChH,WAAO,IAAI,EAAE,UAAU,cAAc;AACrC,WAAO,IAAI,EAAE,UAAU,KAAK;AAAA,EAC9B,CAAC;AACH,CAAC;AAED,SAAS,iCAAiC,MAAM;AAC9C,OAAK,oCAAoC,MAAM;AAC7C,UAAM,OAAO;AAAA,MACX,oBAAC,2BAAwB,eAAc,OAAM,QAAgB,YAAY,MAAM,MAAM,2BAAyB,MAAC,aAAY,sBAAqB;AAAA,IAClJ;AACA,WAAO,IAAI,EAAE,UAAU,mBAAmB;AAC1C,WAAO,IAAI,EAAE,UAAU,2BAA2B;AAAA,EACpD,CAAC;AAED,OAAK,0CAA0C,MAAM;AACnD,UAAM,OAAO;AAAA,MACX,oBAAC,2BAAwB,eAAc,OAAM,QAAgB,YAAY,MAAM,MAAM,2BAA2B,OAAO;AAAA,IACzH;AACA,WAAO,IAAI,EAAE,UAAU,iBAAiB;AAAA,EAC1C,CAAC;AACH,CAAC;","names":[]}
@@ -0,0 +1,90 @@
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 add_guardian_dialog_exports = {};
21
+ __export(add_guardian_dialog_exports, {
22
+ AddGuardianDialog: () => AddGuardianDialog
23
+ });
24
+ module.exports = __toCommonJS(add_guardian_dialog_exports);
25
+ var import_jsx_runtime = require("react/jsx-runtime");
26
+ var import_react = require("react");
27
+ var import_lucide_react = require("lucide-react");
28
+ var import_starknet = require("@medialane/sdk/starknet");
29
+ var import_button = require("../button.js");
30
+ var import_input = require("../input.js");
31
+ var import_dialog = require("../dialog.js");
32
+ var import_describe_error = require("../../utils/describe-error.js");
33
+ function AddGuardianDialog({ open, onOpenChange, sealed, onAdded, wallet }) {
34
+ const [pubkey, setPubkey] = (0, import_react.useState)("");
35
+ const [busy, setBusy] = (0, import_react.useState)(false);
36
+ const [error, setError] = (0, import_react.useState)(null);
37
+ const handleAdd = async () => {
38
+ const trimmed = pubkey.trim();
39
+ if (!(0, import_starknet.isValidStarknetAddress)(trimmed)) {
40
+ setError("Enter a valid Stark-curve public key.");
41
+ return;
42
+ }
43
+ setBusy(true);
44
+ setError(null);
45
+ try {
46
+ await wallet.setFirstGuardian(sealed, trimmed);
47
+ onOpenChange(false);
48
+ setPubkey("");
49
+ onAdded();
50
+ } catch (e) {
51
+ setError((0, import_describe_error.describeError)(e, "We couldn't add that guardian. Please try again.").message);
52
+ } finally {
53
+ setBusy(false);
54
+ }
55
+ };
56
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog, { open, onOpenChange: (next) => {
57
+ if (!busy) onOpenChange(next);
58
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dialog.DialogContent, { className: "sm:max-w-sm", children: [
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dialog.DialogHeader, { children: [
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dialog.DialogTitle, { className: "flex items-center gap-2", children: [
61
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Shield, { className: "h-4 w-4" }),
62
+ " Add a guardian"
63
+ ] }),
64
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.DialogDescription, { children: "A guardian can help you recover this wallet if you lose this device, but can never move your funds. Paste the public key of a wallet you control \u2014 another device's Media Wallet, for example. You can only set this up once from here; changing it later isn't supported in this app yet." })
65
+ ] }),
66
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-3", children: [
67
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
+ import_input.Input,
69
+ {
70
+ value: pubkey,
71
+ onChange: (e) => setPubkey(e.target.value),
72
+ placeholder: "0x\u2026",
73
+ disabled: busy,
74
+ className: "font-mono text-xs",
75
+ onKeyDown: (e) => e.key === "Enter" && pubkey.trim() && void handleAdd()
76
+ }
77
+ ),
78
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-destructive", children: error }),
79
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_button.Button, { onClick: handleAdd, disabled: busy || !pubkey.trim(), className: "w-full", children: [
80
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Loader2, { className: "mr-1.5 h-3.5 w-3.5 animate-spin" }) : null,
81
+ busy ? "Confirm with passkey\u2026" : "Add guardian"
82
+ ] })
83
+ ] })
84
+ ] }) });
85
+ }
86
+ // Annotate the CommonJS export names for ESM import in node:
87
+ 0 && (module.exports = {
88
+ AddGuardianDialog
89
+ });
90
+ //# sourceMappingURL=add-guardian-dialog.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/account/add-guardian-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Shield, Loader2 } from \"lucide-react\";\nimport { isValidStarknetAddress, type SealedOwner } from \"@medialane/sdk/starknet\";\nimport { Button } from \"../button.js\";\nimport { Input } from \"../input.js\";\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from \"../dialog.js\";\nimport { describeError } from \"../../utils/describe-error.js\";\nimport type { GuardianWallet } from \"./wallet-types.js\";\n\nexport interface AddGuardianDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n sealed: SealedOwner;\n onAdded: () => void;\n wallet: Pick<GuardianWallet, \"setFirstGuardian\">;\n}\n\nexport function AddGuardianDialog({ open, onOpenChange, sealed, onAdded, wallet }: AddGuardianDialogProps) {\n const [pubkey, setPubkey] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleAdd = async () => {\n const trimmed = pubkey.trim();\n if (!isValidStarknetAddress(trimmed)) {\n setError(\"Enter a valid Stark-curve public key.\");\n return;\n }\n setBusy(true);\n setError(null);\n try {\n await wallet.setFirstGuardian(sealed, trimmed);\n onOpenChange(false);\n setPubkey(\"\");\n onAdded();\n } catch (e) {\n setError(describeError(e, \"We couldn't add that guardian. Please try again.\").message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={(next) => { if (!busy) onOpenChange(next); }}>\n <DialogContent className=\"sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <Shield className=\"h-4 w-4\" /> Add a guardian\n </DialogTitle>\n <DialogDescription>\n A guardian can help you recover this wallet if you lose this device, but can\n never move your funds. Paste the public key of a wallet you control — another\n device&apos;s Media Wallet, for example. You can only set this up once from here;\n changing it later isn&apos;t supported in this app yet.\n </DialogDescription>\n </DialogHeader>\n <div className=\"space-y-3\">\n <Input\n value={pubkey}\n onChange={(e) => setPubkey(e.target.value)}\n placeholder=\"0x…\"\n disabled={busy}\n className=\"font-mono text-xs\"\n onKeyDown={(e) => e.key === \"Enter\" && pubkey.trim() && void handleAdd()}\n />\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n <Button onClick={handleAdd} disabled={busy || !pubkey.trim()} className=\"w-full\">\n {busy ? <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" /> : null}\n {busy ? \"Confirm with passkey…\" : \"Add guardian\"}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgDU;AA9CV,mBAAyB;AACzB,0BAAgC;AAChC,sBAAyD;AACzD,oBAAuB;AACvB,mBAAsB;AACtB,oBAAoF;AACpF,4BAA8B;AAWvB,SAAS,kBAAkB,EAAE,MAAM,cAAc,QAAQ,SAAS,OAAO,GAA2B;AACzG,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAS,EAAE;AACvC,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB,IAAI;AAEtD,QAAM,YAAY,YAAY;AAC5B,UAAM,UAAU,OAAO,KAAK;AAC5B,QAAI,KAAC,wCAAuB,OAAO,GAAG;AACpC,eAAS,uCAAuC;AAChD;AAAA,IACF;AACA,YAAQ,IAAI;AACZ,aAAS,IAAI;AACb,QAAI;AACF,YAAM,OAAO,iBAAiB,QAAQ,OAAO;AAC7C,mBAAa,KAAK;AAClB,gBAAU,EAAE;AACZ,cAAQ;AAAA,IACV,SAAS,GAAG;AACV,mBAAS,qCAAc,GAAG,kDAAkD,EAAE,OAAO;AAAA,IACvF,UAAE;AACA,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAEA,SACE,4CAAC,wBAAO,MAAY,cAAc,CAAC,SAAS;AAAE,QAAI,CAAC,KAAM,cAAa,IAAI;AAAA,EAAG,GAC3E,uDAAC,+BAAc,WAAU,eACvB;AAAA,iDAAC,8BACC;AAAA,mDAAC,6BAAY,WAAU,2BACrB;AAAA,oDAAC,8BAAO,WAAU,WAAU;AAAA,QAAE;AAAA,SAChC;AAAA,MACA,4CAAC,mCAAkB,6SAKnB;AAAA,OACF;AAAA,IACA,6CAAC,SAAI,WAAU,aACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,UAAU,EAAE,OAAO,KAAK;AAAA,UACzC,aAAY;AAAA,UACZ,UAAU;AAAA,UACV,WAAU;AAAA,UACV,WAAW,CAAC,MAAM,EAAE,QAAQ,WAAW,OAAO,KAAK,KAAK,KAAK,UAAU;AAAA;AAAA,MACzE;AAAA,MACC,SAAS,4CAAC,OAAE,WAAU,4BAA4B,iBAAM;AAAA,MACzD,6CAAC,wBAAO,SAAS,WAAW,UAAU,QAAQ,CAAC,OAAO,KAAK,GAAG,WAAU,UACrE;AAAA,eAAO,4CAAC,+BAAQ,WAAU,mCAAkC,IAAK;AAAA,QACjE,OAAO,+BAA0B;AAAA,SACpC;AAAA,OACF;AAAA,KACF,GACF;AAEJ;","names":[]}
@@ -0,0 +1,14 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { SealedOwner } from '@medialane/sdk/starknet';
3
+ import { GuardianWallet } from './wallet-types.cjs';
4
+
5
+ interface AddGuardianDialogProps {
6
+ open: boolean;
7
+ onOpenChange: (open: boolean) => void;
8
+ sealed: SealedOwner;
9
+ onAdded: () => void;
10
+ wallet: Pick<GuardianWallet, "setFirstGuardian">;
11
+ }
12
+ declare function AddGuardianDialog({ open, onOpenChange, sealed, onAdded, wallet }: AddGuardianDialogProps): react_jsx_runtime.JSX.Element;
13
+
14
+ export { AddGuardianDialog, type AddGuardianDialogProps };
@@ -0,0 +1,14 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { SealedOwner } from '@medialane/sdk/starknet';
3
+ import { GuardianWallet } from './wallet-types.js';
4
+
5
+ interface AddGuardianDialogProps {
6
+ open: boolean;
7
+ onOpenChange: (open: boolean) => void;
8
+ sealed: SealedOwner;
9
+ onAdded: () => void;
10
+ wallet: Pick<GuardianWallet, "setFirstGuardian">;
11
+ }
12
+ declare function AddGuardianDialog({ open, onOpenChange, sealed, onAdded, wallet }: AddGuardianDialogProps): react_jsx_runtime.JSX.Element;
13
+
14
+ export { AddGuardianDialog, type AddGuardianDialogProps };
@@ -0,0 +1,66 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Shield, Loader2 } from "lucide-react";
5
+ import { isValidStarknetAddress } from "@medialane/sdk/starknet";
6
+ import { Button } from "../button.js";
7
+ import { Input } from "../input.js";
8
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "../dialog.js";
9
+ import { describeError } from "../../utils/describe-error.js";
10
+ function AddGuardianDialog({ open, onOpenChange, sealed, onAdded, wallet }) {
11
+ const [pubkey, setPubkey] = useState("");
12
+ const [busy, setBusy] = useState(false);
13
+ const [error, setError] = useState(null);
14
+ const handleAdd = async () => {
15
+ const trimmed = pubkey.trim();
16
+ if (!isValidStarknetAddress(trimmed)) {
17
+ setError("Enter a valid Stark-curve public key.");
18
+ return;
19
+ }
20
+ setBusy(true);
21
+ setError(null);
22
+ try {
23
+ await wallet.setFirstGuardian(sealed, trimmed);
24
+ onOpenChange(false);
25
+ setPubkey("");
26
+ onAdded();
27
+ } catch (e) {
28
+ setError(describeError(e, "We couldn't add that guardian. Please try again.").message);
29
+ } finally {
30
+ setBusy(false);
31
+ }
32
+ };
33
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (next) => {
34
+ if (!busy) onOpenChange(next);
35
+ }, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-sm", children: [
36
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
37
+ /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
38
+ /* @__PURE__ */ jsx(Shield, { className: "h-4 w-4" }),
39
+ " Add a guardian"
40
+ ] }),
41
+ /* @__PURE__ */ jsx(DialogDescription, { children: "A guardian can help you recover this wallet if you lose this device, but can never move your funds. Paste the public key of a wallet you control \u2014 another device's Media Wallet, for example. You can only set this up once from here; changing it later isn't supported in this app yet." })
42
+ ] }),
43
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
44
+ /* @__PURE__ */ jsx(
45
+ Input,
46
+ {
47
+ value: pubkey,
48
+ onChange: (e) => setPubkey(e.target.value),
49
+ placeholder: "0x\u2026",
50
+ disabled: busy,
51
+ className: "font-mono text-xs",
52
+ onKeyDown: (e) => e.key === "Enter" && pubkey.trim() && void handleAdd()
53
+ }
54
+ ),
55
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }),
56
+ /* @__PURE__ */ jsxs(Button, { onClick: handleAdd, disabled: busy || !pubkey.trim(), className: "w-full", children: [
57
+ busy ? /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-3.5 w-3.5 animate-spin" }) : null,
58
+ busy ? "Confirm with passkey\u2026" : "Add guardian"
59
+ ] })
60
+ ] })
61
+ ] }) });
62
+ }
63
+ export {
64
+ AddGuardianDialog
65
+ };
66
+ //# sourceMappingURL=add-guardian-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/account/add-guardian-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Shield, Loader2 } from \"lucide-react\";\nimport { isValidStarknetAddress, type SealedOwner } from \"@medialane/sdk/starknet\";\nimport { Button } from \"../button.js\";\nimport { Input } from \"../input.js\";\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from \"../dialog.js\";\nimport { describeError } from \"../../utils/describe-error.js\";\nimport type { GuardianWallet } from \"./wallet-types.js\";\n\nexport interface AddGuardianDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n sealed: SealedOwner;\n onAdded: () => void;\n wallet: Pick<GuardianWallet, \"setFirstGuardian\">;\n}\n\nexport function AddGuardianDialog({ open, onOpenChange, sealed, onAdded, wallet }: AddGuardianDialogProps) {\n const [pubkey, setPubkey] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleAdd = async () => {\n const trimmed = pubkey.trim();\n if (!isValidStarknetAddress(trimmed)) {\n setError(\"Enter a valid Stark-curve public key.\");\n return;\n }\n setBusy(true);\n setError(null);\n try {\n await wallet.setFirstGuardian(sealed, trimmed);\n onOpenChange(false);\n setPubkey(\"\");\n onAdded();\n } catch (e) {\n setError(describeError(e, \"We couldn't add that guardian. Please try again.\").message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={(next) => { if (!busy) onOpenChange(next); }}>\n <DialogContent className=\"sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <Shield className=\"h-4 w-4\" /> Add a guardian\n </DialogTitle>\n <DialogDescription>\n A guardian can help you recover this wallet if you lose this device, but can\n never move your funds. Paste the public key of a wallet you control — another\n device&apos;s Media Wallet, for example. You can only set this up once from here;\n changing it later isn&apos;t supported in this app yet.\n </DialogDescription>\n </DialogHeader>\n <div className=\"space-y-3\">\n <Input\n value={pubkey}\n onChange={(e) => setPubkey(e.target.value)}\n placeholder=\"0x…\"\n disabled={busy}\n className=\"font-mono text-xs\"\n onKeyDown={(e) => e.key === \"Enter\" && pubkey.trim() && void handleAdd()}\n />\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n <Button onClick={handleAdd} disabled={busy || !pubkey.trim()} className=\"w-full\">\n {busy ? <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" /> : null}\n {busy ? \"Confirm with passkey…\" : \"Add guardian\"}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":";AAgDU,SACE,KADF;AA9CV,SAAS,gBAAgB;AACzB,SAAS,QAAQ,eAAe;AAChC,SAAS,8BAAgD;AACzD,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,QAAQ,eAAe,cAAc,aAAa,yBAAyB;AACpF,SAAS,qBAAqB;AAWvB,SAAS,kBAAkB,EAAE,MAAM,cAAc,QAAQ,SAAS,OAAO,GAA2B;AACzG,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,EAAE;AACvC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,QAAM,YAAY,YAAY;AAC5B,UAAM,UAAU,OAAO,KAAK;AAC5B,QAAI,CAAC,uBAAuB,OAAO,GAAG;AACpC,eAAS,uCAAuC;AAChD;AAAA,IACF;AACA,YAAQ,IAAI;AACZ,aAAS,IAAI;AACb,QAAI;AACF,YAAM,OAAO,iBAAiB,QAAQ,OAAO;AAC7C,mBAAa,KAAK;AAClB,gBAAU,EAAE;AACZ,cAAQ;AAAA,IACV,SAAS,GAAG;AACV,eAAS,cAAc,GAAG,kDAAkD,EAAE,OAAO;AAAA,IACvF,UAAE;AACA,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAEA,SACE,oBAAC,UAAO,MAAY,cAAc,CAAC,SAAS;AAAE,QAAI,CAAC,KAAM,cAAa,IAAI;AAAA,EAAG,GAC3E,+BAAC,iBAAc,WAAU,eACvB;AAAA,yBAAC,gBACC;AAAA,2BAAC,eAAY,WAAU,2BACrB;AAAA,4BAAC,UAAO,WAAU,WAAU;AAAA,QAAE;AAAA,SAChC;AAAA,MACA,oBAAC,qBAAkB,6SAKnB;AAAA,OACF;AAAA,IACA,qBAAC,SAAI,WAAU,aACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,UAAU,EAAE,OAAO,KAAK;AAAA,UACzC,aAAY;AAAA,UACZ,UAAU;AAAA,UACV,WAAU;AAAA,UACV,WAAW,CAAC,MAAM,EAAE,QAAQ,WAAW,OAAO,KAAK,KAAK,KAAK,UAAU;AAAA;AAAA,MACzE;AAAA,MACC,SAAS,oBAAC,OAAE,WAAU,4BAA4B,iBAAM;AAAA,MACzD,qBAAC,UAAO,SAAS,WAAW,UAAU,QAAQ,CAAC,OAAO,KAAK,GAAG,WAAU,UACrE;AAAA,eAAO,oBAAC,WAAQ,WAAU,mCAAkC,IAAK;AAAA,QACjE,OAAO,+BAA0B;AAAA,SACpC;AAAA,OACF;AAAA,KACF,GACF;AAEJ;","names":[]}