diff --git a/packages/ui-react/src/components/TonConnectButton.tsx b/packages/ui-react/src/components/TonConnectButton.tsx index 9479a5a43..d0c7a4eb1 100644 --- a/packages/ui-react/src/components/TonConnectButton.tsx +++ b/packages/ui-react/src/components/TonConnectButton.tsx @@ -1,12 +1,17 @@ -import { CSSProperties, FunctionComponent, memo, useEffect } from 'react'; +import { CSSProperties, FunctionComponent, memo, useEffect, useRef } from 'react'; import { useTonConnectUI } from '../hooks/useTonConnectUI'; - -const buttonRootId = 'ton-connect-button'; +import { + addButtonId, + removeButtonId, + getButtonIds, + DEFAULT_BUTTON_ID +} from '../utils/tonconnect-button-ids'; export interface TonConnectButtonProps { className?: string; - style?: CSSProperties; + + id?: string; } /** @@ -16,17 +21,28 @@ export interface TonConnectButtonProps { * @param [style] style to add to the button container. * @constructor */ -const TonConnectButton: FunctionComponent = ({ className, style }) => { +const TonConnectButton: FunctionComponent = ({ className, style, id }) => { const [_, setOptions] = useTonConnectUI(); + const buttonId = useRef( + id ?? + (getButtonIds().length === 0 + ? DEFAULT_BUTTON_ID + : `ton-connect-button-${Math.random().toString(36).slice(2, 10)}`) + ); useEffect(() => { - setOptions({ buttonRootId }); - return () => setOptions({ buttonRootId: null }); + const newIds = addButtonId(buttonId.current); + setOptions({ buttonRootId: newIds }); + + return () => { + const newIds = removeButtonId(buttonId.current); + setOptions({ buttonRootId: newIds.length > 0 ? newIds : null }); + }; }, [setOptions]); return (
diff --git a/packages/ui-react/src/utils/tonconnect-button-ids.ts b/packages/ui-react/src/utils/tonconnect-button-ids.ts new file mode 100644 index 000000000..706abc216 --- /dev/null +++ b/packages/ui-react/src/utils/tonconnect-button-ids.ts @@ -0,0 +1,19 @@ +export const DEFAULT_BUTTON_ID = 'ton-connect-button'; + +const ids: Set = new Set(); + +export function getButtonIds(): string[] { + return Array.from(ids); +} + +export function addButtonId(id: string): string[] { + if (!ids.has(id)) { + ids.add(id); + } + return getButtonIds(); +} + +export function removeButtonId(id: string): string[] { + ids.delete(id); + return getButtonIds(); +} diff --git a/packages/ui/src/app/App.tsx b/packages/ui/src/app/App.tsx index 4feef6c39..e635e7f65 100644 --- a/packages/ui/src/app/App.tsx +++ b/packages/ui/src/app/App.tsx @@ -33,10 +33,14 @@ const App: Component = props => { - - - - + 0}> + <> + {appState.buttonRootId && (appState.buttonRootId as string[]).map((id) => ( + + + + ))} + diff --git a/packages/ui/src/app/state/app.state.ts b/packages/ui/src/app/state/app.state.ts index f924f5bbb..33dcb8c1f 100644 --- a/packages/ui/src/app/state/app.state.ts +++ b/packages/ui/src/app/state/app.state.ts @@ -7,7 +7,7 @@ import { Loadable } from 'src/models/loadable'; export type AppState = { connector: ITonConnect; - buttonRootId: string | null; + buttonRootId: string | null | string[]; language: Locales; walletsListConfiguration: WalletsListConfiguration | {}; connectRequestParameters?: Loadable | null; diff --git a/packages/ui/src/models/ton-connect-ui-options.ts b/packages/ui/src/models/ton-connect-ui-options.ts index 10c1b4e1f..9286dc2d5 100644 --- a/packages/ui/src/models/ton-connect-ui-options.ts +++ b/packages/ui/src/models/ton-connect-ui-options.ts @@ -14,7 +14,7 @@ export interface TonConnectUiOptions { * HTML element id to attach the wallet connect button. If not passed button won't appear. * @default null. */ - buttonRootId?: string | null; + buttonRootId?: string | string[] | null; /** * Language for the phrases it the UI elements. diff --git a/packages/ui/src/ton-connect-ui.ts b/packages/ui/src/ton-connect-ui.ts index 2e8fecd79..5c02eaba8 100644 --- a/packages/ui/src/ton-connect-ui.ts +++ b/packages/ui/src/ton-connect-ui.ts @@ -993,11 +993,21 @@ export class TonConnectUI { return rootId; } - private checkButtonRootExist(buttonRootId: string | null | undefined): void | never { + private checkButtonRootExist(buttonRootId: string | string[] | null | undefined): void | never { if (buttonRootId == null) { return; } + if (Array.isArray(buttonRootId)) { + for (const buttonId of buttonRootId) { + if (document.getElementById(buttonId)) { + return; + } + } + + throw new TonConnectUIError(`${buttonRootId} element not found in the document.`); + } + if (!document.getElementById(buttonRootId)) { throw new TonConnectUIError(`${buttonRootId} element not found in the document.`); }