Skip to content

Commit

Permalink
Merge pull request #77 from AElf-devops/release/v1.0.0
Browse files Browse the repository at this point in the history
Release/v1.0.0
  • Loading branch information
aelf-lxy authored Mar 14, 2024
2 parents 0ad8aa9 + 6cf449f commit 3608328
Show file tree
Hide file tree
Showing 336 changed files with 28,548 additions and 59,841 deletions.
5 changes: 5 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
7 changes: 7 additions & 0 deletions .dumi/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

// import { ConfigProvider } from 'antd';

export function rootContainer(container: React.ReactNode): React.ReactNode {
return <div>{container}</div>;
}
54 changes: 54 additions & 0 deletions .dumi/global.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#root {
background-color: rgb(248, 248, 250);
.dumi-default-header {
box-shadow:
rgba(0, 0, 0, 0.03) 0px 1px 2px 0px,
rgba(0, 0, 0, 0.02) 0px 1px 6px -1px,
rgba(0, 0, 0, 0.02) 0px 2px 4px 0px;
}
.dumi-default-header-left {
width: 300px;
}
.dumi-default-header-right {
justify-content: end;
}
.dumi-default-navbar {
margin-right: 24px;
}

.dumi-default-hero-title {
font-size: 80px;
}

.dumi-default-content-footer {
line-height: 1.2;
}

.home {
.site-app > div:first-child {
display: block;
}
}
.rc-footer-container {
display: none;
}
}

:not([data-prefers-color='dark']) {
.home {
.dumi-default-header {
background-color: #fff;
}
.dumi-default-content {
background-color: #fff;
}
}
}

[data-prefers-color='dark'] {
.home {
.dumi-default-content {
background-color: #050709;
}
}
}
50 changes: 50 additions & 0 deletions .dumi/theme/SiteThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { useEffect } from 'react';
import { AELFDProvider } from 'aelf-design';
import { theme as antdTheme, type ThemeConfig } from 'antd';
import { ThemeProvider, useTheme, type ThemeProviderProps } from 'antd-style';

interface NewToken {
bannerHeight: number;
headerHeight: number;
anchorTop: number;
}

declare module 'antd-style' {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface CustomToken extends NewToken {}
}

const headerHeight = 64;
const bannerHeight = 38;

const SiteThemeProvider: React.FC<ThemeProviderProps<any>> = ({
children,
appearance = 'light',
...rest
}) => {
return (
<AELFDProvider
prefixCls="aelf-design-doc"
appearance={appearance}
// customToken={{
// customAddress: {
// primaryLinkColor: appearance == 'dark' ? '#c713af' : '#53dd13',
// primaryIconColor: appearance == 'dark' ? '#ea1818' : '#7f7777',
// addressHoverColor: appearance == 'dark' ? '#38b117' : '#149434',
// addressActiveColor: appearance == 'dark' ? '#0756BC' : '#0460D9',
// },
// }}
// theme={{
// token: {
// colorPrimary: appearance == 'dark' ? '#1370DD' : '#764DF1',
// colorPrimaryHover: appearance == 'dark' ? '#3689DD' : '#7F58F5',
// colorPrimaryActive: appearance == 'dark' ? '#0756BC' : '#6F45EF',
// },
// }}
>
{children}
</AELFDProvider>
);
};

export default SiteThemeProvider;
61 changes: 61 additions & 0 deletions .dumi/theme/builtins/IconSearch/Category.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as React from 'react';
import { message } from 'antd';
import { useIntl } from 'dumi';

import CopyableIcon from './CopyableIcon';
import { type CategoriesKeys } from './fields';
import { type ThemeType } from './IconSearch';

interface CategoryProps {
title: CategoriesKeys;
icons: string[];
theme: ThemeType;
newIcons: string[];
}

const Category: React.FC<CategoryProps> = (props) => {
const { icons, title, newIcons, theme } = props;
const intl = useIntl();
const [justCopied, setJustCopied] = React.useState<string | null>(null);
const copyId = React.useRef<ReturnType<typeof setTimeout> | null>(null);

const onCopied = React.useCallback((type: string, text: string) => {
message.success(
<span>
<code className="copied-code">{text}</code> copied 🎉
</span>,
);
setJustCopied(type);
copyId.current = setTimeout(() => {
setJustCopied(null);
}, 200);
}, []);
React.useEffect(
() => () => {
if (copyId.current) {
clearTimeout(copyId.current);
}
},
[],
);

return (
<div>
<h3>{intl.formatMessage({ id: `app.docs.components.icon.category.${title}` })}</h3>
<ul className="anticons-list">
{icons.map((name) => (
<CopyableIcon
key={name}
name={name}
theme={theme}
isNew={newIcons.includes(name)}
justCopied={justCopied}
onCopied={onCopied}
/>
))}
</ul>
</div>
);
};

export default Category;
56 changes: 56 additions & 0 deletions .dumi/theme/builtins/IconSearch/CopyableIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as React from 'react';
import * as AntdWeb3Icons from '@aelf-design/internal-icons';
import { Badge, message } from 'antd';
import classNames from 'classnames';
import CopyToClipboard from 'react-copy-to-clipboard';

import type { ThemeType } from './IconSearch';

const allIcons: {
[key: string]: any;
} = AntdWeb3Icons;

export interface CopyableIconProps {
name: string;
isNew: boolean;
theme: ThemeType;
justCopied: string | null;
onCopied: (type: string, text: string) => any;
}

