@kheopskit/react 3.0.1 → 5.0.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.
- package/README.md +103 -0
- package/dist/index.d.mts +58 -3
- package/dist/index.d.ts +58 -3
- package/dist/index.js +55 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +62 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +21 -10
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# @kheopskit/react
|
|
2
|
+
|
|
3
|
+
React bindings for [Kheopskit](https://github.com/kheopskit/kheopskit) — list
|
|
4
|
+
wallets and accounts across Polkadot, Ethereum and Solana, with injected wallets
|
|
5
|
+
and WalletConnect (Reown AppKit).
|
|
6
|
+
|
|
7
|
+
The framework-agnostic core lives in
|
|
8
|
+
[`@kheopskit/core`](https://www.npmjs.com/package/@kheopskit/core).
|
|
9
|
+
Full docs and the interactive playground:
|
|
10
|
+
https://github.com/kheopskit/kheopskit
|
|
11
|
+
|
|
12
|
+
> **Upgrading from v3?** v4 moves platforms to plugins and makes platform SDKs
|
|
13
|
+
> (and WalletConnect) optional peer dependencies. See
|
|
14
|
+
> [MIGRATING_TO_V4.md](../core/MIGRATING_TO_V4.md).
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
`rxjs` is always required; every platform SDK (and WalletConnect) is an optional
|
|
19
|
+
peer dependency — install only what you use:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add @kheopskit/core @kheopskit/react rxjs
|
|
23
|
+
|
|
24
|
+
pnpm add polkadot-api # Polkadot
|
|
25
|
+
pnpm add viem mipd # Ethereum
|
|
26
|
+
pnpm add @solana/kit @wallet-standard/app @wallet-standard/base # Solana
|
|
27
|
+
pnpm add @reown/appkit # WalletConnect (optional)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
Recommended: bind your platform tuple once with `createKheopskit` and get a
|
|
33
|
+
provider plus hooks already typed to those platforms — no generic to repeat.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
// kheopskit.ts
|
|
37
|
+
import { createKheopskit } from "@kheopskit/react";
|
|
38
|
+
import { polkadot } from "@kheopskit/core/polkadot";
|
|
39
|
+
import { ethereum } from "@kheopskit/core/ethereum";
|
|
40
|
+
import { solana } from "@kheopskit/core/solana";
|
|
41
|
+
|
|
42
|
+
export const { KheopskitProvider, useWallets, useAccounts } = createKheopskit({
|
|
43
|
+
platforms: [polkadot(), ethereum(), solana()],
|
|
44
|
+
autoReconnect: true,
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
// app.tsx
|
|
50
|
+
import { KheopskitProvider } from "./kheopskit";
|
|
51
|
+
|
|
52
|
+
export const App = ({ children }: { children: React.ReactNode }) => (
|
|
53
|
+
<KheopskitProvider>{children}</KheopskitProvider>
|
|
54
|
+
);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
// anywhere — accounts/wallets are platform-precise (account.signer / account.client typed)
|
|
59
|
+
import { useWallets, useAccounts } from "./kheopskit";
|
|
60
|
+
|
|
61
|
+
const { wallets, isHydrating } = useWallets();
|
|
62
|
+
const accounts = useAccounts();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Without the factory
|
|
66
|
+
|
|
67
|
+
You can also use the `KheopskitProvider` component directly and recover precise
|
|
68
|
+
types with a type argument (React context can't be generic):
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { KheopskitProvider, useWallets } from "@kheopskit/react";
|
|
72
|
+
|
|
73
|
+
const platforms = [polkadot(), ethereum(), solana()] as const;
|
|
74
|
+
|
|
75
|
+
<KheopskitProvider config={{ platforms }}>…</KheopskitProvider>;
|
|
76
|
+
|
|
77
|
+
const { accounts } = useWallets<typeof platforms>();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## SSR
|
|
81
|
+
|
|
82
|
+
Pass the request cookie header as `ssrCookies` to hydrate wallet state on the
|
|
83
|
+
server without a UI flash:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
// Next.js App Router
|
|
87
|
+
const cookieStore = await cookies();
|
|
88
|
+
const ssrCookies = cookieStore
|
|
89
|
+
.getAll()
|
|
90
|
+
.map((c) => `${c.name}=${c.value}`)
|
|
91
|
+
.join("; ");
|
|
92
|
+
|
|
93
|
+
<KheopskitProvider ssrCookies={ssrCookies}>{children}</KheopskitProvider>;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> While `state.isHydrating` is `true`, wallets/accounts are cached placeholders
|
|
97
|
+
> carrying only the base fields — SDK fields (`signer`, `client`,
|
|
98
|
+
> provider/extension handles) are absent until hydration completes. Guard access
|
|
99
|
+
> behind `!isHydrating`.
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
ISC
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
import * as _kheopskit_core from '@kheopskit/core';
|
|
2
|
-
import { KheopskitConfig } from '@kheopskit/core';
|
|
2
|
+
import { KheopskitPlatform, KheopskitConfig, KheopskitState } from '@kheopskit/core';
|
|
3
3
|
import { FC, PropsWithChildren } from 'react';
|
|
4
4
|
|
|
5
|
+
type CreateKheopskitConfig<P extends readonly KheopskitPlatform[]> = Omit<Partial<KheopskitConfig<P>>, "platforms"> & {
|
|
6
|
+
/** Platform plugins, e.g. `[polkadot(), solana()]`. Required. */
|
|
7
|
+
platforms: P;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Binds a platform tuple once and returns a `KheopskitProvider` plus hooks
|
|
11
|
+
* (`useWallets`, `useAccounts`) already typed to those platforms — so you don't
|
|
12
|
+
* repeat `useWallets<typeof platforms>()` in every component.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* // kheopskit.ts
|
|
17
|
+
* export const { KheopskitProvider, useWallets, useAccounts } = createKheopskit({
|
|
18
|
+
* platforms: [polkadot(), ethereum(), solana()],
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // anywhere
|
|
22
|
+
* const { accounts } = useWallets(); // accounts are platform-precise, no generic
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare const createKheopskit: <const P extends readonly [KheopskitPlatform, ...KheopskitPlatform[]]>(config: CreateKheopskitConfig<P>) => {
|
|
26
|
+
KheopskitProvider: FC<PropsWithChildren<{
|
|
27
|
+
ssrCookies?: string;
|
|
28
|
+
}>>;
|
|
29
|
+
/** Current state, typed to the bound platform tuple. */
|
|
30
|
+
useWallets: () => _kheopskit_core.KheopskitState<P>;
|
|
31
|
+
/** Current accounts, typed to the bound platform tuple. */
|
|
32
|
+
useAccounts: () => _kheopskit_core.AccountOf<P[number]>[];
|
|
33
|
+
};
|
|
34
|
+
|
|
5
35
|
type KheopskitProviderProps = PropsWithChildren & {
|
|
36
|
+
/**
|
|
37
|
+
* Kheopskit configuration.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Must be a **referentially stable** value — define it once (module scope, a
|
|
41
|
+
* `useMemo`, or via {@link createKheopskit}) and pass the same reference. A
|
|
42
|
+
* new object literal on every render (`config={{ platforms: [...] }}` inline)
|
|
43
|
+
* recreates the underlying store and re-subscribes each render.
|
|
44
|
+
*/
|
|
6
45
|
config?: Partial<KheopskitConfig>;
|
|
7
46
|
/**
|
|
8
47
|
* Cookie string for SSR hydration.
|
|
@@ -25,6 +64,22 @@ type KheopskitProviderProps = PropsWithChildren & {
|
|
|
25
64
|
};
|
|
26
65
|
declare const KheopskitProvider: FC<KheopskitProviderProps>;
|
|
27
66
|
|
|
28
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Convenience hook returning just the accounts from kheopskit state. Pass the
|
|
69
|
+
* platform tuple as a type argument to recover SDK-precise account types —
|
|
70
|
+
* `useAccounts<typeof platforms>()` — or use the pre-typed hook from
|
|
71
|
+
* {@link createKheopskit}.
|
|
72
|
+
*/
|
|
73
|
+
declare const useAccounts: <P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[]>() => _kheopskit_core.AccountOf<P[number]>[];
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns the current kheopskit state (wallets, accounts, config, isHydrating).
|
|
77
|
+
*
|
|
78
|
+
* Pass the platform tuple as a type argument to recover SDK-precise account and
|
|
79
|
+
* wallet types — `useWallets<typeof platforms>()`. React contexts can't be
|
|
80
|
+
* generic, so without the argument the state is typed with the base
|
|
81
|
+
* (SDK-free) wallet/account shapes.
|
|
82
|
+
*/
|
|
83
|
+
declare const useWallets: <P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[]>() => KheopskitState<P>;
|
|
29
84
|
|
|
30
|
-
export { KheopskitProvider, type KheopskitProviderProps, useWallets };
|
|
85
|
+
export { type CreateKheopskitConfig, KheopskitProvider, type KheopskitProviderProps, createKheopskit, useAccounts, useWallets };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
import * as _kheopskit_core from '@kheopskit/core';
|
|
2
|
-
import { KheopskitConfig } from '@kheopskit/core';
|
|
2
|
+
import { KheopskitPlatform, KheopskitConfig, KheopskitState } from '@kheopskit/core';
|
|
3
3
|
import { FC, PropsWithChildren } from 'react';
|
|
4
4
|
|
|
5
|
+
type CreateKheopskitConfig<P extends readonly KheopskitPlatform[]> = Omit<Partial<KheopskitConfig<P>>, "platforms"> & {
|
|
6
|
+
/** Platform plugins, e.g. `[polkadot(), solana()]`. Required. */
|
|
7
|
+
platforms: P;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Binds a platform tuple once and returns a `KheopskitProvider` plus hooks
|
|
11
|
+
* (`useWallets`, `useAccounts`) already typed to those platforms — so you don't
|
|
12
|
+
* repeat `useWallets<typeof platforms>()` in every component.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* // kheopskit.ts
|
|
17
|
+
* export const { KheopskitProvider, useWallets, useAccounts } = createKheopskit({
|
|
18
|
+
* platforms: [polkadot(), ethereum(), solana()],
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // anywhere
|
|
22
|
+
* const { accounts } = useWallets(); // accounts are platform-precise, no generic
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare const createKheopskit: <const P extends readonly [KheopskitPlatform, ...KheopskitPlatform[]]>(config: CreateKheopskitConfig<P>) => {
|
|
26
|
+
KheopskitProvider: FC<PropsWithChildren<{
|
|
27
|
+
ssrCookies?: string;
|
|
28
|
+
}>>;
|
|
29
|
+
/** Current state, typed to the bound platform tuple. */
|
|
30
|
+
useWallets: () => _kheopskit_core.KheopskitState<P>;
|
|
31
|
+
/** Current accounts, typed to the bound platform tuple. */
|
|
32
|
+
useAccounts: () => _kheopskit_core.AccountOf<P[number]>[];
|
|
33
|
+
};
|
|
34
|
+
|
|
5
35
|
type KheopskitProviderProps = PropsWithChildren & {
|
|
36
|
+
/**
|
|
37
|
+
* Kheopskit configuration.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Must be a **referentially stable** value — define it once (module scope, a
|
|
41
|
+
* `useMemo`, or via {@link createKheopskit}) and pass the same reference. A
|
|
42
|
+
* new object literal on every render (`config={{ platforms: [...] }}` inline)
|
|
43
|
+
* recreates the underlying store and re-subscribes each render.
|
|
44
|
+
*/
|
|
6
45
|
config?: Partial<KheopskitConfig>;
|
|
7
46
|
/**
|
|
8
47
|
* Cookie string for SSR hydration.
|
|
@@ -25,6 +64,22 @@ type KheopskitProviderProps = PropsWithChildren & {
|
|
|
25
64
|
};
|
|
26
65
|
declare const KheopskitProvider: FC<KheopskitProviderProps>;
|
|
27
66
|
|
|
28
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Convenience hook returning just the accounts from kheopskit state. Pass the
|
|
69
|
+
* platform tuple as a type argument to recover SDK-precise account types —
|
|
70
|
+
* `useAccounts<typeof platforms>()` — or use the pre-typed hook from
|
|
71
|
+
* {@link createKheopskit}.
|
|
72
|
+
*/
|
|
73
|
+
declare const useAccounts: <P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[]>() => _kheopskit_core.AccountOf<P[number]>[];
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns the current kheopskit state (wallets, accounts, config, isHydrating).
|
|
77
|
+
*
|
|
78
|
+
* Pass the platform tuple as a type argument to recover SDK-precise account and
|
|
79
|
+
* wallet types — `useWallets<typeof platforms>()`. React contexts can't be
|
|
80
|
+
* generic, so without the argument the state is typed with the base
|
|
81
|
+
* (SDK-free) wallet/account shapes.
|
|
82
|
+
*/
|
|
83
|
+
declare const useWallets: <P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[]>() => KheopskitState<P>;
|
|
29
84
|
|
|
30
|
-
export { KheopskitProvider, type KheopskitProviderProps, useWallets };
|
|
85
|
+
export { type CreateKheopskitConfig, KheopskitProvider, type KheopskitProviderProps, createKheopskit, useAccounts, useWallets };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
"use strict";
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -21,12 +22,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
22
|
var index_exports = {};
|
|
22
23
|
__export(index_exports, {
|
|
23
24
|
KheopskitProvider: () => KheopskitProvider,
|
|
25
|
+
createKheopskit: () => createKheopskit,
|
|
26
|
+
useAccounts: () => useAccounts,
|
|
24
27
|
useWallets: () => useWallets
|
|
25
28
|
});
|
|
26
29
|
module.exports = __toCommonJS(index_exports);
|
|
27
30
|
|
|
28
31
|
// src/KheopskitProvider.tsx
|
|
29
32
|
var import_core = require("@kheopskit/core");
|
|
33
|
+
var import_internal = require("@kheopskit/core/internal");
|
|
30
34
|
var import_react2 = require("react");
|
|
31
35
|
|
|
32
36
|
// src/context.ts
|
|
@@ -49,13 +53,12 @@ var createStore = (observable$, initialValue, serverValue) => {
|
|
|
49
53
|
});
|
|
50
54
|
}
|
|
51
55
|
};
|
|
52
|
-
ensureSubscription();
|
|
53
56
|
const getSnapshot = () => latestValue ?? initialValue;
|
|
54
57
|
const getServerSnapshot = () => serverValue ?? initialValue;
|
|
55
58
|
const subscribe = (callback) => {
|
|
56
59
|
subscriberCount++;
|
|
57
|
-
listeners.add(callback);
|
|
58
60
|
ensureSubscription();
|
|
61
|
+
listeners.add(callback);
|
|
59
62
|
callback(getSnapshot());
|
|
60
63
|
return () => {
|
|
61
64
|
subscriberCount--;
|
|
@@ -84,6 +87,17 @@ var KheopskitProvider = ({
|
|
|
84
87
|
ssrCookies
|
|
85
88
|
}) => {
|
|
86
89
|
const resolvedConfig = (0, import_react2.useMemo)(() => (0, import_core.resolveConfig)(config), [config]);
|
|
90
|
+
const lastConfigRef = (0, import_react2.useRef)(config);
|
|
91
|
+
const hasMountedRef = (0, import_react2.useRef)(false);
|
|
92
|
+
(0, import_react2.useEffect)(() => {
|
|
93
|
+
if (hasMountedRef.current && lastConfigRef.current !== config && (typeof process === "undefined" || process.env?.NODE_ENV !== "production")) {
|
|
94
|
+
console.warn(
|
|
95
|
+
"[kheopskit] KheopskitProvider received a new `config` reference; this recreates the store and re-subscribes on every render. Pass a referentially stable config (module scope, useMemo, or createKheopskit())."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
hasMountedRef.current = true;
|
|
99
|
+
lastConfigRef.current = config;
|
|
100
|
+
}, [config]);
|
|
87
101
|
const kheopskitStore = (0, import_react2.useMemo)(
|
|
88
102
|
() => (0, import_core.createKheopskitStore)({
|
|
89
103
|
ssrCookies,
|
|
@@ -102,32 +116,32 @@ var KheopskitProvider = ({
|
|
|
102
116
|
}
|
|
103
117
|
const cached = kheopskitStore.getCachedState();
|
|
104
118
|
return {
|
|
105
|
-
wallets: cached.wallets.map(
|
|
106
|
-
accounts: cached.accounts.
|
|
107
|
-
(account) =>
|
|
108
|
-
),
|
|
119
|
+
wallets: cached.wallets.map(import_internal.hydrateWallet).sort(import_internal.sortWallets),
|
|
120
|
+
accounts: cached.accounts.filter(
|
|
121
|
+
(account) => (0, import_internal.acceptsCachedAccount)(account, resolvedConfig.platforms)
|
|
122
|
+
).map(import_internal.hydrateAccount).sort(import_internal.sortAccounts),
|
|
109
123
|
config: resolvedConfig,
|
|
110
124
|
isHydrating: true
|
|
111
125
|
};
|
|
112
126
|
}, [ssrCookies, kheopskitStore, resolvedConfig]);
|
|
113
127
|
const initialValue = (0, import_react2.useMemo)(() => {
|
|
114
|
-
const
|
|
115
|
-
if (!w.icon) {
|
|
116
|
-
const cachedIcon = (0, import_core.getCachedIcon)(w.id);
|
|
117
|
-
if (cachedIcon) {
|
|
118
|
-
return { ...w, icon: cachedIcon };
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return w;
|
|
122
|
-
});
|
|
128
|
+
const cached = kheopskitStore.getCachedState();
|
|
123
129
|
return {
|
|
124
|
-
|
|
125
|
-
|
|
130
|
+
wallets: cached.wallets.map(import_internal.hydrateWallet).map((wallet) => {
|
|
131
|
+
if (wallet.icon) return wallet;
|
|
132
|
+
const cachedIcon = (0, import_internal.getCachedIcon)(wallet.id);
|
|
133
|
+
return cachedIcon ? { ...wallet, icon: cachedIcon } : wallet;
|
|
134
|
+
}).sort(import_internal.sortWallets),
|
|
135
|
+
accounts: cached.accounts.filter(
|
|
136
|
+
(account) => (0, import_internal.acceptsCachedAccount)(account, resolvedConfig.platforms)
|
|
137
|
+
).map(import_internal.hydrateAccount).sort(import_internal.sortAccounts),
|
|
138
|
+
config: resolvedConfig,
|
|
139
|
+
isHydrating: true
|
|
126
140
|
};
|
|
127
|
-
}, [
|
|
141
|
+
}, [kheopskitStore, resolvedConfig]);
|
|
128
142
|
const store = (0, import_react2.useMemo)(
|
|
129
143
|
() => createStore(
|
|
130
|
-
(0, import_core.getKheopskit$)(config, ssrCookies, kheopskitStore),
|
|
144
|
+
(0, import_core.getKheopskit$)(config, { ssrCookies, store: kheopskitStore }),
|
|
131
145
|
initialValue,
|
|
132
146
|
serverValue
|
|
133
147
|
),
|
|
@@ -153,9 +167,31 @@ var useWallets = () => {
|
|
|
153
167
|
throw new Error("useWallets can't be used without a KheopskitProvider");
|
|
154
168
|
return ctx.state;
|
|
155
169
|
};
|
|
170
|
+
|
|
171
|
+
// src/createKheopskit.tsx
|
|
172
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
173
|
+
var createKheopskit = (config) => {
|
|
174
|
+
const Provider = ({
|
|
175
|
+
children,
|
|
176
|
+
ssrCookies
|
|
177
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(KheopskitProvider, { config, ssrCookies, children });
|
|
178
|
+
Provider.displayName = "KheopskitProvider";
|
|
179
|
+
return {
|
|
180
|
+
KheopskitProvider: Provider,
|
|
181
|
+
/** Current state, typed to the bound platform tuple. */
|
|
182
|
+
useWallets: () => useWallets(),
|
|
183
|
+
/** Current accounts, typed to the bound platform tuple. */
|
|
184
|
+
useAccounts: () => useWallets().accounts
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// src/useAccounts.ts
|
|
189
|
+
var useAccounts = () => useWallets().accounts;
|
|
156
190
|
// Annotate the CommonJS export names for ESM import in node:
|
|
157
191
|
0 && (module.exports = {
|
|
158
192
|
KheopskitProvider,
|
|
193
|
+
createKheopskit,
|
|
194
|
+
useAccounts,
|
|
159
195
|
useWallets
|
|
160
196
|
});
|
|
161
197
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/KheopskitProvider.tsx","../src/context.ts","../src/createStore.ts","../src/useWallets.ts"],"sourcesContent":["export * from \"./KheopskitProvider\";\nexport * from \"./useWallets\";\n","import {\n\tcreateKheopskitStore,\n\tgetCachedIcon,\n\tgetKheopskit$,\n\thydrateAccount,\n\thydrateWallet,\n\ttype KheopskitConfig,\n\ttype KheopskitState,\n\tresolveConfig,\n} from \"@kheopskit/core\";\nimport {\n\ttype FC,\n\ttype PropsWithChildren,\n\tuseEffect,\n\tuseMemo,\n\tuseSyncExternalStore,\n} from \"react\";\nimport { KheopskitContext } from \"./context\";\nimport { createStore } from \"./createStore\";\n\nexport type KheopskitProviderProps = PropsWithChildren & {\n\tconfig?: Partial<KheopskitConfig>;\n\t/**\n\t * Cookie string for SSR hydration.\n\t * Pass the request cookie header (e.g., from Next.js headers or TanStack Start)\n\t * to hydrate wallet state on the server.\n\t *\n\t * @remarks\n\t * This value should be stable per render to avoid unnecessary store recreation.\n\t * Compute it once in your server component or layout and pass it down.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Next.js App Router\n\t * const cookieStore = await cookies();\n\t * const ssrCookies = cookieStore.getAll().map(c => `${c.name}=${c.value}`).join('; ');\n\t * return <Providers ssrCookies={ssrCookies}>{children}</Providers>\n\t * ```\n\t */\n\tssrCookies?: string;\n};\n\nexport const KheopskitProvider: FC<KheopskitProviderProps> = ({\n\tchildren,\n\tconfig,\n\tssrCookies,\n}) => {\n\tconst resolvedConfig = useMemo(() => resolveConfig(config), [config]);\n\n\t// Create a single store for both reading cached state and powering the observable\n\tconst kheopskitStore = useMemo(\n\t\t() =>\n\t\t\tcreateKheopskitStore({\n\t\t\t\tssrCookies,\n\t\t\t\tstorageKey: resolvedConfig.storageKey,\n\t\t\t}),\n\t\t[ssrCookies, resolvedConfig.storageKey],\n\t);\n\n\t// Read cached state from the store for SSR hydration\n\t// This produces wallets WITHOUT localStorage icons (Ethereum wallets have no icon)\n\t// because localStorage isn't available on server\n\tconst serverValue = useMemo<KheopskitState>(() => {\n\t\tif (ssrCookies === undefined) {\n\t\t\treturn {\n\t\t\t\twallets: [],\n\t\t\t\taccounts: [],\n\t\t\t\tconfig: resolvedConfig,\n\t\t\t\tisHydrating: true,\n\t\t\t};\n\t\t}\n\t\tconst cached = kheopskitStore.getCachedState();\n\t\treturn {\n\t\t\twallets: cached.wallets.map(hydrateWallet),\n\t\t\taccounts: cached.accounts\n\t\t\t\t.map(hydrateAccount)\n\t\t\t\t.filter(\n\t\t\t\t\t(account) =>\n\t\t\t\t\t\taccount.platform !== \"polkadot\" ||\n\t\t\t\t\t\tresolvedConfig.polkadotAccountTypes.includes(account.type),\n\t\t\t\t),\n\t\t\tconfig: resolvedConfig,\n\t\t\tisHydrating: true,\n\t\t};\n\t}, [ssrCookies, kheopskitStore, resolvedConfig]);\n\n\t// Initial value for client includes localStorage icons\n\t// This is what we WANT the client to render, not what server rendered\n\tconst initialValue = useMemo<KheopskitState>(() => {\n\t\t// On client, enrich wallets with localStorage icons\n\t\t// getCachedIcon returns empty on server (no localStorage), so this is safe\n\t\tconst enrichedWallets = serverValue.wallets.map((w) => {\n\t\t\tif (!w.icon) {\n\t\t\t\tconst cachedIcon = getCachedIcon(w.id);\n\t\t\t\tif (cachedIcon) {\n\t\t\t\t\treturn { ...w, icon: cachedIcon };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn w;\n\t\t});\n\t\treturn {\n\t\t\t...serverValue,\n\t\t\twallets: enrichedWallets,\n\t\t};\n\t}, [serverValue]);\n\n\tconst store = useMemo(\n\t\t() =>\n\t\t\tcreateStore(\n\t\t\t\tgetKheopskit$(config, ssrCookies, kheopskitStore),\n\t\t\t\tinitialValue,\n\t\t\t\tserverValue,\n\t\t\t),\n\t\t[config, ssrCookies, kheopskitStore, initialValue, serverValue],\n\t);\n\n\t// Cleanup store subscriptions when store changes or component unmounts\n\tuseEffect(() => {\n\t\treturn () => store.destroy();\n\t}, [store]);\n\n\tconst state = useSyncExternalStore(\n\t\tstore.subscribe,\n\t\tstore.getSnapshot,\n\t\tstore.getServerSnapshot,\n\t);\n\n\tconst value = useMemo(() => ({ state }), [state]);\n\n\treturn (\n\t\t<KheopskitContext.Provider value={value}>\n\t\t\t{children}\n\t\t</KheopskitContext.Provider>\n\t);\n};\n","import type { KheopskitState } from \"@kheopskit/core\";\nimport { createContext } from \"react\";\n\nexport const KheopskitContext = createContext<{\n\tstate: KheopskitState;\n} | null>(null);\n","import type { Observable, Subscription } from \"rxjs\";\n\nexport const createStore = <T>(\n\tobservable$: Observable<T>,\n\tinitialValue: T,\n\tserverValue?: T,\n) => {\n\t// Use null as sentinel to indicate we haven't received first emission yet\n\tlet latestValue: T | null = null;\n\tlet subscription: Subscription | null = null;\n\tlet subscriberCount = 0;\n\tconst listeners = new Set<(value: T) => void>();\n\n\tconst ensureSubscription = () => {\n\t\tif (!subscription || subscription.closed) {\n\t\t\tsubscription = observable$.subscribe((value) => {\n\t\t\t\tlatestValue = value;\n\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\tlistener(value);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t// Start subscription immediately\n\tensureSubscription();\n\n\t// If observable emitted synchronously, use that value\n\t// Otherwise fall back to initialValue\n\tconst getSnapshot = () => latestValue ?? initialValue;\n\n\t/**\n\t * Returns the server-side snapshot for SSR hydration.\n\t * This prevents hydration mismatches by providing a consistent\n\t * value during server rendering. Must return the same value as\n\t * what the server rendered.\n\t */\n\tconst getServerSnapshot = () => serverValue ?? initialValue;\n\n\tconst subscribe = (callback: (value: T) => void) => {\n\t\tsubscriberCount++;\n\t\tlisteners.add(callback);\n\t\t// Ensure observable subscription is active when someone subscribes\n\t\tensureSubscription();\n\n\t\t// Immediately emit current value (BehaviorSubject semantics)\n\t\tcallback(getSnapshot());\n\n\t\treturn () => {\n\t\t\tsubscriberCount--;\n\t\t\tlisteners.delete(callback);\n\t\t\t// Don't close the observable subscription on unsubscribe\n\t\t\t// Let destroy() handle that when the store is truly being disposed\n\t\t};\n\t};\n\n\tconst destroy = () => {\n\t\t// Only unsubscribe if no one is listening\n\t\t// React StrictMode may call destroy and then immediately resubscribe\n\t\tif (subscriberCount === 0 && subscription) {\n\t\t\tsubscription.unsubscribe();\n\t\t\tsubscription = null;\n\t\t}\n\t};\n\n\treturn {\n\t\tgetSnapshot,\n\t\tgetServerSnapshot,\n\t\tsubscribe,\n\t\tdestroy,\n\t};\n};\n","import { useContext } from \"react\";\nimport { KheopskitContext } from \"./context\";\n\nexport const useWallets = () => {\n\tconst ctx = useContext(KheopskitContext);\n\n\t// useEffect(() => {\n\t// console.debug(\n\t// \"useWallets wallets:%s accounts:%s\",\n\t// ctx?.state.wallets.length ?? 0,\n\t// ctx?.state.accounts.length ?? 0,\n\t// );\n\t// }, [ctx?.state]);\n\n\tif (!ctx)\n\t\tthrow new Error(\"useWallets can't be used without a KheopskitProvider\");\n\n\treturn ctx.state;\n};\n"],"mappings":"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","names":["import_react","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/KheopskitProvider.tsx","../src/context.ts","../src/createStore.ts","../src/useWallets.ts","../src/createKheopskit.tsx","../src/useAccounts.ts"],"sourcesContent":["export * from \"./createKheopskit\";\nexport * from \"./KheopskitProvider\";\nexport * from \"./useAccounts\";\nexport * from \"./useWallets\";\n","import {\n\tcreateKheopskitStore,\n\tgetKheopskit$,\n\ttype KheopskitConfig,\n\ttype KheopskitState,\n\tresolveConfig,\n} from \"@kheopskit/core\";\nimport {\n\tacceptsCachedAccount,\n\tgetCachedIcon,\n\thydrateAccount,\n\thydrateWallet,\n\tsortAccounts,\n\tsortWallets,\n} from \"@kheopskit/core/internal\";\nimport {\n\ttype FC,\n\ttype PropsWithChildren,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseSyncExternalStore,\n} from \"react\";\nimport { KheopskitContext } from \"./context\";\nimport { createStore } from \"./createStore\";\n\nexport type KheopskitProviderProps = PropsWithChildren & {\n\t/**\n\t * Kheopskit configuration.\n\t *\n\t * @remarks\n\t * Must be a **referentially stable** value — define it once (module scope, a\n\t * `useMemo`, or via {@link createKheopskit}) and pass the same reference. A\n\t * new object literal on every render (`config={{ platforms: [...] }}` inline)\n\t * recreates the underlying store and re-subscribes each render.\n\t */\n\tconfig?: Partial<KheopskitConfig>;\n\t/**\n\t * Cookie string for SSR hydration.\n\t * Pass the request cookie header (e.g., from Next.js headers or TanStack Start)\n\t * to hydrate wallet state on the server.\n\t *\n\t * @remarks\n\t * This value should be stable per render to avoid unnecessary store recreation.\n\t * Compute it once in your server component or layout and pass it down.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Next.js App Router\n\t * const cookieStore = await cookies();\n\t * const ssrCookies = cookieStore.getAll().map(c => `${c.name}=${c.value}`).join('; ');\n\t * return <Providers ssrCookies={ssrCookies}>{children}</Providers>\n\t * ```\n\t */\n\tssrCookies?: string;\n};\n\nexport const KheopskitProvider: FC<KheopskitProviderProps> = ({\n\tchildren,\n\tconfig,\n\tssrCookies,\n}) => {\n\tconst resolvedConfig = useMemo(() => resolveConfig(config), [config]);\n\n\t// Dev-only: warn if the `config` prop reference changes between renders. A new\n\t// object each render recreates the store and re-subscribes the whole pipeline\n\t// (re-hydrating, dropping live connection state) on every render. `config` must\n\t// be referentially stable — define it at module scope, memoize it, or use\n\t// createKheopskit() (which passes a stable reference for you).\n\tconst lastConfigRef = useRef(config);\n\tconst hasMountedRef = useRef(false);\n\tuseEffect(() => {\n\t\tif (\n\t\t\thasMountedRef.current &&\n\t\t\tlastConfigRef.current !== config &&\n\t\t\t(typeof process === \"undefined\" || process.env?.NODE_ENV !== \"production\")\n\t\t) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[kheopskit] KheopskitProvider received a new `config` reference; this \" +\n\t\t\t\t\t\"recreates the store and re-subscribes on every render. Pass a \" +\n\t\t\t\t\t\"referentially stable config (module scope, useMemo, or createKheopskit()).\",\n\t\t\t);\n\t\t}\n\t\thasMountedRef.current = true;\n\t\tlastConfigRef.current = config;\n\t}, [config]);\n\n\t// Create a single store for both reading cached state and powering the observable\n\tconst kheopskitStore = useMemo(\n\t\t() =>\n\t\t\tcreateKheopskitStore({\n\t\t\t\tssrCookies,\n\t\t\t\tstorageKey: resolvedConfig.storageKey,\n\t\t\t}),\n\t\t[ssrCookies, resolvedConfig.storageKey],\n\t);\n\n\t// Read cached state from the store for SSR hydration\n\t// This produces wallets WITHOUT localStorage icons (Ethereum wallets have no icon)\n\t// because localStorage isn't available on server\n\tconst serverValue = useMemo<KheopskitState>(() => {\n\t\tif (ssrCookies === undefined) {\n\t\t\treturn {\n\t\t\t\twallets: [],\n\t\t\t\taccounts: [],\n\t\t\t\tconfig: resolvedConfig,\n\t\t\t\tisHydrating: true,\n\t\t\t};\n\t\t}\n\t\tconst cached = kheopskitStore.getCachedState();\n\t\treturn {\n\t\t\twallets: cached.wallets.map(hydrateWallet).sort(sortWallets),\n\t\t\taccounts: cached.accounts\n\t\t\t\t.filter((account) =>\n\t\t\t\t\tacceptsCachedAccount(account, resolvedConfig.platforms),\n\t\t\t\t)\n\t\t\t\t.map(hydrateAccount)\n\t\t\t\t.sort(sortAccounts),\n\t\t\tconfig: resolvedConfig,\n\t\t\tisHydrating: true,\n\t\t};\n\t}, [ssrCookies, kheopskitStore, resolvedConfig]);\n\n\t// Client-only initial snapshot, read straight from the client cache so a hard\n\t// reload paints the cached wallet/account list on the very first frame instead\n\t// of flashing empty until the live observable produces its first emission —\n\t// which can be asynchronous (e.g. WalletConnect's AppKit is loaded via dynamic\n\t// import, so the underlying combineLatest can't emit synchronously).\n\t//\n\t// We can't derive this from `serverValue`: without SSR cookies that stays empty\n\t// (to keep the server/client hydration markup identical), so the SPA case would\n\t// otherwise render nothing. This snapshot is only ever read on the client via\n\t// getSnapshot, so reading the cache here is safe — and getCachedIcon returns \"\"\n\t// on the server, making the icon enrichment a no-op there.\n\tconst initialValue = useMemo<KheopskitState>(() => {\n\t\tconst cached = kheopskitStore.getCachedState();\n\t\treturn {\n\t\t\twallets: cached.wallets\n\t\t\t\t.map(hydrateWallet)\n\t\t\t\t.map((wallet) => {\n\t\t\t\t\tif (wallet.icon) return wallet;\n\t\t\t\t\tconst cachedIcon = getCachedIcon(wallet.id);\n\t\t\t\t\treturn cachedIcon ? { ...wallet, icon: cachedIcon } : wallet;\n\t\t\t\t})\n\t\t\t\t.sort(sortWallets),\n\t\t\taccounts: cached.accounts\n\t\t\t\t.filter((account) =>\n\t\t\t\t\tacceptsCachedAccount(account, resolvedConfig.platforms),\n\t\t\t\t)\n\t\t\t\t.map(hydrateAccount)\n\t\t\t\t.sort(sortAccounts),\n\t\t\tconfig: resolvedConfig,\n\t\t\tisHydrating: true,\n\t\t};\n\t}, [kheopskitStore, resolvedConfig]);\n\n\tconst store = useMemo(\n\t\t() =>\n\t\t\tcreateStore(\n\t\t\t\tgetKheopskit$(config, { ssrCookies, store: kheopskitStore }),\n\t\t\t\tinitialValue,\n\t\t\t\tserverValue,\n\t\t\t),\n\t\t[config, ssrCookies, kheopskitStore, initialValue, serverValue],\n\t);\n\n\t// Cleanup store subscriptions when store changes or component unmounts\n\tuseEffect(() => {\n\t\treturn () => store.destroy();\n\t}, [store]);\n\n\tconst state = useSyncExternalStore(\n\t\tstore.subscribe,\n\t\tstore.getSnapshot,\n\t\tstore.getServerSnapshot,\n\t);\n\n\tconst value = useMemo(() => ({ state }), [state]);\n\n\treturn (\n\t\t<KheopskitContext.Provider value={value}>\n\t\t\t{children}\n\t\t</KheopskitContext.Provider>\n\t);\n};\n","import type { KheopskitState } from \"@kheopskit/core\";\nimport { createContext } from \"react\";\n\nexport const KheopskitContext = createContext<{\n\tstate: KheopskitState;\n} | null>(null);\n","import type { Observable, Subscription } from \"rxjs\";\n\nexport const createStore = <T>(\n\tobservable$: Observable<T>,\n\tinitialValue: T,\n\tserverValue?: T,\n) => {\n\t// Use null as sentinel to indicate we haven't received first emission yet\n\tlet latestValue: T | null = null;\n\tlet subscription: Subscription | null = null;\n\tlet subscriberCount = 0;\n\tconst listeners = new Set<(value: T) => void>();\n\n\tconst ensureSubscription = () => {\n\t\tif (!subscription || subscription.closed) {\n\t\t\tsubscription = observable$.subscribe((value) => {\n\t\t\t\tlatestValue = value;\n\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\tlistener(value);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t// The subscription is created lazily by subscribe() (which React calls from a\n\t// committed passive effect), never during render. React may render a tree and\n\t// throw it away without committing — StrictMode double-invokes the initial\n\t// render, and concurrent/Suspense can discard renders — so subscribing eagerly\n\t// here (createStore runs inside the Provider's render-phase useMemo) would leak\n\t// the discarded store's observable subscription. Until the first emission,\n\t// getSnapshot falls back to initialValue.\n\tconst getSnapshot = () => latestValue ?? initialValue;\n\n\t/**\n\t * Returns the server-side snapshot for SSR hydration.\n\t * This prevents hydration mismatches by providing a consistent\n\t * value during server rendering. Must return the same value as\n\t * what the server rendered.\n\t */\n\tconst getServerSnapshot = () => serverValue ?? initialValue;\n\n\tconst subscribe = (callback: (value: T) => void) => {\n\t\tsubscriberCount++;\n\t\t// Subscribe to the observable BEFORE registering this listener, so a\n\t\t// synchronous replay (BehaviorSubject / shareReplay) updates latestValue\n\t\t// without double-invoking this callback — the current value is emitted once,\n\t\t// explicitly, just below.\n\t\tensureSubscription();\n\t\tlisteners.add(callback);\n\n\t\t// Immediately emit current value (BehaviorSubject semantics)\n\t\tcallback(getSnapshot());\n\n\t\treturn () => {\n\t\t\tsubscriberCount--;\n\t\t\tlisteners.delete(callback);\n\t\t\t// Don't close the observable subscription on unsubscribe\n\t\t\t// Let destroy() handle that when the store is truly being disposed\n\t\t};\n\t};\n\n\tconst destroy = () => {\n\t\t// Only unsubscribe if no one is listening\n\t\t// React StrictMode may call destroy and then immediately resubscribe\n\t\tif (subscriberCount === 0 && subscription) {\n\t\t\tsubscription.unsubscribe();\n\t\t\tsubscription = null;\n\t\t}\n\t};\n\n\treturn {\n\t\tgetSnapshot,\n\t\tgetServerSnapshot,\n\t\tsubscribe,\n\t\tdestroy,\n\t};\n};\n","import type { KheopskitPlatform, KheopskitState } from \"@kheopskit/core\";\nimport { useContext } from \"react\";\nimport { KheopskitContext } from \"./context\";\n\n/**\n * Returns the current kheopskit state (wallets, accounts, config, isHydrating).\n *\n * Pass the platform tuple as a type argument to recover SDK-precise account and\n * wallet types — `useWallets<typeof platforms>()`. React contexts can't be\n * generic, so without the argument the state is typed with the base\n * (SDK-free) wallet/account shapes.\n */\nexport const useWallets = <\n\tP extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n>(): KheopskitState<P> => {\n\tconst ctx = useContext(KheopskitContext);\n\n\tif (!ctx)\n\t\tthrow new Error(\"useWallets can't be used without a KheopskitProvider\");\n\n\treturn ctx.state as unknown as KheopskitState<P>;\n};\n","import type { KheopskitConfig, KheopskitPlatform } from \"@kheopskit/core\";\nimport type { FC, PropsWithChildren } from \"react\";\nimport { KheopskitProvider } from \"./KheopskitProvider\";\nimport { useWallets } from \"./useWallets\";\n\nexport type CreateKheopskitConfig<P extends readonly KheopskitPlatform[]> =\n\tOmit<Partial<KheopskitConfig<P>>, \"platforms\"> & {\n\t\t/** Platform plugins, e.g. `[polkadot(), solana()]`. Required. */\n\t\tplatforms: P;\n\t};\n\n/**\n * Binds a platform tuple once and returns a `KheopskitProvider` plus hooks\n * (`useWallets`, `useAccounts`) already typed to those platforms — so you don't\n * repeat `useWallets<typeof platforms>()` in every component.\n *\n * @example\n * ```tsx\n * // kheopskit.ts\n * export const { KheopskitProvider, useWallets, useAccounts } = createKheopskit({\n * platforms: [polkadot(), ethereum(), solana()],\n * });\n *\n * // anywhere\n * const { accounts } = useWallets(); // accounts are platform-precise, no generic\n * ```\n */\nexport const createKheopskit = <\n\tconst P extends readonly [KheopskitPlatform, ...KheopskitPlatform[]],\n>(\n\tconfig: CreateKheopskitConfig<P>,\n) => {\n\tconst Provider: FC<PropsWithChildren<{ ssrCookies?: string }>> = ({\n\t\tchildren,\n\t\tssrCookies,\n\t}) => (\n\t\t<KheopskitProvider config={config} ssrCookies={ssrCookies}>\n\t\t\t{children}\n\t\t</KheopskitProvider>\n\t);\n\tProvider.displayName = \"KheopskitProvider\";\n\n\treturn {\n\t\tKheopskitProvider: Provider,\n\t\t/** Current state, typed to the bound platform tuple. */\n\t\tuseWallets: () => useWallets<P>(),\n\t\t/** Current accounts, typed to the bound platform tuple. */\n\t\tuseAccounts: () => useWallets<P>().accounts,\n\t};\n};\n","import type { KheopskitPlatform } from \"@kheopskit/core\";\nimport { useWallets } from \"./useWallets\";\n\n/**\n * Convenience hook returning just the accounts from kheopskit state. Pass the\n * platform tuple as a type argument to recover SDK-precise account types —\n * `useAccounts<typeof platforms>()` — or use the pre-typed hook from\n * {@link createKheopskit}.\n */\nexport const useAccounts = <\n\tP extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n>() => useWallets<P>().accounts;\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
// src/KheopskitProvider.tsx
|
|
2
4
|
import {
|
|
3
5
|
createKheopskitStore,
|
|
4
|
-
getCachedIcon,
|
|
5
6
|
getKheopskit$,
|
|
6
|
-
hydrateAccount,
|
|
7
|
-
hydrateWallet,
|
|
8
7
|
resolveConfig
|
|
9
8
|
} from "@kheopskit/core";
|
|
9
|
+
import {
|
|
10
|
+
acceptsCachedAccount,
|
|
11
|
+
getCachedIcon,
|
|
12
|
+
hydrateAccount,
|
|
13
|
+
hydrateWallet,
|
|
14
|
+
sortAccounts,
|
|
15
|
+
sortWallets
|
|
16
|
+
} from "@kheopskit/core/internal";
|
|
10
17
|
import {
|
|
11
18
|
useEffect,
|
|
12
19
|
useMemo,
|
|
20
|
+
useRef,
|
|
13
21
|
useSyncExternalStore
|
|
14
22
|
} from "react";
|
|
15
23
|
|
|
@@ -33,13 +41,12 @@ var createStore = (observable$, initialValue, serverValue) => {
|
|
|
33
41
|
});
|
|
34
42
|
}
|
|
35
43
|
};
|
|
36
|
-
ensureSubscription();
|
|
37
44
|
const getSnapshot = () => latestValue ?? initialValue;
|
|
38
45
|
const getServerSnapshot = () => serverValue ?? initialValue;
|
|
39
46
|
const subscribe = (callback) => {
|
|
40
47
|
subscriberCount++;
|
|
41
|
-
listeners.add(callback);
|
|
42
48
|
ensureSubscription();
|
|
49
|
+
listeners.add(callback);
|
|
43
50
|
callback(getSnapshot());
|
|
44
51
|
return () => {
|
|
45
52
|
subscriberCount--;
|
|
@@ -68,6 +75,17 @@ var KheopskitProvider = ({
|
|
|
68
75
|
ssrCookies
|
|
69
76
|
}) => {
|
|
70
77
|
const resolvedConfig = useMemo(() => resolveConfig(config), [config]);
|
|
78
|
+
const lastConfigRef = useRef(config);
|
|
79
|
+
const hasMountedRef = useRef(false);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (hasMountedRef.current && lastConfigRef.current !== config && (typeof process === "undefined" || process.env?.NODE_ENV !== "production")) {
|
|
82
|
+
console.warn(
|
|
83
|
+
"[kheopskit] KheopskitProvider received a new `config` reference; this recreates the store and re-subscribes on every render. Pass a referentially stable config (module scope, useMemo, or createKheopskit())."
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
hasMountedRef.current = true;
|
|
87
|
+
lastConfigRef.current = config;
|
|
88
|
+
}, [config]);
|
|
71
89
|
const kheopskitStore = useMemo(
|
|
72
90
|
() => createKheopskitStore({
|
|
73
91
|
ssrCookies,
|
|
@@ -86,32 +104,32 @@ var KheopskitProvider = ({
|
|
|
86
104
|
}
|
|
87
105
|
const cached = kheopskitStore.getCachedState();
|
|
88
106
|
return {
|
|
89
|
-
wallets: cached.wallets.map(hydrateWallet),
|
|
90
|
-
accounts: cached.accounts.
|
|
91
|
-
(account) => account
|
|
92
|
-
),
|
|
107
|
+
wallets: cached.wallets.map(hydrateWallet).sort(sortWallets),
|
|
108
|
+
accounts: cached.accounts.filter(
|
|
109
|
+
(account) => acceptsCachedAccount(account, resolvedConfig.platforms)
|
|
110
|
+
).map(hydrateAccount).sort(sortAccounts),
|
|
93
111
|
config: resolvedConfig,
|
|
94
112
|
isHydrating: true
|
|
95
113
|
};
|
|
96
114
|
}, [ssrCookies, kheopskitStore, resolvedConfig]);
|
|
97
115
|
const initialValue = useMemo(() => {
|
|
98
|
-
const
|
|
99
|
-
if (!w.icon) {
|
|
100
|
-
const cachedIcon = getCachedIcon(w.id);
|
|
101
|
-
if (cachedIcon) {
|
|
102
|
-
return { ...w, icon: cachedIcon };
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return w;
|
|
106
|
-
});
|
|
116
|
+
const cached = kheopskitStore.getCachedState();
|
|
107
117
|
return {
|
|
108
|
-
|
|
109
|
-
|
|
118
|
+
wallets: cached.wallets.map(hydrateWallet).map((wallet) => {
|
|
119
|
+
if (wallet.icon) return wallet;
|
|
120
|
+
const cachedIcon = getCachedIcon(wallet.id);
|
|
121
|
+
return cachedIcon ? { ...wallet, icon: cachedIcon } : wallet;
|
|
122
|
+
}).sort(sortWallets),
|
|
123
|
+
accounts: cached.accounts.filter(
|
|
124
|
+
(account) => acceptsCachedAccount(account, resolvedConfig.platforms)
|
|
125
|
+
).map(hydrateAccount).sort(sortAccounts),
|
|
126
|
+
config: resolvedConfig,
|
|
127
|
+
isHydrating: true
|
|
110
128
|
};
|
|
111
|
-
}, [
|
|
129
|
+
}, [kheopskitStore, resolvedConfig]);
|
|
112
130
|
const store = useMemo(
|
|
113
131
|
() => createStore(
|
|
114
|
-
getKheopskit$(config, ssrCookies, kheopskitStore),
|
|
132
|
+
getKheopskit$(config, { ssrCookies, store: kheopskitStore }),
|
|
115
133
|
initialValue,
|
|
116
134
|
serverValue
|
|
117
135
|
),
|
|
@@ -137,8 +155,30 @@ var useWallets = () => {
|
|
|
137
155
|
throw new Error("useWallets can't be used without a KheopskitProvider");
|
|
138
156
|
return ctx.state;
|
|
139
157
|
};
|
|
158
|
+
|
|
159
|
+
// src/createKheopskit.tsx
|
|
160
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
161
|
+
var createKheopskit = (config) => {
|
|
162
|
+
const Provider = ({
|
|
163
|
+
children,
|
|
164
|
+
ssrCookies
|
|
165
|
+
}) => /* @__PURE__ */ jsx2(KheopskitProvider, { config, ssrCookies, children });
|
|
166
|
+
Provider.displayName = "KheopskitProvider";
|
|
167
|
+
return {
|
|
168
|
+
KheopskitProvider: Provider,
|
|
169
|
+
/** Current state, typed to the bound platform tuple. */
|
|
170
|
+
useWallets: () => useWallets(),
|
|
171
|
+
/** Current accounts, typed to the bound platform tuple. */
|
|
172
|
+
useAccounts: () => useWallets().accounts
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// src/useAccounts.ts
|
|
177
|
+
var useAccounts = () => useWallets().accounts;
|
|
140
178
|
export {
|
|
141
179
|
KheopskitProvider,
|
|
180
|
+
createKheopskit,
|
|
181
|
+
useAccounts,
|
|
142
182
|
useWallets
|
|
143
183
|
};
|
|
144
184
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/KheopskitProvider.tsx","../src/context.ts","../src/createStore.ts","../src/useWallets.ts"],"sourcesContent":["import {\n\tcreateKheopskitStore,\n\tgetCachedIcon,\n\tgetKheopskit$,\n\thydrateAccount,\n\thydrateWallet,\n\ttype KheopskitConfig,\n\ttype KheopskitState,\n\tresolveConfig,\n} from \"@kheopskit/core\";\nimport {\n\ttype FC,\n\ttype PropsWithChildren,\n\tuseEffect,\n\tuseMemo,\n\tuseSyncExternalStore,\n} from \"react\";\nimport { KheopskitContext } from \"./context\";\nimport { createStore } from \"./createStore\";\n\nexport type KheopskitProviderProps = PropsWithChildren & {\n\tconfig?: Partial<KheopskitConfig>;\n\t/**\n\t * Cookie string for SSR hydration.\n\t * Pass the request cookie header (e.g., from Next.js headers or TanStack Start)\n\t * to hydrate wallet state on the server.\n\t *\n\t * @remarks\n\t * This value should be stable per render to avoid unnecessary store recreation.\n\t * Compute it once in your server component or layout and pass it down.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Next.js App Router\n\t * const cookieStore = await cookies();\n\t * const ssrCookies = cookieStore.getAll().map(c => `${c.name}=${c.value}`).join('; ');\n\t * return <Providers ssrCookies={ssrCookies}>{children}</Providers>\n\t * ```\n\t */\n\tssrCookies?: string;\n};\n\nexport const KheopskitProvider: FC<KheopskitProviderProps> = ({\n\tchildren,\n\tconfig,\n\tssrCookies,\n}) => {\n\tconst resolvedConfig = useMemo(() => resolveConfig(config), [config]);\n\n\t// Create a single store for both reading cached state and powering the observable\n\tconst kheopskitStore = useMemo(\n\t\t() =>\n\t\t\tcreateKheopskitStore({\n\t\t\t\tssrCookies,\n\t\t\t\tstorageKey: resolvedConfig.storageKey,\n\t\t\t}),\n\t\t[ssrCookies, resolvedConfig.storageKey],\n\t);\n\n\t// Read cached state from the store for SSR hydration\n\t// This produces wallets WITHOUT localStorage icons (Ethereum wallets have no icon)\n\t// because localStorage isn't available on server\n\tconst serverValue = useMemo<KheopskitState>(() => {\n\t\tif (ssrCookies === undefined) {\n\t\t\treturn {\n\t\t\t\twallets: [],\n\t\t\t\taccounts: [],\n\t\t\t\tconfig: resolvedConfig,\n\t\t\t\tisHydrating: true,\n\t\t\t};\n\t\t}\n\t\tconst cached = kheopskitStore.getCachedState();\n\t\treturn {\n\t\t\twallets: cached.wallets.map(hydrateWallet),\n\t\t\taccounts: cached.accounts\n\t\t\t\t.map(hydrateAccount)\n\t\t\t\t.filter(\n\t\t\t\t\t(account) =>\n\t\t\t\t\t\taccount.platform !== \"polkadot\" ||\n\t\t\t\t\t\tresolvedConfig.polkadotAccountTypes.includes(account.type),\n\t\t\t\t),\n\t\t\tconfig: resolvedConfig,\n\t\t\tisHydrating: true,\n\t\t};\n\t}, [ssrCookies, kheopskitStore, resolvedConfig]);\n\n\t// Initial value for client includes localStorage icons\n\t// This is what we WANT the client to render, not what server rendered\n\tconst initialValue = useMemo<KheopskitState>(() => {\n\t\t// On client, enrich wallets with localStorage icons\n\t\t// getCachedIcon returns empty on server (no localStorage), so this is safe\n\t\tconst enrichedWallets = serverValue.wallets.map((w) => {\n\t\t\tif (!w.icon) {\n\t\t\t\tconst cachedIcon = getCachedIcon(w.id);\n\t\t\t\tif (cachedIcon) {\n\t\t\t\t\treturn { ...w, icon: cachedIcon };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn w;\n\t\t});\n\t\treturn {\n\t\t\t...serverValue,\n\t\t\twallets: enrichedWallets,\n\t\t};\n\t}, [serverValue]);\n\n\tconst store = useMemo(\n\t\t() =>\n\t\t\tcreateStore(\n\t\t\t\tgetKheopskit$(config, ssrCookies, kheopskitStore),\n\t\t\t\tinitialValue,\n\t\t\t\tserverValue,\n\t\t\t),\n\t\t[config, ssrCookies, kheopskitStore, initialValue, serverValue],\n\t);\n\n\t// Cleanup store subscriptions when store changes or component unmounts\n\tuseEffect(() => {\n\t\treturn () => store.destroy();\n\t}, [store]);\n\n\tconst state = useSyncExternalStore(\n\t\tstore.subscribe,\n\t\tstore.getSnapshot,\n\t\tstore.getServerSnapshot,\n\t);\n\n\tconst value = useMemo(() => ({ state }), [state]);\n\n\treturn (\n\t\t<KheopskitContext.Provider value={value}>\n\t\t\t{children}\n\t\t</KheopskitContext.Provider>\n\t);\n};\n","import type { KheopskitState } from \"@kheopskit/core\";\nimport { createContext } from \"react\";\n\nexport const KheopskitContext = createContext<{\n\tstate: KheopskitState;\n} | null>(null);\n","import type { Observable, Subscription } from \"rxjs\";\n\nexport const createStore = <T>(\n\tobservable$: Observable<T>,\n\tinitialValue: T,\n\tserverValue?: T,\n) => {\n\t// Use null as sentinel to indicate we haven't received first emission yet\n\tlet latestValue: T | null = null;\n\tlet subscription: Subscription | null = null;\n\tlet subscriberCount = 0;\n\tconst listeners = new Set<(value: T) => void>();\n\n\tconst ensureSubscription = () => {\n\t\tif (!subscription || subscription.closed) {\n\t\t\tsubscription = observable$.subscribe((value) => {\n\t\t\t\tlatestValue = value;\n\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\tlistener(value);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t// Start subscription immediately\n\tensureSubscription();\n\n\t// If observable emitted synchronously, use that value\n\t// Otherwise fall back to initialValue\n\tconst getSnapshot = () => latestValue ?? initialValue;\n\n\t/**\n\t * Returns the server-side snapshot for SSR hydration.\n\t * This prevents hydration mismatches by providing a consistent\n\t * value during server rendering. Must return the same value as\n\t * what the server rendered.\n\t */\n\tconst getServerSnapshot = () => serverValue ?? initialValue;\n\n\tconst subscribe = (callback: (value: T) => void) => {\n\t\tsubscriberCount++;\n\t\tlisteners.add(callback);\n\t\t// Ensure observable subscription is active when someone subscribes\n\t\tensureSubscription();\n\n\t\t// Immediately emit current value (BehaviorSubject semantics)\n\t\tcallback(getSnapshot());\n\n\t\treturn () => {\n\t\t\tsubscriberCount--;\n\t\t\tlisteners.delete(callback);\n\t\t\t// Don't close the observable subscription on unsubscribe\n\t\t\t// Let destroy() handle that when the store is truly being disposed\n\t\t};\n\t};\n\n\tconst destroy = () => {\n\t\t// Only unsubscribe if no one is listening\n\t\t// React StrictMode may call destroy and then immediately resubscribe\n\t\tif (subscriberCount === 0 && subscription) {\n\t\t\tsubscription.unsubscribe();\n\t\t\tsubscription = null;\n\t\t}\n\t};\n\n\treturn {\n\t\tgetSnapshot,\n\t\tgetServerSnapshot,\n\t\tsubscribe,\n\t\tdestroy,\n\t};\n};\n","import { useContext } from \"react\";\nimport { KheopskitContext } from \"./context\";\n\nexport const useWallets = () => {\n\tconst ctx = useContext(KheopskitContext);\n\n\t// useEffect(() => {\n\t// console.debug(\n\t// \"useWallets wallets:%s accounts:%s\",\n\t// ctx?.state.wallets.length ?? 0,\n\t// ctx?.state.accounts.length ?? 0,\n\t// );\n\t// }, [ctx?.state]);\n\n\tif (!ctx)\n\t\tthrow new Error(\"useWallets can't be used without a KheopskitProvider\");\n\n\treturn ctx.state;\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/KheopskitProvider.tsx","../src/context.ts","../src/createStore.ts","../src/useWallets.ts","../src/createKheopskit.tsx","../src/useAccounts.ts"],"sourcesContent":["import {\n\tcreateKheopskitStore,\n\tgetKheopskit$,\n\ttype KheopskitConfig,\n\ttype KheopskitState,\n\tresolveConfig,\n} from \"@kheopskit/core\";\nimport {\n\tacceptsCachedAccount,\n\tgetCachedIcon,\n\thydrateAccount,\n\thydrateWallet,\n\tsortAccounts,\n\tsortWallets,\n} from \"@kheopskit/core/internal\";\nimport {\n\ttype FC,\n\ttype PropsWithChildren,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseSyncExternalStore,\n} from \"react\";\nimport { KheopskitContext } from \"./context\";\nimport { createStore } from \"./createStore\";\n\nexport type KheopskitProviderProps = PropsWithChildren & {\n\t/**\n\t * Kheopskit configuration.\n\t *\n\t * @remarks\n\t * Must be a **referentially stable** value — define it once (module scope, a\n\t * `useMemo`, or via {@link createKheopskit}) and pass the same reference. A\n\t * new object literal on every render (`config={{ platforms: [...] }}` inline)\n\t * recreates the underlying store and re-subscribes each render.\n\t */\n\tconfig?: Partial<KheopskitConfig>;\n\t/**\n\t * Cookie string for SSR hydration.\n\t * Pass the request cookie header (e.g., from Next.js headers or TanStack Start)\n\t * to hydrate wallet state on the server.\n\t *\n\t * @remarks\n\t * This value should be stable per render to avoid unnecessary store recreation.\n\t * Compute it once in your server component or layout and pass it down.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Next.js App Router\n\t * const cookieStore = await cookies();\n\t * const ssrCookies = cookieStore.getAll().map(c => `${c.name}=${c.value}`).join('; ');\n\t * return <Providers ssrCookies={ssrCookies}>{children}</Providers>\n\t * ```\n\t */\n\tssrCookies?: string;\n};\n\nexport const KheopskitProvider: FC<KheopskitProviderProps> = ({\n\tchildren,\n\tconfig,\n\tssrCookies,\n}) => {\n\tconst resolvedConfig = useMemo(() => resolveConfig(config), [config]);\n\n\t// Dev-only: warn if the `config` prop reference changes between renders. A new\n\t// object each render recreates the store and re-subscribes the whole pipeline\n\t// (re-hydrating, dropping live connection state) on every render. `config` must\n\t// be referentially stable — define it at module scope, memoize it, or use\n\t// createKheopskit() (which passes a stable reference for you).\n\tconst lastConfigRef = useRef(config);\n\tconst hasMountedRef = useRef(false);\n\tuseEffect(() => {\n\t\tif (\n\t\t\thasMountedRef.current &&\n\t\t\tlastConfigRef.current !== config &&\n\t\t\t(typeof process === \"undefined\" || process.env?.NODE_ENV !== \"production\")\n\t\t) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[kheopskit] KheopskitProvider received a new `config` reference; this \" +\n\t\t\t\t\t\"recreates the store and re-subscribes on every render. Pass a \" +\n\t\t\t\t\t\"referentially stable config (module scope, useMemo, or createKheopskit()).\",\n\t\t\t);\n\t\t}\n\t\thasMountedRef.current = true;\n\t\tlastConfigRef.current = config;\n\t}, [config]);\n\n\t// Create a single store for both reading cached state and powering the observable\n\tconst kheopskitStore = useMemo(\n\t\t() =>\n\t\t\tcreateKheopskitStore({\n\t\t\t\tssrCookies,\n\t\t\t\tstorageKey: resolvedConfig.storageKey,\n\t\t\t}),\n\t\t[ssrCookies, resolvedConfig.storageKey],\n\t);\n\n\t// Read cached state from the store for SSR hydration\n\t// This produces wallets WITHOUT localStorage icons (Ethereum wallets have no icon)\n\t// because localStorage isn't available on server\n\tconst serverValue = useMemo<KheopskitState>(() => {\n\t\tif (ssrCookies === undefined) {\n\t\t\treturn {\n\t\t\t\twallets: [],\n\t\t\t\taccounts: [],\n\t\t\t\tconfig: resolvedConfig,\n\t\t\t\tisHydrating: true,\n\t\t\t};\n\t\t}\n\t\tconst cached = kheopskitStore.getCachedState();\n\t\treturn {\n\t\t\twallets: cached.wallets.map(hydrateWallet).sort(sortWallets),\n\t\t\taccounts: cached.accounts\n\t\t\t\t.filter((account) =>\n\t\t\t\t\tacceptsCachedAccount(account, resolvedConfig.platforms),\n\t\t\t\t)\n\t\t\t\t.map(hydrateAccount)\n\t\t\t\t.sort(sortAccounts),\n\t\t\tconfig: resolvedConfig,\n\t\t\tisHydrating: true,\n\t\t};\n\t}, [ssrCookies, kheopskitStore, resolvedConfig]);\n\n\t// Client-only initial snapshot, read straight from the client cache so a hard\n\t// reload paints the cached wallet/account list on the very first frame instead\n\t// of flashing empty until the live observable produces its first emission —\n\t// which can be asynchronous (e.g. WalletConnect's AppKit is loaded via dynamic\n\t// import, so the underlying combineLatest can't emit synchronously).\n\t//\n\t// We can't derive this from `serverValue`: without SSR cookies that stays empty\n\t// (to keep the server/client hydration markup identical), so the SPA case would\n\t// otherwise render nothing. This snapshot is only ever read on the client via\n\t// getSnapshot, so reading the cache here is safe — and getCachedIcon returns \"\"\n\t// on the server, making the icon enrichment a no-op there.\n\tconst initialValue = useMemo<KheopskitState>(() => {\n\t\tconst cached = kheopskitStore.getCachedState();\n\t\treturn {\n\t\t\twallets: cached.wallets\n\t\t\t\t.map(hydrateWallet)\n\t\t\t\t.map((wallet) => {\n\t\t\t\t\tif (wallet.icon) return wallet;\n\t\t\t\t\tconst cachedIcon = getCachedIcon(wallet.id);\n\t\t\t\t\treturn cachedIcon ? { ...wallet, icon: cachedIcon } : wallet;\n\t\t\t\t})\n\t\t\t\t.sort(sortWallets),\n\t\t\taccounts: cached.accounts\n\t\t\t\t.filter((account) =>\n\t\t\t\t\tacceptsCachedAccount(account, resolvedConfig.platforms),\n\t\t\t\t)\n\t\t\t\t.map(hydrateAccount)\n\t\t\t\t.sort(sortAccounts),\n\t\t\tconfig: resolvedConfig,\n\t\t\tisHydrating: true,\n\t\t};\n\t}, [kheopskitStore, resolvedConfig]);\n\n\tconst store = useMemo(\n\t\t() =>\n\t\t\tcreateStore(\n\t\t\t\tgetKheopskit$(config, { ssrCookies, store: kheopskitStore }),\n\t\t\t\tinitialValue,\n\t\t\t\tserverValue,\n\t\t\t),\n\t\t[config, ssrCookies, kheopskitStore, initialValue, serverValue],\n\t);\n\n\t// Cleanup store subscriptions when store changes or component unmounts\n\tuseEffect(() => {\n\t\treturn () => store.destroy();\n\t}, [store]);\n\n\tconst state = useSyncExternalStore(\n\t\tstore.subscribe,\n\t\tstore.getSnapshot,\n\t\tstore.getServerSnapshot,\n\t);\n\n\tconst value = useMemo(() => ({ state }), [state]);\n\n\treturn (\n\t\t<KheopskitContext.Provider value={value}>\n\t\t\t{children}\n\t\t</KheopskitContext.Provider>\n\t);\n};\n","import type { KheopskitState } from \"@kheopskit/core\";\nimport { createContext } from \"react\";\n\nexport const KheopskitContext = createContext<{\n\tstate: KheopskitState;\n} | null>(null);\n","import type { Observable, Subscription } from \"rxjs\";\n\nexport const createStore = <T>(\n\tobservable$: Observable<T>,\n\tinitialValue: T,\n\tserverValue?: T,\n) => {\n\t// Use null as sentinel to indicate we haven't received first emission yet\n\tlet latestValue: T | null = null;\n\tlet subscription: Subscription | null = null;\n\tlet subscriberCount = 0;\n\tconst listeners = new Set<(value: T) => void>();\n\n\tconst ensureSubscription = () => {\n\t\tif (!subscription || subscription.closed) {\n\t\t\tsubscription = observable$.subscribe((value) => {\n\t\t\t\tlatestValue = value;\n\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\tlistener(value);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t// The subscription is created lazily by subscribe() (which React calls from a\n\t// committed passive effect), never during render. React may render a tree and\n\t// throw it away without committing — StrictMode double-invokes the initial\n\t// render, and concurrent/Suspense can discard renders — so subscribing eagerly\n\t// here (createStore runs inside the Provider's render-phase useMemo) would leak\n\t// the discarded store's observable subscription. Until the first emission,\n\t// getSnapshot falls back to initialValue.\n\tconst getSnapshot = () => latestValue ?? initialValue;\n\n\t/**\n\t * Returns the server-side snapshot for SSR hydration.\n\t * This prevents hydration mismatches by providing a consistent\n\t * value during server rendering. Must return the same value as\n\t * what the server rendered.\n\t */\n\tconst getServerSnapshot = () => serverValue ?? initialValue;\n\n\tconst subscribe = (callback: (value: T) => void) => {\n\t\tsubscriberCount++;\n\t\t// Subscribe to the observable BEFORE registering this listener, so a\n\t\t// synchronous replay (BehaviorSubject / shareReplay) updates latestValue\n\t\t// without double-invoking this callback — the current value is emitted once,\n\t\t// explicitly, just below.\n\t\tensureSubscription();\n\t\tlisteners.add(callback);\n\n\t\t// Immediately emit current value (BehaviorSubject semantics)\n\t\tcallback(getSnapshot());\n\n\t\treturn () => {\n\t\t\tsubscriberCount--;\n\t\t\tlisteners.delete(callback);\n\t\t\t// Don't close the observable subscription on unsubscribe\n\t\t\t// Let destroy() handle that when the store is truly being disposed\n\t\t};\n\t};\n\n\tconst destroy = () => {\n\t\t// Only unsubscribe if no one is listening\n\t\t// React StrictMode may call destroy and then immediately resubscribe\n\t\tif (subscriberCount === 0 && subscription) {\n\t\t\tsubscription.unsubscribe();\n\t\t\tsubscription = null;\n\t\t}\n\t};\n\n\treturn {\n\t\tgetSnapshot,\n\t\tgetServerSnapshot,\n\t\tsubscribe,\n\t\tdestroy,\n\t};\n};\n","import type { KheopskitPlatform, KheopskitState } from \"@kheopskit/core\";\nimport { useContext } from \"react\";\nimport { KheopskitContext } from \"./context\";\n\n/**\n * Returns the current kheopskit state (wallets, accounts, config, isHydrating).\n *\n * Pass the platform tuple as a type argument to recover SDK-precise account and\n * wallet types — `useWallets<typeof platforms>()`. React contexts can't be\n * generic, so without the argument the state is typed with the base\n * (SDK-free) wallet/account shapes.\n */\nexport const useWallets = <\n\tP extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n>(): KheopskitState<P> => {\n\tconst ctx = useContext(KheopskitContext);\n\n\tif (!ctx)\n\t\tthrow new Error(\"useWallets can't be used without a KheopskitProvider\");\n\n\treturn ctx.state as unknown as KheopskitState<P>;\n};\n","import type { KheopskitConfig, KheopskitPlatform } from \"@kheopskit/core\";\nimport type { FC, PropsWithChildren } from \"react\";\nimport { KheopskitProvider } from \"./KheopskitProvider\";\nimport { useWallets } from \"./useWallets\";\n\nexport type CreateKheopskitConfig<P extends readonly KheopskitPlatform[]> =\n\tOmit<Partial<KheopskitConfig<P>>, \"platforms\"> & {\n\t\t/** Platform plugins, e.g. `[polkadot(), solana()]`. Required. */\n\t\tplatforms: P;\n\t};\n\n/**\n * Binds a platform tuple once and returns a `KheopskitProvider` plus hooks\n * (`useWallets`, `useAccounts`) already typed to those platforms — so you don't\n * repeat `useWallets<typeof platforms>()` in every component.\n *\n * @example\n * ```tsx\n * // kheopskit.ts\n * export const { KheopskitProvider, useWallets, useAccounts } = createKheopskit({\n * platforms: [polkadot(), ethereum(), solana()],\n * });\n *\n * // anywhere\n * const { accounts } = useWallets(); // accounts are platform-precise, no generic\n * ```\n */\nexport const createKheopskit = <\n\tconst P extends readonly [KheopskitPlatform, ...KheopskitPlatform[]],\n>(\n\tconfig: CreateKheopskitConfig<P>,\n) => {\n\tconst Provider: FC<PropsWithChildren<{ ssrCookies?: string }>> = ({\n\t\tchildren,\n\t\tssrCookies,\n\t}) => (\n\t\t<KheopskitProvider config={config} ssrCookies={ssrCookies}>\n\t\t\t{children}\n\t\t</KheopskitProvider>\n\t);\n\tProvider.displayName = \"KheopskitProvider\";\n\n\treturn {\n\t\tKheopskitProvider: Provider,\n\t\t/** Current state, typed to the bound platform tuple. */\n\t\tuseWallets: () => useWallets<P>(),\n\t\t/** Current accounts, typed to the bound platform tuple. */\n\t\tuseAccounts: () => useWallets<P>().accounts,\n\t};\n};\n","import type { KheopskitPlatform } from \"@kheopskit/core\";\nimport { useWallets } from \"./useWallets\";\n\n/**\n * Convenience hook returning just the accounts from kheopskit state. Pass the\n * platform tuple as a type argument to recover SDK-precise account types —\n * `useAccounts<typeof platforms>()` — or use the pre-typed hook from\n * {@link createKheopskit}.\n */\nexport const useAccounts = <\n\tP extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n>() => useWallets<P>().accounts;\n"],"mappings":";;;AAAA;AAAA,EACC;AAAA,EACA;AAAA,EAGA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP;AAAA,EAGC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;;;ACrBP,SAAS,qBAAqB;AAEvB,IAAM,mBAAmB,cAEtB,IAAI;;;ACHP,IAAM,cAAc,CAC1B,aACA,cACA,gBACI;AAEJ,MAAI,cAAwB;AAC5B,MAAI,eAAoC;AACxC,MAAI,kBAAkB;AACtB,QAAM,YAAY,oBAAI,IAAwB;AAE9C,QAAM,qBAAqB,MAAM;AAChC,QAAI,CAAC,gBAAgB,aAAa,QAAQ;AACzC,qBAAe,YAAY,UAAU,CAAC,UAAU;AAC/C,sBAAc;AACd,mBAAW,YAAY,WAAW;AACjC,mBAAS,KAAK;AAAA,QACf;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AASA,QAAM,cAAc,MAAM,eAAe;AAQzC,QAAM,oBAAoB,MAAM,eAAe;AAE/C,QAAM,YAAY,CAAC,aAAiC;AACnD;AAKA,uBAAmB;AACnB,cAAU,IAAI,QAAQ;AAGtB,aAAS,YAAY,CAAC;AAEtB,WAAO,MAAM;AACZ;AACA,gBAAU,OAAO,QAAQ;AAAA,IAG1B;AAAA,EACD;AAEA,QAAM,UAAU,MAAM;AAGrB,QAAI,oBAAoB,KAAK,cAAc;AAC1C,mBAAa,YAAY;AACzB,qBAAe;AAAA,IAChB;AAAA,EACD;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;;;AFwGE;AA3HK,IAAM,oBAAgD,CAAC;AAAA,EAC7D;AAAA,EACA;AAAA,EACA;AACD,MAAM;AACL,QAAM,iBAAiB,QAAQ,MAAM,cAAc,MAAM,GAAG,CAAC,MAAM,CAAC;AAOpE,QAAM,gBAAgB,OAAO,MAAM;AACnC,QAAM,gBAAgB,OAAO,KAAK;AAClC,YAAU,MAAM;AACf,QACC,cAAc,WACd,cAAc,YAAY,WACzB,OAAO,YAAY,eAAe,QAAQ,KAAK,aAAa,eAC5D;AACD,cAAQ;AAAA,QACP;AAAA,MAGD;AAAA,IACD;AACA,kBAAc,UAAU;AACxB,kBAAc,UAAU;AAAA,EACzB,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,iBAAiB;AAAA,IACtB,MACC,qBAAqB;AAAA,MACpB;AAAA,MACA,YAAY,eAAe;AAAA,IAC5B,CAAC;AAAA,IACF,CAAC,YAAY,eAAe,UAAU;AAAA,EACvC;AAKA,QAAM,cAAc,QAAwB,MAAM;AACjD,QAAI,eAAe,QAAW;AAC7B,aAAO;AAAA,QACN,SAAS,CAAC;AAAA,QACV,UAAU,CAAC;AAAA,QACX,QAAQ;AAAA,QACR,aAAa;AAAA,MACd;AAAA,IACD;AACA,UAAM,SAAS,eAAe,eAAe;AAC7C,WAAO;AAAA,MACN,SAAS,OAAO,QAAQ,IAAI,aAAa,EAAE,KAAK,WAAW;AAAA,MAC3D,UAAU,OAAO,SACf;AAAA,QAAO,CAAC,YACR,qBAAqB,SAAS,eAAe,SAAS;AAAA,MACvD,EACC,IAAI,cAAc,EAClB,KAAK,YAAY;AAAA,MACnB,QAAQ;AAAA,MACR,aAAa;AAAA,IACd;AAAA,EACD,GAAG,CAAC,YAAY,gBAAgB,cAAc,CAAC;AAa/C,QAAM,eAAe,QAAwB,MAAM;AAClD,UAAM,SAAS,eAAe,eAAe;AAC7C,WAAO;AAAA,MACN,SAAS,OAAO,QACd,IAAI,aAAa,EACjB,IAAI,CAAC,WAAW;AAChB,YAAI,OAAO,KAAM,QAAO;AACxB,cAAM,aAAa,cAAc,OAAO,EAAE;AAC1C,eAAO,aAAa,EAAE,GAAG,QAAQ,MAAM,WAAW,IAAI;AAAA,MACvD,CAAC,EACA,KAAK,WAAW;AAAA,MAClB,UAAU,OAAO,SACf;AAAA,QAAO,CAAC,YACR,qBAAqB,SAAS,eAAe,SAAS;AAAA,MACvD,EACC,IAAI,cAAc,EAClB,KAAK,YAAY;AAAA,MACnB,QAAQ;AAAA,MACR,aAAa;AAAA,IACd;AAAA,EACD,GAAG,CAAC,gBAAgB,cAAc,CAAC;AAEnC,QAAM,QAAQ;AAAA,IACb,MACC;AAAA,MACC,cAAc,QAAQ,EAAE,YAAY,OAAO,eAAe,CAAC;AAAA,MAC3D;AAAA,MACA;AAAA,IACD;AAAA,IACD,CAAC,QAAQ,YAAY,gBAAgB,cAAc,WAAW;AAAA,EAC/D;AAGA,YAAU,MAAM;AACf,WAAO,MAAM,MAAM,QAAQ;AAAA,EAC5B,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,QAAQ;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACP;AAEA,QAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC;AAEhD,SACC,oBAAC,iBAAiB,UAAjB,EAA0B,OACzB,UACF;AAEF;;;AGvLA,SAAS,kBAAkB;AAWpB,IAAM,aAAa,MAEA;AACzB,QAAM,MAAM,WAAW,gBAAgB;AAEvC,MAAI,CAAC;AACJ,UAAM,IAAI,MAAM,sDAAsD;AAEvE,SAAO,IAAI;AACZ;;;ACeE,gBAAAA,YAAA;AATK,IAAM,kBAAkB,CAG9B,WACI;AACJ,QAAM,WAA2D,CAAC;AAAA,IACjE;AAAA,IACA;AAAA,EACD,MACC,gBAAAA,KAAC,qBAAkB,QAAgB,YACjC,UACF;AAED,WAAS,cAAc;AAEvB,SAAO;AAAA,IACN,mBAAmB;AAAA;AAAA,IAEnB,YAAY,MAAM,WAAc;AAAA;AAAA,IAEhC,aAAa,MAAM,WAAc,EAAE;AAAA,EACpC;AACD;;;ACxCO,IAAM,cAAc,MAEpB,WAAc,EAAE;","names":["jsx"]}
|
package/package.json
CHANGED
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kheopskit/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"private": false,
|
|
6
|
+
"sideEffects": false,
|
|
6
7
|
"files": [
|
|
7
|
-
"dist"
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
8
10
|
],
|
|
9
11
|
"main": "./dist/index.js",
|
|
10
12
|
"module": "./dist/index.mjs",
|
|
11
13
|
"types": "./dist/index.d.ts",
|
|
12
14
|
"exports": {
|
|
13
15
|
".": {
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.mts",
|
|
18
|
+
"default": "./dist/index.mjs"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"default": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"./package.json": "./package.json"
|
|
18
26
|
},
|
|
19
27
|
"publishConfig": {
|
|
20
28
|
"access": "public"
|
|
@@ -27,7 +35,7 @@
|
|
|
27
35
|
},
|
|
28
36
|
"license": "ISC",
|
|
29
37
|
"peerDependencies": {
|
|
30
|
-
"@kheopskit/core": "^
|
|
38
|
+
"@kheopskit/core": "^5.0.0",
|
|
31
39
|
"react": ">=18.0.0",
|
|
32
40
|
"react-dom": ">=18.0.0",
|
|
33
41
|
"rxjs": ">=7.0.0"
|
|
@@ -38,7 +46,7 @@
|
|
|
38
46
|
"react": "^19.2.7",
|
|
39
47
|
"react-dom": "^19.2.7",
|
|
40
48
|
"rxjs": "^7.8.2",
|
|
41
|
-
"@kheopskit/core": "
|
|
49
|
+
"@kheopskit/core": "5.0.0"
|
|
42
50
|
},
|
|
43
51
|
"tsup": {
|
|
44
52
|
"entry": [
|
|
@@ -53,10 +61,13 @@
|
|
|
53
61
|
"esm",
|
|
54
62
|
"cjs"
|
|
55
63
|
],
|
|
56
|
-
"target": "es2020"
|
|
64
|
+
"target": "es2020",
|
|
65
|
+
"banner": {
|
|
66
|
+
"js": "\"use client\";"
|
|
67
|
+
}
|
|
57
68
|
},
|
|
58
69
|
"scripts": {
|
|
59
|
-
"test": "
|
|
70
|
+
"test": "vitest run --root=../.. packages/react",
|
|
60
71
|
"dev": "tsup --watch",
|
|
61
72
|
"build": "tsup",
|
|
62
73
|
"clean": "rm -rf ./dist && rm -rf ./node_modules",
|