Skip to content

Commit ef818fd

Browse files
authored
fix(ui): admin.dependencies components not added to client config (#7928)
1 parent 0aaf3af commit ef818fd

File tree

6 files changed

+104
-2
lines changed

6 files changed

+104
-2
lines changed

docs/admin/components.mdx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,48 @@ import { MyFieldComponent } from 'my-external-package/client'
196196

197197
which is a valid way to access MyFieldComponent that can be resolved by the consuming project.
198198

199+
### Custom Components from unknown locations
200+
201+
By default, any component paths from known locations are added to the import map. However, if you need to add any components from unknown locations to the import map, you can do so by adding them to the `admin.dependencies` array in your Payload Config. This is mostly only relevant for plugin authors and not for regular Payload users.
202+
203+
Example:
204+
205+
```ts
206+
export default {
207+
// ...
208+
admin: {
209+
// ...
210+
dependencies: {
211+
myTestComponent: { // myTestComponent is the key - can be anything
212+
path: '/components/TestComponent.js#TestComponent',
213+
type: 'component',
214+
clientProps: {
215+
test: 'hello',
216+
},
217+
},
218+
},
219+
}
220+
}
221+
```
222+
223+
This way, `TestComponent` is added to the import map, no matter if it's referenced in a known location or not. On the client, you can then use the component like this:
224+
225+
```tsx
226+
'use client'
227+
228+
import { RenderComponent, useConfig } from '@payloadcms/ui'
229+
import React from 'react'
230+
231+
export const CustomView = () => {
232+
const { config } = useConfig()
233+
return (
234+
<div>
235+
<RenderComponent mappedComponent={config.admin.dependencies?.myTestComponent} />
236+
</div>
237+
)
238+
}
239+
```
240+
199241
## Root Components
200242

201243
Root Components are those that effect the [Admin Panel](./overview) generally, such as the logo or the main nav.

packages/payload/src/config/client.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ export type ClientConfig = {
3939
Logo: MappedComponent
4040
}
4141
}
42+
dependencies?: Record<string, MappedComponent>
4243
livePreview?: Omit<LivePreviewConfig, ServerOnlyLivePreviewProperties>
43-
} & Omit<SanitizedConfig['admin'], 'components' | 'livePreview'>
44+
} & Omit<SanitizedConfig['admin'], 'components' | 'dependencies' | 'livePreview'>
4445
collections: ClientCollectionConfig[]
4546
custom?: Record<string, any>
4647
globals: ClientGlobalConfig[]

packages/ui/src/providers/Config/createClientConfig/index.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
type EditViewProps,
77
type ImportMap,
88
type Payload,
9+
type PayloadComponent,
910
type SanitizedConfig,
1011
deepCopyObjectSimple,
1112
serverOnlyConfigProperties,
@@ -113,6 +114,29 @@ export const createClientConfig = async ({
113114
'config.admin.components.graphics.Logo',
114115
)
115116
}
117+
118+
if (config.admin?.dependencies) {
119+
clientConfig.admin.dependencies = {}
120+
for (const key in config.admin.dependencies) {
121+
const dependency = config.admin.dependencies[key]
122+
123+
if (dependency.type === 'component') {
124+
const payloadComponent: PayloadComponent = {
125+
clientProps: dependency.clientProps,
126+
path: dependency.path,
127+
serverProps: dependency.serverProps,
128+
}
129+
130+
clientConfig.admin.dependencies[key] = createMappedComponent(
131+
payloadComponent,
132+
undefined,
133+
undefined,
134+
`config.admin.dependencies.${key}`,
135+
)
136+
continue
137+
}
138+
}
139+
}
116140
}
117141

118142
if (
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use client'
2+
import type { PayloadClientReactComponent, SanitizedConfig } from 'payload'
3+
4+
import { RenderComponent, useConfig } from '@payloadcms/ui'
5+
import React from 'react'
6+
7+
export const AfterDashboardClient: PayloadClientReactComponent<
8+
SanitizedConfig['admin']['components']['afterDashboard'][0]
9+
> = () => {
10+
const { config } = useConfig()
11+
return (
12+
<div>
13+
<p>Admin Dependency test component:</p>
14+
<RenderComponent mappedComponent={config.admin.dependencies?.myTestComponent} />
15+
</div>
16+
)
17+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use client'
2+
import React from 'react'
3+
4+
export const TestComponent: React.FC = () => {
5+
return <div>Test Component</div>
6+
}

test/admin/config.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ export default buildConfigWithDefaults({
4141
},
4242
components: {
4343
actions: ['/components/AdminButton/index.js#AdminButton'],
44-
afterDashboard: ['/components/AfterDashboard/index.js#AfterDashboard'],
44+
afterDashboard: [
45+
'/components/AfterDashboard/index.js#AfterDashboard',
46+
'/components/AfterDashboardClient/index.js#AfterDashboardClient',
47+
],
4548
afterNavLinks: ['/components/AfterNavLinks/index.js#AfterNavLinks'],
4649
beforeLogin: ['/components/BeforeLogin/index.js#BeforeLogin'],
4750
logout: {
@@ -104,6 +107,15 @@ export default buildConfigWithDefaults({
104107
titleSuffix: '- Custom Title Suffix',
105108
},
106109
routes: customAdminRoutes,
110+
dependencies: {
111+
myTestComponent: {
112+
path: '/components/TestComponent.js#TestComponent',
113+
type: 'component',
114+
clientProps: {
115+
test: 'hello',
116+
},
117+
},
118+
},
107119
},
108120
collections: [
109121
UploadCollection,

0 commit comments

Comments
 (0)