diff --git a/.dumi/components/SemanticPreview.tsx b/.dumi/components/SemanticPreview.tsx index 2fbf2651..00efb5b7 100644 --- a/.dumi/components/SemanticPreview.tsx +++ b/.dumi/components/SemanticPreview.tsx @@ -1,4 +1,5 @@ -import { Col, ConfigProvider, Flex, Row, Tag, Typography, theme } from 'antd'; +import { XProvider } from '@ant-design/x'; +import { Col, Flex, Row, Tag, Typography, theme } from 'antd'; import { createStyles, css } from 'antd-style'; import classnames from 'classnames'; import React from 'react'; @@ -137,7 +138,7 @@ const SemanticPreview: React.FC = (props) => {
- {cloneNode} + {cloneNode}
    diff --git a/.dumi/hooks/useMenu.tsx b/.dumi/hooks/useMenu.tsx index 52f12bca..092f3b2c 100644 --- a/.dumi/hooks/useMenu.tsx +++ b/.dumi/hooks/useMenu.tsx @@ -1,5 +1,6 @@ +import { version } from '@ant-design/x'; import type { MenuProps } from 'antd'; -import { Space, Tag, version } from 'antd'; +import { Space, Tag } from 'antd'; import { createStyles } from 'antd-style'; import classnames from 'classnames'; import { useFullSidebarData, useSidebarData } from 'dumi'; diff --git a/.dumi/pages/index/components/ComponentsList.tsx b/.dumi/pages/index/components/ComponentsList.tsx deleted file mode 100644 index 2ab48da2..00000000 --- a/.dumi/pages/index/components/ComponentsList.tsx +++ /dev/null @@ -1,299 +0,0 @@ -import { CustomerServiceOutlined, QuestionCircleOutlined, SyncOutlined } from '@ant-design/icons'; -import { - Alert, - Carousel, - DatePicker, - Flex, - FloatButton, - Modal, - Progress, - Tag, - Tour, - Typography, -} from 'antd'; -import { createStyles, css } from 'antd-style'; -import classNames from 'classnames'; -import dayjs from 'dayjs'; -import React, { useContext } from 'react'; - -import useDark from '../../../hooks/useDark'; -import useLocale from '../../../hooks/useLocale'; -import SiteContext from '../../../theme/slots/SiteContext'; -import { getCarouselStyle } from './util'; - -const { _InternalPanelDoNotUseOrYouWillBeFired: ModalDoNotUseOrYouWillBeFired } = Modal; -const { _InternalPanelDoNotUseOrYouWillBeFired: DatePickerDoNotUseOrYouWillBeFired } = DatePicker; -const { _InternalPanelDoNotUseOrYouWillBeFired: TourDoNotUseOrYouWillBeFired } = Tour; -const { _InternalPanelDoNotUseOrYouWillBeFired: FloatButtonDoNotUseOrYouWillBeFired } = FloatButton; - -const SAMPLE_CONTENT_EN = - 'Ant Design 5.0 use CSS-in-JS technology to provide dynamic & mix theme ability. And which use component level CSS-in-JS solution get your application a better performance.'; - -const SAMPLE_CONTENT_CN = - 'Ant Design 5.0 使用 CSS-in-JS 技术以提供动态与混合主题的能力。与此同时,我们使用组件级别的 CSS-in-JS 解决方案,让你的应用获得更好的性能。'; - -const locales = { - cn: { - yesterday: '昨天', - lastWeek: '上周', - lastMonth: '上月', - lastYear: '去年', - new: '新增', - update: '更新', - sampleContent: SAMPLE_CONTENT_CN, - inProgress: '进行中', - success: '成功', - taskFailed: '任务失败', - tour: '漫游导览帮助用户对新加的功能进行快速了解', - }, - en: { - yesterday: 'Yesterday', - lastWeek: 'Last Week', - lastMonth: 'Last Month', - lastYear: 'Last Year', - new: 'New', - update: 'Update', - sampleContent: SAMPLE_CONTENT_EN, - inProgress: 'In Progress', - success: 'Success', - taskFailed: 'Task Failed', - tour: 'A quick guide for new come user about how to use app.', - }, -}; - -const useStyle = () => { - const isRootDark = useDark(); - - return createStyles(({ token }) => { - const { carousel } = getCarouselStyle(); - - return { - card: css` - border-radius: ${token.borderRadius}px; - border: 1px solid ${isRootDark ? token.colorBorder : 'transparent'}; - background: ${isRootDark ? token.colorBgContainer : '#f5f8ff'}; - padding: ${token.paddingXL}px; - flex: none; - overflow: hidden; - position: relative; - display: flex; - flex-direction: column; - align-items: stretch; - - > * { - flex: none; - } - `, - cardCircle: css` - position: absolute; - width: 120px; - height: 120px; - background: #1677ff; - border-radius: 50%; - filter: blur(40px); - opacity: 0.1; - `, - mobileCard: css` - height: 395px; - `, - nodeWrap: css` - margin-top: ${token.paddingLG}px; - flex: auto; - display: flex; - align-items: center; - justify-content: center; - `, - carousel, - componentsList: css` - width: 100%; - overflow: hidden; - `, - mobileComponentsList: css` - margin: 0 ${token.margin}px; - `, - }; - })(); -}; - -const ComponentItem: React.FC = ({ title, node, type, index }) => { - const tagColor = type === 'new' ? 'processing' : 'warning'; - const [locale] = useLocale(locales); - const tagText = type === 'new' ? locale.new : locale.update; - const { styles } = useStyle(); - const { isMobile } = useContext(SiteContext); - return ( -
    - {/* Decorator */} -
    - - {/* Title */} - - - {title} - - {tagText} - -
    {node}
    -
    - ); -}; - -interface ComponentItemProps { - title: React.ReactNode; - node: React.ReactNode; - type: 'new' | 'update'; - index: number; -} - -const ComponentsList: React.FC = () => { - const { styles } = useStyle(); - const [locale] = useLocale(locales); - const { isMobile } = useContext(SiteContext); - const COMPONENTS = React.useMemo[]>( - () => [ - { - title: 'Modal', - type: 'update', - node: ( - - {locale.sampleContent} - - ), - }, - - { - title: 'DatePicker', - type: 'update', - node: ( - - ), - }, - - { - title: 'Progress', - type: 'update', - node: ( - - - - {locale.inProgress} - - - - {locale.success} - - - - {locale.taskFailed} - - - ), - }, - { - title: 'Tour', - type: 'new', - node: ( - - ), - }, - { - title: 'FloatButton', - type: 'new', - node: ( - - }, - { icon: }, - { icon: }, - ]} - /> - - }, - { icon: }, - { icon: }, - ]} - /> - - ), - }, - - // { - // title: 'Steps', - // type: 'update', - // node: , - // }, - - { - title: 'Alert', - type: 'update', - node: ( - - ), - }, - ], - [isMobile], - ); - - return isMobile ? ( -
    - - {COMPONENTS.map(({ title, node, type }, index) => ( - - ))} - -
    - ) : ( - - - {COMPONENTS.map(({ title, node, type }, index) => ( - - ))} - - - ); -}; - -export default ComponentsList; diff --git a/.dumi/pages/index/components/Theme/BackgroundImage.tsx b/.dumi/pages/index/components/Theme/BackgroundImage.tsx deleted file mode 100644 index ea9d0ccd..00000000 --- a/.dumi/pages/index/components/Theme/BackgroundImage.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { createStyles, css } from 'antd-style'; -import classNames from 'classnames'; -import { CSSMotionList } from 'rc-motion'; -import React, { useMemo, useState } from 'react'; - -import { COLOR_IMAGES, getClosetColor } from './colorUtil'; - -export interface BackgroundImageProps { - colorPrimary?: string; - isLight?: boolean; -} - -const useStyle = createStyles(({ token }) => ({ - image: css` - transition: all ${token.motionDurationSlow}; - position: absolute; - inset-inline-start: 0; - top: 0; - height: 100%; - width: 100%; - object-fit: cover; - object-position: right top; - `, -})); - -const onShow = () => ({ opacity: 1 }); - -const onHide = () => ({ opacity: 0 }); - -const BackgroundImage: React.FC = ({ colorPrimary, isLight }) => { - const activeColor = useMemo(() => getClosetColor(colorPrimary), [colorPrimary]); - const { styles } = useStyle(); - - const [keyList, setKeyList] = useState([]); - - React.useLayoutEffect(() => { - setKeyList([activeColor as string]); - }, [activeColor]); - - return ( - - {({ key: color, className, style }) => { - const cls = classNames(styles.image, className); - const entity = COLOR_IMAGES.find((ent) => ent.color === color); - - if (!entity || !entity.url) { - return null as unknown as React.ReactElement; - } - - const { opacity } = style || {}; - - return ( - - - - bg - - ); - }} - - ); -}; - -export default BackgroundImage; diff --git a/.dumi/pages/index/components/Theme/ColorPicker.tsx b/.dumi/pages/index/components/Theme/ColorPicker.tsx deleted file mode 100644 index d0b6d655..00000000 --- a/.dumi/pages/index/components/Theme/ColorPicker.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { ColorPicker, Flex, Input } from 'antd'; -import type { ColorPickerProps, GetProp } from 'antd'; -import { createStyles } from 'antd-style'; -import { generateColor } from 'antd/es/color-picker/util'; -import classNames from 'classnames'; -import React, { useEffect, useState } from 'react'; - -import { PRESET_COLORS } from './colorUtil'; - -type Color = Extract, string | { cleared: any }>; - -const useStyle = createStyles(({ token, css }) => ({ - color: css` - width: ${token.controlHeightLG / 2}px; - height: ${token.controlHeightLG / 2}px; - border-radius: 100%; - cursor: pointer; - transition: all ${token.motionDurationFast}; - display: inline-block; - - & > input[type='radio'] { - width: 0; - height: 0; - opacity: 0; - } - - &:focus-within { - // need ? - } - `, - - colorActive: css` - box-shadow: - 0 0 0 1px ${token.colorBgContainer}, - 0 0 0 ${token.controlOutlineWidth * 2 + 1}px ${token.colorPrimary}; - `, -})); - -export interface ThemeColorPickerProps { - id?: string; - value?: string | Color; - onChange?: (value?: Color | string) => void; -} - -const DebouncedColorPicker: React.FC> = (props) => { - const { value: color, children, onChange } = props; - const [value, setValue] = useState(color); - - useEffect(() => { - const timeout = setTimeout(() => { - onChange?.(value); - }, 200); - return () => clearTimeout(timeout); - }, [value]); - - useEffect(() => { - setValue(color); - }, [color]); - - return ( - - {children} - - ); -}; - -const ThemeColorPicker: React.FC = ({ value, onChange, id }) => { - const { styles } = useStyle(); - - const matchColors = React.useMemo(() => { - const valueStr = generateColor(value || '').toRgbString(); - let existActive = false; - const colors = PRESET_COLORS.map((color) => { - const colorStr = generateColor(color).toRgbString(); - const active = colorStr === valueStr; - existActive = existActive || active; - return { color, active, picker: false }; - }); - - return [ - ...colors, - { - color: 'conic-gradient(red, yellow, lime, aqua, blue, magenta, red)', - picker: true, - active: !existActive, - }, - ]; - }, [value]); - - return ( - - onChange?.(event.target.value)} - style={{ width: 120 }} - id={id} - /> - - {matchColors.map(({ color, active, picker }) => { - const colorNode = ( - // eslint-disable-next-line jsx-a11y/label-has-associated-control - - ); - return picker ? ( - - {colorNode} - - ) : ( - colorNode - ); - })} - - - ); -}; - -export default ThemeColorPicker; diff --git a/.dumi/pages/index/components/Theme/MobileCarousel.tsx b/.dumi/pages/index/components/Theme/MobileCarousel.tsx deleted file mode 100644 index 12cf1a54..00000000 --- a/.dumi/pages/index/components/Theme/MobileCarousel.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import { Carousel, Typography } from 'antd'; -import { createStyles, css, useTheme } from 'antd-style'; -import * as React from 'react'; -import { useState } from 'react'; - -import { getCarouselStyle } from '../util'; - -const useStyle = createStyles(() => { - const { carousel } = getCarouselStyle(); - return { - carousel, - container: css` - position: relative; - `, - title: css` - position: absolute; - top: 15%; - z-index: 1; - width: 100%; - text-align: center; - `, - img: css` - width: 100%; - `, - }; -}); - -const mobileImageConfigList = [ - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*KsMrRZaciFcAAAAAAAAAAAAADrJ8AQ/original', - titleColor: 'rgba(0,0,0,.88)', - }, - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*3FkqR6XRNgoAAAAAAAAAAAAADrJ8AQ/original', - titleColor: '#fff', - }, - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*cSX_RbD3k9wAAAAAAAAAAAAADrJ8AQ/original', - titleColor: '#fff', - }, - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*MldsRZeax6EAAAAAAAAAAAAADrJ8AQ/original', - titleColor: '#fff', - }, - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*xCAmSL0xlZ8AAAAAAAAAAAAADrJ8AQ/original', - titleColor: '#fff', - }, - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*vCfCSbiI_VIAAAAAAAAAAAAADrJ8AQ/original', - titleColor: '#fff', - }, - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*xCAmSL0xlZ8AAAAAAAAAAAAADrJ8AQ/original', - titleColor: '#fff', - }, - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*BeDBTY9UnXIAAAAAAAAAAAAADrJ8AQ/original', - titleColor: '#fff', - }, - { - imageSrc: - 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Q63XTbk8YaMAAAAAAAAAAAAADrJ8AQ/original', - titleColor: '#fff', - }, -]; - -export interface MobileCarouselProps { - id?: string; - title?: React.ReactNode; - description?: React.ReactNode; -} - -const MobileCarousel: React.FC = (props) => { - const { styles } = useStyle(); - const { id, title, description } = props; - const token = useTheme(); - const [currentSlider, setCurrentSlider] = useState(0); - - return ( -
    -
    - - {title} - - - {description} - -
    - - {mobileImageConfigList.map((item, index) => ( -
    - carousel -
    - ))} -
    -
    - ); -}; - -export default MobileCarousel; diff --git a/.dumi/pages/index/components/Theme/RadiusPicker.tsx b/.dumi/pages/index/components/Theme/RadiusPicker.tsx deleted file mode 100644 index 45b76c9e..00000000 --- a/.dumi/pages/index/components/Theme/RadiusPicker.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Flex, InputNumber, Slider } from 'antd'; -import React from 'react'; - -export interface RadiusPickerProps { - id?: string; - value?: number; - onChange?: (value: number | null) => void; -} - -const RadiusPicker: React.FC = ({ id, value, onChange }) => ( - - `${val}px`} - parser={(str) => str?.replace('px', '') as unknown as number} - id={id} - /> - - -); - -export default RadiusPicker; diff --git a/.dumi/pages/index/components/Theme/ThemePicker.tsx b/.dumi/pages/index/components/Theme/ThemePicker.tsx deleted file mode 100644 index 249db2af..00000000 --- a/.dumi/pages/index/components/Theme/ThemePicker.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { Flex } from 'antd'; -import { createStyles } from 'antd-style'; -import classNames from 'classnames'; -/* eslint-disable jsx-a11y/label-has-associated-control */ -import * as React from 'react'; - -import useLocale from '../../../../hooks/useLocale'; - -export const THEMES = { - default: 'https://gw.alipayobjects.com/zos/bmw-prod/ae669a89-0c65-46db-b14b-72d1c7dd46d6.svg', - dark: 'https://gw.alipayobjects.com/zos/bmw-prod/0f93c777-5320-446b-9bb7-4d4b499f346d.svg', - lark: 'https://gw.alipayobjects.com/zos/bmw-prod/3e899b2b-4eb4-4771-a7fc-14c7ff078aed.svg', - comic: 'https://gw.alipayobjects.com/zos/bmw-prod/ed9b04e8-9b8d-4945-8f8a-c8fc025e846f.svg', -} as const; - -export type THEME = keyof typeof THEMES; - -const locales = { - cn: { - default: '默认', - dark: '暗黑', - lark: '知识协作', - comic: '桃花缘', - v4: 'V4 主题', - }, - en: { - default: 'Default', - dark: 'Dark', - lark: 'Document', - comic: 'Blossom', - v4: 'V4 Theme', - }, -}; - -const useStyle = createStyles(({ token, css }) => ({ - themeCard: css` - border-radius: ${token.borderRadius}px; - cursor: pointer; - transition: all ${token.motionDurationSlow}; - overflow: hidden; - display: inline-block; - - & > input[type='radio'] { - width: 0; - height: 0; - opacity: 0; - position: absolute; - } - - img { - vertical-align: top; - box-shadow: - 0 3px 6px -4px rgba(0, 0, 0, 0.12), - 0 6px 16px 0 rgba(0, 0, 0, 0.08), - 0 9px 28px 8px rgba(0, 0, 0, 0.05); - } - - &:focus-within, - &:hover { - transform: scale(1.04); - } - `, - - themeCardActive: css` - box-shadow: - 0 0 0 1px ${token.colorBgContainer}, - 0 0 0 ${token.controlOutlineWidth * 2 + 1}px ${token.colorPrimary}; - &, - &:hover:not(:focus-within) { - transform: scale(1); - } - `, -})); - -export interface ThemePickerProps { - id?: string; - value?: string; - onChange?: (value: string) => void; -} - -const ThemePicker: React.FC = (props) => { - const { value, id, onChange } = props; - const { styles } = useStyle(); - const [locale] = useLocale(locales); - return ( - - {(Object.keys(THEMES) as (keyof typeof THEMES)[]).map((theme, index) => ( - - - {locale[theme]} - - ))} - - ); -}; - -export default ThemePicker; diff --git a/.dumi/pages/index/components/Theme/colorUtil.ts b/.dumi/pages/index/components/Theme/colorUtil.ts deleted file mode 100644 index 61b697db..00000000 --- a/.dumi/pages/index/components/Theme/colorUtil.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { ColorPickerProps, GetProp } from 'antd'; -import { generateColor } from 'antd/es/color-picker/util'; - -type Color = GetProp; - -export const DEFAULT_COLOR = '#1677FF'; -export const PINK_COLOR = '#ED4192'; - -export const COLOR_IMAGES = [ - { - color: DEFAULT_COLOR, - // url: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*QEAoSL8uVi4AAAAAAAAAAAAAARQnAQ', - url: null, - webp: null, - }, - { - color: '#5A54F9', - url: 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*H8nRT7_q0EwAAAAAAAAAAAAADrJ8AQ/original', - webp: 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*H8nRT7_q0EwAAAAAAAAAAAAADrJ8AQ/fmt.webp', - }, - { - color: '#9E339F', - url: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*FMluR4vJhaQAAAAAAAAAAAAAARQnAQ', - webp: 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*CMCMTKV51tIAAAAAAAAAAAAADrJ8AQ/fmt.webp', - }, - { - color: PINK_COLOR, - url: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*DGZXS4YOGp0AAAAAAAAAAAAAARQnAQ', - webp: 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*s5OdR6wZZIkAAAAAAAAAAAAADrJ8AQ/fmt.webp', - }, - { - color: '#E0282E', - url: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*w6xcR7MriwEAAAAAAAAAAAAAARQnAQ', - webp: 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*HE_4Qp_XfQQAAAAAAAAAAAAADrJ8AQ/fmt.webp', - }, - { - color: '#F4801A', - url: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*VWFOTbEyU9wAAAAAAAAAAAAAARQnAQ', - webp: 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*xTG2QbottAQAAAAAAAAAAAAADrJ8AQ/fmt.webp', - }, - { - color: '#F2BD27', - url: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*1yydQLzw5nYAAAAAAAAAAAAAARQnAQ', - webp: 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*hbPfSbF-xPIAAAAAAAAAAAAADrJ8AQ/fmt.webp', - }, - { - color: '#00B96B', - url: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*XpGeRoZKGycAAAAAAAAAAAAAARQnAQ', - webp: 'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*iM6CQ496P3oAAAAAAAAAAAAADrJ8AQ/fmt.webp', - }, -] as const; - -export const PRESET_COLORS = COLOR_IMAGES.map(({ color }) => color); - -const DISTANCE = 33; - -export function getClosetColor(colorPrimary?: Color | string | null) { - if (!colorPrimary) { - return null; - } - - const colorPrimaryRGB = generateColor(colorPrimary).toRgb(); - - const distance = COLOR_IMAGES.map(({ color }) => { - const colorObj = generateColor(color).toRgb(); - const dist = Math.sqrt( - (colorObj.r - colorPrimaryRGB.r) ** 2 + - (colorObj.g - colorPrimaryRGB.g) ** 2 + - (colorObj.b - colorPrimaryRGB.b) ** 2, - ); - - return { color, dist }; - }); - - const firstMatch = distance.sort((a, b) => a.dist - b.dist)[0]; - - return firstMatch.dist <= DISTANCE ? firstMatch.color : null; -} - -export function getAvatarURL(color?: string | null) { - const closestColor = getClosetColor(color); - - if (!closestColor) { - return null; - } - - return ( - COLOR_IMAGES.find((obj) => obj.color === closestColor)?.url || - 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*CLp0Qqc11AkAAAAAAAAAAAAAARQnAQ' - ); -} diff --git a/.dumi/pages/index/components/Theme/index.tsx b/.dumi/pages/index/components/Theme/index.tsx deleted file mode 100644 index d33c0a25..00000000 --- a/.dumi/pages/index/components/Theme/index.tsx +++ /dev/null @@ -1,629 +0,0 @@ -import { - BellOutlined, - FolderOutlined, - HomeOutlined, - QuestionCircleOutlined, -} from '@ant-design/icons'; -import { TinyColor } from '@ctrl/tinycolor'; -import type { MenuProps, ThemeConfig } from 'antd'; -import { - Breadcrumb, - Button, - Card, - ConfigProvider, - Flex, - Form, - Layout, - Menu, - Radio, - Typography, - theme, -} from 'antd'; -import { createStyles } from 'antd-style'; -import type { Color } from 'antd/es/color-picker'; -import { generateColor } from 'antd/es/color-picker/util'; -import classNames from 'classnames'; -import { useLocation } from 'dumi'; -import * as React from 'react'; - -import useDark from '../../../../hooks/useDark'; -import useLocale from '../../../../hooks/useLocale'; -import Link from '../../../../theme/common/Link'; -import SiteContext from '../../../../theme/slots/SiteContext'; -import { getLocalizedPathname } from '../../../../theme/utils'; -import Group from '../Group'; -import { getCarouselStyle } from '../util'; -import BackgroundImage from './BackgroundImage'; -import ColorPicker from './ColorPicker'; -import MobileCarousel from './MobileCarousel'; -import RadiusPicker from './RadiusPicker'; -import type { THEME } from './ThemePicker'; -import ThemePicker from './ThemePicker'; -import { DEFAULT_COLOR, PINK_COLOR, getAvatarURL, getClosetColor } from './colorUtil'; - -const { Header, Content, Sider } = Layout; - -const TokenChecker: React.FC = () => { - if (process.env.NODE_ENV !== 'production') { - console.log('Demo Token:', theme.useToken()); - } - return null; -}; - -// ============================= Theme ============================= -const locales = { - cn: { - themeTitle: '定制主题,随心所欲', - themeDesc: 'Ant Design 5.0 开放更多样式算法,让你定制主题更简单', - - customizeTheme: '定制主题', - myTheme: '我的主题', - titlePrimaryColor: '主色', - titleBorderRadius: '圆角', - titleCompact: '宽松度', - default: '默认', - compact: '紧凑', - titleTheme: '主题', - light: '亮色', - dark: '暗黑', - toDef: '深度定制', - toUse: '去使用', - }, - en: { - themeTitle: 'Flexible theme customization', - themeDesc: 'Ant Design 5.0 enable extendable algorithm, make custom theme easier', - - customizeTheme: 'Customize Theme', - myTheme: 'My Theme', - titlePrimaryColor: 'Primary Color', - titleBorderRadius: 'Border Radius', - titleCompact: 'Compact', - titleTheme: 'Theme', - default: 'Default', - compact: 'Compact', - light: 'Light', - dark: 'Dark', - toDef: 'More', - toUse: 'Apply', - }, -}; - -// ============================= Style ============================= -const useStyle = createStyles(({ token, css, cx }) => { - const { carousel } = getCarouselStyle(); - const demo = css` - overflow: hidden; - background: rgba(240, 242, 245, 0.25); - backdrop-filter: blur(50px); - box-shadow: 0 2px 10px 2px rgba(0, 0, 0, 0.1); - transition: all ${token.motionDurationSlow}; - `; - - return { - demo, - - otherDemo: css` - &.${cx(demo)} { - backdrop-filter: blur(10px); - background: rgba(247, 247, 247, 0.5); - } - `, - - darkDemo: css` - &.${cx(demo)} { - background: #000; - } - `, - - larkDemo: css` - &.${cx(demo)} { - // background: #f7f7f7; - background: rgba(240, 242, 245, 0.65); - } - `, - comicDemo: css` - &.${cx(demo)} { - // background: #ffe4e6; - background: rgba(240, 242, 245, 0.65); - } - `, - - menu: css` - margin-inline-start: auto; - `, - - header: css` - display: flex; - align-items: center; - border-bottom: 1px solid ${token.colorSplit}; - padding-inline: ${token.paddingLG}px !important; - height: ${token.controlHeightLG * 1.2}px; - line-height: ${token.controlHeightLG * 1.2}px; - `, - - headerDark: css` - border-bottom-color: rgba(255, 255, 255, 0.1); - `, - - avatar: css` - width: ${token.controlHeight}px; - height: ${token.controlHeight}px; - border-radius: 100%; - background: rgba(240, 240, 240, 0.75); - background-size: cover; - box-shadow: 0 0 2px rgba(0, 0, 0, 0.2); - `, - - avatarDark: css` - background: rgba(200, 200, 200, 0.3); - `, - - logo: css` - display: flex; - align-items: center; - column-gap: ${token.padding}px; - - h1 { - font-weight: 400; - font-size: ${token.fontSizeLG}px; - line-height: 1.5; - } - `, - - logoImg: css` - width: 30px; - height: 30px; - overflow: hidden; - - img { - width: 30px; - height: 30px; - vertical-align: top; - } - `, - - transBg: css` - background: transparent !important; - `, - - form: css` - width: 100%; - margin: 0 auto; - `, - pos: css` - position: absolute; - `, - leftTopImagePos: css` - left: 0; - top: -100px; - height: 500px; - `, - rightBottomPos: css` - right: 0; - bottom: -100px; - height: 287px; - `, - leftTopImage: css` - left: 50%; - transform: translate3d(-900px, 0, 0); - top: -100px; - height: 500px; - `, - rightBottomImage: css` - right: 50%; - transform: translate3d(750px, 0, 0); - bottom: -100px; - height: 287px; - `, - motion: css` - transition: all ${token.motionDurationSlow}; - `, - op1: css` - opacity: 1; - `, - op0: css` - opacity: 0; - `, - carousel, - }; -}); - -// ========================== Menu Config ========================== -const subMenuItems = [ - { - key: `Design Values`, - label: `Design Values`, - }, - { - key: `Global Styles`, - label: `Global Styles`, - }, - { - key: `Themes`, - label: `Themes`, - }, - { - key: `DesignPatterns`, - label: `Design Patterns`, - }, -]; - -const sideMenuItems: MenuProps['items'] = [ - { - key: `Design`, - label: `Design`, - icon: , - children: subMenuItems, - }, - { - key: `Development`, - label: `Development`, - icon: , - }, -]; - -// ============================= Theme ============================= - -function getTitleColor(colorPrimary: string | Color, isLight?: boolean) { - if (!isLight) { - return '#FFF'; - } - - const color = generateColor(colorPrimary); - const closestColor = getClosetColor(colorPrimary); - - switch (closestColor) { - case DEFAULT_COLOR: - case PINK_COLOR: - case '#F2BD27': - return undefined; - - case '#5A54F9': - case '#E0282E': - return '#FFF'; - - default: - return color.toHsb().b < 0.7 ? '#FFF' : undefined; - } -} - -interface ThemeData { - themeType: THEME; - colorPrimary: string | Color; - borderRadius: number; - compact: 'default' | 'compact'; -} - -const ThemeDefault: ThemeData = { - themeType: 'default', - colorPrimary: '#1677FF', - borderRadius: 6, - compact: 'default', -}; - -const ThemesInfo: Record> = { - default: {}, - dark: { - borderRadius: 2, - }, - lark: { - colorPrimary: '#00B96B', - borderRadius: 4, - }, - comic: { - colorPrimary: PINK_COLOR, - borderRadius: 16, - }, -}; - -const normalize = (value: number) => value / 255; - -function rgbToColorMatrix(color: string) { - const rgb = new TinyColor(color).toRgb(); - const { r, g, b } = rgb; - - const invertValue = normalize(r) * 100; - const sepiaValue = 100; - const saturateValue = Math.max(normalize(r), normalize(g), normalize(b)) * 10000; - const hueRotateValue = - ((Math.atan2( - Math.sqrt(3) * (normalize(g) - normalize(b)), - 2 * normalize(r) - normalize(g) - normalize(b), - ) * - 180) / - Math.PI + - 360) % - 360; - - return `invert(${invertValue}%) sepia(${sepiaValue}%) saturate(${saturateValue}%) hue-rotate(${hueRotateValue}deg)`; -} - -const Theme: React.FC = () => { - const { styles } = useStyle(); - const [locale, lang] = useLocale(locales); - const isZhCN = lang === 'cn'; - const { search } = useLocation(); - - const [themeData, setThemeData] = React.useState(ThemeDefault); - - const onThemeChange = (_: Partial, nextThemeData: ThemeData) => { - React.startTransition(() => { - setThemeData({ - ...ThemesInfo[nextThemeData.themeType], - ...nextThemeData, - }); - }); - }; - - const { compact, themeType, colorPrimary, ...themeToken } = themeData; - const isLight = themeType !== 'dark'; - const [form] = Form.useForm(); - const { isMobile } = React.useContext(SiteContext); - const colorPrimaryValue = React.useMemo( - () => (typeof colorPrimary === 'string' ? colorPrimary : colorPrimary.toHexString()), - [colorPrimary], - ); - - // const algorithmFn = isLight ? theme.defaultAlgorithm : theme.darkAlgorithm; - const algorithmFn = React.useMemo(() => { - const algorithms = [isLight ? theme.defaultAlgorithm : theme.darkAlgorithm]; - - if (compact === 'compact') { - algorithms.push(theme.compactAlgorithm); - } - - return algorithms; - }, [isLight, compact, themeType]); - - // ================================ Themes ================================ - React.useEffect(() => { - const mergedData = { - ...ThemeDefault, - themeType, - ...ThemesInfo[themeType], - }; - - setThemeData(mergedData); - form.setFieldsValue(mergedData); - }, [themeType]); - - const isRootDark = useDark(); - - React.useEffect(() => { - onThemeChange({}, { ...themeData, themeType: isRootDark ? 'dark' : 'default' }); - }, [isRootDark]); - - // ================================ Tokens ================================ - const closestColor = getClosetColor(colorPrimaryValue); - - const [backgroundColor, avatarColor] = React.useMemo(() => { - let bgColor = 'transparent'; - - const mapToken = theme.defaultAlgorithm({ - ...theme.defaultConfig.token, - colorPrimary: colorPrimaryValue, - }); - - if (themeType === 'dark') { - bgColor = '#393F4A'; - } else if (closestColor === DEFAULT_COLOR) { - bgColor = '#F5F8FF'; - } else { - bgColor = mapToken.colorPrimaryHover; - } - - return [bgColor, mapToken.colorPrimaryBgHover]; - }, [themeType, closestColor, colorPrimaryValue]); - - const logoColor = React.useMemo(() => { - const hsb = generateColor(colorPrimaryValue).toHsb(); - hsb.b = Math.min(hsb.b, 0.7); - return generateColor(hsb).toHexString(); - }, [colorPrimaryValue]); - - const memoTheme = React.useMemo( - () => ({ - token: { ...themeToken, colorPrimary: colorPrimaryValue }, - algorithm: algorithmFn, - components: { - Layout: isLight - ? { - headerBg: 'transparent', - bodyBg: 'transparent', - } - : {}, - Menu: isLight - ? { - itemBg: 'transparent', - subMenuItemBg: 'transparent', - activeBarBorderWidth: 0, - } - : {}, - }, - }), - [themeToken, colorPrimaryValue, algorithmFn, themeType], - ); - - // ================================ Render ================================ - const themeNode = ( - - -
    - -
    - {/* Logo */} -
    -
    - -
    -

    Ant Design X

    -
    - - - -
    - -
    - - - - - - }, - { title: 'Design', menu: { items: subMenuItems } }, - { title: 'Themes' }, - ]} - /> - - {locale.customizeTheme} - - - - - - - - - } - > -
    - - - - - - - - - - - - -
    -
    -
    -
    - - -
    -
    - ); - - return isMobile ? ( - - ) : ( - - {/* >>>>>> Default <<<<<< */} -
    - {/* Image Left Top */} - - {/* Image Right Bottom */} - -
    - {/* >>>>>> Dark <<<<<< */} -
    - {/* Image Left Top */} - - {/* Image Right Bottom */} - -
    - {/* >>>>>> Background Image <<<<<< */} - - - } - > - {themeNode} -
    - ); -}; - -export default Theme; diff --git a/.dumi/pages/index/index.tsx b/.dumi/pages/index/index.tsx index 30e1aa94..03d3bfe8 100644 --- a/.dumi/pages/index/index.tsx +++ b/.dumi/pages/index/index.tsx @@ -1,4 +1,3 @@ -import { ConfigProvider, theme } from 'antd'; import { createStyles, css } from 'antd-style'; import React, { Suspense } from 'react'; @@ -8,9 +7,7 @@ import BannerRecommends from './components/BannerRecommends'; import Group from './components/Group'; import PreviewBanner from './components/PreviewBanner'; -const ComponentsList = React.lazy(() => import('./components/ComponentsList')); const DesignFramework = React.lazy(() => import('./components/DesignFramework')); -const Theme = React.lazy(() => import('./components/Theme')); const useStyle = createStyles(() => ({ image: css` @@ -39,7 +36,6 @@ const locales = { const Homepage: React.FC = () => { const [locale] = useLocale(locales); const { styles } = useStyle(); - const { token } = theme.useToken(); const isRootDark = useDark(); @@ -50,30 +46,6 @@ const Homepage: React.FC = () => {
    - {/* 定制主题 */} - - - - - - - {/* 组件列表 */} - - - - - - {/* 设计语言 */} ({ color: ${token.magenta8}; margin-inline-end: 0.5em; `, - antd: css` + antdx: css` color: ${token.green8}; `, semicolon: css` @@ -104,7 +104,7 @@ const ComponentMeta: React.FC = (props) => { if (String(source) === 'true') { const kebabComponent = kebabCase(component); return [ - `/~https://github.com/ant-design/ant-design/blob/master/components/${kebabComponent}`, + `/~https://github.com/ant-design/x/blob/main/components/${kebabComponent}`, `components/${kebabComponent}`, ]; } @@ -134,8 +134,8 @@ const ComponentMeta: React.FC = (props) => { from , - - {`"antd"`} + + {`"@ant-design/x"`} , ; @@ -154,7 +154,10 @@ const ComponentMeta: React.FC = (props) => { { label: locale.import, children: ( - + = (props) => { .filter(Boolean); const code = component - ? ` = (props) => { }} > ... -` - : `` + : ` = (props) => { }} > ... -`; +`; return ( <> @@ -176,7 +177,7 @@ const SubTokenTable: React.FC = (props) => {
    {open && ( - + = (props) => { pagination={false} rowKey={(record) => record.name} /> - + )} ); diff --git a/.dumi/theme/builtins/DemoWrapper/index.tsx b/.dumi/theme/builtins/DemoWrapper/index.tsx index 90d33531..80713eba 100644 --- a/.dumi/theme/builtins/DemoWrapper/index.tsx +++ b/.dumi/theme/builtins/DemoWrapper/index.tsx @@ -6,7 +6,8 @@ import { ExperimentFilled, ExperimentOutlined, } from '@ant-design/icons'; -import { ConfigProvider, Tooltip } from 'antd'; +import { XProvider } from '@ant-design/x'; +import { Tooltip } from 'antd'; import classNames from 'classnames'; import { DumiDemoGrid, FormattedMessage } from 'dumi'; import React, { useContext } from 'react'; @@ -108,9 +109,9 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => { )} - + - + ); }; diff --git a/.dumi/theme/builtins/InstallDependencies/index.tsx b/.dumi/theme/builtins/InstallDependencies/index.tsx index 93b5127e..d32ae8b1 100644 --- a/.dumi/theme/builtins/InstallDependencies/index.tsx +++ b/.dumi/theme/builtins/InstallDependencies/index.tsx @@ -1,4 +1,5 @@ -import { ConfigProvider, Tabs } from 'antd'; +import { XProvider } from '@ant-design/x'; +import { Tabs } from 'antd'; import SourceCode from 'dumi/theme-default/builtins/SourceCode'; import type { Tab } from 'rc-tabs/lib/interface'; import React from 'react'; @@ -45,9 +46,9 @@ const InstallDependencies: React.FC = (props) => { ].filter((item) => item.children); return ( - + - + ); }; diff --git a/.dumi/theme/layouts/DocLayout/index.tsx b/.dumi/theme/layouts/DocLayout/index.tsx index c3b01aa5..d650d1c6 100644 --- a/.dumi/theme/layouts/DocLayout/index.tsx +++ b/.dumi/theme/layouts/DocLayout/index.tsx @@ -3,7 +3,7 @@ import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; -import ConfigProvider from 'antd/es/config-provider'; +import { XProvider } from '@ant-design/x'; import zhCN from 'antd/es/locale/zh_CN'; import { Helmet, useOutlet, useSiteData } from 'dumi'; import React, { useContext, useEffect, useLayoutEffect, useRef } from 'react'; @@ -106,11 +106,11 @@ const DocLayout: React.FC = () => { content="https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png" /> - +
    {content} - + ); }; diff --git a/.dumi/theme/slots/Header/Navigation.tsx b/.dumi/theme/slots/Header/Navigation.tsx index 4fa2a9b7..390ae5bc 100644 --- a/.dumi/theme/slots/Header/Navigation.tsx +++ b/.dumi/theme/slots/Header/Navigation.tsx @@ -185,16 +185,16 @@ const HeaderNavigation: React.FC = (props) => { ), key: 'docs/resources', }, - isZhCN - ? { - key: 'mirror', - label: ( - - 国内镜像 - - ), - } - : null, + // isZhCN + // ? { + // key: 'mirror', + // label: ( + // + // 国内镜像 + // + // ), + // } + // : null, ...(additional ?? []), ].filter(Boolean); diff --git a/.dumi/theme/slots/Header/index.tsx b/.dumi/theme/slots/Header/index.tsx index c9e69be2..148236c0 100644 --- a/.dumi/theme/slots/Header/index.tsx +++ b/.dumi/theme/slots/Header/index.tsx @@ -1,5 +1,6 @@ import { GithubOutlined, MenuOutlined } from '@ant-design/icons'; -import { Alert, Col, ConfigProvider, Popover, Row, Select } from 'antd'; +import { XProvider } from '@ant-design/x'; +import { Alert, Col, Popover, Row, Select } from 'antd'; import { createStyles } from 'antd-style'; import classNames from 'classnames'; import dayjs from 'dayjs'; @@ -369,7 +370,7 @@ const Header: React.FC = () => { )} {isZhCN && bannerVisible && ( - { showIcon={false} onClose={onBannerClose} /> - + )}
    diff --git a/.dumi/theme/slots/Sidebar/index.tsx b/.dumi/theme/slots/Sidebar/index.tsx index 7257e4cb..171ecddf 100644 --- a/.dumi/theme/slots/Sidebar/index.tsx +++ b/.dumi/theme/slots/Sidebar/index.tsx @@ -1,4 +1,5 @@ -import { Col, ConfigProvider, Menu } from 'antd'; +import { XProvider } from '@ant-design/x'; +import { Col, Menu } from 'antd'; import { createStyles, useTheme } from 'antd-style'; import { useSidebarData } from 'dumi'; import MobileMenu from 'rc-drawer'; @@ -121,7 +122,7 @@ const Sidebar: React.FC = () => { const { colorBgContainer } = useTheme(); const menuChild = ( - { selectedKeys={[selectedKey]} defaultOpenKeys={sidebarData?.map(({ title }) => title!).filter(Boolean)} /> - + ); return isMobile ? ( diff --git a/.dumi/theme/themeConfig.ts b/.dumi/theme/themeConfig.ts index 313944ad..60ac9806 100644 --- a/.dumi/theme/themeConfig.ts +++ b/.dumi/theme/themeConfig.ts @@ -1,6 +1,3 @@ -const chineseMirror = - typeof location !== 'undefined' && location.hostname.includes('.antgroup.com'); - export default { categoryOrder: { 'Ant Design': 0, @@ -45,14 +42,5 @@ export default { 模板文档: 3, 'Template Document': 3, }, - docVersions: { - '4.x': chineseMirror ? 'https://4x-ant-design.antgroup.com' : 'https://4x.ant.design', - '3.x': 'https://3x.ant.design', - '2.x': 'https://2x.ant.design', - '1.x': 'https://1x.ant.design', - '0.12.x': 'https://012x.ant.design', - '0.11.x': 'https://011x.ant.design', - '0.10.x': 'https://010x.ant.design', - '0.9.x': 'https://09x.ant.design', - }, + docVersions: {}, }; diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 33090255..c8e1ddb2 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -16,6 +16,36 @@ tag: vVERSION --- +## 1.0.0-alpha.1 + +`2024-09-10` + +### 🚀 Features + +- 🔥 feat: Suggestion 建议组件 by [@ONLY-yours](/~https://github.com/ONLY-yours) in [#87](/~https://github.com/ant-design/x/pull/87) + +### 🐛 Fixes + +- 🐛 fix: change the Sender restProps type by [@ONLY-yours](/~https://github.com/ONLY-yours) in [#101](/~https://github.com/ant-design/x/pull/101) +- 🛠 fix: bun install by [@afc163](/~https://github.com/afc163) in [#111](/~https://github.com/ant-design/x/pull/111) + +### 🛠 Refactors + +- 🛠 chore: add layer support by [@zombieJ](/~https://github.com/zombieJ) in [#118](/~https://github.com/ant-design/x/pull/118) +- 🛠 chore: speed up workflows by [@afc163](/~https://github.com/afc163) in [#119](/~https://github.com/ant-design/x/pull/119) +- 🛠 chore(deps-dev): bump the dev-dependencies group with 5 updates by [@dependabot](/~https://github.com/dependabot) in [#120](/~https://github.com/ant-design/x/pull/120) +- 🛠 chore: clean up README.md by [@afc163](/~https://github.com/afc163) in [#102](/~https://github.com/ant-design/x/pull/102) +- 🛠 chore: add issue templates by [@afc163](/~https://github.com/afc163) in [#103](/~https://github.com/ant-design/x/pull/103) +- 🛠 chore: add bun.lockb by [@afc163](/~https://github.com/afc163) in [#108](/~https://github.com/ant-design/x/pull/108) +- 🛠 chore: Delete index-style-only.js by [@afc163](/~https://github.com/afc163) in [#106](/~https://github.com/ant-design/x/pull/106) +- 🛠 chore: Update main.yml by [@afc163](/~https://github.com/afc163) in [#105](/~https://github.com/ant-design/x/pull/105) +- 🛠 chore: Update package.json by [@afc163](/~https://github.com/afc163) in [#110](/~https://github.com/ant-design/x/pull/110) + +### 📖 Documentation + +- 📖 docs: Update README.md by [@afc163](/~https://github.com/afc163) in [#104](/~https://github.com/ant-design/x/pull/104) +- 📖 docs: Update codecov badge by [@afc163](/~https://github.com/afc163) in [#112](/~https://github.com/ant-design/x/pull/112) + ## 1.0.0-alpha.0 `2024-09-05` diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 086dbfe3..3fd915d6 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -15,6 +15,36 @@ tag: vVERSION --- +## 1.0.0-alpha.1 + +`2024-09-10` + +### 🚀 新特性 + +- 🔥 新增:`Suggestion` 建议组件,由 [@ONLY-yours](/~https://github.com/ONLY-yours) 完成 [#87](/~https://github.com/ant-design/x/pull/87) + +### 🐛 修复 + +- 🐛 修复:更改 `Sender` 的 `restProps` 类型,由 [@ONLY-yours](/~https://github.com/ONLY-yours) 完成 [#101](/~https://github.com/ant-design/x/pull/101) +- 🛠 修复:`bun install` 问题,由 [@afc163](/~https://github.com/afc163) 完成 [#111](/~https://github.com/ant-design/x/pull/111) + +### 🛠 重构 + +- 🛠 重构:添加层级支持,由 [@zombieJ](/~https://github.com/zombieJ) 完成 [#118](/~https://github.com/ant-design/x/pull/118) +- 🛠 重构:加速工作流,由 [@afc163](/~https://github.com/afc163) 完成 [#119](/~https://github.com/ant-design/x/pull/119) +- 🛠 重构:升级开发依赖的 5 个更新,由 [@dependabot](/~https://github.com/dependabot) 完成 [#120](/~https://github.com/ant-design/x/pull/120) +- 🛠 重构:清理 `README.md`,由 [@afc163](/~https://github.com/afc163) 完成 [#102](/~https://github.com/ant-design/x/pull/102) +- 🛠 重构:添加 issue 模板,由 [@afc163](/~https://github.com/afc163) 完成 [#103](/~https://github.com/ant-design/x/pull/103) +- 🛠 重构:添加 `bun.lockb`,由 [@afc163](/~https://github.com/afc163) 完成 [#108](/~https://github.com/ant-design/x/pull/108) +- 🛠 删除 `index-style-only.js`,由 [@afc163](/~https://github.com/afc163) 完成 [#106](/~https://github.com/ant-design/x/pull/106) +- 🛠 重构:更新 `main.yml`,由 [@afc163](/~https://github.com/afc163) 完成 [#105](/~https://github.com/ant-design/x/pull/105) +- 🛠 重构:更新 `package.json`,由 [@afc163](/~https://github.com/afc163) 完成 [#110](/~https://github.com/ant-design/x/pull/110) + +### 📖 文档 + +- 📖 文档:更新 `README.md`,由 [@afc163](/~https://github.com/afc163) 完成 [#104](/~https://github.com/ant-design/x/pull/104) +- 📖 文档:更新 `codecov` 徽章,由 [@afc163](/~https://github.com/afc163) 完成 [#112](/~https://github.com/ant-design/x/pull/112) + ## 1.0.0-alpha.0 `2024-09-05` diff --git a/README-zh_CN.md b/README-zh_CN.md index 30c812eb..2e0aadc5 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -6,13 +6,9 @@ 打造 AI 驱动界面,一键接入智能对话组件与 API 服务。 -[![CI status][github-action-image]][github-action-url] -[![codecov][codecov-image]][codecov-url] -[![NPM version][npm-image]][npm-url] -[![NPM downloads][download-image]][download-url] +[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] -[Changelog](./CHANGELOG.zh-US.md) · [Report Bug][github-issues-bug-report] · [Request Feature][github-issues-feature-request] · English · [中文](./README-zh_CN.md) -[更新日志](./CHANGELOG.zh-CN.md) · [报告问题][github-issues-bug-report] · [特性需求][github-issues-feature-request] · [English](./README.md) · 中文 +[Changelog](./CHANGELOG.zh-US.md) · [Report Bug][github-issues-bug-report] · [Request Feature][github-issues-feature-request] · English · [中文](./README-zh_CN.md) [更新日志](./CHANGELOG.zh-CN.md) · [报告问题][github-issues-bug-report] · [特性需求][github-issues-feature-request] · [English](./README.md) · 中文 [npm-image]: http://img.shields.io/npm/v/@ant-design/x.svg?style=flat-square [npm-url]: http://npmjs.org/package/@ant-design/x @@ -28,8 +24,8 @@ [help-wanted-url]: /~https://github.com/ant-design/x/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 [twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design [twitter-url]: https://twitter.com/AntDesignUI -[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/@ant-design/x/dist/antd-x.min.js?label=antd-x.min.js&compression=gzip&style=flat-square -[unpkg-js-url]: https://unpkg.com/browse/@ant-design/x/dist/antd-x.min.js +[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/@ant-design/x/dist/antdx.min.js?label=antdx.min.js&compression=gzip&style=flat-square +[unpkg-js-url]: https://unpkg.com/browse/@ant-design/x/dist/antdx.min.js [bundlephobia-image]: https://badgen.net/bundlephobia/minzip/@ant-design/x?style=flat-square [bundlephobia-url]: https://bundlephobia.com/package/@ant-design/x [issues-helper-image]: https://img.shields.io/badge/using-actions--cool-blue?style=flat-square @@ -40,6 +36,7 @@ [dumi-url]: /~https://github.com/umijs/dumi [github-issues-bug-report]: /~https://github.com/ant-design/x/issues/new?template=bug-report.yml [github-issues-feature-request]: /~https://github.com/ant-design/x/issues/new?template=bug-feature-request.yml + ## 📦 安装 @@ -62,9 +59,7 @@ pnpm add @ant-design/x import React from 'react'; import { Bubble } from '@ant-design/x'; -const App = () => ( - -); +const App = () => ; export default App; ``` diff --git a/README.md b/README.md index 7bf31f93..bc9c4a39 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,7 @@ Crafting AI-driven interfaces with React, seamlessly integrating smart chat components and API services at your fingertips. -[![CI status][github-action-image]][github-action-url] -[![codecov][codecov-image]][codecov-url] -[![NPM version][npm-image]][npm-url] -[![NPM downloads][download-image]][download-url] +[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] [Changelog](./CHANGELOG.en-US.md) · [Report Bug][github-issues-bug-report] · [Request Feature][github-issues-feature-request] · English · [中文](./README-zh_CN.md) @@ -27,8 +24,8 @@ Crafting AI-driven interfaces with React, seamlessly integrating smart chat comp [help-wanted-url]: /~https://github.com/ant-design/x/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 [twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design [twitter-url]: https://twitter.com/AntDesignUI -[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/@ant-design/x/dist/antd-x.min.js?label=antd-x.min.js&compression=gzip&style=flat-square -[unpkg-js-url]: https://unpkg.com/browse/@ant-design/x/dist/antd-x.min.js +[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/@ant-design/x/dist/antdx.min.js?label=antdx.min.js&compression=gzip&style=flat-square +[unpkg-js-url]: https://unpkg.com/browse/@ant-design/x/dist/antdx.min.js [bundlephobia-image]: https://badgen.net/bundlephobia/minzip/@ant-design/x?style=flat-square [bundlephobia-url]: https://bundlephobia.com/package/@ant-design/x [issues-helper-image]: https://img.shields.io/badge/using-actions--cool-blue?style=flat-square @@ -39,6 +36,7 @@ Crafting AI-driven interfaces with React, seamlessly integrating smart chat comp [dumi-url]: /~https://github.com/umijs/dumi [github-issues-bug-report]: /~https://github.com/ant-design/x/issues/new?template=bug-report.yml [github-issues-feature-request]: /~https://github.com/ant-design/x/issues/new?template=bug-feature-request.yml + ## 📦 Install @@ -61,9 +59,7 @@ pnpm add @ant-design/x import React from 'react'; import { Bubble } from '@ant-design/x'; -const App = () => ( - -); +const App = () => ; export default App; ``` diff --git a/components/_util/hooks/use-x-component-config.ts b/components/_util/hooks/use-x-component-config.ts new file mode 100644 index 00000000..2250ae79 --- /dev/null +++ b/components/_util/hooks/use-x-component-config.ts @@ -0,0 +1,27 @@ +import React from 'react'; +import XProviderContext from '../../x-provider/context'; + +import type { XComponentStyleConfig, XComponentsConfig } from '../../x-provider/context'; + +const defaultXComponentStyleConfig: XComponentStyleConfig = { + classNames: {}, + styles: {}, + className: '', + style: {}, +}; + +const useXComponentConfig = ( + component: C, +): Required[C] & XComponentStyleConfig => { + const xProviderContext = React.useContext(XProviderContext); + + return React.useMemo( + () => ({ + ...defaultXComponentStyleConfig, + ...xProviderContext[component], + }), + [xProviderContext[component]], + ); +}; + +export default useXComponentConfig; diff --git a/components/_util/motion.ts b/components/_util/motion.ts index 8d3d5257..edfb18b5 100644 --- a/components/_util/motion.ts +++ b/components/_util/motion.ts @@ -1,6 +1,6 @@ import type { CSSMotionProps, MotionEndEventHandler, MotionEventHandler } from 'rc-motion'; import type { MotionEvent } from 'rc-motion/lib/interface'; -import { defaultPrefixCls } from '../config-provider'; +import { defaultPrefixCls } from '../x-provider'; // ================== Collapse Motion ================== const getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 }); diff --git a/components/bubble/Bubble.tsx b/components/bubble/Bubble.tsx index ebba79f7..9c0229af 100644 --- a/components/bubble/Bubble.tsx +++ b/components/bubble/Bubble.tsx @@ -1,13 +1,14 @@ -import React from 'react'; import classnames from 'classnames'; +import React from 'react'; +import { Avatar } from 'antd'; +import useXComponentConfig from '../_util/hooks/use-x-component-config'; +import { useXProviderContext } from '../x-provider'; +import useTypedEffect from './hooks/useTypedEffect'; +import useTypingConfig from './hooks/useTypingConfig'; import type { BubbleProps } from './interface'; import Loading from './loading'; import useStyle from './style'; -import useTypedEffect from './hooks/useTypedEffect'; -import { Avatar } from 'antd'; -import useTypingConfig from './hooks/useTypingConfig'; -import { useConfigContext } from '../config-provider'; export interface BubbleRef { nativeElement: HTMLElement; @@ -25,8 +26,8 @@ const Bubble: React.ForwardRefRenderFunction = (props, r className, rootClassName, style, - classNames, - styles, + classNames = {}, + styles = {}, avatar, placement = 'start', loading = false, @@ -46,10 +47,13 @@ const Bubble: React.ForwardRefRenderFunction = (props, r })); // ============================ Prefix ============================ - const { direction, getPrefixCls } = useConfigContext(); + const { direction, getPrefixCls } = useXProviderContext(); const prefixCls = getPrefixCls('bubble', customizePrefixCls); + // ===================== Component Config ========================= + const contextConfig = useXComponentConfig('bubble'); + // ============================ Typing ============================ const [typingEnabled, typingStep, typingInterval] = useTypingConfig(typing); @@ -68,9 +72,10 @@ const Bubble: React.ForwardRefRenderFunction = (props, r const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls); const mergedCls = classnames( - className, - rootClassName, prefixCls, + rootClassName, + contextConfig.className, + className, hashId, cssVarCls, `${prefixCls}-${placement}`, @@ -88,12 +93,27 @@ const Bubble: React.ForwardRefRenderFunction = (props, r // ============================ Render ============================ return wrapCSSVar( -
    +
    {/* Avatar */} {avatar && (
    {avatarNode}
    @@ -101,8 +121,15 @@ const Bubble: React.ForwardRefRenderFunction = (props, r {/* Content */}
    {loading ? : mergedContent}
    diff --git a/components/bubble/BubbleList.tsx b/components/bubble/BubbleList.tsx index 7d29eaa3..86c3c34b 100644 --- a/components/bubble/BubbleList.tsx +++ b/components/bubble/BubbleList.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; -import pickAttrs from 'rc-util/lib/pickAttrs'; -import { useConfigContext } from '../config-provider'; import classNames from 'classnames'; -import type { BubbleProps } from './interface'; +import { useEvent } from 'rc-util'; +import pickAttrs from 'rc-util/lib/pickAttrs'; +import * as React from 'react'; +import { useXProviderContext } from '../x-provider'; import Bubble, { BubbleContext } from './Bubble'; import type { BubbleRef } from './Bubble'; -import useStyle from './style'; -import { useEvent } from 'rc-util'; import useListData from './hooks/useListData'; +import type { BubbleProps } from './interface'; +import useStyle from './style'; export interface BubbleListRef { nativeElement: HTMLDivElement; @@ -57,7 +57,7 @@ const BubbleList: React.ForwardRefRenderFunction const bubbleRefs = React.useRef>({}); // ============================ Prefix ============================ - const { getPrefixCls } = useConfigContext(); + const { getPrefixCls } = useXProviderContext(); const prefixCls = getPrefixCls('bubble', customizePrefixCls); const listPrefixCls = `${prefixCls}-list`; diff --git a/components/bubble/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/bubble/__tests__/__snapshots__/demo-extend.test.ts.snap index a5daabaa..1e7b659f 100644 --- a/components/bubble/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/bubble/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -2,16 +2,16 @@ exports[`renders components/bubble/demo/avatar-and-placement.tsx extend context correctly 1`] = `