feat: add config

This commit is contained in:
aibayanyu 2023-03-26 15:49:59 +08:00
parent 59e8b4d56e
commit 2b2ef3a3fb
6 changed files with 185 additions and 15 deletions

View File

@ -1 +1,2 @@
export { default as Button } from './button' export { default as Button } from './button'
export { default as ConfigProvider } from './config-provider'

View File

@ -4,6 +4,7 @@ import { computed } from 'vue'
import type { DerivativeFunc } from '@antd-tiny-vue/cssinjs' import type { DerivativeFunc } from '@antd-tiny-vue/cssinjs'
import type { AliasToken, MapToken, OverrideToken, SeedToken } from '../theme/interface' import type { AliasToken, MapToken, OverrideToken, SeedToken } from '../theme/interface'
import type { RenderEmptyHandler } from './default-render-empty' import type { RenderEmptyHandler } from './default-render-empty'
import type { ConfigProviderProps } from './index'
export type SizeType = 'small' | 'middle' | 'large' | undefined export type SizeType = 'small' | 'middle' | 'large' | undefined
@ -77,21 +78,36 @@ export const configConsumerProps = {
export type ConfigConsumerProps = ExtractPropTypes<typeof configConsumerProps> export type ConfigConsumerProps = ExtractPropTypes<typeof configConsumerProps>
const [useProviderConfigProvide, useProviderConfigInject] = createInjectionState(() => { const configState = (props: ConfigProviderProps) => {
const getPrefixCls = defaultGetPrefixCls const getPrefixCls = (suffixCls?: string, customizePrefixCls?: string) => {
const iconPrefixCls = computed(() => defaultIconPrefixCls) const { prefixCls, getPrefixCls } = props
if (customizePrefixCls) return customizePrefixCls
const mergedPrefixCls = prefixCls || getPrefixCls?.('') || defaultGetPrefixCls('')
return suffixCls ? `${mergedPrefixCls}-${suffixCls}` : mergedPrefixCls
}
const iconPrefixCls = computed(() => props?.iconPrefixCls ?? defaultIconPrefixCls)
const shouldWrapSSR = computed(() => iconPrefixCls.value !== defaultIconPrefixCls)
const csp = computed(() => props?.csp)
const componentSize = computed(() => props?.componentSize)
const componentDisabled = computed(() => props?.componentDisabled)
return { return {
getPrefixCls, getPrefixCls,
iconPrefixCls iconPrefixCls,
shouldWrapSSR,
csp,
componentSize,
componentDisabled
} }
}) }
const [useProviderConfigProvide, useProviderConfigInject] = createInjectionState(configState)
export { useProviderConfigProvide } export { useProviderConfigProvide }
export const useProviderConfigState = () => { export const useProviderConfigState = (): ReturnType<typeof configState> => {
return ( return (
useProviderConfigInject() ?? { useProviderConfigInject() ??
({
getPrefixCls: defaultGetPrefixCls, getPrefixCls: defaultGetPrefixCls,
iconPrefixCls: computed(() => defaultIconPrefixCls) iconPrefixCls: computed(() => defaultIconPrefixCls)
} } as any)
) )
} }

View File

@ -0,0 +1,9 @@
import { useProviderConfigState } from '../context'
export const useConfig = () => {
const { componentDisabled, componentSize } = useProviderConfigState()
return {
componentDisabled,
componentSize
}
}

View File

@ -1,19 +1,44 @@
import { booleanType, someType, stringType } from '@v-c/utils' import { booleanType, objectType, someType, stringType } from '@v-c/utils'
import type { ExtractPropTypes } from 'vue' import type { App, ExtractPropTypes } from 'vue'
import type { SizeType, Theme } from './context' import { computed, defineComponent } from 'vue'
import { configConsumerProps, defaultIconPrefixCls } from './context' import { createTheme } from '@antd-tiny-vue/cssinjs'
import defaultSeedToken from '../theme/themes/seed'
import type { DesignTokenConfig } from '../theme/internal'
import { DesignTokenProviderContext } from '../theme/internal'
import type { CSPConfig, ConfigConsumerProps, DirectionType, SizeType, Theme, ThemeConfig } from './context'
import { configConsumerProps, defaultIconPrefixCls, useProviderConfigProvide } from './context'
import { registerTheme } from './css-variables' import { registerTheme } from './css-variables'
import type { RenderEmptyHandler } from './default-render-empty'
import useStyle from './style'
import { useConfig } from './hooks/config'
export type { RenderEmptyHandler, CSPConfig, DirectionType, ConfigConsumerProps, ThemeConfig }
export { defaultIconPrefixCls }
export const configProviderProps = { export const configProviderProps = {
...configConsumerProps, ...configConsumerProps,
prefixCls: stringType(), prefixCls: stringType(),
componentSize: someType<SizeType>([String]), componentSize: someType<SizeType>([String]),
componentDisabled: booleanType() componentDisabled: booleanType(),
legacyLocale: objectType()
} }
export type ConfigProviderProps = Partial<ExtractPropTypes<typeof configProviderProps>> export type ConfigProviderProps = Partial<ExtractPropTypes<typeof configProviderProps>>
export const defaultPrefixCls = 'ant' export const defaultPrefixCls = 'ant'
// These props is used by `useContext` directly in sub component
// const PASSED_PROPS: Exclude<keyof ConfigConsumerProps, 'rootPrefixCls' | 'getPrefixCls'>[] = [
// 'getTargetContainer',
// 'getPopupContainer',
// 'renderEmpty',
// 'pageHeader',
// 'input',
// 'pagination',
// 'form',
// 'select'
// ]
let globalPrefixCls: string let globalPrefixCls: string
let globalIconPrefixCls: string let globalIconPrefixCls: string
@ -54,3 +79,84 @@ export const globalConfig = () => ({
return getGlobalPrefixCls() return getGlobalPrefixCls()
} }
}) })
const ConfigProvider = defineComponent({
name: 'AConfigProvider',
props: {
...configProviderProps
},
setup(props, { slots }) {
// 依赖注入
const { shouldWrapSSR, iconPrefixCls } = useProviderConfigProvide(props)
const wrapSSR = useStyle(iconPrefixCls)
const memoTheme = computed(() => {
const { algorithm, token, ...rest } = props.theme || {}
const themeObj = algorithm && (!Array.isArray(algorithm) || algorithm.length > 0) ? createTheme(algorithm) : undefined
return {
...rest,
theme: themeObj,
token: {
...defaultSeedToken,
...token
}
}
})
return () => {
const { locale, theme } = props
const children = slots.default?.()
let childNode = shouldWrapSSR.value ? wrapSSR(children) : children
/**
* Form
*/
// const validateMessages = React.useMemo(
// () =>
// setValues(
// {},
// defaultLocale.Form?.defaultValidateMessages || {},
// memoedConfig.locale?.Form?.defaultValidateMessages || {},
// form?.validateMessages || {},
// ),
// [memoedConfig, form?.validateMessages],
// );
//
// if (Object.keys(validateMessages).length > 0) {
// childNode = <RcFormProvider validateMessages={validateMessages}>{children}</RcFormProvider>;
// }
/**
*
*/
if (locale) {
// 多语言部分
// childNode = <LocaleProvider locale={locale}>{childNode}</LocaleProvider>;
}
if (theme) {
childNode = (
<DesignTokenProviderContext
{...(memoTheme.value as DesignTokenConfig)}
token={memoTheme.value.token as any}
>
{childNode}
</DesignTokenProviderContext>
)
}
return childNode
}
}
})
ConfigProvider.install = (app: App) => {
app.component(ConfigProvider.name, ConfigProvider)
}
ConfigProvider.config = setGlobalConfig
ConfigProvider.useConfig = useConfig
export default ConfigProvider as typeof ConfigProvider & {
install(app: App): void
config: typeof setGlobalConfig
useConfig: typeof useConfig
}

