Skip to content

Commit

Permalink
feat: Address support format (#139)
Browse files Browse the repository at this point in the history
* feat: Address support format

* feat: Address support format

* test: update snapshots

* feat: optimize code
  • Loading branch information
kiner-tang authored Nov 30, 2023
1 parent a81b4c9 commit 6ad444f
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 299 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Address > display address with default format 1`] = `
<div
class="ant-space css-dev-only-do-not-override-1ck3jst ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small ant-web3-address css-dev-only-do-not-override-1ck3jst"
>
<div
class="ant-space-item"
>
<span
class="ant-web3-address-text"
>
0x 21CD f097 4d53 a6e9 6eF0 5d7B 324a 9803 735f Fd3B
</span>
</div>
</div>
`;
98 changes: 98 additions & 0 deletions packages/web3/src/address/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Address } from '..';
import { fireEvent, render } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { mockClipboard } from '../../utils/test-utils';
import { readCopyText } from '../../utils';

describe('Address', () => {
let resetMockClipboard: () => void;
beforeEach(() => {
resetMockClipboard = mockClipboard();
});
afterEach(() => {
resetMockClipboard();
});

it('mount correctly', () => {
expect(() => render(<Address />)).not.toThrow();
});

it('display address', () => {
const { baseElement } = render(
<Address address="0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B" />,
);
expect(baseElement.querySelector('.ant-web3-address')?.textContent).toBe(
'0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B',
);
});

it('display address with ellipsis', () => {
const { baseElement } = render(
<Address ellipsis address="0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B" />,
);
expect(baseElement.querySelector('.ant-web3-address')?.textContent).toBe('0x21CD...Fd3B');
});

it('display address with ellipsis and custom clip', () => {
const { baseElement } = render(
<Address
ellipsis={{
headClip: 3,
tailClip: 3,
}}
address="0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B"
/>,
);
expect(baseElement.querySelector('.ant-web3-address')?.textContent).toBe('0x2...d3B');
});

it('display address with tooltip', async () => {
const { baseElement } = render(
<Address address="0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B" ellipsis />,
);

expect(baseElement.querySelector('.ant-web3-address')?.textContent).toBe('0x21CD...Fd3B');
fireEvent.mouseEnter(baseElement.querySelector('.ant-web3-address-text')!);
await vi.waitFor(() => {
expect(baseElement.querySelector('.ant-tooltip-inner')?.textContent).toBe(
'0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B',
);
});
});

it('display address with default format', () => {
const { baseElement } = render(
<Address address="0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B" format />,
);
expect(baseElement.querySelector('.ant-web3-address')?.textContent).toBe(
'0x 21CD f097 4d53 a6e9 6eF0 5d7B 324a 9803 735f Fd3B',
);
expect(baseElement.querySelector('.ant-web3-address')).toMatchSnapshot();
});

it('display address with custom format', () => {
const { baseElement } = render(
<Address
address="0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B"
format={(input) => {
return input.slice(0, 10);
}}
/>,
);
expect(baseElement.querySelector('.ant-web3-address')?.textContent).toBe('0x21CDf097');
});
it('display address with copyable', async () => {
const { baseElement } = render(
<Address address="0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B" ellipsis copyable />,
);
expect(baseElement.querySelector('.ant-web3-address')?.textContent).toBe('0x21CD...Fd3B');
fireEvent.click(baseElement.querySelector('.anticon-copy')!);
await vi.waitFor(() => {
expect(baseElement.querySelector('.ant-message')).not.toBeNull();
expect(baseElement.querySelector('.ant-message-notice-content')?.textContent?.trim()).toBe(
'Address Copied!',
);
expect(readCopyText()).resolves.toBe('0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B');
});
});
});
24 changes: 24 additions & 0 deletions packages/web3/src/address/demos/format.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Address } from '@ant-design/web3';
import { Space } from 'antd';
import { formatAddress } from '../../utils';

const App: React.FC = () => {
return (
<Space direction="vertical">
<div>
Default format: <Address address={'3ea2cfd153b8d8505097b81c87c11f5d05097c18'} format />
</div>
<div>
Custom format:{' '}
<Address
address={'3ea2cfd153b8d8505097b81c87c11f5d05097c18'}
format={(input) => {
return formatAddress(input, 5);
}}
/>
</div>
</Space>
);
};

export default App;
5 changes: 5 additions & 0 deletions packages/web3/src/address/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ group:

<code src="./demos/copyable.tsx"></code>

## Format

<code src="./demos/format.tsx"></code>

## API

| Property | Description | Type | Default | Version |
Expand All @@ -23,3 +27,4 @@ group:
| copyable | Address copyable | `boolean` | `false` | - |
| address | Address | `string` | - | - |
| tooltip | Show tooltip when hover address | `boolean \|`[Tooltip.title](https://ant.design/components/tooltip-cn#api) | Displays the current full address | - |
| format | Address format | `boolean \| (input: string) => ReactNode` | `false` | - |
27 changes: 21 additions & 6 deletions packages/web3/src/address/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CopyOutlined } from '@ant-design/icons';
import type { TooltipProps } from 'antd';
import { Space, Tooltip, message, ConfigProvider } from 'antd';
import React, { useContext } from 'react';
import React, { ReactNode, useContext, useMemo } from 'react';
import { useStyle } from './style';
import classNames from 'classnames';
import { writeCopyText, fillWith0x } from '../utils';
import { writeCopyText, fillWith0x, formatAddress } from '../utils';

export interface AddressProps {
ellipsis?:
Expand All @@ -16,14 +16,25 @@ export interface AddressProps {
address?: string;
copyable?: boolean;
tooltip?: boolean | TooltipProps['title'];
format?: boolean | ((address: string) => ReactNode);
}

export const Address: React.FC<AddressProps> = (props) => {
const { ellipsis, address, copyable, tooltip } = props;
const { ellipsis, address, copyable, tooltip, format = false } = props;
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('web3-address');
const { wrapSSR, hashId } = useStyle(prefixCls);

const mergedFormat = useMemo(() => {
if (typeof format === 'function') {
return format;
}
if (format) {
return formatAddress;
}
return (input: string) => input;
}, [format]);

const isEllipsis = !!ellipsis;
const { headClip = 6, tailClip = 4 } =
typeof ellipsis !== 'object'
Expand All @@ -38,14 +49,18 @@ export const Address: React.FC<AddressProps> = (props) => {
}

const filledAddress = fillWith0x(address);

const formattedAddress = mergedFormat(filledAddress);
const displayTooltip = tooltip === undefined || tooltip === true ? filledAddress : tooltip;

return wrapSSR(
<Space className={classNames(prefixCls, hashId)}>
<Tooltip title={displayTooltip}>
{isEllipsis
? `${filledAddress.slice(0, headClip)}...${filledAddress.slice(-tailClip)}`
: filledAddress}
<span className={`${prefixCls}-text`}>
{isEllipsis
? `${filledAddress.slice(0, headClip)}...${filledAddress.slice(-tailClip)}`
: formattedAddress}
</span>
</Tooltip>
{copyable && (
<CopyOutlined
Expand Down
5 changes: 5 additions & 0 deletions packages/web3/src/address/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ group:

<code src="./demos/copyable.tsx"></code>

## 格式化

<code src="./demos/format.tsx"></code>

## API

| 属性 | 描述 | 类型 | 默认值 | 版本 |
Expand All @@ -23,3 +27,4 @@ group:
| copyable | 是否可复制 | `boolean` | `false` | - |
| address | 地址 | `string` | - | - |
| tooltip | 鼠标移入地址时展示提示 | `boolean \|` [Tooltip.title](https://ant.design/components/tooltip-cn#api) | 展示当前完整地址 | - |
| format | 地址格式化 | `boolean \| (input: string) => ReactNode` | `false` | - |
Loading

0 comments on commit 6ad444f

Please sign in to comment.