feat: add theme and style

This commit is contained in:
2023-03-02 07:16:36 +08:00
parent 7b58fb84eb
commit 8ab55b28fe
52 changed files with 3836 additions and 5 deletions

View File

@ -0,0 +1,17 @@
import type { ColorNeutralMapToken } from '../interface'
export interface ColorMap {
1: string
2: string
3: string
4: string
5: string
6: string
7: string
8: string
9: string
10: string
}
export type GenerateColorMap = (baseColor: string) => ColorMap
export type GenerateNeutralColorMap = (bgBaseColor: string, textBaseColor: string) => ColorNeutralMapToken

View File

@ -0,0 +1,19 @@
import type { SeedToken, SizeMapToken } from '../../interface'
export default function genSizeMapToken(token: SeedToken): SizeMapToken {
const { sizeUnit, sizeStep } = token
const compactSizeStep = sizeStep - 2
return {
sizeXXL: sizeUnit * (compactSizeStep + 10),
sizeXL: sizeUnit * (compactSizeStep + 6),
sizeLG: sizeUnit * (compactSizeStep + 2),
sizeMD: sizeUnit * (compactSizeStep + 2),
sizeMS: sizeUnit * (compactSizeStep + 1),
size: sizeUnit * compactSizeStep,
sizeSM: sizeUnit * compactSizeStep,
sizeXS: sizeUnit * (compactSizeStep - 1),
sizeXXS: sizeUnit * (compactSizeStep - 1)
}
}

View File

@ -0,0 +1,27 @@
import type { DerivativeFunc } from '@antd-tiny-vue/cssinjs'
import genControlHeight from '../shared/genControlHeight'
import type { MapToken, SeedToken } from '../../interface'
import defaultAlgorithm from '../default'
import genFontMapToken from '../shared/genFontMapToken'
import genCompactSizeMapToken from './genCompactSizeMapToken'
const derivative: DerivativeFunc<SeedToken, MapToken> = (token, mapToken) => {
const mergedMapToken = mapToken ?? defaultAlgorithm(token)
const fontSize = mergedMapToken.fontSizeSM // Smaller size font-size as base
const controlHeight = mergedMapToken.controlHeight - 4
return {
...mergedMapToken,
...genCompactSizeMapToken(mapToken ?? token),
// font
...genFontMapToken(fontSize),
// controlHeight
controlHeight,
...genControlHeight({ ...mergedMapToken, controlHeight })
}
}
export default derivative

View File

@ -0,0 +1,8 @@
import { TinyColor } from '@ctrl/tinycolor'
export const getAlphaColor = (baseColor: string, alpha: number) => new TinyColor(baseColor).setAlpha(alpha).toRgbString()
export const getSolidColor = (baseColor: string, brightness: number) => {
const instance = new TinyColor(baseColor)
return instance.lighten(brightness).toHexString()
}

View File

@ -0,0 +1,50 @@
import { generate } from '@ant-design/colors'
import type { GenerateColorMap, GenerateNeutralColorMap } from '../ColorMap'
import { getAlphaColor, getSolidColor } from './colorAlgorithm'
export const generateColorPalettes: GenerateColorMap = (baseColor: string) => {
const colors = generate(baseColor, { theme: 'dark' })
return {
1: colors[0],
2: colors[1],
3: colors[2],
4: colors[3],
5: colors[6],
6: colors[5],
7: colors[4],
8: colors[6],
9: colors[5],
10: colors[4]
// 8: colors[9],
// 9: colors[8],
// 10: colors[7],
}
}
export const generateNeutralColorPalettes: GenerateNeutralColorMap = (bgBaseColor: string, textBaseColor: string) => {
const colorBgBase = bgBaseColor || '#000'
const colorTextBase = textBaseColor || '#fff'
return {
colorBgBase,
colorTextBase,
colorText: getAlphaColor(colorTextBase, 0.85),
colorTextSecondary: getAlphaColor(colorTextBase, 0.65),
colorTextTertiary: getAlphaColor(colorTextBase, 0.45),
colorTextQuaternary: getAlphaColor(colorTextBase, 0.25),
colorFill: getAlphaColor(colorTextBase, 0.18),
colorFillSecondary: getAlphaColor(colorTextBase, 0.12),
colorFillTertiary: getAlphaColor(colorTextBase, 0.08),
colorFillQuaternary: getAlphaColor(colorTextBase, 0.04),
colorBgElevated: getSolidColor(colorBgBase, 12),
colorBgContainer: getSolidColor(colorBgBase, 8),
colorBgLayout: getSolidColor(colorBgBase, 0),
colorBgSpotlight: getSolidColor(colorBgBase, 26),
colorBorder: getSolidColor(colorBgBase, 26),
colorBorderSecondary: getSolidColor(colorBgBase, 19)
}
}

