mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-06 12:17:13 +08:00
feat(button): unstable rtl (#74)
This commit is contained in:
parent
ae4b44dfb5
commit
6177b96e86
51
src/_mixins/use-rtl.ts
Normal file
51
src/_mixins/use-rtl.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { Ref, onBeforeMount, inject, watchEffect, computed } from 'vue'
|
||||||
|
import { ssrInjectionKey } from '../ssr/context'
|
||||||
|
import {
|
||||||
|
RtlEnabledState,
|
||||||
|
RtlItem
|
||||||
|
} from '../config-provider/src/internal-interface'
|
||||||
|
|
||||||
|
// The current implemention will take extra perf & memory usage. I just want to
|
||||||
|
// make it work now. If we can determine whether the style is already mounted,
|
||||||
|
// we won't need to watch effect. However, we need to make css-render support
|
||||||
|
// it. We need to refactor ssrAdapter and expose a exists function
|
||||||
|
export default function useRtl (
|
||||||
|
mountId: string,
|
||||||
|
rtlStateRef: Ref<RtlEnabledState | undefined> | undefined,
|
||||||
|
clsPrefixRef: Ref<string>
|
||||||
|
): Ref<RtlItem | undefined> | undefined {
|
||||||
|
if (!rtlStateRef) return undefined
|
||||||
|
const ssrAdapter = inject(ssrInjectionKey, undefined)
|
||||||
|
const componentRtlStateRef = computed(() => {
|
||||||
|
const { value: rtlState } = rtlStateRef
|
||||||
|
if (!rtlState) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
const componentRtlState = rtlState[mountId as keyof RtlEnabledState]
|
||||||
|
if (!componentRtlState) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return componentRtlState
|
||||||
|
})
|
||||||
|
const mountStyle = (): void => {
|
||||||
|
watchEffect(() => {
|
||||||
|
const { value: clsPrefix } = clsPrefixRef
|
||||||
|
const { value: componentRtlState } = componentRtlStateRef
|
||||||
|
if (!componentRtlState) return
|
||||||
|
componentRtlState.style.mount({
|
||||||
|
id: `${clsPrefix}${mountId}Rtl`,
|
||||||
|
head: true,
|
||||||
|
props: {
|
||||||
|
bPrefix: clsPrefix ? `.${clsPrefix}-` : undefined
|
||||||
|
},
|
||||||
|
ssr: ssrAdapter
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ssrAdapter) {
|
||||||
|
mountStyle()
|
||||||
|
} else {
|
||||||
|
onBeforeMount(mountStyle)
|
||||||
|
}
|
||||||
|
return componentRtlStateRef
|
||||||
|
}
|
@ -18,6 +18,7 @@ ghost
|
|||||||
loading
|
loading
|
||||||
color
|
color
|
||||||
group
|
group
|
||||||
|
rtl-debug
|
||||||
debug
|
debug
|
||||||
```
|
```
|
||||||
|
|
||||||
|
24
src/button/demos/zhCN/rtl-debug.demo.md
Normal file
24
src/button/demos/zhCN/rtl-debug.demo.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Rtl Debug
|
||||||
|
|
||||||
|
```html
|
||||||
|
<n-space vertical>
|
||||||
|
<n-space><n-switch v-model:value="rtlEnabled" />Rtl</n-space>
|
||||||
|
<n-config-provider :rtl="rtlEnabled ? rtlStyles : undefined">
|
||||||
|
<n-button>Rtl Test</n-button>
|
||||||
|
</n-config-provider>
|
||||||
|
</n-space>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { defineComponent, ref } from 'vue'
|
||||||
|
import { unstableButtonRtl } from 'naive-ui'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup () {
|
||||||
|
return {
|
||||||
|
rtlEnabled: ref(false),
|
||||||
|
rtlStyles: [unstableButtonRtl]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
@ -28,6 +28,7 @@ import type { ButtonTheme } from '../styles'
|
|||||||
import { buttonGroupInjectionKey } from './ButtonGroup'
|
import { buttonGroupInjectionKey } from './ButtonGroup'
|
||||||
import type { Type, Size } from './interface'
|
import type { Type, Size } from './interface'
|
||||||
import style from './styles/button.cssr'
|
import style from './styles/button.cssr'
|
||||||
|
import useRtl from '../../_mixins/use-rtl'
|
||||||
|
|
||||||
const buttonProps = {
|
const buttonProps = {
|
||||||
...(useTheme.props as ThemeProps<ButtonTheme>),
|
...(useTheme.props as ThemeProps<ButtonTheme>),
|
||||||
@ -157,7 +158,7 @@ const Button = defineComponent({
|
|||||||
const handleBlur = (): void => {
|
const handleBlur = (): void => {
|
||||||
enterPressedRef.value = false
|
enterPressedRef.value = false
|
||||||
}
|
}
|
||||||
const { mergedClsPrefixRef } = useConfig(props)
|
const { mergedClsPrefixRef, NConfigProvider } = useConfig(props)
|
||||||
const themeRef = useTheme(
|
const themeRef = useTheme(
|
||||||
'Button',
|
'Button',
|
||||||
'Button',
|
'Button',
|
||||||
@ -166,6 +167,11 @@ const Button = defineComponent({
|
|||||||
props,
|
props,
|
||||||
mergedClsPrefixRef
|
mergedClsPrefixRef
|
||||||
)
|
)
|
||||||
|
const rtlEnabledRef = useRtl(
|
||||||
|
'Button',
|
||||||
|
NConfigProvider?.mergedRtlRef,
|
||||||
|
mergedClsPrefixRef
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
selfRef,
|
selfRef,
|
||||||
waveRef,
|
waveRef,
|
||||||
@ -174,6 +180,7 @@ const Button = defineComponent({
|
|||||||
mergedSize: mergedSizeRef,
|
mergedSize: mergedSizeRef,
|
||||||
showBorder: showBorderRef,
|
showBorder: showBorderRef,
|
||||||
enterPressed: enterPressedRef,
|
enterPressed: enterPressedRef,
|
||||||
|
rtlEnabled: rtlEnabledRef,
|
||||||
handleMouseDown,
|
handleMouseDown,
|
||||||
handleKeyDown,
|
handleKeyDown,
|
||||||
handleBlur,
|
handleBlur,
|
||||||
@ -390,6 +397,7 @@ const Button = defineComponent({
|
|||||||
`${mergedClsPrefix}-button`,
|
`${mergedClsPrefix}-button`,
|
||||||
`${mergedClsPrefix}-button--${this.type}-type`,
|
`${mergedClsPrefix}-button--${this.type}-type`,
|
||||||
{
|
{
|
||||||
|
[`${mergedClsPrefix}-button--rtl`]: this.rtlEnabled,
|
||||||
[`${mergedClsPrefix}-button--disabled`]: this.disabled,
|
[`${mergedClsPrefix}-button--disabled`]: this.disabled,
|
||||||
[`${mergedClsPrefix}-button--block`]: this.block,
|
[`${mergedClsPrefix}-button--block`]: this.block,
|
||||||
[`${mergedClsPrefix}-button--pressed`]: this.enterPressed,
|
[`${mergedClsPrefix}-button--pressed`]: this.enterPressed,
|
||||||
|
7
src/button/src/styles/button-rtl.cssr.ts
Normal file
7
src/button/src/styles/button-rtl.cssr.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { cB, cM } from '../../../_utils/cssr'
|
||||||
|
|
||||||
|
export default cB('button', [
|
||||||
|
cM('rtl', `
|
||||||
|
direction: rtl;
|
||||||
|
`)
|
||||||
|
])
|
@ -1,3 +1,4 @@
|
|||||||
export { default as buttonDark } from './dark'
|
export { default as buttonDark } from './dark'
|
||||||
export { default as buttonLight } from './light'
|
export { default as buttonLight } from './light'
|
||||||
|
export { default as buttonRtl } from './rtl'
|
||||||
export type { ButtonThemeVars, ButtonTheme } from './light'
|
export type { ButtonThemeVars, ButtonTheme } from './light'
|
||||||
|
6
src/button/styles/rtl.ts
Normal file
6
src/button/styles/rtl.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import rtlStyle from '../src/styles/button-rtl.cssr'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Button',
|
||||||
|
style: rtlStyle
|
||||||
|
}
|
@ -6,7 +6,9 @@ import {
|
|||||||
PropType,
|
PropType,
|
||||||
provide,
|
provide,
|
||||||
InjectionKey,
|
InjectionKey,
|
||||||
renderSlot
|
renderSlot,
|
||||||
|
ComputedRef,
|
||||||
|
markRaw
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { useMemo } from 'vooks'
|
import { useMemo } from 'vooks'
|
||||||
import { merge } from 'lodash-es'
|
import { merge } from 'lodash-es'
|
||||||
@ -18,17 +20,18 @@ import type {
|
|||||||
GlobalComponentConfig,
|
GlobalComponentConfig,
|
||||||
GlobalIconConfig
|
GlobalIconConfig
|
||||||
} from './interface'
|
} from './interface'
|
||||||
import type { ConfigProviderInjection } from './internal-interface'
|
import type {
|
||||||
|
ConfigProviderInjection,
|
||||||
|
RtlProp,
|
||||||
|
RtlEnabledState
|
||||||
|
} from './internal-interface'
|
||||||
import { NDateLocale, NLocale } from '../../locales'
|
import { NDateLocale, NLocale } from '../../locales'
|
||||||
|
|
||||||
export const configProviderInjectionKey: InjectionKey<ConfigProviderInjection> =
|
export const configProviderInjectionKey: InjectionKey<ConfigProviderInjection> =
|
||||||
Symbol('configProviderInjection')
|
Symbol('configProviderInjection')
|
||||||
|
|
||||||
export const configProviderProps = {
|
export const configProviderProps = {
|
||||||
abstract: {
|
abstract: Boolean,
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
bordered: {
|
bordered: {
|
||||||
type: Boolean as PropType<boolean | undefined>,
|
type: Boolean as PropType<boolean | undefined>,
|
||||||
default: undefined
|
default: undefined
|
||||||
@ -37,6 +40,7 @@ export const configProviderProps = {
|
|||||||
locale: Object as PropType<NLocale | null>,
|
locale: Object as PropType<NLocale | null>,
|
||||||
dateLocale: Object as PropType<NDateLocale | null>,
|
dateLocale: Object as PropType<NDateLocale | null>,
|
||||||
namespace: String,
|
namespace: String,
|
||||||
|
rtl: Array as PropType<RtlProp>,
|
||||||
tag: {
|
tag: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'div'
|
default: 'div'
|
||||||
@ -160,7 +164,21 @@ export default defineComponent({
|
|||||||
const { clsPrefix } = props
|
const { clsPrefix } = props
|
||||||
return NConfigProvider?.mergedClsPrefixRef.value ?? clsPrefix
|
return NConfigProvider?.mergedClsPrefixRef.value ?? clsPrefix
|
||||||
})
|
})
|
||||||
|
const mergedRtlRef: ComputedRef<RtlEnabledState | undefined> = computed(
|
||||||
|
() => {
|
||||||
|
const { rtl } = props
|
||||||
|
if (rtl === undefined) {
|
||||||
|
return NConfigProvider?.mergedRtlRef.value
|
||||||
|
}
|
||||||
|
const rtlEnabledState: RtlEnabledState = {}
|
||||||
|
for (const rtlInfo of rtl) {
|
||||||
|
rtlEnabledState[rtlInfo.name] = markRaw(rtlInfo)
|
||||||
|
}
|
||||||
|
return rtlEnabledState
|
||||||
|
}
|
||||||
|
)
|
||||||
provide(configProviderInjectionKey, {
|
provide(configProviderInjectionKey, {
|
||||||
|
mergedRtlRef,
|
||||||
mergedIconsRef,
|
mergedIconsRef,
|
||||||
mergedComponentPropsRef,
|
mergedComponentPropsRef,
|
||||||
mergedBorderedRef,
|
mergedBorderedRef,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { VNodeChild, Ref } from 'vue'
|
import { VNodeChild, Ref } from 'vue'
|
||||||
|
import { CNode } from 'css-render'
|
||||||
import type { AlertTheme } from '../../alert/styles'
|
import type { AlertTheme } from '../../alert/styles'
|
||||||
import type { AnchorTheme } from '../../anchor/styles'
|
import type { AnchorTheme } from '../../anchor/styles'
|
||||||
import type { AutoCompleteTheme } from '../../auto-complete/styles'
|
import type { AutoCompleteTheme } from '../../auto-complete/styles'
|
||||||
@ -200,6 +201,16 @@ export interface GlobalIconConfig {
|
|||||||
zoomOut?: () => VNodeChild
|
zoomOut?: () => VNodeChild
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RtlItem {
|
||||||
|
name: keyof GlobalThemeWithoutCommon
|
||||||
|
style: CNode
|
||||||
|
}
|
||||||
|
export type RtlProp = RtlItem[]
|
||||||
|
|
||||||
|
export type RtlEnabledState = Partial<
|
||||||
|
Record<keyof GlobalThemeWithoutCommon, RtlItem>
|
||||||
|
>
|
||||||
|
|
||||||
export interface ConfigProviderInjection {
|
export interface ConfigProviderInjection {
|
||||||
mergedClsPrefixRef: Ref<string | undefined>
|
mergedClsPrefixRef: Ref<string | undefined>
|
||||||
mergedBorderedRef: Ref<boolean | undefined>
|
mergedBorderedRef: Ref<boolean | undefined>
|
||||||
@ -211,6 +222,7 @@ export interface ConfigProviderInjection {
|
|||||||
mergedIconsRef: Ref<GlobalIconConfig | undefined>
|
mergedIconsRef: Ref<GlobalIconConfig | undefined>
|
||||||
mergedThemeRef: Ref<GlobalTheme | undefined>
|
mergedThemeRef: Ref<GlobalTheme | undefined>
|
||||||
mergedThemeOverridesRef: Ref<GlobalThemeOverrides | undefined>
|
mergedThemeOverridesRef: Ref<GlobalThemeOverrides | undefined>
|
||||||
|
mergedRtlRef: Ref<RtlEnabledState | undefined>
|
||||||
// deprecated
|
// deprecated
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
mergedLegacyThemeRef: Ref<string | undefined>
|
mergedLegacyThemeRef: Ref<string | undefined>
|
||||||
|
@ -6,7 +6,7 @@ export { avatarDark } from './avatar/styles'
|
|||||||
export { backTopDark } from './back-top/styles'
|
export { backTopDark } from './back-top/styles'
|
||||||
export { badgeDark } from './badge/styles'
|
export { badgeDark } from './badge/styles'
|
||||||
export { breadcrumbDark } from './breadcrumb/styles'
|
export { breadcrumbDark } from './breadcrumb/styles'
|
||||||
export { buttonDark } from './button/styles'
|
export { buttonDark, buttonRtl as unstableButtonRtl } from './button/styles'
|
||||||
export { cardDark } from './card/styles'
|
export { cardDark } from './card/styles'
|
||||||
export { cascaderDark } from './cascader/styles'
|
export { cascaderDark } from './cascader/styles'
|
||||||
export { checkboxDark } from './checkbox/styles'
|
export { checkboxDark } from './checkbox/styles'
|
||||||
|
Loading…
Reference in New Issue
Block a user