diff --git a/demo/client/components/CustomProvider/index.tsx b/demo/client/components/CustomProvider/index.tsx
new file mode 100644
index 0000000000..ea7f3e58d8
--- /dev/null
+++ b/demo/client/components/CustomProvider/index.tsx
@@ -0,0 +1,29 @@
+import React, { createContext, useState, useContext } from 'react';
+
+type CustomContext = {
+ getCustom
+ setCustom
+}
+
+const Context = createContext({} as CustomContext);
+
+const CustomProvider: React.FC = ({ children }) => {
+ const [getCustom, setCustom] = useState({});
+
+ const value = {
+ getCustom,
+ setCustom,
+ };
+
+ console.log('custom provider called');
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default CustomProvider;
+
+export const useCustom = () => useContext(Context);
diff --git a/demo/payload.config.ts b/demo/payload.config.ts
index 7e97f687aa..e2e906b23b 100644
--- a/demo/payload.config.ts
+++ b/demo/payload.config.ts
@@ -40,6 +40,7 @@ import CustomRouteWithDefaultTemplate from './client/components/views/CustomDefa
import AfterDashboard from './client/components/AfterDashboard';
import AfterNavLinks from './client/components/AfterNavLinks';
import BeforeLogin from './client/components/BeforeLogin';
+// import CustomProvider from './client/components/CustomProvider';
export default buildConfig({
cookiePrefix: 'payload',
@@ -58,6 +59,7 @@ export default buildConfig({
// disable: true,
scss: path.resolve(__dirname, './client/scss/overrides.scss'),
components: {
+ // providers: [CustomProvider, CustomProvider],
routes: [
{
path: '/custom-minimal-route',
diff --git a/docs/admin/components.mdx b/docs/admin/components.mdx
index c3b9af480d..cbb1d935ab 100644
--- a/docs/admin/components.mdx
+++ b/docs/admin/components.mdx
@@ -33,13 +33,14 @@ You can override a set of admin panel-wide components by providing a component t
| **`graphics.Icon`** | Used as a graphic within the `Nav` component. Often represents a condensed version of a full logo. |
| **`graphics.Logo`** | The full logo to be used in contexts like the `Login` view. |
| **`routes`** | Define your own routes to add to the Payload Admin UI. [More](#custom-routes) |
+| **`providers`** | Define your own provider components that will wrap the Payload Admin UI. [More](#custom-providers) |
#### Full example:
`payload.config.js`
```js
import { buildConfig } from 'payload/config';
-import { MyCustomNav, MyCustomLogo, MyCustomIcon, MyCustomAccount, MyCustomDashboard } from './customComponents.js';
+import { MyCustomNav, MyCustomLogo, MyCustomIcon, MyCustomAccount, MyCustomDashboard, MyProvider } from './customComponents.js';
export default buildConfig({
admin: {
@@ -52,7 +53,8 @@ export default buildConfig({
views: {
Account: MyCustomAccount,
Dashboard: MyCustomDashboard,
- }
+ },
+ providers: [MyProvider],
}
}
})
@@ -152,6 +154,12 @@ You can find examples of custom route views in the [Payload source code `/demo/c
To see how to pass in your custom views to create custom routes of your own, take a look at the `admin.components.routes` property of the [Payload demo config](https://github.com/payloadcms/payload/blob/master/demo/payload.config.ts).
+## Custom providers
+
+As your admin customizations gets more complex you may want to share state between fields or other components. You can add custom providers to do add your own context to any Payload app for use in other custom components within the admin panel. Within your config add `admin.components.providers`, these can be used to share context or provide other custom functionality. Read the [React context](https://reactjs.org/docs/context.html) docs to learn more.
+
+Remember to pass the `children` prop in to your provider component and return it within to render the admin UI
+
### Styling Custom Components
Payload exports its SCSS variables and mixins for reuse in your own custom components. This is helpful in cases where you might want to style a custom input similarly to Payload's built-ini styling so it blends more thoroughly into the existing admin UI.
diff --git a/src/admin/components/forms/field-types/RichText/RichText.tsx b/src/admin/components/forms/field-types/RichText/RichText.tsx
index 95f6aaff01..0cacaf77e1 100644
--- a/src/admin/components/forms/field-types/RichText/RichText.tsx
+++ b/src/admin/components/forms/field-types/RichText/RichText.tsx
@@ -272,6 +272,7 @@ const RichText: React.FC = (props) => {
ref={editorRef}
>
{
+ const Component = providers[0];
+ if (providers.length > 1) {
+ return (
+
+
+ {children}
+
+
+ );
+ }
+ return (
+
+ {children}
+
+ );
+};
+
+export const CustomProvider: React.FC<{ children }> = ({ children }) => {
+ const config = useConfig();
+
+ const {
+ admin: {
+ components: {
+ providers,
+ },
+ },
+ } = config;
+
+ if (Array.isArray(providers) && providers.length > 0) {
+ return (
+
+ {children}
+
+ );
+ }
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/admin/index.tsx b/src/admin/index.tsx
index dd983e89fd..76ce6ad2a7 100644
--- a/src/admin/index.tsx
+++ b/src/admin/index.tsx
@@ -10,6 +10,7 @@ import { ModalProvider, ModalContainer } from '@faceless-ui/modal';
import { ToastContainer, Slide } from 'react-toastify';
import { ConfigProvider, AuthProvider } from '@payloadcms/config-provider';
import { PreferencesProvider } from './components/utilities/Preferences';
+import { CustomProvider } from './components/utilities/CustomProvider';
import { SearchParamsProvider } from './components/utilities/SearchParams';
import { LocaleProvider } from './components/utilities/Locale';
import Routes from './components/Routes';
@@ -38,7 +39,9 @@ const Index = () => (
-
+
+
+
diff --git a/src/config/schema.ts b/src/config/schema.ts
index aa6a996244..8e4406c185 100644
--- a/src/config/schema.ts
+++ b/src/config/schema.ts
@@ -59,6 +59,7 @@ export default joi.object({
sensitive: joi.bool(),
}),
),
+ providers: joi.array().items(component),
beforeDashboard: joi.array().items(component),
afterDashboard: joi.array().items(component),
beforeLogin: joi.array().items(component),
diff --git a/src/config/types.ts b/src/config/types.ts
index b952f71fdc..6ad3fb4d71 100644
--- a/src/config/types.ts
+++ b/src/config/types.ts
@@ -102,6 +102,7 @@ export type Config = {
dateFormat?: string
components?: {
routes?: AdminRoute[]
+ providers?: React.ComponentType[]
beforeDashboard?: React.ComponentType[]
afterDashboard?: React.ComponentType[]
beforeLogin?: React.ComponentType[]