View File

@ -0,0 +1,43 @@
import { generate } from '@ant-design/colors'
import type { DerivativeFunc } from '@antd-tiny-vue/cssinjs'
import type { ColorPalettes, MapToken, PresetColorType, SeedToken } from '../../interface'
import { defaultPresetColors } from '../seed'
import genColorMapToken from '../shared/genColorMapToken'
import defaultAlgorithm from '../default'
import { generateColorPalettes, generateNeutralColorPalettes } from './colors'
const derivative: DerivativeFunc<SeedToken, MapToken> = (token, mapToken) => {
const colorPalettes = Object.keys(defaultPresetColors)
// @ts-expect-error this is a bug of typescript
.map((colorKey: keyof PresetColorType) => {
const colors = generate(token[colorKey], { theme: 'dark' })
return new Array(10).fill(1).reduce((prev, _, i) => {
prev[`${colorKey}-${i + 1}`] = colors[i]
return prev
}, {}) as ColorPalettes
})
.reduce((prev, cur) => {
prev = {
...prev,
...cur
}
return prev
}, {} as ColorPalettes)
const mergedMapToken = mapToken ?? defaultAlgorithm(token)
return {
...mergedMapToken,
// Dark tokens
...colorPalettes,
// Colors
...genColorMapToken(token, {
generateColorPalettes,
generateNeutralColorPalettes
})
}
}
export default derivative

View File

@ -0,0 +1,8 @@
import { TinyColor } from '@ctrl/tinycolor'
export const getAlphaColor = (baseColor: string, alpha: number) => new TinyColor(baseColor).setAlpha(alpha).toRgbString()
export const getSolidColor = (baseColor: string, brightness: number) => {
const instance = new TinyColor(baseColor)
return instance.darken(brightness).toHexString()
}

View File

@ -0,0 +1,50 @@
import { generate } from '@ant-design/colors'
import type { GenerateColorMap, GenerateNeutralColorMap } from '../ColorMap'
import { getAlphaColor, getSolidColor } from './colorAlgorithm'
export const generateColorPalettes: GenerateColorMap = (baseColor: string) => {
const colors = generate(baseColor)
return {
1: colors[0],
2: colors[1],
3: colors[2],
4: colors[3],
5: colors[4],
6: colors[5],
7: colors[6],
8: colors[4],
9: colors[5],
10: colors[6]
// 8: colors[7],
// 9: colors[8],
// 10: colors[9],
}
}
export const generateNeutralColorPalettes: GenerateNeutralColorMap = (bgBaseColor: string, textBaseColor: string) => {
const colorBgBase = bgBaseColor || '#fff'
const colorTextBase = textBaseColor || '#000'
return {
colorBgBase,
colorTextBase,
colorText: getAlphaColor(colorTextBase, 0.88),
colorTextSecondary: getAlphaColor(colorTextBase, 0.65),
colorTextTertiary: getAlphaColor(colorTextBase, 0.45),
colorTextQuaternary: getAlphaColor(colorTextBase, 0.25),
colorFill: getAlphaColor(colorTextBase, 0.15),
colorFillSecondary: getAlphaColor(colorTextBase, 0.06),
colorFillTertiary: getAlphaColor(colorTextBase, 0.04),
colorFillQuaternary: getAlphaColor(colorTextBase, 0.02),
colorBgLayout: getSolidColor(colorBgBase, 4),
colorBgContainer: getSolidColor(colorBgBase, 0),
colorBgElevated: getSolidColor(colorBgBase, 0),
colorBgSpotlight: getAlphaColor(colorTextBase, 0.85),
colorBorder: getSolidColor(colorBgBase, 15),
colorBorderSecondary: getSolidColor(colorBgBase, 6)
}
}

