From 2569e4ecb001da7cb643072524768b23eac1bb37 Mon Sep 17 00:00:00 2001 From: Victor Oliva Date: Fri, 8 Nov 2024 07:54:03 +0300 Subject: [PATCH] change accountId picker for shadcn component --- package.json | 1 - src/codec-components/EditCodec/CAccountId.tsx | 232 +++++++++--------- src/components/AccountIdDisplay.tsx | 2 +- src/components/ui/button.tsx | 25 +- src/components/ui/command.tsx | 20 +- 5 files changed, 143 insertions(+), 137 deletions(-) diff --git a/package.json b/package.json index c7f4308..5ddca92 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "semi": false }, "dependencies": { - "@headlessui/react": "^2.2.0", "@ledgerhq/hw-transport-webusb": "^6.29.4", "@noble/hashes": "^1.5.0", "@polkadot-api/descriptors": "file:.papi/descriptors", diff --git a/src/codec-components/EditCodec/CAccountId.tsx b/src/codec-components/EditCodec/CAccountId.tsx index f20db6f..7587b58 100644 --- a/src/codec-components/EditCodec/CAccountId.tsx +++ b/src/codec-components/EditCodec/CAccountId.tsx @@ -1,30 +1,33 @@ -import { PolkadotIdenticon } from "@/components/PolkadotIdenticon" -import { useSynchronizeInput } from "@/components/useSynchroniseInput" +import { AccountIdDisplay } from "@/components/AccountIdDisplay" +import { Button } from "@/components/ui/button" +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/components/ui/command" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" import { accountDetail$, accounts$, - getAccountMapKey, getPublicKey, } from "@/extension-accounts.state" import { identity$, isVerified } from "@/identity.state" +import { cn } from "@/utils/cn" import { EditAccountId, NOTIN } from "@codec-components" -import { - Combobox, - ComboboxButton, - ComboboxInput, - ComboboxOption, - ComboboxOptions, -} from "@headlessui/react" -import { - getSs58AddressInfo, - SS58String, -} from "@polkadot-api/substrate-bindings" +import { getSs58AddressInfo } from "@polkadot-api/substrate-bindings" +import { toHex } from "@polkadot-api/utils" import { state, useStateObservable } from "@react-rxjs/core" import { combineKeys } from "@react-rxjs/utils" -import { CheckCircle } from "lucide-react" +import { Check, ChevronsUpDown } from "lucide-react" import { FC, useState } from "react" import { map, switchMap, take } from "rxjs" -import { twMerge } from "tailwind-merge" const hintedAccounts$ = state( combineKeys( @@ -55,129 +58,114 @@ const hintedAccounts$ = state( ) export const CAccountId: EditAccountId = ({ value, onValueChanged }) => { - const [localInput, setLocalInput] = useSynchronizeInput( - value, - onValueChanged, - parseValue, - ) const accounts = useStateObservable(hintedAccounts$) - const valueIdentity = useStateObservable( - identity$(value === NOTIN ? "" : value), - ) const [query, setQuery] = useState("") const queryInfo = getSs58AddressInfo(query) - const filteredAccounts = - query === "" - ? Array.from(accounts.values()) - : Array.from(accounts.values()).filter( - (account) => - account.address.toLowerCase().includes(query.toLowerCase()) || - (account.name && - account.name.toLowerCase().includes(query.toLowerCase())), - ) + + const [open, _setOpen] = useState(false) + const setOpen = (value: boolean) => { + _setOpen(value) + setQuery("") + } + + const valueIsNew = + value !== NOTIN && + !accounts.has(toHex(getPublicKey(value) ?? new Uint8Array())) return ( - setLocalInput(v ?? "")} - onClose={() => setQuery("")} - immediate - > - - {localInput && ( - + + + + + + - )} - - valueIdentity?.displayName ?? - accounts.get(getAccountMapKey(address))?.name ?? - address - } - onChange={(event) => setQuery(event.target.value)} - /> - - - {filteredAccounts.length > 0 ? ( - filteredAccounts.map((account) => ( - - )) - ) : queryInfo.isValid ? ( - - ) : ( -
- The value is not a valid Account ID -
- )} -
-
+ + +
+ The value is not a valid Account ID +
+
+ + {Array.from(accounts.entries()).map(([key, account]) => ( + { + onValueChanged(account.address) + setOpen(false) + }} + /> + ))} + {valueIsNew && ( + setOpen(false)} + /> + )} + {queryInfo.isValid && ( + { + onValueChanged(query) + setOpen(false) + }} + /> + )} + +
+ + + ) } -const AccountOption: FC<{ account: string; publicKey: Uint8Array | null }> = ({ - account, - publicKey, -}) => { +const AccountOption: FC<{ + account: string + selected: boolean + onSelect: () => void +}> = ({ account, selected, onSelect }) => { const details = useStateObservable(accountDetail$(account)) const identity = useStateObservable(identity$(account)) const name = identity?.displayName ?? details?.name return ( - - -
- {name && ( - - {name} - {isVerified(identity) && ( - - )} - + + - {account} - -
-
+ /> + ) } - -const getValidationError = (value: string) => { - if (value === "") return null - const { isValid } = getSs58AddressInfo(value) - return isValid ? null : "Invalid address" -} -const parseValue = (value: string): SS58String | NOTIN => { - if (value.trim() === "") return NOTIN - if (getValidationError(value)) return NOTIN - return value -} diff --git a/src/components/AccountIdDisplay.tsx b/src/components/AccountIdDisplay.tsx index 248485f..6c72bec 100644 --- a/src/components/AccountIdDisplay.tsx +++ b/src/components/AccountIdDisplay.tsx @@ -21,7 +21,7 @@ export const AccountIdDisplay: FC<{
{name && ( diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 36496a2..368839c 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { @@ -30,26 +30,41 @@ const buttonVariants = cva( variant: "default", size: "default", }, - } + }, ) export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { asChild?: boolean + forceSvgSize?: boolean } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { + ( + { + className, + variant, + size, + asChild = false, + forceSvgSize = true, + ...props + }, + ref, + ) => { const Comp = asChild ? Slot : "button" return ( ) - } + }, ) Button.displayName = "Button" diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx index 0ac9af3..f8d3205 100644 --- a/src/components/ui/command.tsx +++ b/src/components/ui/command.tsx @@ -14,7 +14,7 @@ const Command = React.forwardRef< ref={ref} className={cn( "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", - className + className, )} {...props} /> @@ -45,7 +45,7 @@ const CommandInput = React.forwardRef< ref={ref} className={cn( "flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", - className + className, )} {...props} /> @@ -88,7 +88,7 @@ const CommandGroup = React.forwardRef< ref={ref} className={cn( "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", - className + className, )} {...props} /> @@ -110,13 +110,17 @@ CommandSeparator.displayName = CommandPrimitive.Separator.displayName const CommandItem = React.forwardRef< React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( + React.ComponentPropsWithoutRef & { + forceSvgSize?: boolean + } +>(({ className, forceSvgSize = true, ...props }, ref) => ( @@ -132,7 +136,7 @@ const CommandShortcut = ({