View File

@ -0,0 +1,23 @@
import { useStyleRegister } from '@antd-tiny-vue/cssinjs'
import type { Ref } from 'vue'
import { computed } from 'vue'
import { resetIcon } from '../../style'
import { useToken } from '../../theme/internal'
const useStyle = (iconPrefixCls: Ref<string>) => {
const [theme, token] = useToken()
// Generate style for icons
const info = computed(() => ({ theme: theme.value, token: token.value, hashId: '', path: ['ant-design-icons', iconPrefixCls.value] }))
return useStyleRegister(info, () => [
{
[`.${iconPrefixCls.value}`]: {
...resetIcon(),
[`.${iconPrefixCls.value} .${iconPrefixCls.value}-icon`]: {
display: 'block'
}
}
}
])
}
export default useStyle

View File

@ -1,8 +1,8 @@
import type { CSSInterpolation, Theme } from '@antd-tiny-vue/cssinjs' import type { CSSInterpolation, Theme } from '@antd-tiny-vue/cssinjs'
import { createTheme, useCacheToken, useStyleRegister } from '@antd-tiny-vue/cssinjs' import { createTheme, useCacheToken, useStyleRegister } from '@antd-tiny-vue/cssinjs'
import { createInjectionState } from '@v-c/utils' import { createInjectionState, objectType, someType } from '@v-c/utils'
import type { ComputedRef, VNodeChild } from 'vue' import type { ComputedRef, VNodeChild } from 'vue'
import { computed } from 'vue' import { computed, defineComponent } from 'vue'
import version from '../version' import version from '../version'
import type { AliasToken, GlobalToken, MapToken, OverrideToken, PresetColorKey, PresetColorType, SeedToken } from './interface' import type { AliasToken, GlobalToken, MapToken, OverrideToken, PresetColorKey, PresetColorType, SeedToken } from './interface'
import { PresetColors } from './interface' import { PresetColors } from './interface'
@ -54,6 +54,21 @@ const [useDesignTokenProvider, useDesignTokenInject] = createInjectionState((tok
return token return token
}) })
export const DesignTokenProviderContext = defineComponent({
props: {
token: objectType<AliasToken>(),
theme: objectType<Theme<SeedToken, MapToken>>(),
components: objectType<OverrideToken>(),
hashed: someType<string | boolean>([String, Boolean])
},
setup(props, { slots }) {
useDesignTokenProvider(props)
return () => {
return slots.default?.()
}
}
})
export { useDesignTokenProvider } export { useDesignTokenProvider }
export const useDesignTokenState = () => useDesignTokenInject() ?? defaultConfig export const useDesignTokenState = () => useDesignTokenInject() ?? defaultConfig