View File

@ -0,0 +1,46 @@
import { generate } from '@ant-design/colors'
import genControlHeight from '../shared/genControlHeight'
import genSizeMapToken from '../shared/genSizeMapToken'
import type { ColorPalettes, MapToken, PresetColorType, SeedToken } from '../../interface'
import { defaultPresetColors } from '../seed'
import genColorMapToken from '../shared/genColorMapToken'
import genCommonMapToken from '../shared/genCommonMapToken'
import genFontMapToken from '../shared/genFontMapToken'
import { generateColorPalettes, generateNeutralColorPalettes } from './colors'
export default function derivative(token: SeedToken): MapToken {
const colorPalettes = Object.keys(defaultPresetColors)
.map((colorKey: keyof PresetColorType) => {
const colors = generate(token[colorKey])
return new Array(10).fill(1).reduce((prev, _, i) => {
prev[`${colorKey}-${i + 1}`] = colors[i]
return prev
}, {}) as ColorPalettes
})
.reduce((prev, cur) => {
prev = {
...prev,
...cur
}
return prev
}, {} as ColorPalettes)
return {
...token,
...colorPalettes,
// Colors
...genColorMapToken(token, {
generateColorPalettes,
generateNeutralColorPalettes
}),
// Font
...genFontMapToken(token.fontSize),
// Size
...genSizeMapToken(token),
// Height
...genControlHeight(token),
// Others
...genCommonMapToken(token)
}
}

View File

@ -0,0 +1,77 @@
import type { PresetColorType, SeedToken } from '../internal'
export const defaultPresetColors: PresetColorType = {
blue: '#1677ff',
purple: '#722ED1',
cyan: '#13C2C2',
green: '#52C41A',
magenta: '#EB2F96',
pink: '#eb2f96',
red: '#F5222D',
orange: '#FA8C16',
yellow: '#FADB14',
volcano: '#FA541C',
geekblue: '#2F54EB',
gold: '#FAAD14',
lime: '#A0D911'
}
const seedToken: SeedToken = {
// preset color palettes
...defaultPresetColors,
// Color
colorPrimary: '#1677ff',
colorSuccess: '#52c41a',
colorWarning: '#faad14',
colorError: '#ff4d4f',
colorInfo: '#1677ff',
colorTextBase: '',
colorBgBase: '',
// Font
fontFamily: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji'`,
fontFamilyCode: `'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace`,
fontSize: 14,
// Line
lineWidth: 1,
lineType: 'solid',
// Motion
motionUnit: 0.1,
motionBase: 0,
motionEaseOutCirc: 'cubic-bezier(0.08, 0.82, 0.17, 1)',
motionEaseInOutCirc: 'cubic-bezier(0.78, 0.14, 0.15, 0.86)',
motionEaseOut: 'cubic-bezier(0.215, 0.61, 0.355, 1)',
motionEaseInOut: 'cubic-bezier(0.645, 0.045, 0.355, 1)',
motionEaseOutBack: 'cubic-bezier(0.12, 0.4, 0.29, 1.46)',
motionEaseInBack: 'cubic-bezier(0.71, -0.46, 0.88, 0.6)',
motionEaseInQuint: 'cubic-bezier(0.755, 0.05, 0.855, 0.06)',
motionEaseOutQuint: 'cubic-bezier(0.23, 1, 0.32, 1)',
// Radius
borderRadius: 6,
// Size
sizeUnit: 4,
sizeStep: 4,
sizePopupArrow: 16,
// Control Base
controlHeight: 32,
// zIndex
zIndexBase: 0,
zIndexPopupBase: 1000,
// Image
opacityImage: 1,
// Wireframe
wireframe: false
}
export default seedToken

View File

