Skip to content

Commit

Permalink
Tweak generics
Browse files Browse the repository at this point in the history
  • Loading branch information
jessepinho committed Aug 17, 2024
1 parent f138171 commit 5593bbf
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 20 deletions.
18 changes: 10 additions & 8 deletions packages/ui/src/AssetSelector/AssetSelectorDialogContent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,25 @@ const OptionsWrapper = styled.div`
gap: ${props => props.theme.spacing(1)};
`;

export interface AssetSelectorDialogContentProps<IncludesBalancesResponses extends boolean> {
export interface AssetSelectorDialogContentProps<
ValueType extends (BalancesResponse | Metadata) | Metadata,
> {
title: string;
layoutId: string;
value?: IncludesBalancesResponses extends true ? BalancesResponse | Metadata : Metadata;
onChange: (
value: IncludesBalancesResponses extends true ? BalancesResponse | Metadata : Metadata,
) => void;
options: IncludesBalancesResponses extends true ? (BalancesResponse | Metadata)[] : Metadata[];
value?: ValueType;
onChange: (value: ValueType) => void;
options: ValueType[];
}

export const AssetSelectorDialogContent = <IncludesBalancesResponses extends boolean>({
export const AssetSelectorDialogContent = <
ValueType extends (BalancesResponse | Metadata) | Metadata,
>({
title,
layoutId,
value,
onChange,
options,
}: AssetSelectorDialogContentProps<IncludesBalancesResponses>) => {
}: AssetSelectorDialogContentProps<ValueType>) => {
const [search, setSearch] = useState('');
const filteredOptions = useMemo(
() => options.filter(filterMetadataOrBalancesResponseByText(search)),
Expand Down
23 changes: 20 additions & 3 deletions packages/ui/src/AssetSelector/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useArgs } from '@storybook/preview-api';
import { AssetSelector } from '.';
import { AssetId, Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb';
import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb';
import { useState } from 'react';

const u8 = (length: number) => Uint8Array.from({ length }, () => Math.floor(Math.random() * 256));

Expand Down Expand Up @@ -113,7 +114,8 @@ const umBalance1 = new BalancesResponse({
},
});

const options = [pizza, umBalance0, umBalance1, osmoBalance0];
const mixedOptions: (BalancesResponse | Metadata)[] = [pizza, umBalance0, umBalance1, osmoBalance0];
const metadataOnlyOptions: Metadata[] = [pizza, um, osmo];

const meta: Meta<typeof AssetSelector> = {
component: AssetSelector,
Expand All @@ -127,11 +129,11 @@ export default meta;

type Story = StoryObj<typeof AssetSelector>;

export const Basic: Story = {
export const MixedBalancesResponsesAndMetadata: Story = {
args: {
dialogTitle: 'Transfer Assets',
value: umBalance0,
options,
options: mixedOptions,
},

render: function Render(props) {
Expand All @@ -142,3 +144,18 @@ export const Basic: Story = {
return <AssetSelector {...props} onChange={onChange} />;
},
};

export const MetadataOnly: Story = {
render: function Render() {
const [value, setValue] = useState<Metadata>(um);

return (
<AssetSelector
dialogTitle='Transfer Assets'
value={value}
options={metadataOnlyOptions}
onChange={setValue}
/>
);
},
};
16 changes: 7 additions & 9 deletions packages/ui/src/AssetSelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,35 @@ const Row = styled.div<{ $density: Density }>`
align-items: center;
`;

export interface AssetSelectorProps<IncludesBalancesResponses extends boolean> {
export interface AssetSelectorProps<ValueType extends (BalancesResponse | Metadata) | Metadata> {
/**
* The currently selected `Metadata` or `BalancesResponse`.
*/
value?: IncludesBalancesResponses extends true ? BalancesResponse | Metadata : Metadata;
onChange: (
value: IncludesBalancesResponses extends true ? BalancesResponse | Metadata : Metadata,
) => void;
value?: ValueType;
onChange: (value: ValueType) => void;
/**
* An array of `Metadata`s and possibly `BalancesResponse`s to render as
* options. If `BalancesResponse`s are included in the `options` array, those
* options will be rendered with the user's balance of them.
*/
options: IncludesBalancesResponses extends true ? (BalancesResponse | Metadata)[] : Metadata[];
options: ValueType[];
/** The title to show above the asset selector dialog when it opens. */
dialogTitle: string;
}

export const AssetSelector = <IncludesBalancesResponses extends boolean>({
export const AssetSelector = <ValueType extends (BalancesResponse | Metadata) | Metadata>({
value,
onChange,
options,
dialogTitle,
}: AssetSelectorProps<IncludesBalancesResponses>) => {
}: AssetSelectorProps<ValueType>) => {
const layoutId = useId();
const density = useDensity();
const metadata = isMetadata(value) ? value : getMetadataFromBalancesResponse.optional()(value);

const [isOpen, setIsOpen] = useState(false);

const handleChange = (newValue: typeof value) => {
const handleChange = (newValue: ValueType) => {
onChange(newValue);
setIsOpen(false);
};
Expand Down

0 comments on commit 5593bbf

Please sign in to comment.