From 7645f7293d8d9e52eb9120c7c83b3dd1345a81b1 Mon Sep 17 00:00:00 2001 From: Sergey Kintsel Date: Thu, 4 Jul 2024 12:16:47 +0100 Subject: [PATCH 1/2] Move dynamic modal into a separate package --- apps/desktop/package.json | 1 + apps/desktop/src/Router.tsx | 2 +- .../AccountDrawer/AccountDrawerDisplay.tsx | 2 +- .../AccountDrawer/AssetsPanel/EarnTab.tsx | 2 +- .../MultisigSignerTile.tsx | 2 +- .../FinalizableUnstakeRequest.tsx | 2 +- .../DerivationInfo/DerivationInfoButton.tsx | 2 +- .../AccountDrawer/RenameAccountModal.tsx | 2 +- .../AccountDrawer/RenameRemoveMenuSwitch.tsx | 2 +- .../src/components/AccountDrawer/index.tsx | 2 +- .../AddressPill/AddressPillIcon.tsx | 2 +- .../CSVFileUploader/CSVFileUploadForm.tsx | 2 +- .../src/components/CSVFileUploader/index.tsx | 2 +- .../ChangePassword/ChangePasswordForm.tsx | 2 +- .../src/components/ConfirmationModal.tsx | 2 +- .../src/components/DeleteContactModal.tsx | 2 +- .../SendFlow/Beacon/useSignWithBeacon.tsx | 2 +- .../Delegation/ChangeDelegateNoticeModal.tsx | 2 +- .../Delegation/NewDelegateNoticeModal.tsx | 2 +- .../components/SendFlow/Multisig/SignPage.tsx | 2 +- .../MultisigAccount/NameMultisigFormPage.tsx | 2 +- .../components/SendFlow/Stake/NoticeModal.tsx | 2 +- .../src/components/SendFlow/SuccessStep.tsx | 2 +- .../SendFlow/Unstake/NoticeModal.tsx | 2 +- .../SendFlow/onSubmitFormActionHooks.tsx | 2 +- .../desktop/src/components/SendFlow/utils.tsx | 2 +- apps/desktop/src/components/TopBar.tsx | 2 +- .../src/components/UpsertContactModal.tsx | 2 +- apps/desktop/src/mocks/testUtils.tsx | 2 +- .../utils/beacon/PermissionRequestModal.tsx | 2 +- .../utils/beacon/SignPayloadRequestModal.tsx | 2 +- .../utils/beacon/useHandleBeaconMessage.tsx | 2 +- .../src/views/addressBook/AddressBookView.tsx | 2 +- .../src/views/addressBook/ContactTable.tsx | 2 +- apps/desktop/src/views/batch/BatchView.tsx | 2 +- apps/desktop/src/views/home/AccountGroup.tsx | 2 +- apps/desktop/src/views/home/AccountsList.tsx | 2 +- apps/desktop/src/views/nfts/NFTDrawerCard.tsx | 2 +- .../src/views/settings/SettingsView.tsx | 2 +- .../network/NetworkSettingsDrawerBody.tsx | 2 +- .../settings/network/UpsertNetworkModal.tsx | 2 +- .../src/views/tokens/AccountTokens.tsx | 2 +- packages/components/.depcheckrc | 2 + packages/components/.eslintrc.cjs | 9 +++ packages/components/babel.config.json | 3 + packages/components/jest.config.ts | 10 +++ packages/components/package.json | 72 +++++++++++++++++++ .../components/src}/DynamicModal.test.tsx | 10 ++- .../components/src}/DynamicModal.tsx | 46 ++++++------ packages/components/src/index.ts | 1 + packages/components/src/setupTests.ts | 1 + packages/components/src/testUtils.tsx | 5 ++ packages/components/tsconfig.json | 4 ++ yarn.lock | 37 +++++++++- 54 files changed, 218 insertions(+), 65 deletions(-) create mode 100644 packages/components/.depcheckrc create mode 100644 packages/components/.eslintrc.cjs create mode 100644 packages/components/babel.config.json create mode 100644 packages/components/jest.config.ts create mode 100644 packages/components/package.json rename {apps/desktop/src/components => packages/components/src}/DynamicModal.test.tsx (78%) rename {apps/desktop/src/components => packages/components/src}/DynamicModal.tsx (64%) create mode 100644 packages/components/src/index.ts create mode 100644 packages/components/src/setupTests.ts create mode 100644 packages/components/src/testUtils.tsx create mode 100644 packages/components/tsconfig.json diff --git a/apps/desktop/package.json b/apps/desktop/package.json index eaf245e7c..2b34c1770 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -85,6 +85,7 @@ "@types/react-dom": "18.3.0", "@types/react-test-renderer": "^18.3.0", "@tzkt/sdk-api": "^2.2.1", + "@umami/components": "workspace:^", "@umami/core": "workspace:^", "@umami/crypto": "workspace:^", "@umami/data-polling": "workspace:^", diff --git a/apps/desktop/src/Router.tsx b/apps/desktop/src/Router.tsx index c13e40c8f..a55dab455 100644 --- a/apps/desktop/src/Router.tsx +++ b/apps/desktop/src/Router.tsx @@ -1,4 +1,5 @@ /* istanbul ignore file */ +import { DynamicModalContext, useDynamicModal } from "@umami/components"; import { useDataPolling } from "@umami/data-polling"; import { WalletClient, useImplicitAccounts, useResetConnections } from "@umami/state"; import { noop } from "lodash"; @@ -6,7 +7,6 @@ import { useEffect } from "react"; import { HashRouter, Navigate, Route, Routes } from "react-router-dom"; import { AnnouncementBanner } from "./components/AnnouncementBanner"; -import { DynamicModalContext, useDynamicModal } from "./components/DynamicModal"; import { BeaconProvider } from "./utils/beacon/BeaconProvider"; import { useDeeplinkHandler } from "./utils/useDeeplinkHandler"; import { AddressBookView } from "./views/addressBook/AddressBookView"; diff --git a/apps/desktop/src/components/AccountDrawer/AccountDrawerDisplay.tsx b/apps/desktop/src/components/AccountDrawer/AccountDrawerDisplay.tsx index 1a010d248..97925df4b 100644 --- a/apps/desktop/src/components/AccountDrawer/AccountDrawerDisplay.tsx +++ b/apps/desktop/src/components/AccountDrawer/AccountDrawerDisplay.tsx @@ -1,4 +1,5 @@ import { Box, Center, Flex, Heading, IconButton, Text } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account, type FA12TokenBalance, @@ -17,7 +18,6 @@ import { accountIconGradient } from "../AccountTile/AccountTile"; import { AccountTileIcon } from "../AccountTile/AccountTileIcon"; import { AddressPill } from "../AddressPill/AddressPill"; import { BuyTezForm } from "../BuyTez/BuyTezForm"; -import { DynamicModalContext } from "../DynamicModal"; import { NoticeModal as DelegateNoticeModal } from "../SendFlow/Delegation/NoticeModal"; import { TezRecapDisplay } from "../TezRecapDisplay"; diff --git a/apps/desktop/src/components/AccountDrawer/AssetsPanel/EarnTab.tsx b/apps/desktop/src/components/AccountDrawer/AssetsPanel/EarnTab.tsx index 91966e709..8a5761279 100644 --- a/apps/desktop/src/components/AccountDrawer/AssetsPanel/EarnTab.tsx +++ b/apps/desktop/src/components/AccountDrawer/AssetsPanel/EarnTab.tsx @@ -1,4 +1,5 @@ import { Box, Button, Center, Flex, type FlexProps, Heading, Text } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account, type ImplicitAccount } from "@umami/core"; import { useGetAccountDelegate, @@ -13,7 +14,6 @@ import { PendingUnstakeRequests } from "./PendingUnstakeRequests/PendingUnstakeR import { ExternalLinkIcon, PenIcon, XMarkIcon } from "../../../assets/icons"; import colors from "../../../style/colors"; import { AddressPill } from "../../AddressPill/AddressPill"; -import { DynamicModalContext } from "../../DynamicModal"; import { ExternalLink } from "../../ExternalLink"; import { NoticeModal as DelegateNoticeModal } from "../../SendFlow/Delegation/NoticeModal"; import { NoticeModal as StakeNoticeModal } from "../../SendFlow/Stake/NoticeModal"; diff --git a/apps/desktop/src/components/AccountDrawer/AssetsPanel/MultisigPendingOperations/MultisigSignerTile.tsx b/apps/desktop/src/components/AccountDrawer/AssetsPanel/MultisigPendingOperations/MultisigSignerTile.tsx index 54511448d..eb142a8a7 100644 --- a/apps/desktop/src/components/AccountDrawer/AssetsPanel/MultisigPendingOperations/MultisigSignerTile.tsx +++ b/apps/desktop/src/components/AccountDrawer/AssetsPanel/MultisigPendingOperations/MultisigSignerTile.tsx @@ -1,3 +1,4 @@ +import { DynamicModalContext } from "@umami/components"; import { type ImplicitAccount, type MultisigAccount, @@ -16,7 +17,6 @@ import colors from "../../../../style/colors"; import { AccountTileBase, LabelAndAddress } from "../../../AccountTile/AccountTile"; import { AddressTileIcon } from "../../../AddressTile/AddressTileIcon"; import { useAddressKind } from "../../../AddressTile/useAddressKind"; -import { DynamicModalContext } from "../../../DynamicModal"; import { SignPage } from "../../../SendFlow/Multisig/SignPage"; export const MultisigSignerTile: React.FC<{ diff --git a/apps/desktop/src/components/AccountDrawer/AssetsPanel/PendingUnstakeRequests/FinalizableUnstakeRequest.tsx b/apps/desktop/src/components/AccountDrawer/AssetsPanel/PendingUnstakeRequests/FinalizableUnstakeRequest.tsx index 69411c554..09c212c75 100644 --- a/apps/desktop/src/components/AccountDrawer/AssetsPanel/PendingUnstakeRequests/FinalizableUnstakeRequest.tsx +++ b/apps/desktop/src/components/AccountDrawer/AssetsPanel/PendingUnstakeRequests/FinalizableUnstakeRequest.tsx @@ -1,4 +1,5 @@ import { Box, Button, Center, Flex, type FlexProps, Text } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type ImplicitAccount, estimate, makeAccountOperations } from "@umami/core"; import { useAccountTotalFinalizableUnstakeAmount, @@ -9,7 +10,6 @@ import { prettyTezAmount } from "@umami/tezos"; import { useContext } from "react"; import colors from "../../../../style/colors"; -import { DynamicModalContext } from "../../../DynamicModal"; import { PrettyNumber } from "../../../PrettyNumber"; import { SignPage } from "../../../SendFlow/FinalizeUnstake/SignPage"; diff --git a/apps/desktop/src/components/AccountDrawer/DerivationInfo/DerivationInfoButton.tsx b/apps/desktop/src/components/AccountDrawer/DerivationInfo/DerivationInfoButton.tsx index d7bd1262d..c3c7320fa 100644 --- a/apps/desktop/src/components/AccountDrawer/DerivationInfo/DerivationInfoButton.tsx +++ b/apps/desktop/src/components/AccountDrawer/DerivationInfo/DerivationInfoButton.tsx @@ -1,10 +1,10 @@ import { Button, type ButtonProps } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account } from "@umami/core"; import { useContext } from "react"; import { InfoModal } from "./InfoModal"; import { FolderInfoIcon } from "../../../assets/icons"; -import { DynamicModalContext } from "../../DynamicModal"; /** * Button to open a modal with the account's derivation info diff --git a/apps/desktop/src/components/AccountDrawer/RenameAccountModal.tsx b/apps/desktop/src/components/AccountDrawer/RenameAccountModal.tsx index 21e12227f..24dd09317 100644 --- a/apps/desktop/src/components/AccountDrawer/RenameAccountModal.tsx +++ b/apps/desktop/src/components/AccountDrawer/RenameAccountModal.tsx @@ -9,12 +9,12 @@ import { ModalContent, ModalFooter, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account } from "@umami/core"; import { renameAccount, useAppDispatch, useValidateName } from "@umami/state"; import { type FC, useContext } from "react"; import { useForm } from "react-hook-form"; -import { DynamicModalContext } from "../DynamicModal"; import { FormPageHeader } from "../SendFlow/FormPageHeader"; export const RenameAccountModal: FC<{ diff --git a/apps/desktop/src/components/AccountDrawer/RenameRemoveMenuSwitch.tsx b/apps/desktop/src/components/AccountDrawer/RenameRemoveMenuSwitch.tsx index 77a5d3e3d..d2c004123 100644 --- a/apps/desktop/src/components/AccountDrawer/RenameRemoveMenuSwitch.tsx +++ b/apps/desktop/src/components/AccountDrawer/RenameRemoveMenuSwitch.tsx @@ -1,3 +1,4 @@ +import { DynamicModalContext } from "@umami/components"; import { type Account } from "@umami/core"; import { useImplicitAccounts, useRemoveAccount } from "@umami/state"; import { useContext } from "react"; @@ -5,7 +6,6 @@ import { useNavigate } from "react-router-dom"; import { RenameAccountModal } from "./RenameAccountModal"; import { ConfirmationModal } from "../ConfirmationModal"; -import { DynamicModalContext } from "../DynamicModal"; import { RenameRemoveMenu } from "../RenameRemoveMenu"; export const RenameRemoveMenuSwitch: React.FC<{ account: Account }> = ({ account }) => { diff --git a/apps/desktop/src/components/AccountDrawer/index.tsx b/apps/desktop/src/components/AccountDrawer/index.tsx index c74cb17f3..72288290c 100644 --- a/apps/desktop/src/components/AccountDrawer/index.tsx +++ b/apps/desktop/src/components/AccountDrawer/index.tsx @@ -1,10 +1,10 @@ +import { DynamicModalContext } from "@umami/components"; import { useGetAccountAllTokens, useGetAccountNFTs, useGetOwnedAccount } from "@umami/state"; import { type RawPkh } from "@umami/tezos"; import { useContext } from "react"; import { AccountDrawerDisplay } from "./AccountDrawerDisplay"; import { sortedByLastUpdate } from "../../utils/token/utils"; -import { DynamicModalContext } from "../DynamicModal"; import { ReceiveModal } from "../ReceiveModal"; import { FormPage as SendTezForm } from "../SendFlow/Tez/FormPage"; diff --git a/apps/desktop/src/components/AddressPill/AddressPillIcon.tsx b/apps/desktop/src/components/AddressPill/AddressPillIcon.tsx index 9f584ab59..031cc4bfe 100644 --- a/apps/desktop/src/components/AddressPill/AddressPillIcon.tsx +++ b/apps/desktop/src/components/AddressPill/AddressPillIcon.tsx @@ -1,4 +1,5 @@ import { type IconProps } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { useAddressExistsInContacts } from "@umami/state"; import { useContext } from "react"; @@ -13,7 +14,6 @@ import { KeyIcon, XMarkIcon, } from "../../assets/icons"; -import { DynamicModalContext } from "../DynamicModal"; import { UpsertContactModal } from "../UpsertContactModal"; export const LeftIcon: React.FC<{ addressKind: AddressKind } & IconProps> = ({ diff --git a/apps/desktop/src/components/CSVFileUploader/CSVFileUploadForm.tsx b/apps/desktop/src/components/CSVFileUploader/CSVFileUploadForm.tsx index c1b420986..791d30437 100644 --- a/apps/desktop/src/components/CSVFileUploader/CSVFileUploadForm.tsx +++ b/apps/desktop/src/components/CSVFileUploader/CSVFileUploadForm.tsx @@ -13,6 +13,7 @@ import { Text, useToast, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Operation, makeAccountOperations } from "@umami/core"; import { estimateAndUpdateBatch, @@ -31,7 +32,6 @@ import { FormProvider, useForm } from "react-hook-form"; import { parseOperation } from "./utils"; import colors from "../../style/colors"; import { OwnedAccountsAutocomplete } from "../AddressAutocomplete"; -import { DynamicModalContext } from "../DynamicModal"; import { FormErrorMessage } from "../FormErrorMessage"; type FormFields = { diff --git a/apps/desktop/src/components/CSVFileUploader/index.tsx b/apps/desktop/src/components/CSVFileUploader/index.tsx index 871bbdf35..c39936771 100644 --- a/apps/desktop/src/components/CSVFileUploader/index.tsx +++ b/apps/desktop/src/components/CSVFileUploader/index.tsx @@ -1,9 +1,9 @@ import { Button, Text } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { useContext } from "react"; import { CSVFileUploadForm } from "./CSVFileUploadForm"; import { FileArrowDownIcon } from "../../assets/icons"; -import { DynamicModalContext } from "../DynamicModal"; export const CSVFileUploader = () => { const { openWith } = useContext(DynamicModalContext); diff --git a/apps/desktop/src/components/ChangePassword/ChangePasswordForm.tsx b/apps/desktop/src/components/ChangePassword/ChangePasswordForm.tsx index 4c20b758f..13741675e 100644 --- a/apps/desktop/src/components/ChangePassword/ChangePasswordForm.tsx +++ b/apps/desktop/src/components/ChangePassword/ChangePasswordForm.tsx @@ -9,12 +9,12 @@ import { ModalHeader, useToast, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { changeMnemonicPassword, useAppDispatch, useAsyncActionHandler } from "@umami/state"; import { useContext } from "react"; import { FormProvider, useForm } from "react-hook-form"; import colors from "../../style/colors"; -import { DynamicModalContext } from "../DynamicModal"; import { FormErrorMessage } from "../FormErrorMessage"; import { PasswordInput } from "../PasswordInput"; diff --git a/apps/desktop/src/components/ConfirmationModal.tsx b/apps/desktop/src/components/ConfirmationModal.tsx index 1c8904a12..c56a1fdda 100644 --- a/apps/desktop/src/components/ConfirmationModal.tsx +++ b/apps/desktop/src/components/ConfirmationModal.tsx @@ -9,9 +9,9 @@ import { ModalHeader, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { useContext } from "react"; -import { DynamicModalContext } from "./DynamicModal"; import { WarningIcon } from "../assets/icons"; import colors from "../style/colors"; diff --git a/apps/desktop/src/components/DeleteContactModal.tsx b/apps/desktop/src/components/DeleteContactModal.tsx index 7305ba1eb..e3917e1b9 100644 --- a/apps/desktop/src/components/DeleteContactModal.tsx +++ b/apps/desktop/src/components/DeleteContactModal.tsx @@ -10,12 +10,12 @@ import { ModalHeader, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Contact } from "@umami/core"; import { contactsActions, useAppDispatch } from "@umami/state"; import { type FC, useContext } from "react"; import { CopyableAddress } from "./CopyableText"; -import { DynamicModalContext } from "./DynamicModal"; import colors from "../style/colors"; /** diff --git a/apps/desktop/src/components/SendFlow/Beacon/useSignWithBeacon.tsx b/apps/desktop/src/components/SendFlow/Beacon/useSignWithBeacon.tsx index a033aa970..5bd6c6146 100644 --- a/apps/desktop/src/components/SendFlow/Beacon/useSignWithBeacon.tsx +++ b/apps/desktop/src/components/SendFlow/Beacon/useSignWithBeacon.tsx @@ -4,12 +4,12 @@ import { type OperationResponseInput, } from "@airgap/beacon-wallet"; import { type TezosToolkit } from "@taquito/taquito"; +import { DynamicModalContext } from "@umami/components"; import { type EstimatedAccountOperations, executeOperations, totalFee } from "@umami/core"; import { WalletClient, useAsyncActionHandler, useFindNetwork } from "@umami/state"; import { useContext } from "react"; import { useForm } from "react-hook-form"; -import { DynamicModalContext } from "../../DynamicModal"; import { SuccessStep } from "../SuccessStep"; export const useSignWithBeacon = ( diff --git a/apps/desktop/src/components/SendFlow/Delegation/ChangeDelegateNoticeModal.tsx b/apps/desktop/src/components/SendFlow/Delegation/ChangeDelegateNoticeModal.tsx index 325f521df..a1c9ebaee 100644 --- a/apps/desktop/src/components/SendFlow/Delegation/ChangeDelegateNoticeModal.tsx +++ b/apps/desktop/src/components/SendFlow/Delegation/ChangeDelegateNoticeModal.tsx @@ -8,6 +8,7 @@ import { ModalHeader, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account } from "@umami/core"; import { type TzktAlias } from "@umami/tzkt"; import { useContext } from "react"; @@ -15,7 +16,6 @@ import { useContext } from "react"; import { FormPage } from "./FormPage"; import { WarningIcon } from "../../../assets/icons"; import colors from "../../../style/colors"; -import { DynamicModalContext } from "../../DynamicModal"; export const ChangeDelegateNoticeModal = ({ account, diff --git a/apps/desktop/src/components/SendFlow/Delegation/NewDelegateNoticeModal.tsx b/apps/desktop/src/components/SendFlow/Delegation/NewDelegateNoticeModal.tsx index 82dff4bb9..adcb97127 100644 --- a/apps/desktop/src/components/SendFlow/Delegation/NewDelegateNoticeModal.tsx +++ b/apps/desktop/src/components/SendFlow/Delegation/NewDelegateNoticeModal.tsx @@ -8,13 +8,13 @@ import { ModalHeader, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account } from "@umami/core"; import { useContext } from "react"; import { FormPage } from "./FormPage"; import { NoticeIcon } from "../../../assets/icons"; import colors from "../../../style/colors"; -import { DynamicModalContext } from "../../DynamicModal"; import { NoticeSteps } from "../NoticeSteps"; export const NewDelegateNoticeModal = ({ account }: { account: Account }) => { diff --git a/apps/desktop/src/components/SendFlow/Multisig/SignPage.tsx b/apps/desktop/src/components/SendFlow/Multisig/SignPage.tsx index e2972e67b..a9293244b 100644 --- a/apps/desktop/src/components/SendFlow/Multisig/SignPage.tsx +++ b/apps/desktop/src/components/SendFlow/Multisig/SignPage.tsx @@ -1,5 +1,6 @@ import { ModalContent, ModalFooter } from "@chakra-ui/react"; import { type TezosToolkit } from "@taquito/taquito"; +import { DynamicModalContext } from "@umami/components"; import { type ApproveOrExecute, type EstimatedAccountOperations, @@ -13,7 +14,6 @@ import { useContext } from "react"; import { FormProvider, useForm } from "react-hook-form"; import { AdvancedSettingsAccordion } from "../../AdvancedSettingsAccordion"; -import { DynamicModalContext } from "../../DynamicModal"; import { BatchModalBody } from "../BatchModalBody"; import { SignButton } from "../SignButton"; import { SuccessStep } from "../SuccessStep"; diff --git a/apps/desktop/src/components/SendFlow/MultisigAccount/NameMultisigFormPage.tsx b/apps/desktop/src/components/SendFlow/MultisigAccount/NameMultisigFormPage.tsx index d1474c1b4..b25db2c41 100644 --- a/apps/desktop/src/components/SendFlow/MultisigAccount/NameMultisigFormPage.tsx +++ b/apps/desktop/src/components/SendFlow/MultisigAccount/NameMultisigFormPage.tsx @@ -8,6 +8,7 @@ import { ModalContent, ModalFooter, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { useGetMostFundedImplicitAccount, useImplicitAccounts, @@ -17,7 +18,6 @@ import { useContext } from "react"; import { FormProvider, useForm } from "react-hook-form"; import { SelectApproversFormPage } from "./SelectApproversFormPage"; -import { DynamicModalContext } from "../../DynamicModal"; import { FormErrorMessage } from "../../FormErrorMessage"; import { FormPageHeader } from "../FormPageHeader"; diff --git a/apps/desktop/src/components/SendFlow/Stake/NoticeModal.tsx b/apps/desktop/src/components/SendFlow/Stake/NoticeModal.tsx index 56ee4a668..3d3a76fb5 100644 --- a/apps/desktop/src/components/SendFlow/Stake/NoticeModal.tsx +++ b/apps/desktop/src/components/SendFlow/Stake/NoticeModal.tsx @@ -9,6 +9,7 @@ import { ModalHeader, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account } from "@umami/core"; import { useContext } from "react"; import { useForm } from "react-hook-form"; @@ -16,7 +17,6 @@ import { useForm } from "react-hook-form"; import { FormPage } from "./FormPage"; import { WarningIcon } from "../../../assets/icons"; import colors from "../../../style/colors"; -import { DynamicModalContext } from "../../DynamicModal"; export const NoticeModal = ({ account }: { account: Account }) => { const { openWith } = useContext(DynamicModalContext); diff --git a/apps/desktop/src/components/SendFlow/SuccessStep.tsx b/apps/desktop/src/components/SendFlow/SuccessStep.tsx index ea3381106..9fb58c72c 100644 --- a/apps/desktop/src/components/SendFlow/SuccessStep.tsx +++ b/apps/desktop/src/components/SendFlow/SuccessStep.tsx @@ -9,13 +9,13 @@ import { ModalHeader, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { useSelectedNetwork } from "@umami/state"; import type React from "react"; import { useContext } from "react"; import { Link, useNavigate } from "react-router-dom"; import { WindowLinkIcon } from "../../assets/icons/WindowLink"; -import { DynamicModalContext } from "../DynamicModal"; export const SuccessStep: React.FC<{ hash: string }> = ({ hash }) => { const network = useSelectedNetwork(); diff --git a/apps/desktop/src/components/SendFlow/Unstake/NoticeModal.tsx b/apps/desktop/src/components/SendFlow/Unstake/NoticeModal.tsx index 7c8ed6918..1946c499b 100644 --- a/apps/desktop/src/components/SendFlow/Unstake/NoticeModal.tsx +++ b/apps/desktop/src/components/SendFlow/Unstake/NoticeModal.tsx @@ -8,6 +8,7 @@ import { ModalHeader, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account } from "@umami/core"; import { useGetAccountStakedBalance } from "@umami/state"; import { useContext } from "react"; @@ -15,7 +16,6 @@ import { useContext } from "react"; import { FormPage } from "./FormPage"; import { WarningIcon } from "../../../assets/icons"; import colors from "../../../style/colors"; -import { DynamicModalContext } from "../../DynamicModal"; import { NoticeSteps } from "../NoticeSteps"; // TODO: test export const NoticeModal = ({ account }: { account: Account }) => { diff --git a/apps/desktop/src/components/SendFlow/onSubmitFormActionHooks.tsx b/apps/desktop/src/components/SendFlow/onSubmitFormActionHooks.tsx index 8312d82af..881ec1e4e 100644 --- a/apps/desktop/src/components/SendFlow/onSubmitFormActionHooks.tsx +++ b/apps/desktop/src/components/SendFlow/onSubmitFormActionHooks.tsx @@ -1,4 +1,5 @@ import { useToast } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Operation, estimate } from "@umami/core"; import { estimateAndUpdateBatch, @@ -14,7 +15,6 @@ import { type SignPageProps, useMakeFormOperations, } from "./utils"; -import { DynamicModalContext } from "../DynamicModal"; // This file defines hooks to create actions when form is submitted. diff --git a/apps/desktop/src/components/SendFlow/utils.tsx b/apps/desktop/src/components/SendFlow/utils.tsx index 26650f61b..9c3a67587 100644 --- a/apps/desktop/src/components/SendFlow/utils.tsx +++ b/apps/desktop/src/components/SendFlow/utils.tsx @@ -1,5 +1,6 @@ import { Box, Button } from "@chakra-ui/react"; import { type TezosToolkit } from "@taquito/taquito"; +import { DynamicModalContext } from "@umami/components"; import { type Account, type AccountOperations, @@ -24,7 +25,6 @@ import { useContext, useState } from "react"; import { useForm } from "react-hook-form"; import { SuccessStep } from "./SuccessStep"; -import { DynamicModalContext } from "../DynamicModal"; // Convert given optional fields to required // For example: diff --git a/apps/desktop/src/components/TopBar.tsx b/apps/desktop/src/components/TopBar.tsx index a63e5edef..176946628 100644 --- a/apps/desktop/src/components/TopBar.tsx +++ b/apps/desktop/src/components/TopBar.tsx @@ -8,13 +8,13 @@ import { Text, useMediaQuery, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { assetsActions, useAppDispatch, useIsLoading, useLastTimeUpdated } from "@umami/state"; import { differenceInMinutes, differenceInSeconds, formatDistance } from "date-fns"; import type React from "react"; import { useContext, useEffect, useState } from "react"; import { BuyTezForm } from "./BuyTez/BuyTezForm"; -import { DynamicModalContext } from "./DynamicModal"; import { FormPage as SendTezForm } from "./SendFlow/Tez/FormPage"; import { FetchingIcon } from "../assets/icons"; import { CheckIcon } from "../assets/icons/CheckIcon"; diff --git a/apps/desktop/src/components/UpsertContactModal.tsx b/apps/desktop/src/components/UpsertContactModal.tsx index 6b7518f06..71029eb4b 100644 --- a/apps/desktop/src/components/UpsertContactModal.tsx +++ b/apps/desktop/src/components/UpsertContactModal.tsx @@ -10,6 +10,7 @@ import { ModalFooter, ModalHeader, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Contact } from "@umami/core"; import { getNetworksForContracts } from "@umami/multisig"; import { @@ -24,7 +25,6 @@ import { isValidContractPkh } from "@umami/tezos"; import { type FC, useContext, useEffect, useRef } from "react"; import { useForm } from "react-hook-form"; -import { DynamicModalContext } from "./DynamicModal"; import { FormErrorMessage } from "./FormErrorMessage"; /** diff --git a/apps/desktop/src/mocks/testUtils.tsx b/apps/desktop/src/mocks/testUtils.tsx index 4223120ca..f3462ef8c 100644 --- a/apps/desktop/src/mocks/testUtils.tsx +++ b/apps/desktop/src/mocks/testUtils.tsx @@ -1,10 +1,10 @@ import * as testLib from "@testing-library/react"; +import { DynamicModalContext, useDynamicModal } from "@umami/components"; import { type UmamiStore, makeStore } from "@umami/state"; import { type PropsWithChildren, act } from "react"; import { Provider } from "react-redux"; import { HashRouter } from "react-router-dom"; -import { DynamicModalContext, useDynamicModal } from "../components/DynamicModal"; import { ReactQueryProvider } from "../providers/ReactQueryProvider"; import { UmamiTheme } from "../providers/UmamiTheme"; diff --git a/apps/desktop/src/utils/beacon/PermissionRequestModal.tsx b/apps/desktop/src/utils/beacon/PermissionRequestModal.tsx index c994be50c..55273266e 100644 --- a/apps/desktop/src/utils/beacon/PermissionRequestModal.tsx +++ b/apps/desktop/src/utils/beacon/PermissionRequestModal.tsx @@ -23,6 +23,7 @@ import { ModalHeader, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { WalletClient, useAddConnection, @@ -36,7 +37,6 @@ import { FormProvider, useForm } from "react-hook-form"; import { JsValueWrap } from "../../components/AccountDrawer/JsValueWrap"; import { OwnedImplicitAccountsAutocomplete } from "../../components/AddressAutocomplete"; -import { DynamicModalContext } from "../../components/DynamicModal"; import colors from "../../style/colors"; export const PermissionRequestModal: React.FC<{ diff --git a/apps/desktop/src/utils/beacon/SignPayloadRequestModal.tsx b/apps/desktop/src/utils/beacon/SignPayloadRequestModal.tsx index 3f05a8f8a..d07f211a0 100644 --- a/apps/desktop/src/utils/beacon/SignPayloadRequestModal.tsx +++ b/apps/desktop/src/utils/beacon/SignPayloadRequestModal.tsx @@ -15,13 +15,13 @@ import { useToast, } from "@chakra-ui/react"; import { type TezosToolkit } from "@taquito/taquito"; +import { DynamicModalContext } from "@umami/components"; import { WalletClient, useGetImplicitAccount } from "@umami/state"; import type React from "react"; import { useContext } from "react"; import { FormProvider, useForm } from "react-hook-form"; import { decodePayload } from "./decodePayload"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { SignButton } from "../../components/SendFlow/SignButton"; import colors from "../../style/colors"; diff --git a/apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx b/apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx index 90987933d..e87917443 100644 --- a/apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx +++ b/apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx @@ -6,6 +6,7 @@ import { type PartialTezosOperation, TezosOperationType, } from "@airgap/beacon-wallet"; +import { DynamicModalContext } from "@umami/components"; import { type ContractOrigination, type ImplicitAccount, @@ -25,7 +26,6 @@ import { useContext } from "react"; import { PermissionRequestModal } from "./PermissionRequestModal"; import { SignPayloadRequestModal } from "./SignPayloadRequestModal"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { BatchSignPage } from "../../components/SendFlow/Beacon/BatchSignPage"; import { BeaconSignPage } from "../../components/SendFlow/Beacon/BeaconSignPage"; diff --git a/apps/desktop/src/views/addressBook/AddressBookView.tsx b/apps/desktop/src/views/addressBook/AddressBookView.tsx index c76618944..48c6e76b9 100644 --- a/apps/desktop/src/views/addressBook/AddressBookView.tsx +++ b/apps/desktop/src/views/addressBook/AddressBookView.tsx @@ -1,10 +1,10 @@ import { Button, Flex, Text } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { useSortedContacts } from "@umami/state"; import { useContext } from "react"; import { ContactTable } from "./ContactTable"; import { AddContactIcon } from "../../assets/icons"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { NoItems } from "../../components/NoItems"; import { TopBar } from "../../components/TopBar"; import { UpsertContactModal } from "../../components/UpsertContactModal"; diff --git a/apps/desktop/src/views/addressBook/ContactTable.tsx b/apps/desktop/src/views/addressBook/ContactTable.tsx index 4ce990ceb..84b164362 100644 --- a/apps/desktop/src/views/addressBook/ContactTable.tsx +++ b/apps/desktop/src/views/addressBook/ContactTable.tsx @@ -1,10 +1,10 @@ import { Box, Flex, Table, TableContainer, Tbody, Td, Text, Tr } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Contact } from "@umami/core"; import { useContext } from "react"; import { CopyableAddress } from "../../components/CopyableText"; import { DeleteContactModal } from "../../components/DeleteContactModal"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { RenameRemoveMenu } from "../../components/RenameRemoveMenu"; import { SendButton } from "../../components/SendButton"; import { FormPage } from "../../components/SendFlow/Tez/FormPage"; diff --git a/apps/desktop/src/views/batch/BatchView.tsx b/apps/desktop/src/views/batch/BatchView.tsx index 144c43781..0c22c712c 100644 --- a/apps/desktop/src/views/batch/BatchView.tsx +++ b/apps/desktop/src/views/batch/BatchView.tsx @@ -2,6 +2,7 @@ import { Box, Button, Divider, Flex, IconButton, Text } from "@chakra-ui/react"; import { nanoid } from "@reduxjs/toolkit"; import type { OperationContentsAndResult } from "@taquito/rpc"; import { TezosOperationError } from "@taquito/taquito"; +import { DynamicModalContext } from "@umami/components"; import { type Account, type AccountOperations, type Operation, estimate } from "@umami/core"; import { useAsyncActionHandler, @@ -20,7 +21,6 @@ import { OperationView } from "./OperationView"; import { TrashIcon } from "../../assets/icons"; import { accountIconGradient } from "../../components/AccountTile/AccountTile"; import { ConfirmationModal } from "../../components/ConfirmationModal"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { SignPage } from "../../components/SendFlow/Batch/SignPage"; import { headerText } from "../../components/SendFlow/SignPageHeader"; import colors from "../../style/colors"; diff --git a/apps/desktop/src/views/home/AccountGroup.tsx b/apps/desktop/src/views/home/AccountGroup.tsx index 037789eb4..75b62f556 100644 --- a/apps/desktop/src/views/home/AccountGroup.tsx +++ b/apps/desktop/src/views/home/AccountGroup.tsx @@ -1,4 +1,5 @@ import { Box, Center, Heading } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account } from "@umami/core"; import { useImplicitAccounts, useRemoveMnemonic, useRemoveNonMnemonic } from "@umami/state"; import { useContext } from "react"; @@ -8,7 +9,6 @@ import { DeriveMnemonicAccountModal } from "./DeriveMnemonicAccountModal"; import { getAccountGroupLabel } from "./getAccountGroupLabel"; import { AccountTile } from "../../components/AccountTile/AccountTile"; import { ConfirmationModal } from "../../components/ConfirmationModal"; -import { DynamicModalContext } from "../../components/DynamicModal"; export const AccountGroup: React.FC<{ accounts: Account[]; diff --git a/apps/desktop/src/views/home/AccountsList.tsx b/apps/desktop/src/views/home/AccountsList.tsx index 89b060b9a..7002826fa 100644 --- a/apps/desktop/src/views/home/AccountsList.tsx +++ b/apps/desktop/src/views/home/AccountsList.tsx @@ -1,4 +1,5 @@ import { Box, Button, Text } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { useAllAccounts } from "@umami/state"; import { compact, groupBy } from "lodash"; import { useContext } from "react"; @@ -6,7 +7,6 @@ import { useContext } from "react"; import { AccountGroup } from "./AccountGroup"; import { getAccountGroupLabel } from "./getAccountGroupLabel"; import { KeyIcon } from "../../assets/icons"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { NestedScroll } from "../../components/NestedScroll"; import { NameMultisigFormPage } from "../../components/SendFlow/MultisigAccount/NameMultisigFormPage"; import colors from "../../style/colors"; diff --git a/apps/desktop/src/views/nfts/NFTDrawerCard.tsx b/apps/desktop/src/views/nfts/NFTDrawerCard.tsx index 0cf7889c4..c96927b74 100644 --- a/apps/desktop/src/views/nfts/NFTDrawerCard.tsx +++ b/apps/desktop/src/views/nfts/NFTDrawerCard.tsx @@ -12,6 +12,7 @@ import { Image, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { artifactUri, mimeType, tokenName } from "@umami/core"; import { useGetOwnedAccount } from "@umami/state"; import { useContext } from "react"; @@ -21,7 +22,6 @@ import { AttributesAccordionItem } from "./drawer/AttributesAccordionItem"; import { PropertiesAccordionItem } from "./drawer/PropertiesAccordionItem"; import { TagsSection } from "./drawer/TagsSection"; import { JsValueWrap } from "../../components/AccountDrawer/JsValueWrap"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { FormPage as SendNFTForm } from "../../components/SendFlow/NFT/FormPage"; import colors from "../../style/colors"; import { type NFTWithOwner, getIPFSurl } from "../../utils/token/utils"; diff --git a/apps/desktop/src/views/settings/SettingsView.tsx b/apps/desktop/src/views/settings/SettingsView.tsx index e15dd0f30..a62869d60 100644 --- a/apps/desktop/src/views/settings/SettingsView.tsx +++ b/apps/desktop/src/views/settings/SettingsView.tsx @@ -1,4 +1,5 @@ import { Box, Button, Flex, Heading } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { useContext } from "react"; import { DAppsDrawerCard } from "./DAppsDrawerCard"; @@ -7,7 +8,6 @@ import { NetworkSettingsDrawerCard } from "./network/NetworkSettingsDrawerCard"; import { DownloadIcon } from "../../assets/icons"; import { ChangePasswordForm } from "../../components/ChangePassword/ChangePasswordForm"; import { ClickableCard, SettingsCardWithDrawerIcon } from "../../components/ClickableCard"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { useOffboardingModal } from "../../components/Offboarding/useOffboardingModal"; import { downloadBackupFile } from "../../components/Onboarding/restoreBackupFile/utils"; import { TopBar } from "../../components/TopBar"; diff --git a/apps/desktop/src/views/settings/network/NetworkSettingsDrawerBody.tsx b/apps/desktop/src/views/settings/network/NetworkSettingsDrawerBody.tsx index 8c4a49f0d..8dc5ae879 100644 --- a/apps/desktop/src/views/settings/network/NetworkSettingsDrawerBody.tsx +++ b/apps/desktop/src/views/settings/network/NetworkSettingsDrawerBody.tsx @@ -9,6 +9,7 @@ import { Stack, Text, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { networksActions, useAppDispatch, @@ -21,7 +22,6 @@ import { Fragment, useContext } from "react"; import { UpsertNetworkModal } from "./UpsertNetworkModal"; import { PenIcon, PlusIcon, TrashIcon } from "../../../assets/icons"; -import { DynamicModalContext } from "../../../components/DynamicModal"; import { PopoverMenu } from "../../../components/PopoverMenu"; import colors from "../../../style/colors"; diff --git a/apps/desktop/src/views/settings/network/UpsertNetworkModal.tsx b/apps/desktop/src/views/settings/network/UpsertNetworkModal.tsx index 84b5a2f2b..8f91505d5 100644 --- a/apps/desktop/src/views/settings/network/UpsertNetworkModal.tsx +++ b/apps/desktop/src/views/settings/network/UpsertNetworkModal.tsx @@ -9,13 +9,13 @@ import { ModalFooter, ModalHeader, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { networksActions, useAvailableNetworks } from "@umami/state"; import { type Network } from "@umami/tezos"; import { useContext } from "react"; import { useForm } from "react-hook-form"; import { useDispatch } from "react-redux"; -import { DynamicModalContext } from "../../../components/DynamicModal"; import { FormErrorMessage } from "../../../components/FormErrorMessage"; const removeTrailingSlashes = (url: string) => url.replace(/\/+$/g, ""); diff --git a/apps/desktop/src/views/tokens/AccountTokens.tsx b/apps/desktop/src/views/tokens/AccountTokens.tsx index 678bd3fdd..772d16fff 100644 --- a/apps/desktop/src/views/tokens/AccountTokens.tsx +++ b/apps/desktop/src/views/tokens/AccountTokens.tsx @@ -10,6 +10,7 @@ import { Text, Tr, } from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; import { type Account, type FA12TokenBalance, @@ -27,7 +28,6 @@ import { AccountBalance } from "../../components/AccountBalance"; import { accountIconGradient } from "../../components/AccountTile/AccountTile"; import { AccountTileIcon } from "../../components/AccountTile/AccountTileIcon"; import { AddressPill } from "../../components/AddressPill/AddressPill"; -import { DynamicModalContext } from "../../components/DynamicModal"; import { SendButton } from "../../components/SendButton"; import { FormPage as SendTokenFormPage } from "../../components/SendFlow/Token/FormPage"; import colors from "../../style/colors"; diff --git a/packages/components/.depcheckrc b/packages/components/.depcheckrc new file mode 100644 index 000000000..5236e62cb --- /dev/null +++ b/packages/components/.depcheckrc @@ -0,0 +1,2 @@ +ignores: ["@types/*", "rimraf", "depcheck", "madge"] +quiet: true diff --git a/packages/components/.eslintrc.cjs b/packages/components/.eslintrc.cjs new file mode 100644 index 000000000..effe41d41 --- /dev/null +++ b/packages/components/.eslintrc.cjs @@ -0,0 +1,9 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: ["@umami/eslint-config"], + parserOptions: { + project: "tsconfig.json", + parser: "@typescript-eslint/parser", + tsconfigRootDir: __dirname, + }, +}; diff --git a/packages/components/babel.config.json b/packages/components/babel.config.json new file mode 100644 index 000000000..ac08da0a4 --- /dev/null +++ b/packages/components/babel.config.json @@ -0,0 +1,3 @@ +{ + "extends": "../../babel.config.json" +} diff --git a/packages/components/jest.config.ts b/packages/components/jest.config.ts new file mode 100644 index 000000000..62ce434ab --- /dev/null +++ b/packages/components/jest.config.ts @@ -0,0 +1,10 @@ +import baseConfig from "@umami/jest-config"; +import type { Config } from "jest"; + +const config: Config = { + ...baseConfig, + testEnvironment: "jsdom", + setupFilesAfterEnv: ["/src/setupTests.ts"], + rootDir: "./", +}; +export default config; diff --git a/packages/components/package.json b/packages/components/package.json new file mode 100644 index 000000000..6f14a7751 --- /dev/null +++ b/packages/components/package.json @@ -0,0 +1,72 @@ +{ + "name": "@umami/components", + "packageManager": "yarn@4.3.1", + "type": "module", + "module": "./dist/index.js", + "main": "./dist/index.cjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "@umami/source": "./src/index.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs", + "types": "./dist/index.d.ts" + } + }, + "devDependencies": { + "@babel/core": "^7.24.7", + "@testing-library/dom": "^10.3.0", + "@testing-library/jest-dom": "^6.4.6", + "@testing-library/react": "^16.0.0", + "@types/babel__core": "^7.20.5", + "@types/eslint": "^8", + "@types/react": "18.3.3", + "@types/react-dom": "18.3.0", + "@umami/eslint-config": "workspace:^", + "@umami/jest-config": "workspace:^", + "@umami/typescript-config": "workspace:^", + "babel-jest": "^29.7.0", + "depcheck": "^1.4.7", + "eslint": "^8.57.0", + "jest": "^29.7.0", + "madge": "^7.0.0", + "prettier": "^3.3.2", + "rimraf": "^5.0.7", + "tsup": "^8.1.0", + "typescript": "^5.5.3" + }, + "scripts": { + "build": "tsup-node", + "clean": "rimraf build dist .turbo", + "check-circular-deps": "madge --circular src/index.ts", + "check-types:watch": "yarn check-types --watch", + "check-types": "tsc", + "dev": "tsup-node --watch", + "format:ci": "prettier --ignore-path ../../.gitignore --check .", + "format": "prettier --ignore-path ../../.gitignore --write .", + "lint:ci": "eslint src --ext .ts --max-warnings=0", + "lint": "eslint src --ext .ts --fix", + "test:watch": "jest --watch", + "test": "jest" + }, + "tsup": { + "entry": [ + "src/index.ts" + ], + "clean": true, + "format": [ + "cjs", + "esm" + ], + "dts": true + }, + "dependencies": { + "@chakra-ui/react": "^2.8.2", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "framer-motion": "^11.2.12", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-remove-scroll": "^2.5.10" + } +} diff --git a/apps/desktop/src/components/DynamicModal.test.tsx b/packages/components/src/DynamicModal.test.tsx similarity index 78% rename from apps/desktop/src/components/DynamicModal.test.tsx rename to packages/components/src/DynamicModal.test.tsx index 1ab9f7d88..2eebfd2f7 100644 --- a/apps/desktop/src/components/DynamicModal.test.tsx +++ b/packages/components/src/DynamicModal.test.tsx @@ -1,5 +1,5 @@ import { useDynamicModal } from "./DynamicModal"; -import { act, render, renderHook, screen } from "../mocks/testUtils"; +import { act, render, renderHook, screen } from "./testUtils"; describe("useDynamicModal", () => { it("is closed by default", () => { @@ -33,4 +33,12 @@ describe("useDynamicModal", () => { render(view.result.current.content); expect(screen.queryByText("test data")).not.toBeInTheDocument(); }); + + it("calls the onClose callback when the modal is closed", async () => { + const onClose = jest.fn(); + const view = renderHook(() => useDynamicModal()); + await act(() => view.result.current.openWith(
test data
, { onClose })); + act(() => view.result.current.onClose()); + expect(onClose).toHaveBeenCalled(); + }); }); diff --git a/apps/desktop/src/components/DynamicModal.tsx b/packages/components/src/DynamicModal.tsx similarity index 64% rename from apps/desktop/src/components/DynamicModal.tsx rename to packages/components/src/DynamicModal.tsx index 3a3696f13..e56de05e6 100644 --- a/apps/desktop/src/components/DynamicModal.tsx +++ b/packages/components/src/DynamicModal.tsx @@ -2,7 +2,10 @@ import { Modal, ModalOverlay, type ThemingProps, useDisclosure } from "@chakra-u import { type ReactElement, createContext, useCallback, useState } from "react"; import { RemoveScroll } from "react-remove-scroll"; -// this should be used in components as useContext(DynamicModalContext); +/** + * You need to wrap the app into `DynamicModalContext.Provider` and then + * use it in components as `useContext(DynamicModalContext)` to interact with the modal. + */ export const DynamicModalContext = createContext<{ openWith: ( content: ReactElement, @@ -11,33 +14,30 @@ export const DynamicModalContext = createContext<{ onClose: () => void; isOpen: boolean; }>({ - openWith: _ => Promise.resolve(), - onClose: () => {}, + openWith: /* istanbul ignore next */ _ => Promise.resolve(), + onClose: /* istanbul ignore next */ () => {}, isOpen: false, }); -// It's easier to have just one global place where you can put a modal -// and open it from anywhere in the app instead of including a modal related -// code in each place where it's used. Sometimes, it's even a problem because we -// need to have a modal next to a button that was created in a loop (e.g. lots of unused data). -// -// This hook solves this problem. It wraps the whole app in a context provider so that any -// component can open a modal from anywhere in the app using the `openWith` function. -// This hook should be used only once in the app. You place the modal wrapper and then -// use the `openWith` provided by the `DynamicModalContext` in components. +/** + * It's easier to have just one global place where you can put a modal + * and open it from anywhere in the app instead of including a modal related + * code in each place where it's used. Sometimes, it's even a problem because we + * need to have a modal next to a button that was created in a loop (e.g. lots of unused data). + * + * This hook solves this problem. It wraps the whole app in a context provider so that any + * component can open a modal from anywhere in the app using the `openWith` function. + * This hook should be used only once in the app. You place the modal wrapper and then + * use the `openWith` provided by the `DynamicModalContext` in components. + * + */ export const useDynamicModal = () => { const { isOpen, onClose: closeModal, onOpen } = useDisclosure(); const [modalContent, setModalContent] = useState(null); + const defaultModalProps = { size: "md", onClose: closeModal }; const [modalProps, setModalProps] = useState< ThemingProps & { onClose: () => void | Promise } - >({ - size: "md", - onClose: closeModal, - }); - - const onClose = useCallback(() => { - closeModal(); - }, [closeModal]); + >(defaultModalProps); const openWith = useCallback( async ( @@ -46,8 +46,10 @@ export const useDynamicModal = () => { ) => { const onClose = () => { closeModal(); - return props.onClose?.(); + void props.onClose?.(); + setModalProps(defaultModalProps); }; + setModalProps({ size: "md", ...props, onClose }); setModalContent(content); onOpen(); @@ -58,7 +60,7 @@ export const useDynamicModal = () => { return { isOpen, - onClose, + onClose: modalProps.onClose, openWith, content: ( Date: Thu, 4 Jul 2024 12:51:52 +0100 Subject: [PATCH 2/2] Add dynamic modal to umami/web --- apps/web/package.json | 3 +- apps/web/src/App.tsx | 9 +- .../components/AccountCard/AccountBalance.tsx | 128 +++++++++++------- apps/web/src/index.scss | 2 +- yarn.lock | 36 ++++- 5 files changed, 124 insertions(+), 54 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 90848be54..453e5e6e3 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -41,6 +41,7 @@ "@taquito/taquito": "^20.0.1", "@taquito/utils": "^20.0.1", "@tzkt/sdk-api": "^2.2.1", + "@umami/components": "workspace:^", "@umami/core": "workspace:^", "@umami/data-polling": "workspace:^", "@umami/state": "workspace:^", @@ -84,6 +85,7 @@ "@svgr/plugin-svgo": "^8.1.0", "@testing-library/dom": "^10.3.0", "@testing-library/react": "^16.0.0", + "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.5.2", "@types/jest": "^29.5.12", "@types/node": "20.14.9", @@ -102,7 +104,6 @@ "react-hooks-testing-library": "^0.6.0", "rimraf": "^5.0.7", "storybook": "^8.1.11", - "ts-node": "^10.9.2", "typescript": "^5.5.3", "vite": "^5.3.3", "vite-plugin-svgr": "^4.2.0" diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 98dab75b8..57d775a07 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -1,9 +1,16 @@ +import { DynamicModalContext, useDynamicModal } from "@umami/components"; import { useDataPolling } from "@umami/data-polling"; import { Layout } from "./Layout"; export const App = () => { useDataPolling(); + const dynamicModal = useDynamicModal(); - return ; + return ( + + + {dynamicModal.content} + + ); }; diff --git a/apps/web/src/components/AccountCard/AccountBalance.tsx b/apps/web/src/components/AccountCard/AccountBalance.tsx index 3ace487a6..d666a27b8 100644 --- a/apps/web/src/components/AccountCard/AccountBalance.tsx +++ b/apps/web/src/components/AccountCard/AccountBalance.tsx @@ -1,54 +1,82 @@ -import { Box, Button, Flex, IconButton, Text } from "@chakra-ui/react"; +import { + Box, + Button, + Flex, + IconButton, + ModalBody, + ModalCloseButton, + ModalContent, + ModalHeader, + Text, +} from "@chakra-ui/react"; +import { DynamicModalContext } from "@umami/components"; +import { useContext } from "react"; import { ArrowDownLeftIcon, PlusIcon } from "../../assets/icons"; -export const AccountBalance = () => ( - - - - Tez Balance - - - 2882.675746 ꜩ - - $3603.34 - - - } - isRound - size="lg" - variant="iconButtonSolid" - /> - } - size="lg" - variant="iconButtonOutline" - /> - - - -); + } + isRound + size="lg" + variant="iconButtonSolid" + /> + } + size="lg" + variant="iconButtonOutline" + /> + + + + ); +}; diff --git a/apps/web/src/index.scss b/apps/web/src/index.scss index d67c79af6..f5e8f601b 100644 --- a/apps/web/src/index.scss +++ b/apps/web/src/index.scss @@ -3,10 +3,10 @@ body { margin: 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - padding: 20px 46px 0; position: relative; & .layout { + padding: 20px 46px 0; height: calc(100vh - 20px); } diff --git a/yarn.lock b/yarn.lock index 966452bb5..dcc05246e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6830,6 +6830,28 @@ __metadata: languageName: node linkType: hard +"@testing-library/react-hooks@npm:^8.0.1": + version: 8.0.1 + resolution: "@testing-library/react-hooks@npm:8.0.1" + dependencies: + "@babel/runtime": "npm:^7.12.5" + react-error-boundary: "npm:^3.1.0" + peerDependencies: + "@types/react": ^16.9.0 || ^17.0.0 + react: ^16.9.0 || ^17.0.0 + react-dom: ^16.9.0 || ^17.0.0 + react-test-renderer: ^16.9.0 || ^17.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + react-dom: + optional: true + react-test-renderer: + optional: true + checksum: 10/f7b69373feebe99bc7d60595822cc5c00a1a5a4801bc4f99b597256a5c1d23c45a51f359051dd8a7bdffcc23b26f324c582e9433c25804934fd351a886812790 + languageName: node + linkType: hard + "@testing-library/react-hooks@npm:~1.0.2": version: 1.0.4 resolution: "@testing-library/react-hooks@npm:1.0.4" @@ -8582,12 +8604,14 @@ __metadata: "@taquito/utils": "npm:^20.0.1" "@testing-library/dom": "npm:^10.3.0" "@testing-library/react": "npm:^16.0.0" + "@testing-library/react-hooks": "npm:^8.0.1" "@testing-library/user-event": "npm:^14.5.2" "@types/jest": "npm:^29.5.12" "@types/node": "npm:20.14.9" "@types/react": "npm:^18.3.3" "@types/react-dom": "npm:^18.3.0" "@tzkt/sdk-api": "npm:^2.2.1" + "@umami/components": "workspace:^" "@umami/core": "workspace:^" "@umami/data-polling": "workspace:^" "@umami/eslint-config": "workspace:^" @@ -8627,7 +8651,6 @@ __metadata: redux-persist: "npm:^6.0.0" rimraf: "npm:^5.0.7" storybook: "npm:^8.1.11" - ts-node: "npm:^10.9.2" typescript: "npm:^5.5.3" vite: "npm:^5.3.3" vite-plugin-svgr: "npm:^4.2.0" @@ -18921,6 +18944,17 @@ __metadata: languageName: node linkType: hard +"react-error-boundary@npm:^3.1.0": + version: 3.1.4 + resolution: "react-error-boundary@npm:3.1.4" + dependencies: + "@babel/runtime": "npm:^7.12.5" + peerDependencies: + react: ">=16.13.1" + checksum: 10/7418637bf352b88f35ff3798e6faa094ee046df9d422fc08f54c017892c3c0738dac661ba3d64d97209464e7a60e7fbbeffdbeaee5edc38f3aaf5f1f4a8bf610 + languageName: node + linkType: hard + "react-error-boundary@npm:^4.0.13": version: 4.0.13 resolution: "react-error-boundary@npm:4.0.13"