@ -0,0 +1,81 @@
import { TinyColor } from '@ctrl/tinycolor'
import type { ColorMapToken, SeedToken } from '../../interface'
import type { GenerateColorMap, GenerateNeutralColorMap } from '../ColorMap'
interface PaletteGenerators {
generateColorPalettes: GenerateColorMap
generateNeutralColorPalettes: GenerateNeutralColorMap
}
export default function genColorMapToken(seed: SeedToken, { generateColorPalettes, generateNeutralColorPalettes }: PaletteGenerators): ColorMapToken {
const { colorSuccess: colorSuccessBase, colorWarning: colorWarningBase, colorError: colorErrorBase, colorInfo: colorInfoBase, colorPrimary: colorPrimaryBase, colorBgBase, colorTextBase } = seed
const primaryColors = generateColorPalettes(colorPrimaryBase)
const successColors = generateColorPalettes(colorSuccessBase)
const warningColors = generateColorPalettes(colorWarningBase)
const errorColors = generateColorPalettes(colorErrorBase)
const infoColors = generateColorPalettes(colorInfoBase)
const neutralColors = generateNeutralColorPalettes(colorBgBase, colorTextBase)
return {
...neutralColors,
colorPrimaryBg: primaryColors[1],
colorPrimaryBgHover: primaryColors[2],
colorPrimaryBorder: primaryColors[3],
colorPrimaryBorderHover: primaryColors[4],
colorPrimaryHover: primaryColors[5],
colorPrimary: primaryColors[6],
colorPrimaryActive: primaryColors[7],
colorPrimaryTextHover: primaryColors[8],
colorPrimaryText: primaryColors[9],
colorPrimaryTextActive: primaryColors[10],
colorSuccessBg: successColors[1],
colorSuccessBgHover: successColors[2],
colorSuccessBorder: successColors[3],
colorSuccessBorderHover: successColors[4],
colorSuccessHover: successColors[4],
colorSuccess: successColors[6],
colorSuccessActive: successColors[7],
colorSuccessTextHover: successColors[8],
colorSuccessText: successColors[9],
colorSuccessTextActive: successColors[10],
colorErrorBg: errorColors[1],
colorErrorBgHover: errorColors[2],
colorErrorBorder: errorColors[3],
colorErrorBorderHover: errorColors[4],
colorErrorHover: errorColors[5],
colorError: errorColors[6],
colorErrorActive: errorColors[7],
colorErrorTextHover: errorColors[8],
colorErrorText: errorColors[9],
colorErrorTextActive: errorColors[10],
colorWarningBg: warningColors[1],
colorWarningBgHover: warningColors[2],
colorWarningBorder: warningColors[3],
colorWarningBorderHover: warningColors[4],
colorWarningHover: warningColors[4],
colorWarning: warningColors[6],
colorWarningActive: warningColors[7],
colorWarningTextHover: warningColors[8],
colorWarningText: warningColors[9],
colorWarningTextActive: warningColors[10],
colorInfoBg: infoColors[1],
colorInfoBgHover: infoColors[2],
colorInfoBorder: infoColors[3],
colorInfoBorderHover: infoColors[4],
colorInfoHover: infoColors[4],
colorInfo: infoColors[6],
colorInfoActive: infoColors[7],
colorInfoTextHover: infoColors[8],
colorInfoText: infoColors[9],
colorInfoTextActive: infoColors[10],
colorBgMask: new TinyColor('#000').setAlpha(0.45).toRgbString(),
colorWhite: '#fff'
}
}

View File

@ -0,0 +1,19 @@
import type { CommonMapToken, SeedToken } from '../../interface'
import genRadius from './genRadius'
export default function genCommonMapToken(token: SeedToken): CommonMapToken {
const { motionUnit, motionBase, borderRadius, lineWidth } = token
return {
// motion
motionDurationFast: `${(motionBase + motionUnit).toFixed(1)}s`,
motionDurationMid: `${(motionBase + motionUnit * 2).toFixed(1)}s`,
motionDurationSlow: `${(motionBase + motionUnit * 3).toFixed(1)}s`,
// line
lineWidthBold: lineWidth + 1,
// radius
...genRadius(borderRadius)
}
}

View File

@ -0,0 +1,13 @@
import type { HeightMapToken, SeedToken } from '../../interface'
const genControlHeight = (token: SeedToken): HeightMapToken => {
const { controlHeight } = token
return {
controlHeightSM: controlHeight * 0.75,
controlHeightXS: controlHeight * 0.5,
controlHeightLG: controlHeight * 1.25
}
}
export default genControlHeight

View File

