@reclack/walletkit 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.
Files changed (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -2
  3. package/assets/backpack.webp +0 -0
  4. package/assets/berasig.webp +0 -0
  5. package/assets/bestwallet.webp +0 -0
  6. package/assets/bifrostwallet.webp +0 -0
  7. package/assets/binance.webp +0 -0
  8. package/assets/bitcoincom.webp +0 -0
  9. package/assets/bitget.webp +0 -0
  10. package/assets/bitpay.webp +0 -0
  11. package/assets/bitski.webp +0 -0
  12. package/assets/bitverse.webp +0 -0
  13. package/assets/blockchaincom.webp +0 -0
  14. package/assets/brave.webp +0 -0
  15. package/assets/bybit.webp +0 -0
  16. package/assets/clv.webp +0 -0
  17. package/assets/coin98.webp +0 -0
  18. package/assets/coinbase.webp +0 -0
  19. package/assets/compass.webp +0 -0
  20. package/assets/core.webp +0 -0
  21. package/assets/crypto_com.webp +0 -0
  22. package/assets/ctrl.webp +0 -0
  23. package/assets/dawn.webp +0 -0
  24. package/assets/desig.webp +0 -0
  25. package/assets/enkrypt.webp +0 -0
  26. package/assets/exodus.webp +0 -0
  27. package/assets/foxwallet.webp +0 -0
  28. package/assets/frame.webp +0 -0
  29. package/assets/frontier.webp +0 -0
  30. package/assets/gate.webp +0 -0
  31. package/assets/gemini.webp +0 -0
  32. package/assets/imtoken.webp +0 -0
  33. package/assets/iopay.webp +0 -0
  34. package/assets/kaia.webp +0 -0
  35. package/assets/kaikas.webp +0 -0
  36. package/assets/kraken.webp +0 -0
  37. package/assets/kresuswallet.webp +0 -0
  38. package/assets/ledger.webp +0 -0
  39. package/assets/magiceden.webp +0 -0
  40. package/assets/meco.webp +0 -0
  41. package/assets/metamask.webp +0 -0
  42. package/assets/mew.webp +0 -0
  43. package/assets/nest.webp +0 -0
  44. package/assets/nova.webp +0 -0
  45. package/assets/okto.webp +0 -0
  46. package/assets/okx.webp +0 -0
  47. package/assets/oneinch.webp +0 -0
  48. package/assets/onekey.webp +0 -0
  49. package/assets/phantom.webp +0 -0
  50. package/assets/rabby.webp +0 -0
  51. package/assets/rainbow.webp +0 -0
  52. package/assets/ramper.webp +0 -0
  53. package/assets/ready.webp +0 -0
  54. package/assets/ronin.webp +0 -0
  55. package/assets/safe.webp +0 -0
  56. package/assets/safepal.webp +0 -0
  57. package/assets/solflare.webp +0 -0
  58. package/assets/subwallet.webp +0 -0
  59. package/assets/taho.webp +0 -0
  60. package/assets/talisman.webp +0 -0
  61. package/assets/tokenary.webp +0 -0
  62. package/assets/tokenpocket.webp +0 -0
  63. package/assets/trust-wallet.webp +0 -0
  64. package/assets/uniswap.webp +0 -0
  65. package/assets/universalprofiles.webp +0 -0
  66. package/assets/valora.webp +0 -0
  67. package/assets/wigwam.webp +0 -0
  68. package/assets/xportal.webp +0 -0
  69. package/assets/zeal.webp +0 -0
  70. package/assets/zerion.webp +0 -0
  71. package/custom-elements.json +207 -0
  72. package/dist/abi.d.ts +21 -0
  73. package/dist/abi.d.ts.map +1 -0
  74. package/dist/abi.js +50 -0
  75. package/dist/abi.js.map +1 -0
  76. package/dist/address.d.ts +15 -0
  77. package/dist/address.d.ts.map +1 -0
  78. package/dist/address.js +25 -0
  79. package/dist/address.js.map +1 -0
  80. package/dist/balance.d.ts +78 -0
  81. package/dist/balance.d.ts.map +1 -0
  82. package/dist/balance.js +146 -0
  83. package/dist/balance.js.map +1 -0
  84. package/dist/base58.d.ts +15 -0
  85. package/dist/base58.d.ts.map +1 -0
  86. package/dist/base58.js +52 -0
  87. package/dist/base58.js.map +1 -0
  88. package/dist/catalog-fetch.d.ts +18 -0
  89. package/dist/catalog-fetch.d.ts.map +1 -0
  90. package/dist/catalog-fetch.js +85 -0
  91. package/dist/catalog-fetch.js.map +1 -0
  92. package/dist/catalog.d.ts +57 -0
  93. package/dist/catalog.d.ts.map +1 -0
  94. package/dist/catalog.js +80 -0
  95. package/dist/catalog.js.map +1 -0
  96. package/dist/chains.d.ts +32 -0
  97. package/dist/chains.d.ts.map +1 -0
  98. package/dist/chains.js +103 -0
  99. package/dist/chains.js.map +1 -0
  100. package/dist/config.d.ts +40 -0
  101. package/dist/config.d.ts.map +1 -0
  102. package/dist/config.js +44 -0
  103. package/dist/config.js.map +1 -0
  104. package/dist/deep-links.d.ts +22 -0
  105. package/dist/deep-links.d.ts.map +1 -0
  106. package/dist/deep-links.js +201 -0
  107. package/dist/deep-links.js.map +1 -0
  108. package/dist/device.d.ts +23 -0
  109. package/dist/device.d.ts.map +1 -0
  110. package/dist/device.js +59 -0
  111. package/dist/device.js.map +1 -0
  112. package/dist/element/attributes.d.ts +48 -0
  113. package/dist/element/element.d.ts +92 -0
  114. package/dist/element/index.d.ts +4 -0
  115. package/dist/element/props.d.ts +67 -0
  116. package/dist/element/ui/app.d.ts +22 -0
  117. package/dist/element/ui/assets.d.ts +7 -0
  118. package/dist/element/ui/qr.d.ts +16 -0
  119. package/dist/element/ui/use-handheld.d.ts +8 -0
  120. package/dist/element/ui/wallet-connect-panel.d.ts +26 -0
  121. package/dist/element/ui/wallet-dialog.d.ts +37 -0
  122. package/dist/element/ui/wallet-list.d.ts +26 -0
  123. package/dist/element/ui/wallet-mark.d.ts +15 -0
  124. package/dist/element.js +2079 -0
  125. package/dist/errors.d.ts +34 -0
  126. package/dist/errors.d.ts.map +1 -0
  127. package/dist/errors.js +64 -0
  128. package/dist/errors.js.map +1 -0
  129. package/dist/evm.d.ts +49 -0
  130. package/dist/evm.d.ts.map +1 -0
  131. package/dist/evm.js +217 -0
  132. package/dist/evm.js.map +1 -0
  133. package/dist/icons.d.ts +22 -0
  134. package/dist/icons.d.ts.map +1 -0
  135. package/dist/icons.js +98 -0
  136. package/dist/icons.js.map +1 -0
  137. package/dist/index.d.ts +39 -0
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/index.js +43 -0
  140. package/dist/index.js.map +1 -0
  141. package/dist/intent.d.ts +60 -0
  142. package/dist/intent.d.ts.map +1 -0
  143. package/dist/intent.js +2 -0
  144. package/dist/intent.js.map +1 -0
  145. package/dist/kit.d.ts +124 -0
  146. package/dist/kit.d.ts.map +1 -0
  147. package/dist/kit.js +362 -0
  148. package/dist/kit.js.map +1 -0
  149. package/dist/svm.d.ts +45 -0
  150. package/dist/svm.d.ts.map +1 -0
  151. package/dist/svm.js +201 -0
  152. package/dist/svm.js.map +1 -0
  153. package/dist/theme.d.ts +101 -0
  154. package/dist/theme.d.ts.map +1 -0
  155. package/dist/theme.js +217 -0
  156. package/dist/theme.js.map +1 -0
  157. package/dist/types.d.ts +144 -0
  158. package/dist/types.d.ts.map +1 -0
  159. package/dist/types.js +2 -0
  160. package/dist/types.js.map +1 -0
  161. package/dist/wallet-standard.d.ts +77 -0
  162. package/dist/wallet-standard.d.ts.map +1 -0
  163. package/dist/wallet-standard.js +89 -0
  164. package/dist/wallet-standard.js.map +1 -0
  165. package/dist/walletconnect.d.ts +74 -0
  166. package/dist/walletconnect.d.ts.map +1 -0
  167. package/dist/walletconnect.js +133 -0
  168. package/dist/walletconnect.js.map +1 -0
  169. package/package.json +71 -3
  170. package/vscode.html-custom-data.json +55 -0
package/dist/svm.js ADDED
@@ -0,0 +1,201 @@
1
+ import { base58Encode, fromBase64 } from './base58.js';
2
+ import { detect, engineOf, walletsFor } from './catalog.js';
3
+ import { WalletError } from './errors.js';
4
+ import { connectFeature, disconnectFeature, discoverStandardWallets, signFeature, usable, } from './wallet-standard.js';
5
+ /** Reads whatever shape a wallet returns its public key in. */
6
+ function addressOf(value) {
7
+ if (typeof value === 'string') {
8
+ return value;
9
+ }
10
+ // Wallets that ship a web3.js PublicKey return an object. toBase58 is the
11
+ // documented accessor; toString gives the same thing, and both are tried
12
+ // rather than assuming which one a given wallet exposes.
13
+ const key = value;
14
+ if (typeof key?.toBase58 === 'function') {
15
+ return key.toBase58();
16
+ }
17
+ if (typeof key?.toString === 'function') {
18
+ const text = key.toString();
19
+ return text === '[object Object]' ? undefined : text;
20
+ }
21
+ return undefined;
22
+ }
23
+ /**
24
+ * Prompts the wallet for an account.
25
+ *
26
+ * Two routes because there are two kinds of wallet here. A registered one is
27
+ * asked through its connect feature and hands back accounts; an injected one
28
+ * is asked through its provider. The account object from the first is kept,
29
+ * because signing needs it back.
30
+ */
31
+ export async function connectSvmWallet(wallet) {
32
+ if (wallet.standard) {
33
+ const { accounts } = await connectFeature(wallet.standard).connect();
34
+ const account = accounts.find((entry) => entry.chains.some((chain) => chain.startsWith('solana:'))) ?? accounts[0];
35
+ if (!account?.address) {
36
+ throw new WalletError('No account was shared by the wallet.');
37
+ }
38
+ return { address: account.address, account };
39
+ }
40
+ const provider = wallet.provider;
41
+ if (!provider) {
42
+ throw new WalletError('This wallet cannot be connected.');
43
+ }
44
+ const response = provider.connect
45
+ ? await provider.connect()
46
+ : await provider.request?.({ method: 'connect' });
47
+ const fromResponse = addressOf(response?.publicKey);
48
+ const address = fromResponse ?? addressOf(provider.publicKey);
49
+ if (!address) {
50
+ throw new WalletError('No account was shared by the wallet.');
51
+ }
52
+ return { address };
53
+ }
54
+ /** Ends the session where the wallet offers a way to. */
55
+ export async function disconnectSvmWallet(wallet) {
56
+ if (wallet.standard) {
57
+ await disconnectFeature(wallet.standard)?.disconnect();
58
+ return;
59
+ }
60
+ await wallet.provider?.disconnect?.();
61
+ }
62
+ /**
63
+ * Signs the prepared transaction and lets the wallet submit it.
64
+ *
65
+ * Nothing here builds or alters a transaction: the plan arrives built, in
66
+ * both the forms a wallet might want, and this picks the one its route takes.
67
+ * The payer still sees the wallet decode and display it before approving.
68
+ *
69
+ * Letting the wallet send it, rather than signing and sending separately,
70
+ * means one prompt and no RPC endpoint in this bundle.
71
+ */
72
+ export async function signAndSendSvm(wallet, plan) {
73
+ if (wallet.standard && wallet.account) {
74
+ const [result] = await signFeature(wallet.standard).signAndSendTransaction({
75
+ account: wallet.account,
76
+ chain: wallet.account.chains.find((chain) => chain === plan.chain)
77
+ ?? plan.chain,
78
+ transaction: fromBase64(plan.transaction),
79
+ });
80
+ if (!result?.signature) {
81
+ throw new WalletError('The wallet did not return a transaction signature.');
82
+ }
83
+ // Raw bytes from this route, where every other part of the system
84
+ // names a transaction by its base58 string.
85
+ return base58Encode(result.signature);
86
+ }
87
+ const provider = wallet.provider;
88
+ if (typeof provider?.request !== 'function') {
89
+ throw new WalletError('This wallet cannot sign Solana payments. Try another wallet.');
90
+ }
91
+ let response;
92
+ try {
93
+ response = await provider.request({
94
+ method: 'signAndSendTransaction',
95
+ params: { message: plan.message },
96
+ });
97
+ }
98
+ catch (error) {
99
+ // A wallet that rejected it, or one whose provider does not speak
100
+ // this method. The two are told apart by the code: a rejection is the
101
+ // payer's own choice and must be reported as such rather than as an
102
+ // unsupported wallet.
103
+ const code = error.code;
104
+ if (code === 4001 || code === -32002 || code === -32603) {
105
+ throw error;
106
+ }
107
+ throw new WalletError('This wallet could not sign the payment. Try another wallet.');
108
+ }
109
+ const signature = response?.signature;
110
+ if (typeof signature !== 'string' || signature === '') {
111
+ throw new WalletError('The wallet did not return a transaction signature.');
112
+ }
113
+ return signature;
114
+ }
115
+ /** Truncates a base58 address for display: 5e9y…xAQf. */
116
+ export function shortSvmAddress(address) {
117
+ if (address.length < 12) {
118
+ return address;
119
+ }
120
+ return `${address.slice(0, 4)}…${address.slice(-4)}`;
121
+ }
122
+ /** Matches a registered wallet to a catalogued id, for its mark. */
123
+ /**
124
+ * The catalogue id for a wallet that registered under a name.
125
+ *
126
+ * Exact first, and only then a containing match. The two differ now that the
127
+ * catalogue names dozens of wallets: "Core" is a substring of plenty of other
128
+ * names, and a loose match handed one wallet another's artwork. The loose
129
+ * match is still worth keeping for the wallet that registers as "Phantom
130
+ * Wallet" where the catalogue says "Phantom".
131
+ */
132
+ function idFor(name, known) {
133
+ const key = name.toLowerCase();
134
+ const match = known.find((wallet) => wallet.name.toLowerCase() === key)
135
+ ?? known.find((wallet) => key.includes(wallet.name.toLowerCase()));
136
+ return match?.id ?? key.replace(/[^a-z0-9]+/g, '-');
137
+ }
138
+ /**
139
+ * Finds the Solana wallets available in this browser.
140
+ *
141
+ * The Wallet Standard first: it is how wallets announce Solana support, it
142
+ * survives several being installed at once, and the wallet supplies its own
143
+ * name and icon. Sniffing globals is only a fallback for one that has not
144
+ * adopted it, and never overrides a registered wallet.
145
+ *
146
+ * Returns a cleanup function; callers must call it to drop the listener.
147
+ */
148
+ export function discoverSvmWallets(catalog, onChange) {
149
+ const known = walletsFor(catalog, 'svm');
150
+ let registered = [];
151
+ function emit() {
152
+ const found = new Map();
153
+ for (const wallet of registered) {
154
+ if (!usable(wallet)) {
155
+ continue;
156
+ }
157
+ const id = idFor(wallet.name, known);
158
+ found.set(id, { id, name: wallet.name, icon: wallet.icon, standard: wallet });
159
+ }
160
+ // Only for a wallet that did not register. Every wallet worth naming
161
+ // does now, so in practice this catches the ones that have not
162
+ // caught up.
163
+ for (const definition of known) {
164
+ if (found.has(definition.id)) {
165
+ continue;
166
+ }
167
+ const provider = detect(window, engineOf(definition, 'svm'));
168
+ if (typeof provider?.request === 'function') {
169
+ found.set(definition.id, {
170
+ id: definition.id,
171
+ name: definition.name,
172
+ provider,
173
+ });
174
+ }
175
+ }
176
+ // Registry order first, so the list is stable rather than dependent
177
+ // on which wallet answered first; anything else follows.
178
+ const ordered = known
179
+ .map((definition) => found.get(definition.id))
180
+ .filter((wallet) => Boolean(wallet));
181
+ for (const [id, wallet] of found) {
182
+ if (!known.some((definition) => definition.id === id)) {
183
+ ordered.push(wallet);
184
+ }
185
+ }
186
+ onChange(ordered);
187
+ }
188
+ const stop = discoverStandardWallets((wallets) => {
189
+ registered = wallets;
190
+ emit();
191
+ });
192
+ // A wallet that injects a global late would otherwise be missed, the same
193
+ // race the EIP-6963 discovery keeps a retry for.
194
+ const retry = window.setTimeout(emit, 400);
195
+ emit();
196
+ return () => {
197
+ stop();
198
+ window.clearTimeout(retry);
199
+ };
200
+ }
201
+ //# sourceMappingURL=svm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svm.js","sourceRoot":"","sources":["../src/svm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * How a host dresses the wallet picker.
3
+ *
4
+ * Tokens rather than class names or a stylesheet to override. A wallet picker
5
+ * appears inside a merchant's checkout, a dashboard form and a partner's own
6
+ * page, and the only thing those three agree on is that it should not look
7
+ * like somebody else's component. Twelve values is the whole contract.
8
+ *
9
+ * Every value is validated rather than trusted, even though a host is usually
10
+ * passing its own constants. In the embedded checkout the branding comes from
11
+ * an API response, and a colour ends up inside a style: a page that takes
12
+ * payment details must not interpolate whatever a response happens to carry.
13
+ * An unreadable value is dropped and the default stands, which is a picker
14
+ * that looks generic rather than one that does not render.
15
+ */
16
+ /**
17
+ * Light, dark, or whatever the reader's system says.
18
+ *
19
+ * `system` is the default. A picker that ignores the setting is a white
20
+ * rectangle in a dark checkout.
21
+ */
22
+ export type ThemeMode = 'light' | 'dark' | 'system';
23
+ /** The resolved mode: what `system` turned out to mean. */
24
+ export type ColorScheme = 'light' | 'dark';
25
+ export interface ThemeTokens {
26
+ /** The panel itself. */
27
+ surface?: string;
28
+ /** Behind the panel. */
29
+ ground?: string;
30
+ /** Rows and plates inside it, such as the square a wallet mark sits on. */
31
+ plate?: string;
32
+ /** Primary text. */
33
+ ink?: string;
34
+ /** Secondary text: captions, addresses, the word "Detected". */
35
+ inkMuted?: string;
36
+ /** Hairlines and borders. */
37
+ line?: string;
38
+ /** The host's own colour, worn by the primary action and the focus ring. */
39
+ brand?: string;
40
+ /** Text on `brand`. Computed for contrast when not given. */
41
+ brandInk?: string;
42
+ /** A refusal. */
43
+ danger?: string;
44
+ /** A success. */
45
+ ok?: string;
46
+ /** Corner radius, as a CSS length. */
47
+ radius?: string;
48
+ /** The host's type, so the picker does not arrive in a different face. */
49
+ fontFamily?: string;
50
+ }
51
+ export interface WalletKitTheme extends ThemeTokens {
52
+ mode?: ThemeMode;
53
+ /** Applied on top of the shared tokens when the resolved mode is dark. */
54
+ dark?: ThemeTokens;
55
+ /** Applied on top of the shared tokens when the resolved mode is light. */
56
+ light?: ThemeTokens;
57
+ }
58
+ /**
59
+ * The defaults, which are the hosted checkout's own.
60
+ *
61
+ * Dark is chosen rather than derived. Inverting a light palette gives muddy
62
+ * greys and a brand colour that has stopped contrasting with anything; every
63
+ * step here was picked against the surface it sits on.
64
+ */
65
+ export declare const LIGHT_TOKENS: Required<Omit<ThemeTokens, 'brandInk' | 'fontFamily'>>;
66
+ export declare const DARK_TOKENS: Required<Omit<ThemeTokens, 'brandInk' | 'fontFamily'>>;
67
+ /** A colour, or nothing where it is not one. */
68
+ export declare function safeColor(value: string | undefined): string | undefined;
69
+ /**
70
+ * Black or white, whichever can actually be read on this colour.
71
+ *
72
+ * Relative luminance per WCAG, so a pale brand gets dark text instead of the
73
+ * white that would leave the primary button unreadable. Computed rather than
74
+ * configured: a host choosing this by eye gets it wrong, and the one place it
75
+ * matters is the button somebody has to find.
76
+ */
77
+ export declare function readableInk(hex: string): string;
78
+ /**
79
+ * Every token for one mode, as the custom properties a stylesheet reads.
80
+ *
81
+ * Shared tokens first, then the mode's own overrides on top, so a host can
82
+ * set one brand colour for both and a different surface for each.
83
+ */
84
+ export declare function themeVariables(theme: WalletKitTheme | undefined, scheme: ColorScheme): Record<string, string>;
85
+ /** The same thing as a declaration block, for a stylesheet rather than an element. */
86
+ export declare function themeCss(theme: WalletKitTheme | undefined, scheme: ColorScheme, selector?: string): string;
87
+ /** Sets the tokens on one element, which is what a renderer actually does. */
88
+ export declare function applyTheme(target: {
89
+ style: {
90
+ setProperty(name: string, value: string): void;
91
+ };
92
+ }, theme: WalletKitTheme | undefined, scheme: ColorScheme): void;
93
+ /** What `system` means right now, or the mode itself when it is not system. */
94
+ export declare function resolveScheme(mode: ThemeMode | undefined): ColorScheme;
95
+ /**
96
+ * Follows the resolved mode, which only moves when the mode is `system`.
97
+ *
98
+ * Calls back once immediately, so a caller never has to read the value
99
+ * separately before subscribing to it. Returns the cleanup.
100
+ */
101
+ export declare function subscribeScheme(mode: ThemeMode | undefined, onChange: (scheme: ColorScheme) => void): () => void;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEnD,2DAA2D;AAC3D,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAA;AAE1C,MAAM,WAAW,WAAW;IAC3B,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iBAAiB;IACjB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW;IAClD,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,WAAW,CAAA;CACnB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,YAAY,CAAC,CAW/E,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,YAAY,CAAC,CAc9E,CAAA;AA+CD,gDAAgD;AAChD,wBAAgB,SAAS,CAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGxE;AAeD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAQhD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,MAAM,EAAE,WAAW,GACjB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyCxB;AAED,sFAAsF;AACtF,wBAAgB,QAAQ,CACvB,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,MAAM,EAAE,WAAW,EACnB,QAAQ,SAAU,GAChB,MAAM,CAMR;AAED,8EAA8E;AAC9E,wBAAgB,UAAU,CACzB,MAAM,EAAE;IAAE,KAAK,EAAE;QAAE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CAAE,EACrE,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,MAAM,EAAE,WAAW,GACjB,IAAI,CAON;AAID,+EAA+E;AAC/E,wBAAgB,aAAa,CAAE,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAQvE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,SAAS,GAAG,SAAS,EAC3B,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GACrC,MAAM,IAAI,CAcZ"}
package/dist/theme.js ADDED
@@ -0,0 +1,217 @@
1
+ /**
2
+ * How a host dresses the wallet picker.
3
+ *
4
+ * Tokens rather than class names or a stylesheet to override. A wallet picker
5
+ * appears inside a merchant's checkout, a dashboard form and a partner's own
6
+ * page, and the only thing those three agree on is that it should not look
7
+ * like somebody else's component. Twelve values is the whole contract.
8
+ *
9
+ * Every value is validated rather than trusted, even though a host is usually
10
+ * passing its own constants. In the embedded checkout the branding comes from
11
+ * an API response, and a colour ends up inside a style: a page that takes
12
+ * payment details must not interpolate whatever a response happens to carry.
13
+ * An unreadable value is dropped and the default stands, which is a picker
14
+ * that looks generic rather than one that does not render.
15
+ */
16
+ /**
17
+ * The defaults, which are the hosted checkout's own.
18
+ *
19
+ * Dark is chosen rather than derived. Inverting a light palette gives muddy
20
+ * greys and a brand colour that has stopped contrasting with anything; every
21
+ * step here was picked against the surface it sits on.
22
+ */
23
+ export const LIGHT_TOKENS = {
24
+ surface: '#ffffff',
25
+ ground: '#f6f7f9',
26
+ plate: '#f6f7f9',
27
+ ink: '#101014',
28
+ inkMuted: '#6b6b76',
29
+ line: '#e5e5ea',
30
+ brand: '#533afd',
31
+ danger: '#b42318',
32
+ ok: '#12a150',
33
+ radius: '10px',
34
+ };
35
+ export const DARK_TOKENS = {
36
+ surface: '#16161a',
37
+ ground: '#0e0e11',
38
+ plate: '#1f1f26',
39
+ ink: '#f4f4f6',
40
+ inkMuted: '#9a9aa6',
41
+ line: '#2b2b33',
42
+ // Lifted off the light value, which goes nearly black against a dark
43
+ // panel. A host that sets its own brand keeps it in both modes: it is
44
+ // their colour, and second-guessing it is how a brand ends up wrong.
45
+ brand: '#8b74ff',
46
+ danger: '#f97066',
47
+ ok: '#3ccb7f',
48
+ radius: '10px',
49
+ };
50
+ /**
51
+ * The stylesheet's name for each token.
52
+ *
53
+ * Prefixed, because these are set on an element a host also styles, and an
54
+ * unprefixed `--surface` would silently take over or be taken over.
55
+ */
56
+ const VARIABLE = {
57
+ surface: '--rkw-surface',
58
+ ground: '--rkw-ground',
59
+ plate: '--rkw-plate',
60
+ ink: '--rkw-ink',
61
+ inkMuted: '--rkw-ink-muted',
62
+ line: '--rkw-line',
63
+ brand: '--rkw-brand',
64
+ brandInk: '--rkw-brand-ink',
65
+ danger: '--rkw-danger',
66
+ ok: '--rkw-ok',
67
+ radius: '--rkw-radius',
68
+ fontFamily: '--rkw-font',
69
+ };
70
+ /**
71
+ * The wash under whatever is being pointed at.
72
+ *
73
+ * Grey until the host picks a colour, and that distinction is deliberate. The
74
+ * default brand is Reclack's own, so a page nobody has branded would
75
+ * otherwise hover in our indigo: somebody else's product, quietly wearing our
76
+ * colour. The moment a host sets a brand it is theirs to hover in.
77
+ *
78
+ * Written as a reference to a token, never with the colour folded in, so
79
+ * nothing a host or an API response supplied is interpolated into a value. A
80
+ * twelfth reads as a hover on both a white panel and a dark one, which a
81
+ * fixed grey does not.
82
+ */
83
+ function hoverWash(branded) {
84
+ const token = branded ? '--rkw-brand' : '--rkw-ink-muted';
85
+ return `color-mix(in srgb, var(${token}) 12%, transparent)`;
86
+ }
87
+ const HEX = /^#[0-9a-f]{6}$/i;
88
+ const LENGTH = /^\d+(\.\d+)?(px|rem|em|%)$/;
89
+ // Letters, digits, spaces, quotes, commas and hyphens: everything a font
90
+ // stack is made of, and nothing that closes a declaration.
91
+ const FONT = /^[\w\s'",.-]{1,200}$/;
92
+ /** A colour, or nothing where it is not one. */
93
+ export function safeColor(value) {
94
+ const trimmed = value?.trim().toLowerCase();
95
+ return trimmed && HEX.test(trimmed) ? trimmed : undefined;
96
+ }
97
+ function safeRadius(value) {
98
+ if (typeof value === 'number') {
99
+ return Number.isFinite(value) && value >= 0 ? `${value}px` : undefined;
100
+ }
101
+ const trimmed = value?.trim();
102
+ return trimmed && LENGTH.test(trimmed) ? trimmed : undefined;
103
+ }
104
+ function safeFont(value) {
105
+ const trimmed = value?.trim();
106
+ return trimmed && FONT.test(trimmed) ? trimmed : undefined;
107
+ }
108
+ /**
109
+ * Black or white, whichever can actually be read on this colour.
110
+ *
111
+ * Relative luminance per WCAG, so a pale brand gets dark text instead of the
112
+ * white that would leave the primary button unreadable. Computed rather than
113
+ * configured: a host choosing this by eye gets it wrong, and the one place it
114
+ * matters is the button somebody has to find.
115
+ */
116
+ export function readableInk(hex) {
117
+ const channel = (from) => {
118
+ const raw = Number.parseInt(hex.slice(from, from + 2), 16) / 255;
119
+ return raw <= 0.03928 ? raw / 12.92 : ((raw + 0.055) / 1.055) ** 2.4;
120
+ };
121
+ const luminance = 0.2126 * channel(1) + 0.7152 * channel(3) + 0.0722 * channel(5);
122
+ return luminance > 0.45 ? '#101014' : '#ffffff';
123
+ }
124
+ /**
125
+ * Every token for one mode, as the custom properties a stylesheet reads.
126
+ *
127
+ * Shared tokens first, then the mode's own overrides on top, so a host can
128
+ * set one brand colour for both and a different surface for each.
129
+ */
130
+ export function themeVariables(theme, scheme) {
131
+ const base = scheme === 'dark' ? DARK_TOKENS : LIGHT_TOKENS;
132
+ const given = {
133
+ ...theme,
134
+ ...(scheme === 'dark' ? theme?.dark : theme?.light),
135
+ };
136
+ const variables = {};
137
+ const colors = ['surface', 'ground', 'plate', 'ink', 'inkMuted', 'line', 'brand', 'danger', 'ok'];
138
+ for (const token of colors) {
139
+ variables[VARIABLE[token]] = safeColor(given[token]) ?? base[token];
140
+ }
141
+ variables[VARIABLE.radius] = safeRadius(given.radius) ?? base.radius;
142
+ // Only when the host has type of its own. Absent, the element inherits
143
+ // whatever the page is already set in, which is almost always right.
144
+ const font = safeFont(given.fontFamily);
145
+ if (font) {
146
+ variables[VARIABLE.fontFamily] = font;
147
+ }
148
+ // Taken when given, computed when not: a host that sets a brand colour
149
+ // should not also have to work out what reads on it.
150
+ variables[VARIABLE.brandInk] =
151
+ safeColor(given.brandInk) ?? readableInk(variables[VARIABLE.brand]);
152
+ // Branded means the host said so, not that a brand token has a value:
153
+ // every token always has one, and the default is ours.
154
+ variables['--rkw-hover'] = hoverWash(Boolean(safeColor(given.brand)));
155
+ // Not a colour of ours: what the browser draws its own controls in.
156
+ variables['--rkw-color-scheme'] = scheme;
157
+ // The "installed" badge, which is not the same green as a success
158
+ // message and never was: it is a quieter, deeper one, chosen against a
159
+ // white row. Derived rather than exposed as a token, like the hover
160
+ // wash: a host theming the picker is not choosing this.
161
+ const installed = scheme === 'dark'
162
+ ? { mark: '#4ade80', ink: '#86efac' }
163
+ : { mark: '#16a34a', ink: '#15803d' };
164
+ variables['--rkw-installed'] = installed.mark;
165
+ variables['--rkw-installed-ink'] = installed.ink;
166
+ return variables;
167
+ }
168
+ /** The same thing as a declaration block, for a stylesheet rather than an element. */
169
+ export function themeCss(theme, scheme, selector = ':host') {
170
+ const variables = themeVariables(theme, scheme);
171
+ const body = Object.entries(variables)
172
+ .map(([name, value]) => `\t${name}: ${value};`)
173
+ .join('\n');
174
+ return `${selector} {\n${body}\n}`;
175
+ }
176
+ /** Sets the tokens on one element, which is what a renderer actually does. */
177
+ export function applyTheme(target, theme, scheme) {
178
+ for (const [name, value] of Object.entries(themeVariables(theme, scheme))) {
179
+ // setProperty rather than a built style string: the value is written
180
+ // as a value, so nothing in it can close the declaration and start
181
+ // another.
182
+ target.style.setProperty(name, value);
183
+ }
184
+ }
185
+ const DARK_QUERY = '(prefers-color-scheme: dark)';
186
+ /** What `system` means right now, or the mode itself when it is not system. */
187
+ export function resolveScheme(mode) {
188
+ if (mode === 'light' || mode === 'dark') {
189
+ return mode;
190
+ }
191
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
192
+ return 'light';
193
+ }
194
+ return window.matchMedia(DARK_QUERY).matches ? 'dark' : 'light';
195
+ }
196
+ /**
197
+ * Follows the resolved mode, which only moves when the mode is `system`.
198
+ *
199
+ * Calls back once immediately, so a caller never has to read the value
200
+ * separately before subscribing to it. Returns the cleanup.
201
+ */
202
+ export function subscribeScheme(mode, onChange) {
203
+ if (mode === 'light' || mode === 'dark') {
204
+ onChange(mode);
205
+ return () => undefined;
206
+ }
207
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
208
+ onChange('light');
209
+ return () => undefined;
210
+ }
211
+ const query = window.matchMedia(DARK_QUERY);
212
+ const update = () => onChange(query.matches ? 'dark' : 'light');
213
+ update();
214
+ query.addEventListener('change', update);
215
+ return () => query.removeEventListener('change', update);
216
+ }
217
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"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"}