const CopyableIcon: React.FC<CopyableIconProps> = ({
name,
isNew,
justCopied,
onCopied,
theme,
}) => {
const className = classNames({
copied: justCopied === name,
[theme]: !!theme,

// 一些白色图标需要添加背景色
isWhite: name.includes('White'),
});

const onCopy = (text: string, result: boolean) => {
if (result) {
onCopied(name, text);
} else {
message.error('Copy icon name failed, please try again.');
}
};

return (
<CopyToClipboard text={`<${name} />`} onCopy={onCopy}>
<li className={className}>
{React.createElement(allIcons[name])}
<span className="anticon-class">
<Badge dot={isNew}>{name}</Badge>
</span>
</li>
</CopyToClipboard>
);
};

export default CopyableIcon;
143 changes: 143 additions & 0 deletions .dumi/theme/builtins/IconSearch/IconSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import React, { CSSProperties, useCallback, useMemo, useState } from 'react';
import * as AntdWeb3Icons from '@aelf-design/internal-icons';
import AntdIcon from '@ant-design/icons';
import { Affix, Empty, Grid, Input, Segmented, type SegmentedProps } from 'antd';
import { createStyles, useTheme } from 'antd-style';
import { useIntl } from 'dumi';
import { debounce } from 'lodash-es';

import Category from './Category';
import { categories, CategoriesKeys } from './fields';
import { CircleFilledIcon, FilledIcon } from './themeIcons';

export enum ThemeType {
Filled = 'Filled',
CircleFilled = 'CircleFilled',
Colorful = 'Colorful',
CircleColorful = 'CircleColorful',
}

const allIcons: Record<string, any> = AntdWeb3Icons;

const useStyle = createStyles(({ css }) => ({
iconSearchAffix: css`
display: flex;
transition: all 0.3s;
justify-content: space-between;
`,
}));

const options = (
formatMessage: (values: Record<string, string>) => React.ReactNode,
onlyIcon?: boolean,
): SegmentedProps['options'] => [
{
value: ThemeType.CircleFilled,
icon: <AntdIcon component={CircleFilledIcon} />,
label: !onlyIcon && formatMessage({ id: 'app.docs.components.icon.circle-filled' }),
},
{
value: ThemeType.Filled,
icon: <AntdIcon component={FilledIcon} />,
label: !onlyIcon && formatMessage({ id: 'app.docs.components.icon.filled' }),
},
];

interface IconSearchState {
theme: ThemeType;
searchKey: string;
}

const IconSearch: React.FC = () => {
const intl = useIntl();
const token = useTheme();
const { md } = Grid.useBreakpoint();
const { styles } = useStyle();
const [displayState, setDisplayState] = useState<IconSearchState>({
searchKey: '',
theme: ThemeType.CircleColorful,
});

const newIconNames: string[] = [];

const handleSearchIcon = debounce((e: React.ChangeEvent<HTMLInputElement>) => {
setDisplayState((prevState) => ({ ...prevState, searchKey: e.target.value }));
}, 300);

const handleChangeTheme = useCallback((theme: any) => {
setDisplayState((prevState) => ({ ...prevState, theme }));
}, []);

const renderCategories = useMemo<React.ReactNode | React.ReactNode[]>(() => {
const { searchKey = '', theme } = displayState;

const categoriesResult = Object.keys(categories)
.map((key) => {
let iconList = categories[key as CategoriesKeys];
if (searchKey) {
const matchKey = searchKey
.replace(new RegExp(`^<([a-zA-Z]*)\\s/>$`, 'gi'), (_, name) => name)
.replace(/(Colorful|Filled|CircleFilled)$/gi, '')
.toLowerCase();
iconList = iconList.filter((iconName) => iconName.toLowerCase().includes(matchKey));
}

return {
category: key,
icons: iconList
.map((iconName) => iconName + theme)
.filter((iconName) => allIcons[iconName]),
};
})
.filter(({ icons }) => !!icons.length)
.map(({ category, icons }) => (
<Category
key={category}
title={category as CategoriesKeys}
theme={theme}
icons={icons}
newIcons={newIconNames}
/>
));

return categoriesResult.length ? categoriesResult : <Empty style={{ margin: '2em 0' }} />;
}, [displayState.searchKey, displayState.theme]);

const [searchBarAffixed, setSearchBarAffixed] = useState<boolean | undefined>(false);

const { borderRadius, colorBgContainer, anchorTop } = token;

const affixedStyle: CSSProperties = {
boxShadow: 'rgba(50, 50, 93, 0.25) 0 6px 12px -2px, rgba(0, 0, 0, 0.3) 0 3px 7px -3px',
padding: 8,
margin: -8,
borderRadius,
backgroundColor: colorBgContainer,
};

return (
<div className="markdown">
<Affix offsetTop={anchorTop} onChange={setSearchBarAffixed}>
<div className={styles.iconSearchAffix} style={searchBarAffixed ? affixedStyle : {}}>
<Segmented
size="large"
value={displayState.theme}
options={options(intl.formatMessage, !md)}
onChange={handleChangeTheme}
/>
<Input.Search
placeholder={intl.formatMessage({ id: 'app.docs.components.icon.search.placeholder' })}
style={{ flex: 1, marginInlineStart: 16 }}
allowClear
autoFocus
size="large"
onChange={handleSearchIcon}
/>
</div>
</Affix>
{renderCategories}
</div>
);
};

export default IconSearch;
Loading

0 comments on commit 3608328

Please sign in to comment.