@ -0,0 +1,33 @@
import type { FontMapToken } from '../../interface'
import genFontSizes from './genFontSizes'
const genFontMapToken = (fontSize: number): FontMapToken => {
const fontSizePairs = genFontSizes(fontSize)
const fontSizes = fontSizePairs.map(pair => pair.size)
const lineHeights = fontSizePairs.map(pair => pair.lineHeight)
return {
fontSizeSM: fontSizes[0],
fontSize: fontSizes[1],
fontSizeLG: fontSizes[2],
fontSizeXL: fontSizes[3],
fontSizeHeading1: fontSizes[6],
fontSizeHeading2: fontSizes[5],
fontSizeHeading3: fontSizes[4],
fontSizeHeading4: fontSizes[3],
fontSizeHeading5: fontSizes[2],
lineHeight: lineHeights[1],
lineHeightLG: lineHeights[2],
lineHeightSM: lineHeights[0],
lineHeightHeading1: lineHeights[6],
lineHeightHeading2: lineHeights[5],
lineHeightHeading3: lineHeights[4],
lineHeightHeading4: lineHeights[3],
lineHeightHeading5: lineHeights[2]
}
}
export default genFontMapToken

View File

@ -0,0 +1,22 @@
// https://zhuanlan.zhihu.com/p/32746810
export default function getFontSizes(base: number) {
const fontSizes = new Array(10).fill(null).map((_, index) => {
const i = index - 1
const baseSize = base * 2.71828 ** (i / 5)
const intSize = index > 1 ? Math.floor(baseSize) : Math.ceil(baseSize)
// Convert to even
return Math.floor(intSize / 2) * 2
})
fontSizes[1] = base
return fontSizes.map(size => {
const height = size + 8
return {
size,
lineHeight: height / size
}
})
}

View File

@ -0,0 +1,54 @@
import type { MapToken } from '../../interface'
const genRadius = (radiusBase: number): Pick<MapToken, 'borderRadiusXS' | 'borderRadiusSM' | 'borderRadiusLG' | 'borderRadius' | 'borderRadiusOuter'> => {
let radiusLG = radiusBase
let radiusSM = radiusBase
let radiusXS = radiusBase
let radiusOuter = radiusBase
// radiusLG
if (radiusBase < 6 && radiusBase >= 5) {
radiusLG = radiusBase + 1
} else if (radiusBase < 16 && radiusBase >= 6) {
radiusLG = radiusBase + 2
} else if (radiusBase >= 16) {
radiusLG = 16
}
// radiusSM
if (radiusBase < 7 && radiusBase >= 5) {
radiusSM = 4
} else if (radiusBase < 8 && radiusBase >= 7) {
radiusSM = 5
} else if (radiusBase < 14 && radiusBase >= 8) {
radiusSM = 6
} else if (radiusBase < 16 && radiusBase >= 14) {
radiusSM = 7
} else if (radiusBase >= 16) {
radiusSM = 8
}
// radiusXS
if (radiusBase < 6 && radiusBase >= 2) {
radiusXS = 1
} else if (radiusBase >= 6) {
radiusXS = 2
}
// radiusOuter
if (radiusBase > 4 && radiusBase < 8) {
radiusOuter = 4
} else if (radiusBase >= 8) {
radiusOuter = 6
}
return {
borderRadius: radiusBase > 16 ? 16 : radiusBase,
borderRadiusXS: radiusXS,
borderRadiusSM: radiusSM,
borderRadiusLG: radiusLG,
borderRadiusOuter: radiusOuter
}
}
export default genRadius

View File

@ -0,0 +1,17 @@
import type { SeedToken, SizeMapToken } from '../../interface'
export default function genSizeMapToken(token: SeedToken): SizeMapToken {
const { sizeUnit, sizeStep } = token
return {
sizeXXL: sizeUnit * (sizeStep + 8), // 48
sizeXL: sizeUnit * (sizeStep + 4), // 32
sizeLG: sizeUnit * (sizeStep + 2), // 24
sizeMD: sizeUnit * (sizeStep + 1), // 20
sizeMS: sizeUnit * sizeStep, // 16
size: sizeUnit * sizeStep, // 16
sizeSM: sizeUnit * (sizeStep - 1), // 12
sizeXS: sizeUnit * (sizeStep - 2), // 8
sizeXXS: sizeUnit * (sizeStep - 3) // 4
}
}