mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-21 04:50:14 +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
|
||||
color
|
||||
group
|
||||
rtl-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 type { Type, Size } from './interface'
|
||||
import style from './styles/button.cssr'
|
||||
import useRtl from '../../_mixins/use-rtl'
|
||||
|
||||
const buttonProps = {
|
||||
...(useTheme.props as ThemeProps<ButtonTheme>),
|
||||
@ -157,7 +158,7 @@ const Button = defineComponent({
|
||||
const handleBlur = (): void => {
|
||||
enterPressedRef.value = false
|
||||
}
|
||||
const { mergedClsPrefixRef } = useConfig(props)
|
||||
const { mergedClsPrefixRef, NConfigProvider } = useConfig(props)
|
||||
const themeRef = useTheme(
|
||||
'Button',
|
||||
'Button',
|
||||
@ -166,6 +167,11 @@ const Button = defineComponent({
|
||||
props,
|
||||
mergedClsPrefixRef
|
||||
)
|
||||
const rtlEnabledRef = useRtl(
|
||||
'Button',
|
||||
NConfigProvider?.mergedRtlRef,
|
||||
mergedClsPrefixRef
|
||||
)
|
||||
return {
|
||||
selfRef,
|
||||
waveRef,
|
||||
@ -174,6 +180,7 @@ const Button = defineComponent({
|
||||
mergedSize: mergedSizeRef,
|
||||
showBorder: showBorderRef,
|
||||
enterPressed: enterPressedRef,
|
||||
rtlEnabled: rtlEnabledRef,
|
||||
handleMouseDown,
|
||||
handleKeyDown,
|
||||
handleBlur,
|
||||
@ -390,6 +397,7 @@ const Button = defineComponent({
|
||||
`${mergedClsPrefix}-button`,
|
||||
`${mergedClsPrefix}-button--${this.type}-type`,
|
||||
{
|
||||
[`${mergedClsPrefix}-button--rtl`]: this.rtlEnabled,
|
||||
[`${mergedClsPrefix}-button--disabled`]: this.disabled,
|
||||
[`${mergedClsPrefix}-button--block`]: this.block,
|
||||
[`${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 buttonLight } from './light'
|
||||
export { default as buttonRtl } from './rtl'
|
||||
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,
|
||||
provide,
|
||||
InjectionKey,
|
||||
renderSlot
|
||||
renderSlot,
|
||||
ComputedRef,
|
||||
markRaw
|
||||
} from 'vue'
|
||||
import { useMemo } from 'vooks'
|
||||
import { merge } from 'lodash-es'
|
||||
@ -18,17 +20,18 @@ import type {
|
||||
GlobalComponentConfig,
|
||||
GlobalIconConfig
|
||||
} from './interface'
|
||||
import type { ConfigProviderInjection } from './internal-interface'
|
||||
import type {
|
||||
ConfigProviderInjection,
|
||||
RtlProp,
|
||||
RtlEnabledState
|
||||
} from './internal-interface'
|
||||
import { NDateLocale, NLocale } from '../../locales'
|
||||
|
||||
export const configProviderInjectionKey: InjectionKey<ConfigProviderInjection> =
|
||||
Symbol('configProviderInjection')
|
||||
|
||||
export const configProviderProps = {
|
||||
abstract: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
abstract: Boolean,
|
||||
bordered: {
|
||||
type: Boolean as PropType<boolean | undefined>,
|
||||
default: undefined
|
||||
@ -37,6 +40,7 @@ export const configProviderProps = {
|
||||
locale: Object as PropType<NLocale | null>,
|
||||
dateLocale: Object as PropType<NDateLocale | null>,
|
||||
namespace: String,
|
||||
rtl: Array as PropType<RtlProp>,
|
||||
tag: {
|
||||
type: String,
|
||||
default: 'div'
|
||||
@ -160,7 +164,21 @@ export default defineComponent({
|
||||
const { clsPrefix } = props
|
||||
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, {
|
||||
mergedRtlRef,
|
||||
mergedIconsRef,
|
||||
mergedComponentPropsRef,
|
||||
mergedBorderedRef,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { VNodeChild, Ref } from 'vue'
|
||||
import { CNode } from 'css-render'
|
||||
import type { AlertTheme } from '../../alert/styles'
|
||||
import type { AnchorTheme } from '../../anchor/styles'
|
||||
import type { AutoCompleteTheme } from '../../auto-complete/styles'
|
||||
@ -200,6 +201,16 @@ export interface GlobalIconConfig {
|
||||
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 {
|
||||
mergedClsPrefixRef: Ref<string | undefined>
|
||||
mergedBorderedRef: Ref<boolean | undefined>
|
||||
@ -211,6 +222,7 @@ export interface ConfigProviderInjection {
|
||||
mergedIconsRef: Ref<GlobalIconConfig | undefined>
|
||||
mergedThemeRef: Ref<GlobalTheme | undefined>
|
||||
mergedThemeOverridesRef: Ref<GlobalThemeOverrides | undefined>
|
||||
mergedRtlRef: Ref<RtlEnabledState | undefined>
|
||||
// deprecated
|
||||
/** @deprecated */
|
||||
mergedLegacyThemeRef: Ref<string | undefined>
|
||||
|
@ -6,7 +6,7 @@ export { avatarDark } from './avatar/styles'
|
||||
export { backTopDark } from './back-top/styles'
|
||||
export { badgeDark } from './badge/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 { cascaderDark } from './cascader/styles'
|
||||
export { checkboxDark } from './checkbox/styles'
|
||||
|
Loading…
Reference in New Issue
Block a user