From b4bc3a24546bba2f0c47da887021417b6a182b74 Mon Sep 17 00:00:00 2001 From: David Totraev Date: Thu, 21 Nov 2024 20:34:52 +0500 Subject: [PATCH] feat: install core-ui --- package-lock.json | 15 ++- package.json | 1 + src/components/Avatar/Avatar.stories.tsx | 26 ----- src/components/Avatar/Avatar.tsx | 40 ------- src/components/Avatar/AvatarGroup.stories.tsx | 30 ----- src/components/Avatar/AvatarGroup.tsx | 41 ------- src/components/Avatar/index.ts | 2 - src/components/Button/Button.stories.tsx | 16 --- src/components/Button/Button.tsx | 53 --------- src/components/Button/IconButton.stories.tsx | 19 ---- src/components/Button/IconButton.tsx | 16 --- src/components/Button/index.tsx | 2 - .../ChainButton/index.stories.tsx | 8 +- .../ChainButton/index.tsx | 3 +- .../Chains/index.stories.ts | 0 src/{widgets => components}/Chains/index.tsx | 11 +- src/components/Chip/Chip.stories.tsx | 16 --- src/components/Chip/Chip.tsx | 14 --- src/components/Chip/index.ts | 1 - .../ConnectedWallet/index.stories.tsx | 0 .../ConnectedWallet/index.tsx | 3 +- src/components/Dialog/Dialog.stories.tsx | 79 ------------- src/components/Dialog/Dialog.tsx | 34 ------ .../Dialog/MobileDialog.stories.tsx | 79 ------------- src/components/Dialog/MobileDialog.tsx | 33 ------ src/components/Dialog/components/Backdrop.tsx | 17 --- .../Dialog/components/DialogBody.tsx | 6 - .../Dialog/components/DialogFooter.tsx | 6 - .../Dialog/components/DialogHeader.tsx | 30 ----- src/components/Dialog/index.ts | 5 - .../FieldControl/index.stories.tsx | 2 +- .../FieldControl/index.tsx | 0 src/components/Heading/Heading.stories.tsx | 40 ------- src/components/Heading/Heading.tsx | 33 ------ src/components/Heading/index.ts | 1 - src/components/Input/Checkbox.stories.tsx | 20 ---- src/components/Input/Checkbox.tsx | 42 ------- src/components/Input/Radio.stories.tsx | 20 ---- src/components/Input/Radio.tsx | 42 ------- src/components/Input/components/Toggle.tsx | 106 ------------------ src/components/Input/index.tsx | 2 - .../Inscriptions/index.stories.tsx | 0 .../Inscriptions/index.tsx | 6 +- src/components/Portal/Portal.tsx | 29 ----- src/components/Portal/index.ts | 1 - .../TermsOfService/index.stories.tsx | 0 .../TermsOfService/index.tsx | 4 +- src/components/Text/Text.stories.tsx | 40 ------- src/components/Text/Text.tsx | 34 ------ src/components/Text/index.ts | 1 - .../WalletButton/index.stories.tsx | 0 .../WalletButton/index.tsx | 3 +- .../WalletProvider/components/Screen.tsx | 15 +-- .../components/WalletDialog.tsx | 32 ++++-- .../WalletProvider/index.stories.tsx | 10 +- .../WalletProvider/index.tsx | 10 +- .../Wallets/index.stories.tsx | 4 +- src/{widgets => components}/Wallets/index.tsx | 5 +- src/context/Chain.context.tsx | 8 +- src/context/Dialog.context.tsx | 46 -------- src/core/Wallet.ts | 54 +-------- src/core/WalletConnector.ts | 16 +-- src/core/index.ts | 69 ++++++++++++ src/hocs/withAppState.tsx | 2 +- src/hooks/useControlledState.ts | 31 ----- src/hooks/useModalManager.ts | 42 ------- src/hooks/usePortalRoot.ts | 29 ----- src/index.css | 2 + src/index.tsx | 15 +-- src/state/state.tsx | 4 +- src/state/{state.d.ts => types.ts} | 10 +- src/utils/css.ts | 7 -- 72 files changed, 171 insertions(+), 1272 deletions(-) delete mode 100644 src/components/Avatar/Avatar.stories.tsx delete mode 100644 src/components/Avatar/Avatar.tsx delete mode 100644 src/components/Avatar/AvatarGroup.stories.tsx delete mode 100644 src/components/Avatar/AvatarGroup.tsx delete mode 100644 src/components/Avatar/index.ts delete mode 100644 src/components/Button/Button.stories.tsx delete mode 100644 src/components/Button/Button.tsx delete mode 100644 src/components/Button/IconButton.stories.tsx delete mode 100644 src/components/Button/IconButton.tsx delete mode 100644 src/components/Button/index.tsx rename src/{widgets => components}/ChainButton/index.stories.tsx (77%) rename src/{widgets => components}/ChainButton/index.tsx (96%) rename src/{widgets => components}/Chains/index.stories.ts (100%) rename src/{widgets => components}/Chains/index.tsx (92%) delete mode 100644 src/components/Chip/Chip.stories.tsx delete mode 100644 src/components/Chip/Chip.tsx delete mode 100644 src/components/Chip/index.ts rename src/{widgets => components}/ConnectedWallet/index.stories.tsx (100%) rename src/{widgets => components}/ConnectedWallet/index.tsx (96%) delete mode 100644 src/components/Dialog/Dialog.stories.tsx delete mode 100644 src/components/Dialog/Dialog.tsx delete mode 100644 src/components/Dialog/MobileDialog.stories.tsx delete mode 100644 src/components/Dialog/MobileDialog.tsx delete mode 100644 src/components/Dialog/components/Backdrop.tsx delete mode 100644 src/components/Dialog/components/DialogBody.tsx delete mode 100644 src/components/Dialog/components/DialogFooter.tsx delete mode 100644 src/components/Dialog/components/DialogHeader.tsx delete mode 100644 src/components/Dialog/index.ts rename src/{widgets => components}/FieldControl/index.stories.tsx (93%) rename src/{widgets => components}/FieldControl/index.tsx (100%) delete mode 100644 src/components/Heading/Heading.stories.tsx delete mode 100644 src/components/Heading/Heading.tsx delete mode 100644 src/components/Heading/index.ts delete mode 100644 src/components/Input/Checkbox.stories.tsx delete mode 100644 src/components/Input/Checkbox.tsx delete mode 100644 src/components/Input/Radio.stories.tsx delete mode 100644 src/components/Input/Radio.tsx delete mode 100644 src/components/Input/components/Toggle.tsx delete mode 100644 src/components/Input/index.tsx rename src/{widgets => components}/Inscriptions/index.stories.tsx (100%) rename src/{widgets => components}/Inscriptions/index.tsx (95%) delete mode 100644 src/components/Portal/Portal.tsx delete mode 100644 src/components/Portal/index.ts rename src/{widgets => components}/TermsOfService/index.stories.tsx (100%) rename src/{widgets => components}/TermsOfService/index.tsx (95%) delete mode 100644 src/components/Text/Text.stories.tsx delete mode 100644 src/components/Text/Text.tsx delete mode 100644 src/components/Text/index.ts rename src/{widgets => components}/WalletButton/index.stories.tsx (100%) rename src/{widgets => components}/WalletButton/index.tsx (92%) rename src/{widgets => components}/WalletProvider/components/Screen.tsx (63%) rename src/{widgets => components}/WalletProvider/components/WalletDialog.tsx (68%) rename src/{widgets => components}/WalletProvider/index.stories.tsx (89%) rename src/{widgets => components}/WalletProvider/index.tsx (75%) rename src/{widgets => components}/Wallets/index.stories.tsx (91%) rename src/{widgets => components}/Wallets/index.tsx (96%) delete mode 100644 src/context/Dialog.context.tsx create mode 100644 src/core/index.ts delete mode 100644 src/hooks/useControlledState.ts delete mode 100644 src/hooks/useModalManager.ts delete mode 100644 src/hooks/usePortalRoot.ts rename src/state/{state.d.ts => types.ts} (71%) delete mode 100644 src/utils/css.ts diff --git a/package-lock.json b/package-lock.json index 46096d5..0dce9e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,14 @@ { "name": "@babylonlabs-io/bbn-wallet-connect", - "version": "0.0.0", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@babylonlabs-io/bbn-wallet-connect", - "version": "0.0.0", + "version": "0.0.1", "dependencies": { + "@babylonlabs-io/bbn-core-ui": "^0.0.4", "react-icons": "^5.3.0" }, "devDependencies": { @@ -358,6 +359,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babylonlabs-io/bbn-core-ui": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@babylonlabs-io/bbn-core-ui/-/bbn-core-ui-0.0.4.tgz", + "integrity": "sha512-1UwG60/4czDvM8SqmlHWAF5h5Mg1PCzohN5XXbkADZp//5Lr7hs5tA0v11XKKGjN3BEOILs0A8qYLT5y2EK4Ag==", + "peerDependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1", + "tailwind-merge": "^2.5.4" + } + }, "node_modules/@changesets/apply-release-plan": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.5.tgz", diff --git a/package.json b/package.json index 074c329..ac7f846 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "release": "npm run build && changeset publish" }, "dependencies": { + "@babylonlabs-io/bbn-core-ui": "^0.0.4", "react-icons": "^5.3.0" }, "files": [ diff --git a/src/components/Avatar/Avatar.stories.tsx b/src/components/Avatar/Avatar.stories.tsx deleted file mode 100644 index 884c436..0000000 --- a/src/components/Avatar/Avatar.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import { Avatar } from "./Avatar"; - -const meta: Meta = { - component: Avatar, - tags: ["autodocs"], -}; - -export default meta; - -type Story = StoryObj; - -export const Image: Story = { - args: { - alt: "Binance", - url: "/images/wallets/binance.webp", - }, -}; - -export const Text: Story = { - args: { - className: "bg-primary text-primary-contrast", - children: "DT", - }, -}; diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx deleted file mode 100644 index 3d6113c..0000000 --- a/src/components/Avatar/Avatar.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import type { CSSProperties, PropsWithChildren } from "react"; -import { twMerge } from "tailwind-merge"; - -export interface AvatarProps extends PropsWithChildren { - alt?: string; - url?: string; - className?: string; - style?: CSSProperties; - size?: "tiny" | "small" | "medium" | "large"; - variant?: "circular" | "rounded" | "square"; -} - -const SIZES = { - tiny: "size-[1.125rem]", - small: "size-6", - medium: "size-8", - large: "size-10", -} as const; - -const VARIANTS = { - circular: "rounded-full", - rounded: "rounded", - square: "", -} as const; - -export function Avatar({ className, style, size = "large", variant = "circular", alt, url, children }: AvatarProps) { - return ( -
- {url ? {alt} : children} -
- ); -} diff --git a/src/components/Avatar/AvatarGroup.stories.tsx b/src/components/Avatar/AvatarGroup.stories.tsx deleted file mode 100644 index b71506e..0000000 --- a/src/components/Avatar/AvatarGroup.stories.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; -import { Avatar } from "./Avatar"; -import { AvatarGroup } from "./AvatarGroup"; - -const meta: Meta = { - component: AvatarGroup, - tags: ["autodocs"], -}; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - args: { - max: 3, - avatarClassName: "bg-primary/50 text-primary-contrast", - variant: "circular", - children: [ - , - , - DT, - JK, - ], - }, -}; diff --git a/src/components/Avatar/AvatarGroup.tsx b/src/components/Avatar/AvatarGroup.tsx deleted file mode 100644 index 51030df..0000000 --- a/src/components/Avatar/AvatarGroup.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { type PropsWithChildren, Children, cloneElement, isValidElement } from "react"; -import { twMerge } from "tailwind-merge"; - -import { type AvatarProps, Avatar } from "./Avatar"; - -export interface AvatarGroupProps extends PropsWithChildren, AvatarProps { - max?: number; - className?: string; - avatarClassName?: string; -} - -export const AvatarGroup = ({ - max = Infinity, - className, - children, - avatarClassName, - variant, - ...restProps -}: AvatarGroupProps) => { - const count = Children.count(children); - - return ( -
- {Children.map(children, (child, index) => - isValidElement(child) && index + 1 <= max - ? cloneElement(child, { - ...restProps, - className: twMerge(avatarClassName, child.props.className), - variant, - }) - : null, - )} - - {count > max && ( - - +{count - max} - - )} -
- ); -}; diff --git a/src/components/Avatar/index.ts b/src/components/Avatar/index.ts deleted file mode 100644 index 6758a3c..0000000 --- a/src/components/Avatar/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./Avatar"; -export * from "./AvatarGroup"; diff --git a/src/components/Button/Button.stories.tsx b/src/components/Button/Button.stories.tsx deleted file mode 100644 index 409ab83..0000000 --- a/src/components/Button/Button.stories.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import { Button } from "./Button"; - -const meta: Meta = { - component: Button, - tags: ["autodocs"], -}; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - args: { children: "Button" }, -}; diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx deleted file mode 100644 index 4ab82b9..0000000 --- a/src/components/Button/Button.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { type DetailedHTMLProps, type HTMLAttributes, forwardRef } from "react"; -import { twMerge } from "tailwind-merge"; - -const STYLES = { - contained: { - primary: "bg-primary-light text-secondary-contrast hover:bg-primary-main disabled:bg-primary/12", - secondary: "bg-secondary-main text-secondary-contrast hover:bg-secondary-dark disabled:bg-primary/12", - }, - outlined: { - primary: "bg-primary-light text-secondary-contrast hover:bg-primary", - secondary: "bg-secondary-main text-secondary-contrast hover:bg-secondary-dark", - }, -} as const; - -const SIZES = { - large: "h-10 px-6 text-base tracking-0.5", - medium: "h-9 px-4 text-sm tracking-0.5", - small: "h-8 px-2.5 text-xs tracking-0.5", -} as const; - -export interface ButtonProps - extends Omit, HTMLButtonElement>, "size"> { - className?: string; - disabled?: boolean; - fluid?: boolean; - variant?: "outlined" | "contained"; - color?: "primary" | "secondary"; - size?: "small" | "medium" | "large"; -} - -export const Button = forwardRef( - ( - { variant = "contained", size = "large", color = "primary", fluid = false, className, disabled, ...restProps }, - ref, - ) => { - return ( - - - { - setVisibility(false); - }} - > - { - setVisibility(false); - }} - > - Bitcoin Inscriptions - - - - - This staking interface attempts to detect bitcoin ordinals, NFTs, Ruins, and other inscriptions - (“Inscriptions”) within the Unspent Transaction Outputs (“UTXOs”) in your wallet. If you stake bitcoin - with Inscriptions, those UTXOs may be spent on staking, unbonding, or withdrawal fees, which will cause - you to lose those Inscriptions permanently. This interface will not detect all Inscriptions. - - - Chose one: (you can change this later) - - - - - - - - - - ); - }, -}; diff --git a/src/components/Dialog/Dialog.tsx b/src/components/Dialog/Dialog.tsx deleted file mode 100644 index 2a655a4..0000000 --- a/src/components/Dialog/Dialog.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { type DetailedHTMLProps, type HTMLAttributes } from "react"; -import { twMerge } from "tailwind-merge"; - -import { Portal } from "@/components/Portal"; -import { useModalManager } from "@/hooks/useModalManager"; -import { Backdrop } from "./components/Backdrop"; - -export interface DialogProps extends DetailedHTMLProps, HTMLDivElement> { - open?: boolean; - onClose?: () => void; -} - -export const Dialog = ({ children, open = false, className, onClose, ...restProps }: DialogProps) => { - const { mounted, unmount } = useModalManager({ open }); - - return ( - -
-
- {children} -
-
- - -
- ); -}; diff --git a/src/components/Dialog/MobileDialog.stories.tsx b/src/components/Dialog/MobileDialog.stories.tsx deleted file mode 100644 index 221afe7..0000000 --- a/src/components/Dialog/MobileDialog.stories.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { useState } from "react"; -import type { Meta, StoryObj } from "@storybook/react"; - -import { MobileDialog, DialogFooter, DialogBody, DialogHeader } from "./index"; - -import { ScrollLocker } from "@/context/Dialog.context"; -import { Button } from "@/components/Button"; -import { Checkbox } from "@/components/Input"; -import { Text } from "@/components/Text"; - -const meta: Meta = { - component: MobileDialog, - tags: ["autodocs"], -}; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - args: {}, - render: (props) => { - const [visible, setVisibility] = useState(false); - - return ( - - - - { - setVisibility(false); - }} - > - { - setVisibility(false); - }} - > - Bitcoin Inscriptions - - - - - This staking interface attempts to detect bitcoin ordinals, NFTs, Ruins, and other inscriptions - (“Inscriptions”) within the Unspent Transaction Outputs (“UTXOs”) in your wallet. If you stake bitcoin - with Inscriptions, those UTXOs may be spent on staking, unbonding, or withdrawal fees, which will cause - you to lose those Inscriptions permanently. This interface will not detect all Inscriptions. - - - Chose one: (you can change this later) - - - - - - - - - - ); - }, -}; diff --git a/src/components/Dialog/MobileDialog.tsx b/src/components/Dialog/MobileDialog.tsx deleted file mode 100644 index 0a15871..0000000 --- a/src/components/Dialog/MobileDialog.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { type DetailedHTMLProps, type HTMLAttributes } from "react"; -import { twMerge } from "tailwind-merge"; - -import { Portal } from "@/components/Portal"; -import { useModalManager } from "@/hooks/useModalManager"; -import { Backdrop } from "./components/Backdrop"; - -export interface MobileDialogProps extends DetailedHTMLProps, HTMLDivElement> { - open?: boolean; - onClose?: () => void; -} - -export const MobileDialog = ({ children, open = false, className, onClose, ...restProps }: MobileDialogProps) => { - const { mounted, unmount } = useModalManager({ open }); - - return ( - -
- {children} -
- - -
- ); -}; diff --git a/src/components/Dialog/components/Backdrop.tsx b/src/components/Dialog/components/Backdrop.tsx deleted file mode 100644 index 1683e2d..0000000 --- a/src/components/Dialog/components/Backdrop.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import type { DetailedHTMLProps, HTMLAttributes } from "react"; -import { twMerge } from "tailwind-merge"; - -export interface BackdropProps extends DetailedHTMLProps, HTMLDivElement> { - open?: boolean; -} - -export const Backdrop = ({ open = false, ...props }: BackdropProps) => ( -
-); diff --git a/src/components/Dialog/components/DialogBody.tsx b/src/components/Dialog/components/DialogBody.tsx deleted file mode 100644 index 64d2510..0000000 --- a/src/components/Dialog/components/DialogBody.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import type { DetailedHTMLProps, HTMLAttributes } from "react"; -import { twMerge } from "tailwind-merge"; - -export const DialogBody = (props: DetailedHTMLProps, HTMLDivElement>) => ( -
-); diff --git a/src/components/Dialog/components/DialogFooter.tsx b/src/components/Dialog/components/DialogFooter.tsx deleted file mode 100644 index 4991b18..0000000 --- a/src/components/Dialog/components/DialogFooter.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import type { DetailedHTMLProps, HTMLAttributes } from "react"; -import { twMerge } from "tailwind-merge"; - -export const DialogFooter = (props: DetailedHTMLProps, HTMLDivElement>) => ( -
-); diff --git a/src/components/Dialog/components/DialogHeader.tsx b/src/components/Dialog/components/DialogHeader.tsx deleted file mode 100644 index 90b9133..0000000 --- a/src/components/Dialog/components/DialogHeader.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import type { DetailedHTMLProps, HTMLAttributes } from "react"; - -import { Heading } from "@/components/Heading"; -import { IconButton } from "@/components/Button"; - -export interface DialogHeaderProps extends DetailedHTMLProps, HTMLDivElement> { - title?: string; - onClose?: () => void; -} - -export const DialogHeader = ({ className, title, children, onClose, ...restProps }: DialogHeaderProps) => ( -
-
- {title} - - {Boolean(onClose) && ( - - - - - - )} -
- - {children} -
-); diff --git a/src/components/Dialog/index.ts b/src/components/Dialog/index.ts deleted file mode 100644 index 6765fdb..0000000 --- a/src/components/Dialog/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./Dialog"; -export * from "./MobileDialog"; -export * from "./components/DialogHeader"; -export * from "./components/DialogBody"; -export * from "./components/DialogFooter"; diff --git a/src/widgets/FieldControl/index.stories.tsx b/src/components/FieldControl/index.stories.tsx similarity index 93% rename from src/widgets/FieldControl/index.stories.tsx rename to src/components/FieldControl/index.stories.tsx index 09b0b17..f721b0d 100644 --- a/src/widgets/FieldControl/index.stories.tsx +++ b/src/components/FieldControl/index.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { FieldControl } from "./index"; -import { Checkbox, Radio } from "@/index"; +import { Checkbox, Radio } from "@babylonlabs-io/bbn-core-ui"; const meta: Meta = { component: FieldControl, diff --git a/src/widgets/FieldControl/index.tsx b/src/components/FieldControl/index.tsx similarity index 100% rename from src/widgets/FieldControl/index.tsx rename to src/components/FieldControl/index.tsx diff --git a/src/components/Heading/Heading.stories.tsx b/src/components/Heading/Heading.stories.tsx deleted file mode 100644 index 0ab19ca..0000000 --- a/src/components/Heading/Heading.stories.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import { Heading } from "./Heading"; - -const meta: Meta = { - component: Heading, - tags: ["autodocs"], -}; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - render: (args) => - args.variant ? ( - Heading--{args.variant} - ) : ( -
- - Heading--H1 - - - Heading--H2 - - - Heading--H3 - - - Heading--H4 - - - Heading--H5 - - - Heading--H6 - -
- ), -}; diff --git a/src/components/Heading/Heading.tsx b/src/components/Heading/Heading.tsx deleted file mode 100644 index b085f6f..0000000 --- a/src/components/Heading/Heading.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { createElement, forwardRef, type HTMLProps } from "react"; -import { twMerge } from "tailwind-merge"; - -const STYLES = { - h1: "text-8xl leading-[7rem]", - h2: "text-6xl leading-[4.5rem]", - h3: "text-5xl leading-[3.5rem]", - h4: "text-[2.125rem] leading-[2.625rem] tracking-0.25", - h5: "text-2xl", - h6: "text-xl leading-8 tracking-0.15", -} as const; - -type HeadingVariant = keyof typeof STYLES; - -export interface HeadingProps extends HTMLProps { - variant: HeadingVariant; - as?: string; -} - -export const Heading = forwardRef( - ({ variant, as = variant, children, className, ...restProps }, ref) => - createElement( - as, - { - ...restProps, - ref, - className: twMerge(STYLES[variant], className), - }, - children, - ), -); - -Heading.displayName = "Heading"; diff --git a/src/components/Heading/index.ts b/src/components/Heading/index.ts deleted file mode 100644 index 8c56f4e..0000000 --- a/src/components/Heading/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./Heading"; diff --git a/src/components/Input/Checkbox.stories.tsx b/src/components/Input/Checkbox.stories.tsx deleted file mode 100644 index 2bde96f..0000000 --- a/src/components/Input/Checkbox.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import { Checkbox } from "./Checkbox"; - -const meta: Meta = { - component: Checkbox, - tags: ["autodocs"], -}; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - args: { - name: "group", - value: "test", - label: "Label", - }, -}; diff --git a/src/components/Input/Checkbox.tsx b/src/components/Input/Checkbox.tsx deleted file mode 100644 index 45c2ffb..0000000 --- a/src/components/Input/Checkbox.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { forwardRef } from "react"; - -import { type ToggleProps, Toggle } from "./components/Toggle"; - -export type CheckboxProps = Omit; - -const ICONS: Record = { - false: ( - - - - ), - true: ( - - - - ), -}; - -export const Checkbox = forwardRef(function Checkbox(props, ref) { - return ICONS[checked.toString()]} />; -}); diff --git a/src/components/Input/Radio.stories.tsx b/src/components/Input/Radio.stories.tsx deleted file mode 100644 index 26bc0e4..0000000 --- a/src/components/Input/Radio.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import { Radio } from "./Radio"; - -const meta: Meta = { - component: Radio, - tags: ["autodocs"], -}; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - args: { - name: "group", - value: "test", - label: "Label", - }, -}; diff --git a/src/components/Input/Radio.tsx b/src/components/Input/Radio.tsx deleted file mode 100644 index 56f29cf..0000000 --- a/src/components/Input/Radio.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { type JSX, forwardRef } from "react"; - -import { type ToggleProps, Toggle } from "./components/Toggle"; - -export type RadioProps = Omit; - -const ICONS: Record = { - true: ( - - - - ), - false: ( - - - - ), -}; - -export const Radio = forwardRef(function Radio(props, ref) { - return ICONS[selected.toString()]} />; -}); diff --git a/src/components/Input/components/Toggle.tsx b/src/components/Input/components/Toggle.tsx deleted file mode 100644 index c73bc38..0000000 --- a/src/components/Input/components/Toggle.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { - type ChangeEvent, - type DetailedHTMLProps, - type FocusEventHandler, - type HTMLAttributes, - forwardRef, -} from "react"; -import { twMerge, twJoin } from "tailwind-merge"; - -import { Text } from "@/components/Text"; -import { useControlledState } from "@/hooks/useControlledState"; - -export interface ToggleProps { - id?: string; - name?: string; - label?: string | JSX.Element; - inputType: "radio" | "checkbox"; - orientation?: "left" | "right"; - value?: string; - checked?: boolean; - defaultChecked?: boolean; - disabled?: boolean; - className?: string; - labelClassName?: string; - inputProps?: Omit< - DetailedHTMLProps, HTMLInputElement>, - "id" | "name" | "value" | "checked" | "defaultChecked" | "disabled" | "ref" - > & { - pattern?: string; - }; - renderIcon: (checked: boolean) => JSX.Element; - onChange?: (value?: boolean) => void; - onFocus?: FocusEventHandler; - onBlur?: FocusEventHandler; -} - -export const Toggle = forwardRef(function Toggle( - { - label, - checked, - defaultChecked = false, - inputProps, - orientation = "left", - disabled = false, - className, - inputType, - labelClassName, - renderIcon, - onChange, - ...restProps - }, - ref, -) { - const [checkedState = false, setCheckedState] = useControlledState({ - value: checked, - defaultValue: defaultChecked, - onStateChange: onChange, - }); - - function handleChange(e: ChangeEvent) { - setCheckedState(e.currentTarget.checked); - inputProps?.onChange?.(e); - } - - const toggle = ( - - {renderIcon(checkedState)} - - - - ); - - if (label) { - return ( - - {toggle} - {label} - - ); - } - - return toggle; -}); diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx deleted file mode 100644 index 2146854..0000000 --- a/src/components/Input/index.tsx +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./Checkbox"; -export * from "./Radio"; diff --git a/src/widgets/Inscriptions/index.stories.tsx b/src/components/Inscriptions/index.stories.tsx similarity index 100% rename from src/widgets/Inscriptions/index.stories.tsx rename to src/components/Inscriptions/index.stories.tsx diff --git a/src/widgets/Inscriptions/index.tsx b/src/components/Inscriptions/index.tsx similarity index 95% rename from src/widgets/Inscriptions/index.tsx rename to src/components/Inscriptions/index.tsx index 748e176..5efeb8a 100644 --- a/src/widgets/Inscriptions/index.tsx +++ b/src/components/Inscriptions/index.tsx @@ -1,8 +1,8 @@ -import { Text, Radio, Button, DialogBody, DialogFooter, DialogHeader, Checkbox } from "@/index"; - -import { FieldControl } from "@/widgets/FieldControl"; import { useState } from "react"; import { twMerge } from "tailwind-merge"; +import { Text, Radio, Button, DialogBody, DialogFooter, DialogHeader, Checkbox } from "@babylonlabs-io/bbn-core-ui"; + +import { FieldControl } from "@/components/FieldControl"; export interface Props { className?: string; diff --git a/src/components/Portal/Portal.tsx b/src/components/Portal/Portal.tsx deleted file mode 100644 index 16bf3fa..0000000 --- a/src/components/Portal/Portal.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { PropsWithChildren, useEffect, useState } from "react"; -import { createPortal } from "react-dom"; - -interface PortalProps { - mounted?: boolean; - rootClassName?: string; -} - -export function Portal({ children, mounted = false, rootClassName = "portal-root" }: PropsWithChildren) { - const [rootRef, setRootRef] = useState(null); - - useEffect(() => { - if (!mounted) { - setRootRef(null); - return; - } - - const root = document.createElement("div"); - root.className = rootClassName; - setRootRef(root); - document.body.appendChild(root); - - return () => { - document.body.removeChild(root); - }; - }, [mounted]); - - return rootRef ? createPortal(children, rootRef) : null; -} diff --git a/src/components/Portal/index.ts b/src/components/Portal/index.ts deleted file mode 100644 index c134372..0000000 --- a/src/components/Portal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./Portal"; diff --git a/src/widgets/TermsOfService/index.stories.tsx b/src/components/TermsOfService/index.stories.tsx similarity index 100% rename from src/widgets/TermsOfService/index.stories.tsx rename to src/components/TermsOfService/index.stories.tsx diff --git a/src/widgets/TermsOfService/index.tsx b/src/components/TermsOfService/index.tsx similarity index 95% rename from src/widgets/TermsOfService/index.tsx rename to src/components/TermsOfService/index.tsx index e835eb1..e1cf3d1 100644 --- a/src/widgets/TermsOfService/index.tsx +++ b/src/components/TermsOfService/index.tsx @@ -1,8 +1,8 @@ import { useCallback, useMemo, useState } from "react"; import { twMerge } from "tailwind-merge"; -import { Text, Checkbox, Button, DialogBody, DialogFooter, DialogHeader } from "@/index"; +import { Text, Checkbox, Button, DialogBody, DialogFooter, DialogHeader } from "@babylonlabs-io/bbn-core-ui"; -import { FieldControl } from "@/widgets/FieldControl"; +import { FieldControl } from "@/components/FieldControl"; export interface Props { className?: string; diff --git a/src/components/Text/Text.stories.tsx b/src/components/Text/Text.stories.tsx deleted file mode 100644 index 46434ad..0000000 --- a/src/components/Text/Text.stories.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import { Text } from "./Text"; - -const meta: Meta = { - component: Text, - tags: ["autodocs"], -}; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - render: (args) => - args.variant ? ( - Text--{args.variant} - ) : ( -
- - Text--Body1 - - - Text--Body2 - - - Text--subtitle1 - - - Text--subtitle2 - - - Text--overline - - - Text--caption - -
- ), -}; diff --git a/src/components/Text/Text.tsx b/src/components/Text/Text.tsx deleted file mode 100644 index 1bbce66..0000000 --- a/src/components/Text/Text.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { HTMLProps, createElement, forwardRef } from "react"; -import { twMerge } from "tailwind-merge"; - -const STYLES = { - body1: "text-base tracking-0.15", - body2: "text-sm tracking-0.15", - subtitle1: "text-base leading-7 tracking-0.15", - subtitle2: "text-sm font-bold leading-normal tracking-0.1", - overline: "text-xs leading-8 tracking-1 uppercase", - caption: "text-xs tracking-0.4", -} as const; - -type Variant = keyof typeof STYLES; - -export interface TextProps extends HTMLProps { - variant?: Variant; - as?: string; -} - -export const Text = forwardRef( - ({ variant = "body1", as = "p", children, className, ...restProps }, ref) => { - return createElement( - as, - { - ...restProps, - ref, - className: twMerge(STYLES[variant], className), - }, - children, - ); - }, -); - -Text.displayName = "Text"; diff --git a/src/components/Text/index.ts b/src/components/Text/index.ts deleted file mode 100644 index 22e10b6..0000000 --- a/src/components/Text/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./Text"; diff --git a/src/widgets/WalletButton/index.stories.tsx b/src/components/WalletButton/index.stories.tsx similarity index 100% rename from src/widgets/WalletButton/index.stories.tsx rename to src/components/WalletButton/index.stories.tsx diff --git a/src/widgets/WalletButton/index.tsx b/src/components/WalletButton/index.tsx similarity index 92% rename from src/widgets/WalletButton/index.tsx rename to src/components/WalletButton/index.tsx index b650080..e399ed2 100644 --- a/src/widgets/WalletButton/index.tsx +++ b/src/components/WalletButton/index.tsx @@ -1,6 +1,5 @@ import { twMerge } from "tailwind-merge"; - -import { Text, Avatar, Chip } from "@/index"; +import { Text, Avatar, Chip } from "@babylonlabs-io/bbn-core-ui"; interface WalletButtonProps { className?: string; diff --git a/src/widgets/WalletProvider/components/Screen.tsx b/src/components/WalletProvider/components/Screen.tsx similarity index 63% rename from src/widgets/WalletProvider/components/Screen.tsx rename to src/components/WalletProvider/components/Screen.tsx index 832f012..073a5ea 100644 --- a/src/widgets/WalletProvider/components/Screen.tsx +++ b/src/components/WalletProvider/components/Screen.tsx @@ -1,10 +1,10 @@ -import Chains from "@/widgets/Chains"; -import Wallets from "@/widgets/Wallets"; -import { Inscriptions } from "@/widgets/Inscriptions"; -import { TermsOfService } from "@/widgets/TermsOfService"; +import Chains from "@/components/Chains"; +import Wallets from "@/components/Wallets"; +import { Inscriptions } from "@/components/Inscriptions"; +import { TermsOfService } from "@/components/TermsOfService"; import type { IChain, IWallet } from "@/core/types"; -import type { Screen } from "@/state/state.d"; +import type { Screen } from "@/state/types"; interface ScreenProps { current: Screen; @@ -24,11 +24,12 @@ const SCREENS = { WALLETS: ({ className, onClose, onSelectWallet }: ScreenProps) => ( ), - INSCRIPTIONS: ({ onToggleInscriptions }) => , + INSCRIPTIONS: ({ onToggleInscriptions }: ScreenProps) => , + EMPTY: ({ className }: ScreenProps) =>
, } as const; export function Screen(props: ScreenProps) { - const CurrentScreen = SCREENS[props.current.type] ?? SCREENS.CHAINS; + const CurrentScreen = SCREENS[props.current.type as keyof typeof SCREENS] ?? SCREENS.EMPTY; return ; } diff --git a/src/widgets/WalletProvider/components/WalletDialog.tsx b/src/components/WalletProvider/components/WalletDialog.tsx similarity index 68% rename from src/widgets/WalletProvider/components/WalletDialog.tsx rename to src/components/WalletProvider/components/WalletDialog.tsx index 3158b82..d50930e 100644 --- a/src/widgets/WalletProvider/components/WalletDialog.tsx +++ b/src/components/WalletProvider/components/WalletDialog.tsx @@ -1,6 +1,6 @@ import { useCallback } from "react"; +import { Dialog } from "@babylonlabs-io/bbn-core-ui"; -import { Dialog } from "@/index"; import { useAppState } from "@/state/state"; import { useChainProviders } from "@/context/Chain.context"; import { useInscriptionProvider } from "@/context/Inscriptions.context"; @@ -8,26 +8,34 @@ import type { IChain, IWallet } from "@/core/types"; import { Screen } from "./Screen"; -export function WalletDialog() { +interface WalletDialogProps { + onError?: (e: Error) => void; +} + +export function WalletDialog({ onError }: WalletDialogProps) { const { visible, screen, close, selectWallet, displayLoader, displayChains, displayInscriptions } = useAppState(); const { showAgain, toggleShowAgain, toggleLockInscriptions } = useInscriptionProvider(); const connectors = useChainProviders(); const handleSelectWallet = useCallback( async (chain: IChain, wallet: IWallet) => { - displayLoader?.(); + try { + displayLoader?.(); - const connector = connectors[chain.id]; - const connectedWallet = await connector?.connect(wallet.id); + const connector = connectors[chain.id as keyof typeof connectors]; + const connectedWallet = await connector?.connect(wallet.id); - if (connectedWallet) { - selectWallet?.(chain.id, connectedWallet); - } + if (connectedWallet) { + selectWallet?.(chain.id, connectedWallet); + } - if (showAgain) { - displayInscriptions?.(); - } else { - displayChains?.(); + if (showAgain) { + displayInscriptions?.(); + } else { + displayChains?.(); + } + } catch (e: any) { + onError?.(e); } }, [displayLoader, selectWallet, displayInscriptions, connectors, showAgain], diff --git a/src/widgets/WalletProvider/index.stories.tsx b/src/components/WalletProvider/index.stories.tsx similarity index 89% rename from src/widgets/WalletProvider/index.stories.tsx rename to src/components/WalletProvider/index.stories.tsx index c25e27a..7e6c4db 100644 --- a/src/widgets/WalletProvider/index.stories.tsx +++ b/src/components/WalletProvider/index.stories.tsx @@ -1,12 +1,11 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { Button, ScrollLocker } from "@babylonlabs-io/bbn-core-ui"; -import { WalletProvider } from "./index"; - -import { Button } from "@/components/Button"; -import { ScrollLocker } from "@/context/Dialog.context"; import { useAppState } from "@/state/state"; import { Network } from "@/core/types"; +import { WalletProvider } from "./index"; + const meta: Meta = { component: WalletProvider, tags: ["autodocs"], @@ -25,6 +24,9 @@ const networkConfig = { }; export const Default: Story = { + args: { + onError: console.log, + }, decorators: [ (Story) => ( diff --git a/src/widgets/WalletProvider/index.tsx b/src/components/WalletProvider/index.tsx similarity index 75% rename from src/widgets/WalletProvider/index.tsx rename to src/components/WalletProvider/index.tsx index c80cb85..58f6aab 100644 --- a/src/widgets/WalletProvider/index.tsx +++ b/src/components/WalletProvider/index.tsx @@ -10,15 +10,21 @@ import { WalletDialog } from "./components/WalletDialog"; interface WalletProviderProps { context?: any; config: NetworkConfig; + onError?: (e: Error) => void; } -export function WalletProvider({ children, config, context = window }: PropsWithChildren) { +export function WalletProvider({ + children, + config, + context = window, + onError, +}: PropsWithChildren) { return ( {children} - + diff --git a/src/widgets/Wallets/index.stories.tsx b/src/components/Wallets/index.stories.tsx similarity index 91% rename from src/widgets/Wallets/index.stories.tsx rename to src/components/Wallets/index.stories.tsx index 6033131..fb4e107 100644 --- a/src/widgets/Wallets/index.stories.tsx +++ b/src/components/Wallets/index.stories.tsx @@ -1,8 +1,8 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Text } from "@/index"; +import { Text } from "@babylonlabs-io/bbn-core-ui"; +import { WalletButton } from "@/components/WalletButton"; import { Wallets } from "./index"; -import { WalletButton } from "@/widgets/WalletButton"; const meta: Meta = { component: Wallets, diff --git a/src/widgets/Wallets/index.tsx b/src/components/Wallets/index.tsx similarity index 96% rename from src/widgets/Wallets/index.tsx rename to src/components/Wallets/index.tsx index 0aaa088..d172ca0 100644 --- a/src/widgets/Wallets/index.tsx +++ b/src/components/Wallets/index.tsx @@ -1,9 +1,8 @@ import { twMerge } from "tailwind-merge"; import { useMemo } from "react"; +import { Text, Button, DialogBody, DialogFooter, DialogHeader } from "@babylonlabs-io/bbn-core-ui"; -import { Text, Button, DialogBody, DialogFooter, DialogHeader } from "@/index"; - -import { WalletButton } from "@/widgets/WalletButton"; +import { WalletButton } from "@/components/WalletButton"; import { withAppState } from "@/hocs/withAppState"; import type { IChain, IWallet } from "@/core/types"; diff --git a/src/context/Chain.context.tsx b/src/context/Chain.context.tsx index c89f9a6..1320bc1 100644 --- a/src/context/Chain.context.tsx +++ b/src/context/Chain.context.tsx @@ -1,11 +1,13 @@ import { createContext, PropsWithChildren, useEffect, useState, useCallback, useContext } from "react"; + import { useAppState } from "@/state/state"; -import { WalletConnector } from "@/core/WalletConnector"; -import type { NetworkConfig } from "@/core/types"; +import { createWalletConnector } from "@/core"; import metadata from "@/core/wallets"; +import { WalletConnector } from "@/core/WalletConnector"; import { BTCProvider } from "@/core/wallets/btc/BTCProvider"; import { BBNProvider } from "@/core/wallets/bbn/BBNProvider"; +import type { NetworkConfig } from "@/core/types"; interface ProviderProps { context: any; @@ -34,7 +36,7 @@ export function ChainProvider({ children, context, config }: PropsWithChildren

WalletConnector.create(data, context, config))); + const connectorArr = await Promise.all(metadataArr.map((data) => createWalletConnector(data, context, config))); return connectorArr.reduce((acc, connector) => ({ ...acc, [connector.id]: connector }), {} as Connectors); }, []); diff --git a/src/context/Dialog.context.tsx b/src/context/Dialog.context.tsx deleted file mode 100644 index 7d2c6dd..0000000 --- a/src/context/Dialog.context.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { type PropsWithChildren, createContext, useState, useMemo, useCallback, useEffect } from "react"; -import { toPixels } from "@/utils/css"; - -interface DialogContext { - removeDialog: (id: string, value?: boolean) => void; - updateDialog: (id: string, value: boolean) => void; -} - -export const DialogContext = createContext({ - removeDialog: () => null, - updateDialog: () => null, -}); - -export function ScrollLocker({ children }: PropsWithChildren) { - const [dialogs, setDialogs] = useState>({}); - const bodyLocked = useMemo(() => Object.values(dialogs).some((v) => v), [dialogs]); - - useEffect( - function lockBody() { - if (bodyLocked) { - const width = document.body.offsetWidth; - document.body.style.overflow = "hidden"; - document.body.style.paddingRight = - document.body.offsetWidth - width >= 1 - ? (toPixels(document.body.offsetWidth - width) ?? "") - : document.body.style.paddingRight; - } else { - document.body.style.overflow = ""; - document.body.style.paddingRight = ""; - } - }, - [bodyLocked], - ); - - const removeDialog = useCallback((id: string) => { - setDialogs((state) => (Reflect.deleteProperty(state, id) ? { ...state } : state)); - }, []); - - const updateDialog = useCallback((id: string, value: boolean) => { - setDialogs((state) => ({ ...state, [id]: value })); - }, []); - - const value = useMemo(() => ({ removeDialog, updateDialog }), [removeDialog, updateDialog]); - - return {children}; -} diff --git a/src/core/Wallet.ts b/src/core/Wallet.ts index 295c4df..dd483e3 100644 --- a/src/core/Wallet.ts +++ b/src/core/Wallet.ts @@ -1,6 +1,6 @@ -import { IWallet, Network, IProvider, type NetworkConfig, type WalletMetadata, Account } from "@/core/types"; +import type { IWallet, IProvider, Network, Account } from "@/core/types"; -interface Options

{ +export interface WalletOptions

{ id: string; name: string; icon: string; @@ -10,8 +10,6 @@ interface Options

{ provider: P | null; } -const defaultWalletGetter = (key: string) => (context: any) => context[key]; - export class Wallet

implements IWallet { readonly id: string; readonly origin: any; @@ -22,53 +20,7 @@ export class Wallet

implements IWallet { readonly provider: P | null = null; account: Account | null = null; - static create = async

(metadata: WalletMetadata

, context: any, config: NetworkConfig) => { - const { - id, - wallet: walletGetter, - name: nameGetter, - icon: iconGetter, - docs = "", - networks = [], - createProvider, - } = metadata; - - const options: Options

= { - id, - name: "", - icon: "", - origin: null, - provider: null, - docs, - networks, - }; - - if (walletGetter) { - const getWallet = typeof walletGetter === "string" ? defaultWalletGetter(walletGetter) : walletGetter; - - options.origin = getWallet(context, config) ?? null; - options.provider = options.origin ? createProvider(options.origin, config) : null; - } else { - options.origin = null; - options.provider = createProvider(null, config); - } - - if (typeof nameGetter === "string") { - options.name = nameGetter ?? ""; - } else { - options.name = options.origin ? await nameGetter(options.origin, config) : ""; - } - - if (typeof iconGetter === "string") { - options.icon = iconGetter ?? ""; - } else { - options.icon = options.origin ? await iconGetter(options.origin, config) : ""; - } - - return new Wallet(options); - }; - - constructor({ id, origin, name, icon, docs, networks, provider }: Options

) { + constructor({ id, origin, name, icon, docs, networks, provider }: WalletOptions

) { this.id = id; this.origin = origin; this.name = name; diff --git a/src/core/WalletConnector.ts b/src/core/WalletConnector.ts index dcbb929..bc3b4d8 100644 --- a/src/core/WalletConnector.ts +++ b/src/core/WalletConnector.ts @@ -1,23 +1,9 @@ import { Wallet } from "@/core/Wallet"; -import type { NetworkConfig, IProvider, IChain, ChainMetadata } from "@/core/types"; +import type { IProvider, IChain } from "@/core/types"; export class WalletConnector implements IChain { private _connectedWallet: Wallet

| null = null; - static async create( - metadata: ChainMetadata, - context: any, - config: NetworkConfig, - ): Promise> { - const wallets: Wallet

[] = []; - - for (const walletMetadata of metadata.wallets) { - wallets.push(await Wallet.create(walletMetadata, context, config)); - } - - return new WalletConnector(metadata.chain, metadata.name, metadata.icon, wallets); - } - constructor( public readonly id: N, public readonly name: string, diff --git a/src/core/index.ts b/src/core/index.ts new file mode 100644 index 0000000..0a3b2c2 --- /dev/null +++ b/src/core/index.ts @@ -0,0 +1,69 @@ +import { type WalletOptions, Wallet } from "./Wallet"; +import { WalletConnector } from "./WalletConnector"; +import { ChainMetadata, IProvider, NetworkConfig, WalletMetadata } from "./types"; + +const defaultWalletGetter = (key: string) => (context: any) => context[key]; + +export const createWallet = async

( + metadata: WalletMetadata

, + context: any, + config: NetworkConfig, +) => { + const { + id, + wallet: walletGetter, + name: nameGetter, + icon: iconGetter, + docs = "", + networks = [], + createProvider, + } = metadata; + + const options: WalletOptions

= { + id, + name: "", + icon: "", + origin: null, + provider: null, + docs, + networks, + }; + + if (walletGetter) { + const getWallet = typeof walletGetter === "string" ? defaultWalletGetter(walletGetter) : walletGetter; + + options.origin = getWallet(context, config) ?? null; + options.provider = options.origin ? createProvider(options.origin, config) : null; + } else { + options.origin = null; + options.provider = createProvider(null, config); + } + + if (typeof nameGetter === "string") { + options.name = nameGetter ?? ""; + } else { + options.name = options.origin ? await nameGetter(options.origin, config) : ""; + } + + if (typeof iconGetter === "string") { + options.icon = iconGetter ?? ""; + } else { + options.icon = options.origin ? await iconGetter(options.origin, config) : ""; + } + + return new Wallet(options); +}; + +export const createWalletConnector = async ( + metadata: ChainMetadata, + context: any, + config: NetworkConfig, +): Promise> => { + const wallets: Wallet

[] = []; + + for (const walletMetadata of metadata.wallets) { + wallets.push(await createWallet(walletMetadata, context, config)); + } + + return new WalletConnector(metadata.chain, metadata.name, metadata.icon, wallets); +}; diff --git a/src/hocs/withAppState.tsx b/src/hocs/withAppState.tsx index 0b9e296..e8f862f 100644 --- a/src/hocs/withAppState.tsx +++ b/src/hocs/withAppState.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-empty-object-type */ import { ComponentType, memo, useMemo } from "react"; import { useAppState } from "@/state/state"; -import type { Actions, State } from "@/state/state.d"; +import type { Actions, State } from "@/state/types"; export const withAppState = (stateMapper: (state: State & Actions) => IP) => diff --git a/src/hooks/useControlledState.ts b/src/hooks/useControlledState.ts deleted file mode 100644 index bfbe88e..0000000 --- a/src/hooks/useControlledState.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useState, useRef, useCallback } from "react"; - -interface Options { - value?: V; - defaultValue?: V; - onStateChange?: (state: V) => void; -} - -export function useControlledState({ - value: controlledState, - defaultValue: defaultState, - onStateChange, -}: Options = {}): [V | undefined, (state: V) => void] { - const [uncontrolledState, setUncontrolledState] = useState(defaultState); - const { current: isControlled } = useRef(controlledState != null); - - const state = isControlled ? controlledState : uncontrolledState; - - const handleStateChange = useCallback( - (newValue: V) => { - if (!isControlled) { - setUncontrolledState(newValue); - } - - onStateChange?.(newValue); - }, - [isControlled, onStateChange, setUncontrolledState], - ); - - return [state, handleStateChange]; -} diff --git a/src/hooks/useModalManager.ts b/src/hooks/useModalManager.ts deleted file mode 100644 index b1f89ab..0000000 --- a/src/hooks/useModalManager.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { DialogContext } from "@/context/Dialog.context"; -import { useCallback, useContext, useEffect, useId, useState } from "react"; - -interface Options { - open?: boolean; - unmountOnClose?: boolean; -} - -export function useModalManager({ open = false }: Options = {}) { - const modalId = useId(); - const [mounted, setMounted] = useState(open); - const { updateDialog, removeDialog } = useContext(DialogContext); - const visible = open || mounted; - - useEffect( - () => () => { - removeDialog(modalId); - }, - [modalId], - ); - - useEffect(() => { - updateDialog(modalId, visible); - }, [modalId, visible, updateDialog]); - - useEffect(() => { - if (open) { - setMounted(true); - } - }, [open]); - - const unmount = useCallback(() => { - if (!open) { - setMounted(false); - } - }, [open]); - - return { - mounted, - unmount, - }; -} diff --git a/src/hooks/usePortalRoot.ts b/src/hooks/usePortalRoot.ts deleted file mode 100644 index f91505b..0000000 --- a/src/hooks/usePortalRoot.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { useState, useEffect } from "react"; - -interface Options { - unmountOnClose?: boolean; - className?: string; -} - -export function usePortalRoot(enabled = true, { unmountOnClose = true, className = "portal-root" }: Options = {}) { - const [rootRef, setRootRef] = useState(null); - const mounted = enabled || !unmountOnClose; - - useEffect(() => { - if (!mounted) { - setRootRef(null); - return; - } - - const root = document.createElement("div"); - root.className = className; - setRootRef(root); - document.body.appendChild(root); - - return () => { - document.body.removeChild(root); - }; - }, [mounted]); - - return rootRef; -} diff --git a/src/index.css b/src/index.css index 0e00bdd..5b34fb4 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +1,5 @@ +@import "../node_modules/@babylonlabs-io/bbn-core-ui/dist/style.css"; + @tailwind base; @tailwind components; @tailwind utilities; diff --git a/src/index.tsx b/src/index.tsx index a495f17..d4ebeef 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,16 +2,5 @@ import "./index.css"; export { useChainConnector } from "@/hooks/useChainConnector"; export { useAppState } from "@/state/state"; -export { WalletProvider } from "@/widgets/WalletProvider"; -export * from "@/state/state.d"; - -// core-ui -export * from "./components/Text"; -export * from "./components/Heading"; -export * from "./components/Button"; -export * from "./components/Avatar"; -export * from "./components/Input"; -export * from "./components/Dialog"; -export * from "./components/Chip"; - -export { ScrollLocker } from "@/context/Dialog.context"; +export { WalletProvider } from "@/components/WalletProvider"; +export * from "@/state/types"; diff --git a/src/state/state.tsx b/src/state/state.tsx index e0fa3a0..7875dfe 100644 --- a/src/state/state.tsx +++ b/src/state/state.tsx @@ -1,7 +1,7 @@ import { type PropsWithChildren, createContext, useContext, useMemo, useState } from "react"; -import { Actions, type State } from "./state.d"; import { IChain, IWallet } from "@/core/types"; +import { Actions, type State } from "./types"; const defaultState: State = { visible: false, @@ -55,7 +55,7 @@ export function StateProvider({ children }: PropsWithChildren) { removeWallet: (chain: string) => { setState((state) => ({ ...state, - selectedWallets: { ...state.selectedWallets, [chain]: null }, + selectedWallets: { ...state.selectedWallets, [chain]: undefined }, })); }, diff --git a/src/state/state.d.ts b/src/state/types.ts similarity index 71% rename from src/state/state.d.ts rename to src/state/types.ts index 85cba8a..e4939d5 100644 --- a/src/state/state.d.ts +++ b/src/state/types.ts @@ -1,11 +1,11 @@ -import type { IChain, IWalllet } from "@/core/types"; +import type { IChain, IWallet } from "@/core/types"; -type Screen = { +export type Screen = { type: T; params?: Record; }; -type Screens = +export type Screens = | Screen<"LOADER"> | Screen<"TERMS_OF_SERVICE"> | Screen<"CHAINS"> @@ -15,7 +15,7 @@ type Screens = export interface State { visible: boolean; screen: Screens; - selectedWallets: Record; + selectedWallets: Record; chains: Record; } @@ -27,7 +27,7 @@ export interface Actions { displayWallets?: (chain: string) => void; displayInscriptions?: () => void; displayTermsOfService?: () => void; - selectWallet?: (chain: string, wallet: IWalllet) => void; + selectWallet?: (chain: string, wallet: IWallet) => void; removeWallet?: (chain: string) => void; addChain?: (chain: IChain) => void; } diff --git a/src/utils/css.ts b/src/utils/css.ts deleted file mode 100644 index b56364e..0000000 --- a/src/utils/css.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function toPixels(val?: number, defaultValue?: number | "auto"): `${string}px` | "auto" | undefined { - if (typeof val !== "number") { - return typeof defaultValue === "number" ? toPixels(defaultValue) : defaultValue; - } - - return `${val}px`; -}