fix: api components support locale, close #4780

pull/4825/head
tangjinzhou 2021-10-26 16:12:56 +08:00
parent c76b46fa1a
commit a6d9d36343
8 changed files with 78 additions and 79 deletions

View File

@ -1,5 +1,5 @@
import type { PropType, ExtractPropTypes, UnwrapRef, App, Plugin, WatchStopHandle } from 'vue';
import { reactive, provide, defineComponent, watch, ref, unref, watchEffect } from 'vue';
import { reactive, provide, defineComponent, watch, watchEffect } from 'vue';
import PropTypes from '../_util/vue-types';
import defaultRenderEmpty from './renderEmpty';
import type { RenderEmptyHandler } from './renderEmpty';
@ -58,7 +58,47 @@ export const configConsumerProps = [
];
export const defaultPrefixCls = 'ant';
const globalPrefixCls = ref<string>();
function getGlobalPrefixCls() {
return globalConfigForApi.prefixCls || defaultPrefixCls;
}
const globalConfigByCom = reactive<ConfigProviderProps>({});
const globalConfigBySet = reactive<ConfigProviderProps>({}); //
export const globalConfigForApi = reactive<
ConfigProviderProps & {
getRootPrefixCls?: (rootPrefixCls?: string, customizePrefixCls?: string) => string;
}
>({});
watchEffect(() => {
Object.assign(globalConfigForApi, globalConfigByCom, globalConfigBySet);
globalConfigForApi.prefixCls = getGlobalPrefixCls();
globalConfigForApi.getPrefixCls = (suffixCls?: string, customizePrefixCls?: string) => {
if (customizePrefixCls) return customizePrefixCls;
return suffixCls
? `${globalConfigForApi.prefixCls}-${suffixCls}`
: globalConfigForApi.prefixCls;
};
globalConfigForApi.getRootPrefixCls = (rootPrefixCls?: string, customizePrefixCls?: string) => {
// Customize rootPrefixCls is first priority
if (rootPrefixCls) {
return rootPrefixCls;
}
// If Global prefixCls provided, use this
if (globalConfigForApi.prefixCls) {
return globalConfigForApi.prefixCls;
}
// [Legacy] If customize prefixCls provided, we cut it to get the prefixCls
if (customizePrefixCls && customizePrefixCls.includes('-')) {
return customizePrefixCls.replace(/^(.*)-[^-]*$/, '$1');
}
// Fallback to default prefixCls
return getGlobalPrefixCls();
};
});
type GlobalConfigProviderProps = {
prefixCls?: MaybeRef<ConfigProviderProps['prefixCls']>;
@ -70,17 +110,10 @@ const setGlobalConfig = (params: GlobalConfigProviderProps) => {
stopWatchEffect();
}
stopWatchEffect = watchEffect(() => {
const prefixCls = unref(params.prefixCls);
if (prefixCls !== undefined) {
globalPrefixCls.value = prefixCls;
}
Object.assign(globalConfigBySet, reactive(params));
});
};
function getGlobalPrefixCls() {
return globalPrefixCls.value || defaultPrefixCls;
}
export const globalConfig = () => ({
getPrefixCls: (suffixCls?: string, customizePrefixCls?: string) => {
if (customizePrefixCls) return customizePrefixCls;
@ -93,8 +126,8 @@ export const globalConfig = () => ({
}
// If Global prefixCls provided, use this
if (globalPrefixCls.value) {
return globalPrefixCls.value;
if (globalConfigForApi.prefixCls) {
return globalConfigForApi.prefixCls;
}
// [Legacy] If customize prefixCls provided, we cut it to get the prefixCls
@ -148,6 +181,8 @@ export const configProviderProps = {
form: {
type: Object as PropType<{ requiredMark?: RequiredMark }>,
},
// internal use
notUpdateGlobalConfig: Boolean,
};
export type ConfigProviderProps = Partial<ExtractPropTypes<typeof configProviderProps>>;
@ -193,6 +228,12 @@ const ConfigProvider = defineComponent({
},
);
});
if (!props.notUpdateGlobalConfig) {
Object.assign(globalConfigByCom, configProvider);
watch(configProvider, () => {
Object.assign(globalConfigByCom, configProvider);
});
}
provide('configProvider', configProvider);

View File

@ -1,8 +1,7 @@
import type { App, VNode, PropType } from 'vue';
import { provide, defineComponent, reactive, watch, onUnmounted } from 'vue';
import { provide, defineComponent, reactive, watch } from 'vue';
import PropTypes from '../_util/vue-types';
import type { ModalLocale } from '../modal/locale';
import { changeConfirmLocale } from '../modal/locale';
import warning from '../_util/warning';
import { withInstall } from '../_util/type';
import type { ValidateMessages } from '../form/interface';
@ -72,18 +71,14 @@ const LocaleProvider = defineComponent({
provide('localeData', state);
watch(
() => props.locale,
val => {
() => {
state.antLocale = {
...props.locale,
exist: true,
} as any;
changeConfirmLocale(val && val.Modal);
},
{ immediate: true },
);
onUnmounted(() => {
changeConfirmLocale();
});
return () => {
return slots.default?.();

View File

@ -2,8 +2,8 @@ import classNames from '../_util/classNames';
import type { ModalFuncProps } from './Modal';
import Dialog from './Modal';
import ActionButton from './ActionButton';
import { getConfirmLocale } from './locale';
import { defineComponent, computed } from 'vue';
import { defineComponent } from 'vue';
import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
interface ConfirmDialogProps extends ModalFuncProps {
afterClose?: () => void;
@ -52,7 +52,7 @@ export default defineComponent<ConfirmDialogProps>({
'content',
] as any,
setup(props, { attrs }) {
const runtimeLocale = computed(() => getConfirmLocale());
const [locale] = useLocaleReceiver('Modal');
return () => {
const {
icon,
@ -86,9 +86,9 @@ export default defineComponent<ConfirmDialogProps>({
const style = attrs.style || {};
const okText =
renderSomeContent('okText', props.okText) ||
(okCancel ? runtimeLocale.value.okText : runtimeLocale.value.justOkText);
(okCancel ? locale.value.okText : locale.value.justOkText);
const cancelText =
renderSomeContent('cancelText', props.cancelText) || runtimeLocale.value.cancelText;
renderSomeContent('cancelText', props.cancelText) || locale.value.cancelText;
const autoFocusButton =
props.autoFocusButton === null ? false : props.autoFocusButton || 'ok';

View File

@ -1,15 +1,14 @@
import type { ExtractPropTypes, CSSProperties, PropType } from 'vue';
import { defineComponent, inject, computed } from 'vue';
import { defineComponent, inject } from 'vue';
import classNames from '../_util/classNames';
import Dialog from '../vc-dialog';
import PropTypes from '../_util/vue-types';
import addEventListener from '../vc-util/Dom/addEventListener';
import { getConfirmLocale } from './locale';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import Button from '../button';
import type { ButtonProps as ButtonPropsType, LegacyButtonType } from '../button/buttonTypes';
import buttonTypes, { convertLegacyProps } from '../button/buttonTypes';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
import { getComponent, getSlot } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import { defaultConfigProvider } from '../config-provider';
@ -158,9 +157,9 @@ export default defineComponent({
}),
emits: ['update:visible', 'cancel', 'change', 'ok'],
setup() {
const confirmLocale = computed(() => getConfirmLocale());
const [locale] = useLocaleReceiver('Modal');
return {
confirmLocale,
locale,
configProvider: inject('configProvider', defaultConfigProvider),
};
},
@ -184,8 +183,8 @@ export default defineComponent({
handleOk(e: MouseEvent) {
this.$emit('ok', e);
},
renderFooter(locale: ModalLocale) {
const { okType, confirmLoading } = this;
renderFooter() {
const { okType, confirmLoading, locale } = this;
const cancelBtnProps = { onClick: this.handleCancel, ...(this.cancelButtonProps || {}) };
const okBtnProps = {
onClick: this.handleOk,
@ -213,19 +212,12 @@ export default defineComponent({
centered,
getContainer,
$attrs,
confirmLocale,
} = this;
const children = getSlot(this);
const { getPrefixCls, getPopupContainer: getContextPopupContainer } = this.configProvider;
const prefixCls = getPrefixCls('modal', customizePrefixCls);
const defaultFooter = (
<LocaleReceiver
componentName="Modal"
defaultLocale={confirmLocale}
children={this.renderFooter}
/>
);
const defaultFooter = this.renderFooter();
const closeIcon = getComponent(this, 'closeIcon');
const closeIconToRender = (
<span class={`${prefixCls}-close-x`}>

View File

@ -2,15 +2,9 @@ import { createVNode, render as vueRender } from 'vue';
import ConfirmDialog from './ConfirmDialog';
import type { ModalFuncProps } from './Modal';
import { destroyFns } from './Modal';
import ConfigProvider, { globalConfig } from '../config-provider';
import ConfigProvider, { globalConfigForApi } from '../config-provider';
import omit from '../_util/omit';
const defaultRootPrefixCls = '';
function getRootPrefixCls() {
return defaultRootPrefixCls;
}
const confirm = (config: ModalFuncProps) => {
const div = document.createElement('div');
document.body.appendChild(div);
@ -60,11 +54,11 @@ const confirm = (config: ModalFuncProps) => {
}
}
const Wrapper = (p: ModalFuncProps) => {
const { getPrefixCls } = globalConfig();
const rootPrefixCls = getPrefixCls(undefined, getRootPrefixCls());
const global = globalConfigForApi;
const rootPrefixCls = global.prefixCls;
const prefixCls = p.prefixCls || `${rootPrefixCls}-modal`;
return (
<ConfigProvider prefixCls={rootPrefixCls}>
<ConfigProvider {...(global as any)} notUpdateGlobalConfig={true} prefixCls={rootPrefixCls}>
<ConfirmDialog {...p} prefixCls={prefixCls}></ConfirmDialog>
</ConfigProvider>
);

View File

@ -1,29 +1,5 @@
import { ref } from 'vue';
import defaultLocale from '../locale/default';
export interface ModalLocale {
okText: string;
cancelText: string;
justOkText: string;
}
const runtimeLocale = ref({
...defaultLocale.Modal,
});
export function changeConfirmLocale(newLocale?: ModalLocale) {
if (newLocale) {
runtimeLocale.value = {
...runtimeLocale,
...newLocale,
};
} else {
runtimeLocale.value = {
...defaultLocale.Modal,
};
}
}
export function getConfirmLocale() {
return runtimeLocale.value;
}

View File

@ -5,7 +5,7 @@ import BaseMixin from '../_util/BaseMixin';
import createChainedFunction from '../_util/createChainedFunction';
import Notice from './Notice';
import { getTransitionGroupProps, TransitionGroup } from '../_util/transition';
import ConfigProvider, { globalConfig } from '../config-provider';
import ConfigProvider, { globalConfigForApi } from '../config-provider';
function noop() {}
@ -158,11 +158,11 @@ Notification.newInstance = function newNotificationInstance(properties, callback
});
});
return () => {
const { getPrefixCls, getRootPrefixCls } = globalConfig();
const prefixCls = getPrefixCls(name, customizePrefixCls);
const rootPrefixCls = getRootPrefixCls(customRootPrefixCls, prefixCls);
const global = globalConfigForApi;
const prefixCls = global.getPrefixCls(name, customizePrefixCls);
const rootPrefixCls = global.getRootPrefixCls(customRootPrefixCls, prefixCls);
return (
<ConfigProvider prefixCls={rootPrefixCls}>
<ConfigProvider {...global} notUpdateGlobalConfig={true} prefixCls={rootPrefixCls}>
<Notification ref={notiRef} {...attrs} prefixCls={prefixCls} />
</ConfigProvider>
);

View File

@ -1,7 +1,8 @@
// debugger tsx
import Demo from '../../components/tabs/demo/card-top.vue';
import Demo from './demo/demo.vue';
export default {
setup() {},
render() {
return <Demo />;
},