Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(color): @ctrl/tinycolor to color2k #48671

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 2 additions & 3 deletions .dumi/pages/index/components/Theme/index.tsx
Expand Up @@ -6,7 +6,6 @@ import {
HomeOutlined,
QuestionCircleOutlined,
} from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor';
import type { MenuProps } from 'antd';
import {
Breadcrumb,
Expand All @@ -25,6 +24,7 @@ import { createStyles, css, useTheme } from 'antd-style';
import type { Color } from 'antd/es/color-picker';
import { generateColor } from 'antd/es/color-picker/util';
import classNames from 'classnames';
import { parseToRgba } from 'color2k';
import { useLocation } from 'dumi';

import useDark from '../../../../hooks/useDark';
Expand Down Expand Up @@ -290,8 +290,7 @@ const ThemesInfo: Record<THEME, Partial<ThemeData>> = {
const normalize = (value: number) => value / 255;

function rgbToColorMatrix(color: string) {
const rgb = new TinyColor(color).toRgb();
const { r, g, b } = rgb;
const [r, g, b] = parseToRgba(color);

const invertValue = normalize(r) * 100;
const sepiaValue = 100;
Expand Down
37 changes: 17 additions & 20 deletions .dumi/theme/builtins/ColorChunk/index.tsx
@@ -1,38 +1,35 @@
import { TinyColor, type ColorInput } from '@ctrl/tinycolor';
import { createStyles } from 'antd-style';
import * as React from 'react';
import { createStyles } from 'antd-style';
import { toHex } from 'color2k';

interface ColorChunkProps {
children?: React.ReactNode;
value?: ColorInput;
value: string;
}

const useStyle = createStyles(({ token, css }) => ({
codeSpan: css`
padding: 0.2em 0.4em;
font-size: 0.9em;
background: ${token.siteMarkdownCodeBg};
border-radius: ${token.borderRadius}px;
font-family: monospace;
`,
padding: 0.2em 0.4em;
font-size: 0.9em;
background: ${token.siteMarkdownCodeBg};
border-radius: ${token.borderRadius}px;
font-family: monospace;
`,
dot: css`
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
margin-inline-end: 4px;
border: 1px solid ${token.colorSplit};
`,
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
margin-inline-end: 4px;
border: 1px solid ${token.colorSplit};
`,
}));

const ColorChunk: React.FC<ColorChunkProps> = (props) => {
const { styles } = useStyle();
const { value, children } = props;

const dotColor = React.useMemo(() => {
const _color = new TinyColor(value).toHex8String();
return _color.endsWith('ff') ? _color.slice(0, -2) : _color;
}, [value]);
const dotColor = React.useMemo(() => toHex(value || '#fff'), [value]);

return (
<span className={styles.codeSpan}>
Expand Down
11 changes: 6 additions & 5 deletions .dumi/theme/builtins/TokenCompare/index.tsx
@@ -1,10 +1,11 @@
// 用于 color.md 中的颜色对比
import React from 'react';
import classNames from 'classnames';
import { TinyColor } from '@ctrl/tinycolor';
import { Space, theme } from 'antd';
import { createStyles } from 'antd-style';
import tokenMeta from 'antd/es/version/token-meta.json';
import { Space, theme } from 'antd';
import classNames from 'classnames';
import { toHex } from 'color2k';

import useLocale from '../../../hooks/useLocale';

const useStyle = createStyles(({ token, css }) => {
Expand All @@ -29,7 +30,7 @@ const useStyle = createStyles(({ token, css }) => {
display: flex;
align-items: center;
justify-content: center;
color: rgba(0,0,0,0.88);
color: rgba(0, 0, 0, 0.88);
border-right: 1px solid rgba(0, 0, 0, 0.1);
`,

Expand All @@ -54,7 +55,7 @@ const useStyle = createStyles(({ token, css }) => {
});

function color2Rgba(color: string) {
return `#${new TinyColor(color).toHex8().toUpperCase()}`;
return `#${toHex(color).toUpperCase()}`;
}

interface ColorCircleProps {
Expand Down
10 changes: 5 additions & 5 deletions .dumi/theme/common/styles/Markdown.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { TinyColor } from '@ctrl/tinycolor';
import { css, Global } from '@emotion/react';
import { useTheme } from 'antd-style';
import { transparentize } from 'color2k';

const GlobalStyle: React.FC = () => {
const token = useTheme();
Expand Down Expand Up @@ -400,7 +400,7 @@ const GlobalStyle: React.FC = () => {
background: ${demoGridColor};

&:nth-child(2n + 1) {
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHex8String()};
background: ${transparentize(demoGridColor, 0.75)};
}
}

Expand All @@ -416,12 +416,12 @@ const GlobalStyle: React.FC = () => {
}

${antCls}-row .demo-col-1 {
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHexString()};
background: ${transparentize(demoGridColor, 0.75)};
}

${antCls}-row .demo-col-2,
.code-box-demo ${antCls}-row .demo-col-2 {
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHexString()};
background: ${transparentize(demoGridColor, 0.75)};
}

${antCls}-row .demo-col-3,
Expand All @@ -432,7 +432,7 @@ const GlobalStyle: React.FC = () => {

${antCls}-row .demo-col-4,
.code-box-demo ${antCls}-row .demo-col-4 {
background: ${new TinyColor(demoGridColor).setAlpha(0.6).toHexString()};
background: ${transparentize(demoGridColor, 0.6)};
}

${antCls}-row .demo-col-5,
Expand Down
75 changes: 37 additions & 38 deletions .dumi/theme/slots/Footer/index.tsx
@@ -1,3 +1,4 @@
import React, { useContext } from 'react';
import {
AntDesignOutlined,
BgColorsOutlined,
Expand All @@ -12,13 +13,13 @@ import {
UsergroupAddOutlined,
ZhihuOutlined,
} from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor';
import { createStyles } from 'antd-style';
import { onBackground } from 'antd/es/_util/colors';
import getAlphaColor from 'antd/es/theme/util/getAlphaColor';
import { FormattedMessage, Link } from 'dumi';
import RcFooter from 'rc-footer';
import type { FooterColumn } from 'rc-footer/lib/column';
import React, { useContext } from 'react';
import getAlphaColor from 'antd/es/theme/util/getAlphaColor';

import useLocale from '../../../hooks/useLocale';
import useLocation from '../../../hooks/useLocation';
import SiteContext from '../SiteContext';
Expand All @@ -36,53 +37,51 @@ const locales = {
const useStyle = () => {
const { isMobile } = useContext(SiteContext);
return createStyles(({ token, css }) => {
const background = new TinyColor(getAlphaColor('#f0f3fa', '#fff'))
.onBackground(token.colorBgContainer)
.toHexString();
const background = onBackground(getAlphaColor('#f0f3fa', '#fff'), token.colorBgContainer);

return {
holder: css`
background: ${background};
`,
background: ${background};
`,

footer: css`
background: ${background};
color: ${token.colorTextSecondary};
box-shadow: inset 0 106px 36px -116px rgba(0, 0, 0, 0.14);
background: ${background};
color: ${token.colorTextSecondary};
box-shadow: inset 0 106px 36px -116px rgba(0, 0, 0, 0.14);

* {
box-sizing: border-box;
}
* {
box-sizing: border-box;
}

h2,
a {
color: ${token.colorText};
}
h2,
a {
color: ${token.colorText};
}

.rc-footer-column {
margin-bottom: ${isMobile ? 60 : 0}px;
:last-child {
margin-bottom: ${isMobile ? 20 : 0}px;
.rc-footer-column {
margin-bottom: ${isMobile ? 60 : 0}px;
:last-child {
margin-bottom: ${isMobile ? 20 : 0}px;
}
}
}

.rc-footer-item-icon {
top: -1.5px;
}
.rc-footer-item-icon {
top: -1.5px;
}

.rc-footer-container {
max-width: 1208px;
margin-inline: auto;
padding-inline: ${token.marginXXL}px;
}
.rc-footer-container {
max-width: 1208px;
margin-inline: auto;
padding-inline: ${token.marginXXL}px;
}

.rc-footer-bottom {
box-shadow: inset 0 106px 36px -116px rgba(0, 0, 0, 0.14);
.rc-footer-bottom-container {
font-size: ${token.fontSize}px;
.rc-footer-bottom {
box-shadow: inset 0 106px 36px -116px rgba(0, 0, 0, 0.14);
.rc-footer-bottom-container {
font-size: ${token.fontSize}px;
}
}
}
`,
`,
};
})();
};
Expand Down Expand Up @@ -246,7 +245,7 @@ const Footer: React.FC = () => {
en: 'JoinUs',
}),
LinkComponent: Link,
} as unknown as typeof col2['items'][number]);
} as unknown as (typeof col2)['items'][number]);
}

const col3 = {
Expand Down
17 changes: 16 additions & 1 deletion components/_util/colors.ts
@@ -1,3 +1,5 @@
import { parseToRgba, rgba } from 'color2k';

import type { PresetColorKey } from '../theme/interface';
import { PresetColors } from '../theme/interface';

Expand All @@ -14,7 +16,7 @@ export const PresetStatusColorTypes = [

export type PresetColorType = PresetColorKey | InverseColor;

export type PresetStatusColorType = typeof PresetStatusColorTypes[number];
export type PresetStatusColorType = (typeof PresetStatusColorTypes)[number];

/**
* determine if the color keyword belongs to the `Ant Design` {@link PresetColors}.
Expand All @@ -32,3 +34,16 @@ export function isPresetColor(color?: any, includeInverse = true) {
export function isPresetStatusColor(color?: any): color is PresetStatusColorType {
return PresetStatusColorTypes.includes(color);
}

export function onBackground(foreground: string, background: string): string {
const [fr, fg, fb, fa] = parseToRgba(foreground);
const [br, bg, bb, ba] = parseToRgba(background);
const a = fa + ba * (1 - fa);

return rgba(
(fr * fa + br * ba * (1 - fa)) / a,
(fg * fa + bg * ba * (1 - fa)) / a,
(fb * fa + bb * ba * (1 - fa)) / a,
a,
);
}
7 changes: 3 additions & 4 deletions components/theme/util/alias.ts
@@ -1,4 +1,3 @@
import { TinyColor } from '@ctrl/tinycolor';
import type { AliasToken, MapToken, OverrideToken, SeedToken } from '../interface';
import seedToken from '../themes/seed';
import getAlphaColor from './getAlphaColor';
Expand Down Expand Up @@ -166,9 +165,9 @@ export default function formatToken(derivativeToken: RawMergedToken): AliasToken

boxShadowPopoverArrow: '2px 2px 5px rgba(0, 0, 0, 0.05)',
boxShadowCard: `
0 1px 2px -2px ${new TinyColor('rgba(0, 0, 0, 0.16)').toRgbString()},
0 3px 6px 0 ${new TinyColor('rgba(0, 0, 0, 0.12)').toRgbString()},
0 5px 12px 4px ${new TinyColor('rgba(0, 0, 0, 0.09)').toRgbString()}
0 1px 2px -2px rgba(0, 0, 0, 0.16),
0 3px 6px 0 rgba(0, 0, 0, 0.12,
0 5px 12px 4px rgba(0, 0, 0, 0.09)
`,
boxShadowDrawerRight: `
-6px 0 16px 0 rgba(0, 0, 0, 0.08),
Expand Down
10 changes: 5 additions & 5 deletions components/theme/util/getAlphaColor.ts
@@ -1,29 +1,29 @@
import { TinyColor } from '@ctrl/tinycolor';
import { parseToRgba, rgba } from 'color2k';

function isStableColor(color: number): boolean {
return color >= 0 && color <= 255;
}

function getAlphaColor(frontColor: string, backgroundColor: string): string {
const { r: fR, g: fG, b: fB, a: originAlpha } = new TinyColor(frontColor).toRgb();
const [fR, fG, fB, originAlpha] = parseToRgba(frontColor);
if (originAlpha < 1) {
return frontColor;
}

const { r: bR, g: bG, b: bB } = new TinyColor(backgroundColor).toRgb();
const [bR, bG, bB] = parseToRgba(backgroundColor);

for (let fA = 0.01; fA <= 1; fA += 0.01) {
const r = Math.round((fR - bR * (1 - fA)) / fA);
const g = Math.round((fG - bG * (1 - fA)) / fA);
const b = Math.round((fB - bB * (1 - fA)) / fA);
if (isStableColor(r) && isStableColor(g) && isStableColor(b)) {
return new TinyColor({ r, g, b, a: Math.round(fA * 100) / 100 }).toRgbString();
return rgba(r, g, b, Math.round(fA * 100) / 100);
}
}

// fallback
/* istanbul ignore next */
return new TinyColor({ r: fR, g: fG, b: fB, a: 1 }).toRgbString();
return rgba(fR, fG, fB, 1);
}

export default getAlphaColor;
15 changes: 7 additions & 8 deletions components/tour/style/index.ts
@@ -1,16 +1,17 @@
import { TinyColor } from '@ctrl/tinycolor';
import { unit } from '@ant-design/cssinjs';
import { transparentize } from 'color2k';

import { onBackground } from '../../_util/colors';
import { resetComponent } from '../../style';
import type { ArrowOffsetToken } from '../../style/placementArrow';
import getArrowStyle, {
getArrowOffsetToken,
MAX_VERTICAL_CONTENT_RADIUS,
} from '../../style/placementArrow';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import type { ArrowToken } from '../../style/roundedArrow';
import { getArrowToken } from '../../style/roundedArrow';
import { unit } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';

export interface ComponentToken extends ArrowOffsetToken, ArrowToken {
/**
Expand Down Expand Up @@ -270,11 +271,9 @@ const genBaseStyle: GenerateStyle<TourToken> = (token) => {
export const prepareComponentToken: GetDefaultToken<'Tour'> = (token) => ({
zIndexPopup: token.zIndexPopupBase + 70,
closeBtnSize: token.fontSize * token.lineHeight,
primaryPrevBtnBg: new TinyColor(token.colorTextLightSolid).setAlpha(0.15).toRgbString(),
primaryPrevBtnBg: transparentize(token.colorTextLightSolid, 0.15),
closeBtnHoverBg: token.wireframe ? 'transparent' : token.colorFillContent,
primaryNextBtnHoverBg: new TinyColor(token.colorBgTextHover)
.onBackground(token.colorWhite)
.toRgbString(),
primaryNextBtnHoverBg: onBackground(token.colorBgTextHover, token.colorWhite),
...getArrowOffsetToken({
contentRadius: token.borderRadiusLG,
limitVerticalRadius: true,
Expand Down