@goodcash/react 0.0.0-stage → 0.1.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.
@@ -0,0 +1,123 @@
1
+ import React from 'react';
2
+ import { GoodCashOptions, GoodCash, Bank, GoodCashError, CashOutArgs, CashOut, CashOutStep, Quote, Signer } from '@goodcash/sdk';
3
+
4
+ /** Look and feel. The default is GoodCash's own sticker-pop style; every colour can be changed. */
5
+ interface GoodCashTheme {
6
+ /** Page/panel background */
7
+ background?: string;
8
+ /** Cards and inputs */
9
+ surface?: string;
10
+ /** Text and borders */
11
+ ink?: string;
12
+ /** Main buttons */
13
+ accent?: string;
14
+ /** Text on main buttons */
15
+ accentInk?: string;
16
+ /** Highlights (amount chips) */
17
+ highlight?: string;
18
+ /** Success */
19
+ success?: string;
20
+ /** Corner radius in px */
21
+ radius?: number;
22
+ /** CSS font-family. Defaults to the app's system font stack (no web fonts are loaded for you). */
23
+ font?: string;
24
+ /** 'auto' follows the device setting */
25
+ mode?: 'light' | 'dark' | 'auto';
26
+ }
27
+ declare function themeVars(t?: GoodCashTheme, dark?: boolean): Record<string, string>;
28
+
29
+ interface Ctx {
30
+ client: GoodCash;
31
+ theme: GoodCashTheme;
32
+ }
33
+ interface GoodCashProviderProps extends Omit<GoodCashOptions, 'secretKey'> {
34
+ /** Your publishable key (gc_pk_...). Never a secret key. */
35
+ publishableKey: string;
36
+ theme?: GoodCashTheme;
37
+ /** Advanced/tests: bring your own client */
38
+ client?: GoodCash;
39
+ children: React.ReactNode;
40
+ }
41
+ declare function GoodCashProvider({ publishableKey, appId, baseUrl, rpcUrl, fetch, theme, client, children }: GoodCashProviderProps): React.JSX.Element;
42
+ declare function useGoodCash(): Ctx;
43
+
44
+ /** A live quote for an amount: waits until typing pauses, then refreshes every 25 seconds. */
45
+ declare function useQuote(amountG: string | number | null | undefined, opts?: {
46
+ debounceMs?: number;
47
+ refreshMs?: number;
48
+ }): {
49
+ quote: Quote | null;
50
+ error: GoodCashError | null;
51
+ loading: boolean;
52
+ };
53
+ declare function useBanks(): {
54
+ banks: Bank[];
55
+ error: GoodCashError | null;
56
+ loading: boolean;
57
+ };
58
+ /** Looks up the account holder's name as soon as a full account number is typed. */
59
+ declare function useVerifyAccount(bankCode: string, accountNumber: string): {
60
+ accountName: string | null;
61
+ error: GoodCashError | null;
62
+ loading: boolean;
63
+ };
64
+ /** Runs the whole cash out (create, check, sign, report). */
65
+ declare function useCashOut(): {
66
+ start: (args: Omit<CashOutArgs, "onStep">, onStep?: CashOutArgs["onStep"]) => Promise<{
67
+ cashOut: CashOut;
68
+ txHash: string;
69
+ } | null>;
70
+ step: CashOutStep | null;
71
+ cashOut: CashOut | null;
72
+ error: GoodCashError | null;
73
+ reset: () => void;
74
+ };
75
+ /** Follows a cash out until it is paid (or failed, refunded, expired). */
76
+ declare function useCashOutStatus(id: string | null | undefined): {
77
+ cashOut: CashOut | null;
78
+ error: GoodCashError | null;
79
+ };
80
+
81
+ type CashOutEvent = {
82
+ type: 'cashout.created';
83
+ cashOut: CashOut;
84
+ } | {
85
+ type: 'cashout.sent';
86
+ cashOut: CashOut;
87
+ } | {
88
+ type: 'cashout.paid';
89
+ cashOut: CashOut;
90
+ } | {
91
+ type: 'cashout.failed';
92
+ cashOut: CashOut;
93
+ } | {
94
+ type: 'closed';
95
+ };
96
+ interface CashOutFlowProps {
97
+ /** The customer's wallet. Defaults to the browser wallet (window.ethereum) when there is one. */
98
+ signer?: Signer;
99
+ /** The wallet address, when the signer cannot tell (send functions) */
100
+ wallet?: `0x${string}`;
101
+ defaultAmountG?: string | number;
102
+ partnerRef?: string;
103
+ onEvent?: (e: CashOutEvent) => void;
104
+ /** Shows a close button when given */
105
+ onClose?: () => void;
106
+ /** Heading id for dialogs */
107
+ titleId?: string;
108
+ }
109
+ declare function CashOutFlow({ signer, wallet, defaultAmountG, partnerRef, onEvent, onClose, titleId }: CashOutFlowProps): React.JSX.Element;
110
+
111
+ interface CashOutButtonProps extends Omit<CashOutFlowProps, 'onClose' | 'titleId'> {
112
+ label?: string;
113
+ className?: string;
114
+ style?: React.CSSProperties;
115
+ }
116
+ /** A button that opens the whole cash-out flow in an accessible dialog. */
117
+ declare function CashOutButton({ label, className, style, onEvent, ...flow }: CashOutButtonProps): React.JSX.Element;
118
+
119
+ /** Scoped styles: every class starts with gcw- and everything lives under .gcw, so it never clashes with the host app. */
120
+ declare const CSS = "\n.gcw{font-family:var(--gcw-font);color:var(--gcw-ink);background:var(--gcw-bg);border-radius:calc(var(--gcw-radius) + 6px);padding:16px;box-sizing:border-box;max-width:440px;width:100%;line-height:1.35;-webkit-font-smoothing:antialiased}\n.gcw *{box-sizing:border-box}\n.gcw-h{font-size:22px;font-weight:800;margin:0 0 4px;letter-spacing:-.3px}\n.gcw-sub{font-size:14px;margin:0 0 12px;opacity:.85}\n.gcw-card{background:var(--gcw-surface);border:2.5px solid var(--gcw-ink);border-radius:var(--gcw-radius);padding:14px;margin:0 0 10px;box-shadow:4px 4px 0 var(--gcw-ink)}\n.gcw-card--ok{background:var(--gcw-success)}\n.gcw-lab{font-size:11px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;opacity:.8;margin:0 0 6px;display:block}\n.gcw-big{font-size:30px;font-weight:800;letter-spacing:-.6px}\n.gcw-row{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:14px;padding:3px 0}\n.gcw-input{width:100%;font:inherit;font-size:18px;font-weight:700;color:var(--gcw-ink);background:var(--gcw-surface);border:2.5px solid var(--gcw-ink);border-radius:calc(var(--gcw-radius) - 6px);padding:12px 14px;outline:none}\n.gcw-input:focus-visible,.gcw-btn:focus-visible,.gcw-bank:focus-visible,.gcw-x:focus-visible{outline:3px solid var(--gcw-accent);outline-offset:2px}\n.gcw-btn{display:flex;align-items:center;justify-content:center;width:100%;min-height:52px;font:inherit;font-size:17px;font-weight:800;color:var(--gcw-accent-ink);background:var(--gcw-accent);border:2.5px solid var(--gcw-ink);border-radius:999px;box-shadow:4px 4px 0 var(--gcw-ink);cursor:pointer;margin-top:6px}\n.gcw-btn:active{transform:translate(3px,3px);box-shadow:1px 1px 0 var(--gcw-ink)}\n.gcw-btn[disabled]{opacity:.55;cursor:not-allowed}\n.gcw-btn--ghost{background:var(--gcw-surface);color:var(--gcw-ink)}\n.gcw-note{font-size:14px;background:var(--gcw-surface);border:2px dashed var(--gcw-ink);border-radius:calc(var(--gcw-radius) - 6px);padding:10px 12px;margin:8px 0}\n.gcw-err{font-size:14px;font-weight:700;background:#ffe1e1;color:#5a0000;border:2.5px solid #5a0000;border-radius:calc(var(--gcw-radius) - 6px);padding:10px 12px;margin:8px 0}\n.gcw-steps{display:flex;gap:6px;margin:0 0 12px}\n.gcw-step{flex:1;height:8px;border-radius:99px;border:2px solid var(--gcw-ink);background:var(--gcw-surface)}\n.gcw-step--done{background:var(--gcw-success)}\n.gcw-step--on{background:var(--gcw-accent)}\n.gcw-banks{max-height:260px;overflow-y:auto;display:flex;flex-direction:column;gap:6px;margin-top:8px}\n.gcw-bank{display:flex;align-items:center;gap:10px;width:100%;text-align:left;font:inherit;font-weight:700;color:var(--gcw-ink);background:var(--gcw-surface);border:2.5px solid var(--gcw-ink);border-radius:calc(var(--gcw-radius) - 6px);padding:10px 12px;cursor:pointer}\n.gcw-bank[aria-selected=true]{background:var(--gcw-success)}\n.gcw-chip{display:inline-block;font-size:12px;font-weight:800;background:var(--gcw-highlight);color:#111;border:2px solid var(--gcw-ink);border-radius:99px;padding:2px 8px}\n.gcw-top{display:flex;justify-content:space-between;align-items:center;gap:10px;margin:0 0 10px}\n.gcw-top .gcw-h{flex:1;min-width:0;margin:0}\n.gcw-x{flex:none;font:inherit;font-size:18px;font-weight:800;width:40px;height:40px;border-radius:99px;border:2.5px solid var(--gcw-ink);background:var(--gcw-surface);color:var(--gcw-ink);cursor:pointer}\n.gcw-foot{font-size:12px;text-align:center;opacity:.75;margin-top:10px}\n.gcw-spin{width:40px;height:40px;border-radius:99px;border:4px solid var(--gcw-ink);border-top-color:transparent;margin:10px auto;animation:gcw-spin 1s linear infinite}\n@keyframes gcw-spin{to{transform:rotate(360deg)}}\n@media (prefers-reduced-motion:reduce){.gcw-spin{animation:none;border-top-color:var(--gcw-ink)}.gcw-btn:active{transform:none}}\n.gcw-overlay{position:fixed;inset:0;background:rgba(17,17,17,.55);display:flex;align-items:flex-end;justify-content:center;z-index:2147483000;padding:12px}\n@media (min-width:560px){.gcw-overlay{align-items:center}}\n.gcw-dialog{max-height:calc(100vh - 24px);overflow-y:auto;width:100%;max-width:440px;border:2.5px solid #111;border-radius:24px;box-shadow:6px 6px 0 #111}\n.gcw-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n";
121
+ declare function injectStyles(): void;
122
+
123
+ export { CashOutButton, type CashOutButtonProps, type CashOutEvent, CashOutFlow, type CashOutFlowProps, CSS as GOODCASH_CSS, GoodCashProvider, type GoodCashProviderProps, type GoodCashTheme, injectStyles, themeVars, useBanks, useCashOut, useCashOutStatus, useGoodCash, useQuote, useVerifyAccount };
@@ -0,0 +1,123 @@
1
+ import React from 'react';
2
+ import { GoodCashOptions, GoodCash, Bank, GoodCashError, CashOutArgs, CashOut, CashOutStep, Quote, Signer } from '@goodcash/sdk';
3
+
4
+ /** Look and feel. The default is GoodCash's own sticker-pop style; every colour can be changed. */
5
+ interface GoodCashTheme {
6
+ /** Page/panel background */
7
+ background?: string;
8
+ /** Cards and inputs */
9
+ surface?: string;
10
+ /** Text and borders */
11
+ ink?: string;
12
+ /** Main buttons */
13
+ accent?: string;
14
+ /** Text on main buttons */
15
+ accentInk?: string;
16
+ /** Highlights (amount chips) */
17
+ highlight?: string;
18
+ /** Success */
19
+ success?: string;
20
+ /** Corner radius in px */
21
+ radius?: number;
22
+ /** CSS font-family. Defaults to the app's system font stack (no web fonts are loaded for you). */
23
+ font?: string;
24
+ /** 'auto' follows the device setting */
25
+ mode?: 'light' | 'dark' | 'auto';
26
+ }
27
+ declare function themeVars(t?: GoodCashTheme, dark?: boolean): Record<string, string>;
28
+
29
+ interface Ctx {
30
+ client: GoodCash;
31
+ theme: GoodCashTheme;
32
+ }
33
+ interface GoodCashProviderProps extends Omit<GoodCashOptions, 'secretKey'> {
34
+ /** Your publishable key (gc_pk_...). Never a secret key. */
35
+ publishableKey: string;
36
+ theme?: GoodCashTheme;
37
+ /** Advanced/tests: bring your own client */
38
+ client?: GoodCash;
39
+ children: React.ReactNode;
40
+ }
41
+ declare function GoodCashProvider({ publishableKey, appId, baseUrl, rpcUrl, fetch, theme, client, children }: GoodCashProviderProps): React.JSX.Element;
42
+ declare function useGoodCash(): Ctx;
43
+
44
+ /** A live quote for an amount: waits until typing pauses, then refreshes every 25 seconds. */
45
+ declare function useQuote(amountG: string | number | null | undefined, opts?: {
46
+ debounceMs?: number;
47
+ refreshMs?: number;
48
+ }): {
49
+ quote: Quote | null;
50
+ error: GoodCashError | null;
51
+ loading: boolean;
52
+ };
53
+ declare function useBanks(): {
54
+ banks: Bank[];
55
+ error: GoodCashError | null;
56
+ loading: boolean;
57
+ };
58
+ /** Looks up the account holder's name as soon as a full account number is typed. */
59
+ declare function useVerifyAccount(bankCode: string, accountNumber: string): {
60
+ accountName: string | null;
61
+ error: GoodCashError | null;
62
+ loading: boolean;
63
+ };
64
+ /** Runs the whole cash out (create, check, sign, report). */
65
+ declare function useCashOut(): {
66
+ start: (args: Omit<CashOutArgs, "onStep">, onStep?: CashOutArgs["onStep"]) => Promise<{
67
+ cashOut: CashOut;
68
+ txHash: string;
69
+ } | null>;
70
+ step: CashOutStep | null;
71
+ cashOut: CashOut | null;
72
+ error: GoodCashError | null;
73
+ reset: () => void;
74
+ };
75
+ /** Follows a cash out until it is paid (or failed, refunded, expired). */
76
+ declare function useCashOutStatus(id: string | null | undefined): {
77
+ cashOut: CashOut | null;
78
+ error: GoodCashError | null;
79
+ };
80
+
81
+ type CashOutEvent = {
82
+ type: 'cashout.created';
83
+ cashOut: CashOut;
84
+ } | {
85
+ type: 'cashout.sent';
86
+ cashOut: CashOut;
87
+ } | {
88
+ type: 'cashout.paid';
89
+ cashOut: CashOut;
90
+ } | {
91
+ type: 'cashout.failed';
92
+ cashOut: CashOut;
93
+ } | {
94
+ type: 'closed';
95
+ };
96
+ interface CashOutFlowProps {
97
+ /** The customer's wallet. Defaults to the browser wallet (window.ethereum) when there is one. */
98
+ signer?: Signer;
99
+ /** The wallet address, when the signer cannot tell (send functions) */
100
+ wallet?: `0x${string}`;
101
+ defaultAmountG?: string | number;
102
+ partnerRef?: string;
103
+ onEvent?: (e: CashOutEvent) => void;
104
+ /** Shows a close button when given */
105
+ onClose?: () => void;
106
+ /** Heading id for dialogs */
107
+ titleId?: string;
108
+ }
109
+ declare function CashOutFlow({ signer, wallet, defaultAmountG, partnerRef, onEvent, onClose, titleId }: CashOutFlowProps): React.JSX.Element;
110
+
111
+ interface CashOutButtonProps extends Omit<CashOutFlowProps, 'onClose' | 'titleId'> {
112
+ label?: string;
113
+ className?: string;
114
+ style?: React.CSSProperties;
115
+ }
116
+ /** A button that opens the whole cash-out flow in an accessible dialog. */
117
+ declare function CashOutButton({ label, className, style, onEvent, ...flow }: CashOutButtonProps): React.JSX.Element;
118
+
119
+ /** Scoped styles: every class starts with gcw- and everything lives under .gcw, so it never clashes with the host app. */
120
+ declare const CSS = "\n.gcw{font-family:var(--gcw-font);color:var(--gcw-ink);background:var(--gcw-bg);border-radius:calc(var(--gcw-radius) + 6px);padding:16px;box-sizing:border-box;max-width:440px;width:100%;line-height:1.35;-webkit-font-smoothing:antialiased}\n.gcw *{box-sizing:border-box}\n.gcw-h{font-size:22px;font-weight:800;margin:0 0 4px;letter-spacing:-.3px}\n.gcw-sub{font-size:14px;margin:0 0 12px;opacity:.85}\n.gcw-card{background:var(--gcw-surface);border:2.5px solid var(--gcw-ink);border-radius:var(--gcw-radius);padding:14px;margin:0 0 10px;box-shadow:4px 4px 0 var(--gcw-ink)}\n.gcw-card--ok{background:var(--gcw-success)}\n.gcw-lab{font-size:11px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;opacity:.8;margin:0 0 6px;display:block}\n.gcw-big{font-size:30px;font-weight:800;letter-spacing:-.6px}\n.gcw-row{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:14px;padding:3px 0}\n.gcw-input{width:100%;font:inherit;font-size:18px;font-weight:700;color:var(--gcw-ink);background:var(--gcw-surface);border:2.5px solid var(--gcw-ink);border-radius:calc(var(--gcw-radius) - 6px);padding:12px 14px;outline:none}\n.gcw-input:focus-visible,.gcw-btn:focus-visible,.gcw-bank:focus-visible,.gcw-x:focus-visible{outline:3px solid var(--gcw-accent);outline-offset:2px}\n.gcw-btn{display:flex;align-items:center;justify-content:center;width:100%;min-height:52px;font:inherit;font-size:17px;font-weight:800;color:var(--gcw-accent-ink);background:var(--gcw-accent);border:2.5px solid var(--gcw-ink);border-radius:999px;box-shadow:4px 4px 0 var(--gcw-ink);cursor:pointer;margin-top:6px}\n.gcw-btn:active{transform:translate(3px,3px);box-shadow:1px 1px 0 var(--gcw-ink)}\n.gcw-btn[disabled]{opacity:.55;cursor:not-allowed}\n.gcw-btn--ghost{background:var(--gcw-surface);color:var(--gcw-ink)}\n.gcw-note{font-size:14px;background:var(--gcw-surface);border:2px dashed var(--gcw-ink);border-radius:calc(var(--gcw-radius) - 6px);padding:10px 12px;margin:8px 0}\n.gcw-err{font-size:14px;font-weight:700;background:#ffe1e1;color:#5a0000;border:2.5px solid #5a0000;border-radius:calc(var(--gcw-radius) - 6px);padding:10px 12px;margin:8px 0}\n.gcw-steps{display:flex;gap:6px;margin:0 0 12px}\n.gcw-step{flex:1;height:8px;border-radius:99px;border:2px solid var(--gcw-ink);background:var(--gcw-surface)}\n.gcw-step--done{background:var(--gcw-success)}\n.gcw-step--on{background:var(--gcw-accent)}\n.gcw-banks{max-height:260px;overflow-y:auto;display:flex;flex-direction:column;gap:6px;margin-top:8px}\n.gcw-bank{display:flex;align-items:center;gap:10px;width:100%;text-align:left;font:inherit;font-weight:700;color:var(--gcw-ink);background:var(--gcw-surface);border:2.5px solid var(--gcw-ink);border-radius:calc(var(--gcw-radius) - 6px);padding:10px 12px;cursor:pointer}\n.gcw-bank[aria-selected=true]{background:var(--gcw-success)}\n.gcw-chip{display:inline-block;font-size:12px;font-weight:800;background:var(--gcw-highlight);color:#111;border:2px solid var(--gcw-ink);border-radius:99px;padding:2px 8px}\n.gcw-top{display:flex;justify-content:space-between;align-items:center;gap:10px;margin:0 0 10px}\n.gcw-top .gcw-h{flex:1;min-width:0;margin:0}\n.gcw-x{flex:none;font:inherit;font-size:18px;font-weight:800;width:40px;height:40px;border-radius:99px;border:2.5px solid var(--gcw-ink);background:var(--gcw-surface);color:var(--gcw-ink);cursor:pointer}\n.gcw-foot{font-size:12px;text-align:center;opacity:.75;margin-top:10px}\n.gcw-spin{width:40px;height:40px;border-radius:99px;border:4px solid var(--gcw-ink);border-top-color:transparent;margin:10px auto;animation:gcw-spin 1s linear infinite}\n@keyframes gcw-spin{to{transform:rotate(360deg)}}\n@media (prefers-reduced-motion:reduce){.gcw-spin{animation:none;border-top-color:var(--gcw-ink)}.gcw-btn:active{transform:none}}\n.gcw-overlay{position:fixed;inset:0;background:rgba(17,17,17,.55);display:flex;align-items:flex-end;justify-content:center;z-index:2147483000;padding:12px}\n@media (min-width:560px){.gcw-overlay{align-items:center}}\n.gcw-dialog{max-height:calc(100vh - 24px);overflow-y:auto;width:100%;max-width:440px;border:2.5px solid #111;border-radius:24px;box-shadow:6px 6px 0 #111}\n.gcw-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n";
121
+ declare function injectStyles(): void;
122
+
123
+ export { CashOutButton, type CashOutButtonProps, type CashOutEvent, CashOutFlow, type CashOutFlowProps, CSS as GOODCASH_CSS, GoodCashProvider, type GoodCashProviderProps, type GoodCashTheme, injectStyles, themeVars, useBanks, useCashOut, useCashOutStatus, useGoodCash, useQuote, useVerifyAccount };