ant-design/components/config-provider/index.tsx
zombieJ 4cdf37bedb
feat: New Form (#17327)
* init form

* first demo

* add normal login

* add style

* webit

* support nest errors

* beauti form errors

* use onReset

* modal demo

* add list demo

* match key of errors logic

* date demo

* customize component

* moving style

* add status style

* without form create

* add demos

* add inline style

* clean up legacy

* fix drawer demo

* mention

* fix edit-row

* editable table cell

* update mentions demo

* fix some test case

* fix upload test

* fix lint

* part of doc

* fix ts

* doc update

* rm react 15

* rm config

* enhance test coverage

* clean up

* fix FormItem context pass logic

* add more demo

* en to build

* update demo

* update demo & snapshot

* more doc

* update list doc

* update doc

* update demo to display condition render

* update snapshot

* add provider doc

* support configProvider

* more doc about validateMessages

* more description

* more and more doc

* fix typo

* en doc

* Form.List doc

* m v3 -> v4

* add skip
2019-07-03 20:14:39 +08:00

149 lines
4.1 KiB
TypeScript

import * as React from 'react';
import { FormProvider as RcFormProvider } from 'rc-field-form';
import { ValidateMessages } from 'rc-field-form/lib/interface';
import defaultRenderEmpty, { RenderEmptyHandler } from './renderEmpty';
export { RenderEmptyHandler };
export interface CSPConfig {
nonce?: string;
}
export interface ConfigConsumerProps {
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
rootPrefixCls?: string;
getPrefixCls: (suffixCls: string, customizePrefixCls?: string) => string;
renderEmpty: RenderEmptyHandler;
csp?: CSPConfig;
autoInsertSpaceInButton?: boolean;
}
export const configConsumerProps = [
'getPopupContainer',
'rootPrefixCls',
'getPrefixCls',
'renderEmpty',
'csp',
'autoInsertSpaceInButton',
];
export interface ConfigProviderProps {
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
prefixCls?: string;
children?: React.ReactNode;
renderEmpty?: RenderEmptyHandler;
csp?: CSPConfig;
autoInsertSpaceInButton?: boolean;
form?: {
validateMessages?: ValidateMessages;
};
}
export const ConfigContext = React.createContext<ConfigConsumerProps>({
// We provide a default function for Context without provider
getPrefixCls: (suffixCls: string, customizePrefixCls?: string) => {
if (customizePrefixCls) return customizePrefixCls;
return `ant-${suffixCls}`;
},
renderEmpty: defaultRenderEmpty,
});
export const ConfigConsumer = ConfigContext.Consumer;
class ConfigProvider extends React.Component<ConfigProviderProps> {
getPrefixCls = (suffixCls: string, customizePrefixCls?: string) => {
const { prefixCls = 'ant' } = this.props;
if (customizePrefixCls) return customizePrefixCls;
return suffixCls ? `${prefixCls}-${suffixCls}` : prefixCls;
};
renderProvider = (context: ConfigConsumerProps) => {
const {
children,
getPopupContainer,
renderEmpty,
csp,
autoInsertSpaceInButton,
form,
} = this.props;
const config: ConfigConsumerProps = {
...context,
getPrefixCls: this.getPrefixCls,
csp,
autoInsertSpaceInButton,
};
if (getPopupContainer) {
config.getPopupContainer = getPopupContainer;
}
if (renderEmpty) {
config.renderEmpty = renderEmpty;
}
let childNode = children;
// Additional Form provider
if (form && form.validateMessages) {
childNode = (
<RcFormProvider validateMessages={form.validateMessages}>{children}</RcFormProvider>
);
}
return <ConfigContext.Provider value={config}>{childNode}</ConfigContext.Provider>;
};
render() {
return <ConfigConsumer>{this.renderProvider}</ConfigConsumer>;
}
}
// =========================== withConfigConsumer ===========================
// We need define many types here. So let's put in the block region
type IReactComponent<P = any> =
| React.StatelessComponent<P>
| React.ComponentClass<P>
| React.ClassicComponentClass<P>;
interface BasicExportProps {
prefixCls?: string;
}
interface ConsumerConfig {
prefixCls: string;
}
interface ConstructorProps {
displayName?: string;
}
export function withConfigConsumer<ExportProps extends BasicExportProps>(config: ConsumerConfig) {
return function<ComponentDef>(Component: IReactComponent): React.SFC<ExportProps> & ComponentDef {
// Wrap with ConfigConsumer. Since we need compatible with react 15, be care when using ref methods
const SFC = ((props: ExportProps) => (
<ConfigConsumer>
{(configProps: ConfigConsumerProps) => {
const { prefixCls: basicPrefixCls } = config;
const { getPrefixCls } = configProps;
const { prefixCls: customizePrefixCls } = props;
const prefixCls = getPrefixCls(basicPrefixCls, customizePrefixCls);
return <Component {...configProps} {...props} prefixCls={prefixCls} />;
}}
</ConfigConsumer>
)) as React.SFC<ExportProps> & ComponentDef;
const cons: ConstructorProps = Component.constructor as ConstructorProps;
const name = (cons && cons.displayName) || Component.name || 'Component';
SFC.displayName = `withConfigConsumer(${name})`;
return SFC;
};
}
export default ConfigProvider;