From 5369aa086b0f65aea523c4e88c3f38d63d36980f Mon Sep 17 00:00:00 2001 From: buqiyuan <1743369777@qq.com> Date: Mon, 6 Feb 2023 00:39:08 +0800 Subject: [PATCH 1/3] refactor(empty): less to cssinjs --- components/empty/empty.tsx | 99 +++++++++------ components/empty/index.tsx | 103 ++++++++-------- components/empty/simple.tsx | 48 ++++--- components/empty/style/index.less | 151 ----------------------- components/empty/style/index.ts | 80 ++++++++++++ components/empty/style/index.tsx | 2 - components/empty/style/rtl.less | 10 -- components/theme/interface/components.ts | 4 +- 8 files changed, 226 insertions(+), 271 deletions(-) delete mode 100644 components/empty/style/index.less create mode 100644 components/empty/style/index.ts delete mode 100644 components/empty/style/index.tsx delete mode 100644 components/empty/style/rtl.less diff --git a/components/empty/empty.tsx b/components/empty/empty.tsx index a4853758b5..941da7ea76 100644 --- a/components/empty/empty.tsx +++ b/components/empty/empty.tsx @@ -1,44 +1,71 @@ -import useConfigInject from '../config-provider/hooks/useConfigInject'; +import { useToken } from '../theme/internal'; +import { TinyColor } from '@ctrl/tinycolor'; +import type { CSSProperties } from 'vue'; +import { defineComponent } from 'vue'; -const Empty = () => { - const { getPrefixCls } = useConfigInject('empty', {}); - const prefixCls = getPrefixCls('empty-img-default'); +const Empty = defineComponent({ + setup() { + const [, token] = useToken(); - return ( - - - - - - - + const bgColor = new TinyColor(token.value.colorBgBase); + let themeStyle: CSSProperties = {}; + + // Dark Theme need more dark of this + if (bgColor.toHsl().l < 0.5) { + themeStyle = { + opacity: 0.65, + }; + } + + return () => ( + + + + + + + + + + + + + - - - - - - - - ); -}; + + ); + }, +}); Empty.PRESENTED_IMAGE_DEFAULT = true; diff --git a/components/empty/index.tsx b/components/empty/index.tsx index 4565a7b85d..2f1f4f93e8 100644 --- a/components/empty/index.tsx +++ b/components/empty/index.tsx @@ -1,4 +1,5 @@ -import type { CSSProperties, FunctionalComponent, PropType } from 'vue'; +import { defineComponent } from 'vue'; +import type { App, CSSProperties, Plugin, PropType } from 'vue'; import classNames from '../_util/classNames'; import LocaleReceiver from '../locale-provider/LocaleReceiver'; import DefaultEmptyImg from './empty'; @@ -9,6 +10,8 @@ import type { VueNode } from '../_util/type'; import { withInstall } from '../_util/type'; import useConfigInject from '../config-provider/hooks/useConfigInject'; +import useStyle from './style'; + const defaultEmptyImg = ; const simpleEmptyImg = ; @@ -25,61 +28,59 @@ export interface EmptyProps { description?: VueNode; } -interface EmptyType extends FunctionalComponent { - displayName: string; - PRESENTED_IMAGE_DEFAULT: VueNode; - PRESENTED_IMAGE_SIMPLE: VueNode; -} - -const Empty: EmptyType = (props, { slots = {}, attrs }) => { - const { direction, prefixCls: prefixClsRef } = useConfigInject('empty', props); - const prefixCls = prefixClsRef.value; +const Empty = defineComponent({ + name: 'AEmpty', + setup(props, { slots = {}, attrs }) { + const { direction, prefixCls: prefixClsRef } = useConfigInject('empty', props); + const prefixCls = prefixClsRef.value; - const { - image = defaultEmptyImg, - description = slots.description?.() || undefined, - imageStyle, - class: className = '', - ...restProps - } = { ...props, ...attrs }; + const [wrapSSR, hashId] = useStyle(prefixClsRef); - return ( - { - const des = typeof description !== 'undefined' ? description : locale.description; - const alt = typeof des === 'string' ? des : 'empty'; - let imageNode: EmptyProps['image'] = null; + const { + image = defaultEmptyImg, + description = slots.description?.() || undefined, + imageStyle, + class: className = '', + ...restProps + } = { ...props, ...attrs }; - if (typeof image === 'string') { - imageNode = {alt}; - } else { - imageNode = image; - } + return () => + wrapSSR( + { + const des = typeof description !== 'undefined' ? description : locale.description; + const alt = typeof des === 'string' ? des : 'empty'; + let imageNode: EmptyProps['image'] = null; - return ( -
-
- {imageNode} -
- {des &&

{des}

} - {slots.default && ( -
{filterEmpty(slots.default())}
- )} -
- ); - }} - /> - ); -}; + if (typeof image === 'string') { + imageNode = {alt}; + } else { + imageNode = image; + } -Empty.displayName = 'AEmpty'; + return ( +
+
+ {imageNode} +
+ {des &&

{des}

} + {slots.default && ( +
{filterEmpty(slots.default())}
+ )} +
+ ); + }} + />, + ); + }, +}); Empty.PRESENTED_IMAGE_DEFAULT = defaultEmptyImg; Empty.PRESENTED_IMAGE_SIMPLE = simpleEmptyImg; diff --git a/components/empty/simple.tsx b/components/empty/simple.tsx index 2be63b3a00..e4680b01d1 100644 --- a/components/empty/simple.tsx +++ b/components/empty/simple.tsx @@ -1,25 +1,35 @@ -import useConfigInject from '../config-provider/hooks/useConfigInject'; +import { TinyColor } from '@ctrl/tinycolor'; +import { computed, defineComponent } from 'vue'; +import { useToken } from '../theme/internal'; -const Simple = () => { - const { getPrefixCls } = useConfigInject('empty', {}); - const prefixCls = getPrefixCls('empty-img-simple'); +const Simple = defineComponent({ + setup() { + const [, token] = useToken(); - return ( - - - - - - + const { colorFill, colorFillTertiary, colorFillQuaternary, colorBgContainer } = token.value; + + const color = computed(() => ({ + borderColor: new TinyColor(colorFill).onBackground(colorBgContainer).toHexString(), + shadowColor: new TinyColor(colorFillTertiary).onBackground(colorBgContainer).toHexString(), + contentColor: new TinyColor(colorFillQuaternary).onBackground(colorBgContainer).toHexString(), + })); + + return () => ( + + + + + + + - - - ); -}; + + ); + }, +}); Simple.PRESENTED_IMAGE_SIMPLE = true; export default Simple; diff --git a/components/empty/style/index.less b/components/empty/style/index.less deleted file mode 100644 index c696372c13..0000000000 --- a/components/empty/style/index.less +++ /dev/null @@ -1,151 +0,0 @@ -@import '../../style/themes/index'; -@import '../../style/mixins/index'; - -@empty-prefix-cls: ~'@{ant-prefix}-empty'; -@empty-img-prefix-cls: ~'@{ant-prefix}-empty-img'; - -.@{empty-prefix-cls} { - margin: 0 8px; - font-size: @empty-font-size; - line-height: @line-height-base; - text-align: center; - - &-image { - height: 100px; - margin-bottom: 8px; - - img { - height: 100%; - } - - svg { - height: 100%; - margin: auto; - } - } - - &-footer { - margin-top: 16px; - } - - // antd internal empty style - &-normal { - margin: 32px 0; - color: @disabled-color; - - .@{empty-prefix-cls}-image { - height: 40px; - } - } - - &-small { - margin: 8px 0; - color: @disabled-color; - - .@{empty-prefix-cls}-image { - height: 35px; - } - } -} - -.@{empty-img-prefix-cls}-default { - // not support the definition because the less variables have no meaning - & when (@theme = dark) { - &-ellipse { - fill: @white; - fill-opacity: 0.08; - } - - &-path { - &-1 { - fill: #262626; - } - - &-2 { - fill: url('#linearGradient-1'); - } - - &-3 { - fill: #595959; - } - - &-4 { - fill: #434343; - } - - &-5 { - fill: #595959; - } - } - - &-g { - fill: #434343; - } - } - & when not (@theme = dark) { - &-ellipse { - fill: #f5f5f5; - fill-opacity: 0.8; - } - - &-path { - &-1 { - fill: #aeb8c2; - } - - &-2 { - fill: url('#linearGradient-1'); - } - - &-3 { - fill: #f5f5f7; - } - - &-4 { - fill: #dce0e6; - } - - &-5 { - fill: #dce0e6; - } - } - - &-g { - fill: @white; - } - } -} - -.@{empty-img-prefix-cls}-simple { - // not support the definition because the less variables have no meaning - & when (@theme = dark) { - &-ellipse { - fill: @white; - fill-opacity: 0.08; - } - - &-g { - stroke: #434343; - } - - &-path { - fill: #262626; - stroke: #434343; - } - } - & when not (@theme = dark) { - &-ellipse { - fill: #f5f5f5; - } - - &-g { - stroke: #d9d9d9; - } - - &-path { - fill: #fafafa; - } - } -} - -@import './rtl'; diff --git a/components/empty/style/index.ts b/components/empty/style/index.ts new file mode 100644 index 0000000000..f7d32ded47 --- /dev/null +++ b/components/empty/style/index.ts @@ -0,0 +1,80 @@ +import type { CSSObject } from '../../_util/cssinjs'; +import type { FullToken, GenerateStyle } from '../../theme/internal'; +import { genComponentStyleHook, mergeToken } from '../../theme/internal'; + +/** Component only token. Which will handle additional calculation of alias token */ +export interface ComponentToken {} + +interface EmptyToken extends FullToken<'Empty'> { + emptyImgCls: string; + emptyImgHeight: number; + emptyImgHeightSM: number; + emptyImgHeightMD: number; +} + +// ============================== Shared ============================== +const genSharedEmptyStyle: GenerateStyle = (token): CSSObject => { + const { componentCls, margin, marginXS, marginXL, fontSize, lineHeight } = token; + + return { + [componentCls]: { + marginInline: marginXS, + fontSize, + lineHeight, + textAlign: 'center', + + // 原来 &-image 没有父子结构,现在为了外层承担我们的hashId,改成父子结果 + [`${componentCls}-image`]: { + height: token.emptyImgHeight, + marginBottom: marginXS, + opacity: token.opacityImage, + + img: { + height: '100%', + }, + + svg: { + height: '100%', + margin: 'auto', + }, + }, + + // 原来 &-footer 没有父子结构,现在为了外层承担我们的hashId,改成父子结果 + [`${componentCls}-footer`]: { + marginTop: margin, + }, + + '&-normal': { + marginBlock: marginXL, + color: token.colorTextDisabled, + + [`${componentCls}-image`]: { + height: token.emptyImgHeightMD, + }, + }, + + '&-small': { + marginBlock: marginXS, + color: token.colorTextDisabled, + + [`${componentCls}-image`]: { + height: token.emptyImgHeightSM, + }, + }, + }, + }; +}; + +// ============================== Export ============================== +export default genComponentStyleHook('Empty', token => { + const { componentCls, controlHeightLG } = token; + + const emptyToken: EmptyToken = mergeToken(token, { + emptyImgCls: `${componentCls}-img`, + emptyImgHeight: controlHeightLG * 2.5, + emptyImgHeightMD: controlHeightLG, + emptyImgHeightSM: controlHeightLG * 0.875, + }); + + return [genSharedEmptyStyle(emptyToken)]; +}); diff --git a/components/empty/style/index.tsx b/components/empty/style/index.tsx deleted file mode 100644 index 3a3ab0de59..0000000000 --- a/components/empty/style/index.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import '../../style/index.less'; -import './index.less'; diff --git a/components/empty/style/rtl.less b/components/empty/style/rtl.less deleted file mode 100644 index bf3f6c46e7..0000000000 --- a/components/empty/style/rtl.less +++ /dev/null @@ -1,10 +0,0 @@ -@import '../../style/themes/index'; -@import '../../style/mixins/index'; - -@empty-prefix-cls: ~'@{ant-prefix}-empty'; - -.@{empty-prefix-cls} { - &-rtl { - direction: rtl; - } -} diff --git a/components/theme/interface/components.ts b/components/theme/interface/components.ts index 997061b133..cfe3bb90dc 100644 --- a/components/theme/interface/components.ts +++ b/components/theme/interface/components.ts @@ -14,7 +14,7 @@ import type { ComponentToken as ButtonComponentToken } from '../../button/style' import type { ComponentToken as DividerComponentToken } from '../../divider/style'; import type { ComponentToken as DropdownComponentToken } from '../../dropdown/style'; // import type { ComponentToken as DrawerComponentToken } from '../../drawer/style'; -// import type { ComponentToken as EmptyComponentToken } from '../../empty/style'; +import type { ComponentToken as EmptyComponentToken } from '../../empty/style'; // import type { ComponentToken as ImageComponentToken } from '../../image/style'; // import type { ComponentToken as InputNumberComponentToken } from '../../input-number/style'; // import type { ComponentToken as LayoutComponentToken } from '../../layout/style'; @@ -69,7 +69,7 @@ export interface ComponentTokenMap { Divider?: DividerComponentToken; // Drawer?: DrawerComponentToken; Dropdown?: DropdownComponentToken; - // Empty?: EmptyComponentToken; + Empty?: EmptyComponentToken; // FloatButton?: FloatButtonComponentToken; Form?: {}; Grid?: {}; From e9cca28817c9a9659e29bb329817ad0385b50132 Mon Sep 17 00:00:00 2001 From: buqiyuan <1743369777@qq.com> Date: Mon, 6 Feb 2023 00:45:11 +0800 Subject: [PATCH 2/3] chore: remove unuse code --- components/empty/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/empty/index.tsx b/components/empty/index.tsx index 2f1f4f93e8..29f1688b1d 100644 --- a/components/empty/index.tsx +++ b/components/empty/index.tsx @@ -1,5 +1,5 @@ import { defineComponent } from 'vue'; -import type { App, CSSProperties, Plugin, PropType } from 'vue'; +import type { CSSProperties, PropType } from 'vue'; import classNames from '../_util/classNames'; import LocaleReceiver from '../locale-provider/LocaleReceiver'; import DefaultEmptyImg from './empty'; From 57b3e9eadffab9da914267082338ed4845224349 Mon Sep 17 00:00:00 2001 From: buqiyuan <1743369777@qq.com> Date: Tue, 7 Feb 2023 00:25:59 +0800 Subject: [PATCH 3/3] fix: reactivity lose --- components/empty/empty.tsx | 22 ++++++++++--------- components/empty/index.tsx | 44 ++++++++++++++++++++----------------- components/empty/simple.tsx | 16 +++++++++----- 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/components/empty/empty.tsx b/components/empty/empty.tsx index 941da7ea76..090326bf21 100644 --- a/components/empty/empty.tsx +++ b/components/empty/empty.tsx @@ -1,25 +1,27 @@ import { useToken } from '../theme/internal'; import { TinyColor } from '@ctrl/tinycolor'; import type { CSSProperties } from 'vue'; -import { defineComponent } from 'vue'; +import { defineComponent, computed } from 'vue'; const Empty = defineComponent({ setup() { const [, token] = useToken(); - const bgColor = new TinyColor(token.value.colorBgBase); - let themeStyle: CSSProperties = {}; + const themeStyle = computed(() => { + const bgColor = new TinyColor(token.value.colorBgBase); - // Dark Theme need more dark of this - if (bgColor.toHsl().l < 0.5) { - themeStyle = { - opacity: 0.65, - }; - } + // Dark Theme need more dark of this + if (bgColor.toHsl().l < 0.5) { + return { + opacity: 0.65, + }; + } + return {}; + }); return () => ( ({ + prefixCls: String, + class: PropTypes.any, + style: [String, Object] as PropType, + imageStyle: Object as PropType, + image: PropTypes.any, + description: PropTypes.any, +}); + +export type EmptyProps = Partial>>; const Empty = defineComponent({ name: 'AEmpty', + inheritAttrs: false, + props: emptyProps(), setup(props, { slots = {}, attrs }) { const { direction, prefixCls: prefixClsRef } = useConfigInject('empty', props); - const prefixCls = prefixClsRef.value; const [wrapSSR, hashId] = useStyle(prefixClsRef); - const { - image = defaultEmptyImg, - description = slots.description?.() || undefined, - imageStyle, - class: className = '', - ...restProps - } = { ...props, ...attrs }; + return () => { + const prefixCls = prefixClsRef.value; + const { + image = defaultEmptyImg, + description = slots.description?.() || undefined, + imageStyle, + class: className = '', + ...restProps + } = { ...props, ...attrs }; - return () => - wrapSSR( + return wrapSSR( { @@ -79,6 +82,7 @@ const Empty = defineComponent({ }} />, ); + }; }, }); diff --git a/components/empty/simple.tsx b/components/empty/simple.tsx index e4680b01d1..8ae99ecc8d 100644 --- a/components/empty/simple.tsx +++ b/components/empty/simple.tsx @@ -6,13 +6,17 @@ const Simple = defineComponent({ setup() { const [, token] = useToken(); - const { colorFill, colorFillTertiary, colorFillQuaternary, colorBgContainer } = token.value; + const color = computed(() => { + const { colorFill, colorFillTertiary, colorFillQuaternary, colorBgContainer } = token.value; - const color = computed(() => ({ - borderColor: new TinyColor(colorFill).onBackground(colorBgContainer).toHexString(), - shadowColor: new TinyColor(colorFillTertiary).onBackground(colorBgContainer).toHexString(), - contentColor: new TinyColor(colorFillQuaternary).onBackground(colorBgContainer).toHexString(), - })); + return { + borderColor: new TinyColor(colorFill).onBackground(colorBgContainer).toHexString(), + shadowColor: new TinyColor(colorFillTertiary).onBackground(colorBgContainer).toHexString(), + contentColor: new TinyColor(colorFillQuaternary) + .onBackground(colorBgContainer) + .toHexString(), + }; + }); return () => (