@ckb-ccc/connector-react 1.1.8 → 2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @ckb-ccc/connector-react
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#503](https://github.com/ckb-devrel/ccc/pull/503) [`2001c3b`](https://github.com/ckb-devrel/ccc/commit/2001c3b47c1eca82485621e3541c393b5ccf6a3e) Thanks [@Hanssen0](https://github.com/Hanssen0)! - refactor(connector): emit owned wallet and signer connections, remove deprecated compatibility APIs, require setClient callers to transfer Client ownership, and release connections from the React Provider.
8
+
9
+ See the [Connector 2.0 migration guide](https://docs.ckbccc.com/en/docs/migration/connector-v2)
10
+ for the required `setClient`, connection event, Client ownership, and removed
11
+ property changes.
12
+
13
+ ### Minor Changes
14
+
15
+ - [#498](https://github.com/ckb-devrel/ccc/pull/498) [`c75b49e`](https://github.com/ckb-devrel/ccc/commit/c75b49e282991949e2240779608a4c5b2277a34e) Thanks [@Hanssen0](https://github.com/Hanssen0)! - feat(connector-react): control Web Component Client requests in the Provider, manage ownership transferred through setClient, and add useBorrowedOrOwned for an internally owned fallback to an optional borrowed value
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [[`2001c3b`](https://github.com/ckb-devrel/ccc/commit/2001c3b47c1eca82485621e3541c393b5ccf6a3e), [`230cf6c`](https://github.com/ckb-devrel/ccc/commit/230cf6c870680faeb560628aa989d92ba66ddf10), [`251232a`](https://github.com/ckb-devrel/ccc/commit/251232abcae0320eb9b991b5f8a05b655f45d426), [`7e38c51`](https://github.com/ckb-devrel/ccc/commit/7e38c51a38d45e92b96639bdce575880ba88ee9b)]:
20
+ - @ckb-ccc/connector@2.0.0
21
+
22
+ ## 1.1.9
23
+
24
+ ### Patch Changes
25
+
26
+ - [#482](https://github.com/ckb-devrel/ccc/pull/482) [`403ac43`](https://github.com/ckb-devrel/ccc/commit/403ac439826c2b028ee8360881b9d723ca123509) Thanks [@Hanssen0](https://github.com/Hanssen0)! - feat(connector): styling variables for hovered button
27
+ - Updated dependencies [[`403ac43`](https://github.com/ckb-devrel/ccc/commit/403ac439826c2b028ee8360881b9d723ca123509)]:
28
+ - @ckb-ccc/connector@1.3.0
29
+
3
30
  ## 1.1.8
4
31
 
5
32
  ### Patch Changes
@@ -1,6 +1,8 @@
1
1
  import { ccc } from "@ckb-ccc/connector";
2
+ import { EventName } from "@lit/react";
2
3
  export declare const Connector: import("@lit/react").ReactWebComponent<ccc.WebComponentConnector, {
3
- onWillUpdate: string;
4
- onClose: string;
4
+ onClose: EventName<ccc.ConnectorCloseEvent>;
5
+ onSelectClient: EventName<ccc.SelectClientEvent>;
6
+ onConnection: EventName<ccc.ConnectorConnectionEvent>;
5
7
  }>;
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAIzC,eAAO,MAAM,SAAS;;;EAQpB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,SAAS,EAAmB,MAAM,YAAY,CAAC;AAGxD,eAAO,MAAM,SAAS;aAMF,SAAS,CAAC,GAAG,CAAC,mBAAmB,CAAC;oBAElC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC;kBAEhC,SAAS,CAAC,GAAG,CAAC,wBAAwB,CAAC;EAEzD,CAAC"}
@@ -7,7 +7,11 @@ export const Connector = createComponent({
7
7
  elementClass: ccc.WebComponentConnector,
8
8
  react: React,
9
9
  events: {
10
- onWillUpdate: "willUpdate",
11
- onClose: "close",
10
+ onClose: ccc.ConnectorCloseEvent
11
+ .eventName,
12
+ onSelectClient: ccc.SelectClientEvent
13
+ .eventName,
14
+ onConnection: ccc.ConnectorConnectionEvent
15
+ .eventName,
12
16
  },
13
17
  });
@@ -1,3 +1,4 @@
1
+ export * from "./useBorrowedOrOwned.js";
1
2
  export * from "./useCcc.js";
2
3
  export * from "./useSigner.js";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -1,2 +1,3 @@
1
+ export * from "./useBorrowedOrOwned.js";
1
2
  export * from "./useCcc.js";
2
3
  export * from "./useSigner.js";
@@ -0,0 +1,7 @@
1
+ import { ccc } from "@ckb-ccc/connector";
2
+ /**
3
+ * Opens and owns a fallback value after the component commits, while returning
4
+ * a borrowed value whenever one is provided.
5
+ */
6
+ export declare function useBorrowedOrOwned<T>(borrowed: T | undefined, open: () => ccc.Owner<T>): T | undefined;
7
+ //# sourceMappingURL=useBorrowedOrOwned.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBorrowedOrOwned.d.ts","sourceRoot":"","sources":["../../src/hooks/useBorrowedOrOwned.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAGzC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,QAAQ,EAAE,CAAC,GAAG,SAAS,EACvB,IAAI,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GACvB,CAAC,GAAG,SAAS,CAUf"}
@@ -0,0 +1,14 @@
1
+ import { useEffect, useState } from "react";
2
+ /**
3
+ * Opens and owns a fallback value after the component commits, while returning
4
+ * a borrowed value whenever one is provided.
5
+ */
6
+ export function useBorrowedOrOwned(borrowed, open) {
7
+ const [owned, setOwned] = useState();
8
+ useEffect(() => {
9
+ const owner = open();
10
+ setOwned(owner.value);
11
+ return () => void owner.dispose().catch(() => { });
12
+ }, [open]);
13
+ return borrowed ?? owned;
14
+ }
@@ -1,6 +1,6 @@
1
1
  import { ccc } from "@ckb-ccc/connector";
2
2
  import React, { HTMLAttributes, ReactNode } from "react";
3
- export declare function Provider({ children, connectorProps, hideMark, name, icon, signerFilter, signersController, defaultClient, clientOptions, preferredNetworks, }: {
3
+ export declare function Provider({ children, connectorProps, hideMark, name, icon, signerFilter, signersController, defaultClient, clientOptions, }: {
4
4
  children: ReactNode;
5
5
  connectorProps?: HTMLAttributes<{}>;
6
6
  hideMark?: boolean;
@@ -14,14 +14,13 @@ export declare function Provider({ children, connectorProps, hideMark, name, ico
14
14
  client: ccc.Client;
15
15
  name: string;
16
16
  }[];
17
- preferredNetworks?: ccc.NetworkPreference[];
18
- }): React.JSX.Element;
17
+ }): React.JSX.Element | null;
19
18
  export declare function useCcc(): {
20
19
  isOpen: boolean;
21
20
  open: () => unknown;
22
21
  close: () => unknown;
23
22
  disconnect: () => unknown;
24
- setClient: (client: ccc.Client) => unknown;
23
+ setClient: (owner: ccc.Owner<ccc.Client>) => void;
25
24
  client: ccc.Client;
26
25
  wallet?: ccc.Wallet;
27
26
  signerInfo?: ccc.SignerInfo;
@@ -1 +1 @@
1
- {"version":3,"file":"useCcc.d.ts","sourceRoot":"","sources":["../../src/hooks/useCcc.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,KAAK,EAAE,EAEZ,cAAc,EACd,SAAS,EAQV,MAAM,OAAO,CAAC;AA4Cf,wBAAgB,QAAQ,CAAC,EACvB,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,iBAAiB,GAClB,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,cAAc,CAAC,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,CACb,UAAU,EAAE,GAAG,CAAC,UAAU,EAC1B,MAAM,EAAE,GAAG,CAAC,MAAM,KACf,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,iBAAiB,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAC;IAC1C,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtE,iBAAiB,CAAC,EAAE,GAAG,CAAC,iBAAiB,EAAE,CAAC;CAC7C,qBA8FA;AAED,wBAAgB,MAAM;YAhKR,OAAO;UACT,MAAM,OAAO;WACZ,MAAM,OAAO;gBACR,MAAM,OAAO;eACd,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,OAAO;YAClC,GAAG,CAAC,MAAM;aACT,GAAG,CAAC,MAAM;iBACN,GAAG,CAAC,UAAU;EAiKhC"}
1
+ {"version":3,"file":"useCcc.d.ts","sourceRoot":"","sources":["../../src/hooks/useCcc.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,KAAK,EAAE,EAEZ,cAAc,EACd,SAAS,EAQV,MAAM,OAAO,CAAC;AAiDf,wBAAgB,QAAQ,CAAC,EACvB,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,cAAc,CAAC,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,CACb,UAAU,EAAE,GAAG,CAAC,UAAU,EAC1B,MAAM,EAAE,GAAG,CAAC,MAAM,KACf,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,iBAAiB,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAC;IAC1C,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvE,4BAuIA;AAED,wBAAgB,MAAM;YAvMR,OAAO;UACT,MAAM,OAAO;WACZ,MAAM,OAAO;gBACR,MAAM,OAAO;eACd,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI;YACzC,GAAG,CAAC,MAAM;aACT,GAAG,CAAC,MAAM;iBACN,GAAG,CAAC,UAAU;EAwMhC"}
@@ -1,6 +1,10 @@
1
1
  import { ccc } from "@ckb-ccc/connector";
2
2
  import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
3
3
  import { Connector } from "../components/index.js";
4
+ import { useBorrowedOrOwned } from "./useBorrowedOrOwned.js";
5
+ function openDefaultClient() {
6
+ return ccc.ClientPublicTestnet.open();
7
+ }
4
8
  const CCC_CONTEXT = createContext(undefined);
5
9
  class SignersControllerWithFilter extends ccc.SignersController {
6
10
  constructor(filter) {
@@ -15,12 +19,55 @@ class SignersControllerWithFilter extends ccc.SignersController {
15
19
  return super.addSigner(walletName, icon, signerInfo, context);
16
20
  }
17
21
  }
18
- export function Provider({ children, connectorProps, hideMark, name, icon, signerFilter, signersController, defaultClient, clientOptions, preferredNetworks, }) {
22
+ export function Provider({ children, connectorProps, hideMark, name, icon, signerFilter, signersController, defaultClient, clientOptions, }) {
19
23
  const [ref, setRef] = useState(null);
24
+ const connectionOwner = useRef(undefined);
25
+ const [connection, setConnection] = useState();
20
26
  const [isOpen, setIsOpen] = useState(false);
21
- const [_, setFlag] = useState(0);
22
- const defaultSignersController = useRef(undefined);
23
- const client = useMemo(() => ref?.client ?? new ccc.ClientPublicTestnet(), [ref?.client]);
27
+ const defaultSignersController = useMemo(() => new SignersControllerWithFilter(signerFilter), [signerFilter]);
28
+ const initialClient = useBorrowedOrOwned(defaultClient ?? clientOptions?.[0]?.client, openDefaultClient);
29
+ const [selectedClient, setSelectedClient] = useState();
30
+ const adoptedClientOwner = useRef(undefined);
31
+ const client = selectedClient ?? initialClient;
32
+ const setClient = useCallback((resource) => {
33
+ const owner = resource.map((value) => value);
34
+ const previous = adoptedClientOwner.current;
35
+ adoptedClientOwner.current = owner;
36
+ if (previous)
37
+ void previous.dispose().catch(() => { });
38
+ setSelectedClient(owner.value);
39
+ }, []);
40
+ const onSelectClient = useCallback((event) => {
41
+ setSelectedClient(event.client);
42
+ }, []);
43
+ const onConnection = useCallback((event) => {
44
+ event.stopPropagation();
45
+ if (event.connectionOwner && !event.connectionOwner.isValid) {
46
+ return;
47
+ }
48
+ const owner = event.connectionOwner?.map((connection) => connection);
49
+ const previous = connectionOwner.current;
50
+ connectionOwner.current = owner;
51
+ const connection = owner?.value;
52
+ setConnection(connection);
53
+ connection?.signerInfo.signer.onReplaced(() => {
54
+ if (connectionOwner.current === owner) {
55
+ connectionOwner.current = undefined;
56
+ setConnection(undefined);
57
+ }
58
+ void owner?.dispose().catch(() => { });
59
+ });
60
+ if (previous) {
61
+ void previous.dispose().catch(() => { });
62
+ }
63
+ }, []);
64
+ useEffect(() => () => {
65
+ const owner = connectionOwner.current;
66
+ connectionOwner.current = undefined;
67
+ void owner?.dispose().catch(() => { });
68
+ void adoptedClientOwner.current?.dispose().catch(() => { });
69
+ adoptedClientOwner.current = undefined;
70
+ }, []);
24
71
  const open = useCallback(() => {
25
72
  setIsOpen(true);
26
73
  ref?.requestUpdate();
@@ -30,20 +77,8 @@ export function Provider({ children, connectorProps, hideMark, name, icon, signe
30
77
  ref?.requestUpdate();
31
78
  }, [setIsOpen, ref, ref?.requestUpdate]);
32
79
  const disconnect = useMemo(() => ref?.disconnect.bind(ref) ?? (() => { }), [ref, ref?.disconnect]);
33
- const setClient = useMemo(() => ref?.setClient.bind(ref) ?? (() => { }), [ref, ref?.setClient]);
34
- useEffect(() => {
35
- if (defaultClient) {
36
- setClient(defaultClient);
37
- }
38
- }, [setClient]);
39
- useEffect(() => {
40
- if (!defaultSignersController.current) {
41
- defaultSignersController.current = new SignersControllerWithFilter(signerFilter);
42
- }
43
- else {
44
- defaultSignersController.current.filter = signerFilter;
45
- }
46
- }, [signerFilter]);
80
+ if (!client)
81
+ return null;
47
82
  return (React.createElement(CCC_CONTEXT.Provider, { value: {
48
83
  isOpen,
49
84
  open,
@@ -51,10 +86,10 @@ export function Provider({ children, connectorProps, hideMark, name, icon, signe
51
86
  disconnect,
52
87
  setClient,
53
88
  client,
54
- wallet: ref?.wallet,
55
- signerInfo: ref?.signer,
89
+ wallet: connection?.wallet,
90
+ signerInfo: connection?.signerInfo,
56
91
  } },
57
- React.createElement(Connector, { hideMark: hideMark, name: name, icon: icon, signersController: signersController ?? defaultSignersController.current, ref: setRef, onWillUpdate: () => setFlag((f) => f + 1), onClose: close, preferredNetworks: preferredNetworks, clientOptions: clientOptions, ...connectorProps,
92
+ React.createElement(Connector, { client: client, hideMark: hideMark, name: name, icon: icon, signersController: signersController ?? defaultSignersController, ref: setRef, onClose: close, onConnection: onConnection, clientOptions: clientOptions, ...connectorProps,
58
93
  style: {
59
94
  zIndex: 999,
60
95
  ...(isOpen ? {} : { display: "none" }),
@@ -65,13 +100,16 @@ export function Provider({ children, connectorProps, hideMark, name, icon, signe
65
100
  "--btn-primary-hover": "#efeeee",
66
101
  "--btn-secondary": "#ddd",
67
102
  "--btn-secondary-hover": "#ccc",
103
+ "--btn-color": "currentColor",
104
+ "--btn-color-hover": "var(--btn-color)",
68
105
  "--icon-primary": "#1E1E1E",
69
106
  "--icon-secondary": "#666666",
70
107
  color: "#1e1e1e",
71
108
  "--tip-color": "#666",
109
+ "--tip-color-hover": "var(--tip-color)",
72
110
  },
73
111
  ...connectorProps?.style,
74
- } }),
112
+ }, onSelectClient: onSelectClient }),
75
113
  children));
76
114
  }
77
115
  export function useCcc() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckb-ccc/connector-react",
3
- "version": "1.1.8",
3
+ "version": "2.0.0",
4
4
  "description": "CCC - CKBer's Codebase. Common Chains Connector UI Component for React",
5
5
  "author": "Hanssen0 <hanssen0@hanssen0.com>",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@lit/react": "^1.0.8",
37
- "@ckb-ccc/connector": "1.2.0"
37
+ "@ckb-ccc/connector": "2.0.0"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@types/react": ">=16",
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { ccc } from "@ckb-ccc/connector";
4
- import { createComponent } from "@lit/react";
4
+ import { EventName, createComponent } from "@lit/react";
5
5
  import * as React from "react";
6
6
 
7
7
  export const Connector = createComponent({
@@ -9,7 +9,11 @@ export const Connector = createComponent({
9
9
  elementClass: ccc.WebComponentConnector,
10
10
  react: React,
11
11
  events: {
12
- onWillUpdate: "willUpdate",
13
- onClose: "close",
12
+ onClose: ccc.ConnectorCloseEvent
13
+ .eventName as EventName<ccc.ConnectorCloseEvent>,
14
+ onSelectClient: ccc.SelectClientEvent
15
+ .eventName as EventName<ccc.SelectClientEvent>,
16
+ onConnection: ccc.ConnectorConnectionEvent
17
+ .eventName as EventName<ccc.ConnectorConnectionEvent>,
14
18
  },
15
19
  });
@@ -1,2 +1,3 @@
1
+ export * from "./useBorrowedOrOwned.js";
1
2
  export * from "./useCcc.js";
2
3
  export * from "./useSigner.js";
@@ -0,0 +1,21 @@
1
+ import { ccc } from "@ckb-ccc/connector";
2
+ import { useEffect, useState } from "react";
3
+
4
+ /**
5
+ * Opens and owns a fallback value after the component commits, while returning
6
+ * a borrowed value whenever one is provided.
7
+ */
8
+ export function useBorrowedOrOwned<T>(
9
+ borrowed: T | undefined,
10
+ open: () => ccc.Owner<T>,
11
+ ): T | undefined {
12
+ const [owned, setOwned] = useState<T>();
13
+
14
+ useEffect(() => {
15
+ const owner = open();
16
+ setOwned(owner.value);
17
+ return () => void owner.dispose().catch(() => {});
18
+ }, [open]);
19
+
20
+ return borrowed ?? owned;
21
+ }
@@ -12,6 +12,11 @@ import React, {
12
12
  useState,
13
13
  } from "react";
14
14
  import { Connector } from "../components/index.js";
15
+ import { useBorrowedOrOwned } from "./useBorrowedOrOwned.js";
16
+
17
+ function openDefaultClient(): ccc.Owner<ccc.Client> {
18
+ return ccc.ClientPublicTestnet.open();
19
+ }
15
20
 
16
21
  const CCC_CONTEXT = createContext<
17
22
  | {
@@ -19,7 +24,7 @@ const CCC_CONTEXT = createContext<
19
24
  open: () => unknown;
20
25
  close: () => unknown;
21
26
  disconnect: () => unknown;
22
- setClient: (client: ccc.Client) => unknown;
27
+ setClient: (owner: ccc.Owner<ccc.Client>) => void;
23
28
  client: ccc.Client;
24
29
  wallet?: ccc.Wallet;
25
30
  signerInfo?: ccc.SignerInfo;
@@ -29,7 +34,7 @@ const CCC_CONTEXT = createContext<
29
34
 
30
35
  class SignersControllerWithFilter extends ccc.SignersController {
31
36
  constructor(
32
- public filter?: (
37
+ public readonly filter?: (
33
38
  signerInfo: ccc.SignerInfo,
34
39
  wallet: ccc.Wallet,
35
40
  ) => Promise<boolean>,
@@ -64,7 +69,6 @@ export function Provider({
64
69
  signersController,
65
70
  defaultClient,
66
71
  clientOptions,
67
- preferredNetworks,
68
72
  }: {
69
73
  children: ReactNode;
70
74
  connectorProps?: HTMLAttributes<{}>;
@@ -78,19 +82,75 @@ export function Provider({
78
82
  signersController?: ccc.SignersController;
79
83
  defaultClient?: ccc.Client;
80
84
  clientOptions?: { icon?: string; client: ccc.Client; name: string }[];
81
- preferredNetworks?: ccc.NetworkPreference[];
82
85
  }) {
83
86
  const [ref, setRef] = useState<ccc.WebComponentConnector | null>(null);
84
- const [isOpen, setIsOpen] = useState(false);
85
- const [_, setFlag] = useState(0);
86
- const defaultSignersController = useRef<
87
- SignersControllerWithFilter | undefined
87
+ const connectionOwner = useRef<
88
+ ccc.Owner<ccc.ConnectorConnection> | undefined
88
89
  >(undefined);
90
+ const [connection, setConnection] = useState<ccc.ConnectorConnection>();
91
+ const [isOpen, setIsOpen] = useState(false);
92
+ const defaultSignersController = useMemo(
93
+ () => new SignersControllerWithFilter(signerFilter),
94
+ [signerFilter],
95
+ );
89
96
 
90
- const client = useMemo(
91
- () => ref?.client ?? new ccc.ClientPublicTestnet(),
92
- [ref?.client],
97
+ const initialClient = useBorrowedOrOwned(
98
+ defaultClient ?? clientOptions?.[0]?.client,
99
+ openDefaultClient,
100
+ );
101
+ const [selectedClient, setSelectedClient] = useState<ccc.Client>();
102
+ const adoptedClientOwner = useRef<ccc.Owner<ccc.Client> | undefined>(
103
+ undefined,
93
104
  );
105
+ const client = selectedClient ?? initialClient;
106
+
107
+ const setClient = useCallback((resource: ccc.Owner<ccc.Client>) => {
108
+ const owner = resource.map((value) => value);
109
+
110
+ const previous = adoptedClientOwner.current;
111
+ adoptedClientOwner.current = owner;
112
+ if (previous) void previous.dispose().catch(() => {});
113
+ setSelectedClient(owner.value);
114
+ }, []);
115
+
116
+ const onSelectClient = useCallback((event: ccc.SelectClientEvent) => {
117
+ setSelectedClient(event.client);
118
+ }, []);
119
+
120
+ const onConnection = useCallback((event: ccc.ConnectorConnectionEvent) => {
121
+ event.stopPropagation();
122
+ if (event.connectionOwner && !event.connectionOwner.isValid) {
123
+ return;
124
+ }
125
+ const owner = event.connectionOwner?.map((connection) => connection);
126
+ const previous = connectionOwner.current;
127
+ connectionOwner.current = owner;
128
+ const connection = owner?.value;
129
+ setConnection(connection);
130
+
131
+ connection?.signerInfo.signer.onReplaced(() => {
132
+ if (connectionOwner.current === owner) {
133
+ connectionOwner.current = undefined;
134
+ setConnection(undefined);
135
+ }
136
+ void owner?.dispose().catch(() => {});
137
+ });
138
+ if (previous) {
139
+ void previous.dispose().catch(() => {});
140
+ }
141
+ }, []);
142
+
143
+ useEffect(
144
+ () => () => {
145
+ const owner = connectionOwner.current;
146
+ connectionOwner.current = undefined;
147
+ void owner?.dispose().catch(() => {});
148
+ void adoptedClientOwner.current?.dispose().catch(() => {});
149
+ adoptedClientOwner.current = undefined;
150
+ },
151
+ [],
152
+ );
153
+
94
154
  const open = useCallback(() => {
95
155
  setIsOpen(true);
96
156
  ref?.requestUpdate();
@@ -103,25 +163,7 @@ export function Provider({
103
163
  () => ref?.disconnect.bind(ref) ?? (() => {}),
104
164
  [ref, ref?.disconnect],
105
165
  );
106
- const setClient = useMemo(
107
- () => ref?.setClient.bind(ref) ?? (() => {}),
108
- [ref, ref?.setClient],
109
- );
110
-
111
- useEffect(() => {
112
- if (defaultClient) {
113
- setClient(defaultClient);
114
- }
115
- }, [setClient]);
116
- useEffect(() => {
117
- if (!defaultSignersController.current) {
118
- defaultSignersController.current = new SignersControllerWithFilter(
119
- signerFilter,
120
- );
121
- } else {
122
- defaultSignersController.current.filter = signerFilter;
123
- }
124
- }, [signerFilter]);
166
+ if (!client) return null;
125
167
 
126
168
  return (
127
169
  <CCC_CONTEXT.Provider
@@ -133,21 +175,19 @@ export function Provider({
133
175
  setClient,
134
176
 
135
177
  client,
136
- wallet: ref?.wallet,
137
- signerInfo: ref?.signer,
178
+ wallet: connection?.wallet,
179
+ signerInfo: connection?.signerInfo,
138
180
  }}
139
181
  >
140
182
  <Connector
183
+ client={client}
141
184
  hideMark={hideMark}
142
185
  name={name}
143
186
  icon={icon}
144
- signersController={
145
- signersController ?? defaultSignersController.current
146
- }
187
+ signersController={signersController ?? defaultSignersController}
147
188
  ref={setRef}
148
- onWillUpdate={() => setFlag((f) => f + 1)}
149
189
  onClose={close}
150
- preferredNetworks={preferredNetworks}
190
+ onConnection={onConnection}
151
191
  clientOptions={clientOptions}
152
192
  {...{
153
193
  ...connectorProps,
@@ -161,14 +201,18 @@ export function Provider({
161
201
  "--btn-primary-hover": "#efeeee",
162
202
  "--btn-secondary": "#ddd",
163
203
  "--btn-secondary-hover": "#ccc",
204
+ "--btn-color": "currentColor",
205
+ "--btn-color-hover": "var(--btn-color)",
164
206
  "--icon-primary": "#1E1E1E",
165
207
  "--icon-secondary": "#666666",
166
208
  color: "#1e1e1e",
167
209
  "--tip-color": "#666",
210
+ "--tip-color-hover": "var(--tip-color)",
168
211
  } as CSSProperties),
169
212
  ...connectorProps?.style,
170
213
  },
171
214
  }}
215
+ onSelectClient={onSelectClient}
172
216
  />
173
217
  {children}
174
218
  </CCC_CONTEXT.Provider>