@veiag/payload-enhanced-sidebar 0.2.0 → 0.3.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -5
- package/dist/components/EnhancedSidebar/NavContent/index.d.ts +3 -0
- package/dist/components/EnhancedSidebar/NavContent/index.js +34 -0
- package/dist/components/EnhancedSidebar/NavContent/index.js.map +1 -0
- package/dist/components/EnhancedSidebar/NavItem/index.d.ts +0 -2
- package/dist/components/EnhancedSidebar/NavItem/index.js +3 -1
- package/dist/components/EnhancedSidebar/NavItem/index.js.map +1 -1
- package/dist/components/EnhancedSidebar/SidebarContent.d.ts +6 -4
- package/dist/components/EnhancedSidebar/SidebarContent.js +31 -140
- package/dist/components/EnhancedSidebar/SidebarContent.js.map +1 -1
- package/dist/components/EnhancedSidebar/TabsBar/TabItem.d.ts +2 -0
- package/dist/components/EnhancedSidebar/TabsBar/TabItem.js +4 -4
- package/dist/components/EnhancedSidebar/TabsBar/TabItem.js.map +1 -1
- package/dist/components/EnhancedSidebar/TabsBar/index.d.ts +2 -0
- package/dist/components/EnhancedSidebar/TabsBar/index.js +4 -2
- package/dist/components/EnhancedSidebar/TabsBar/index.js.map +1 -1
- package/dist/components/EnhancedSidebar/context.d.ts +6 -0
- package/dist/components/EnhancedSidebar/context.js +9 -0
- package/dist/components/EnhancedSidebar/context.js.map +1 -0
- package/dist/components/EnhancedSidebar/hooks/useNavItemState.d.ts +23 -0
- package/dist/components/EnhancedSidebar/hooks/useNavItemState.js +32 -0
- package/dist/components/EnhancedSidebar/hooks/useNavItemState.js.map +1 -0
- package/dist/components/EnhancedSidebar/hooks/useTabState.d.ts +13 -0
- package/dist/components/EnhancedSidebar/hooks/useTabState.js +19 -0
- package/dist/components/EnhancedSidebar/hooks/useTabState.js.map +1 -0
- package/dist/components/EnhancedSidebar/index.js +286 -9
- package/dist/components/EnhancedSidebar/index.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +243 -14
- package/dist/types.js.map +1 -1
- package/dist/utils/index.d.ts +8 -1
- package/dist/utils/index.js +14 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/components/EnhancedSidebar/index.client.d.ts +0 -8
- package/dist/components/EnhancedSidebar/index.client.js +0 -87
- package/dist/components/EnhancedSidebar/index.client.js.map +0 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type EnhancedSidebarContextValue = {
|
|
2
|
+
activeTabId: string;
|
|
3
|
+
onTabChange: (tabId: string) => void;
|
|
4
|
+
};
|
|
5
|
+
export declare const EnhancedSidebarContext: import("react").Context<EnhancedSidebarContextValue>;
|
|
6
|
+
export declare const useEnhancedSidebar: () => EnhancedSidebarContextValue;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
export const EnhancedSidebarContext = createContext({
|
|
4
|
+
activeTabId: '',
|
|
5
|
+
onTabChange: ()=>{}
|
|
6
|
+
});
|
|
7
|
+
export const useEnhancedSidebar = ()=>useContext(EnhancedSidebarContext);
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/EnhancedSidebar/context.ts"],"sourcesContent":["'use client'\n\nimport { createContext, useContext } from 'react'\n\nexport type EnhancedSidebarContextValue = {\n activeTabId: string\n onTabChange: (tabId: string) => void\n}\n\nexport const EnhancedSidebarContext = createContext<EnhancedSidebarContextValue>({\n activeTabId: '',\n onTabChange: () => {},\n})\n\nexport const useEnhancedSidebar = () => useContext(EnhancedSidebarContext)\n"],"names":["createContext","useContext","EnhancedSidebarContext","activeTabId","onTabChange","useEnhancedSidebar"],"mappings":"AAAA;AAEA,SAASA,aAAa,EAAEC,UAAU,QAAQ,QAAO;AAOjD,OAAO,MAAMC,yBAAyBF,cAA2C;IAC/EG,aAAa;IACbC,aAAa,KAAO;AACtB,GAAE;AAEF,OAAO,MAAMC,qBAAqB,IAAMJ,WAAWC,wBAAuB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook to get the active state of a nav item based on the current pathname.
|
|
3
|
+
* Use this in your custom NavItem component registered via `customComponents.NavItem`.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* 'use client'
|
|
8
|
+
* import { useNavItemState } from '@veiag/payload-enhanced-sidebar'
|
|
9
|
+
*
|
|
10
|
+
* export const MyNavItem = ({ href, label }) => {
|
|
11
|
+
* const { isActive, isCurrentPage } = useNavItemState(href)
|
|
12
|
+
* return (
|
|
13
|
+
* <a href={href} style={{ fontWeight: isActive ? 'bold' : 'normal' }}>
|
|
14
|
+
* {label}
|
|
15
|
+
* </a>
|
|
16
|
+
* )
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare const useNavItemState: (href: string) => {
|
|
21
|
+
isActive: boolean;
|
|
22
|
+
isCurrentPage: boolean;
|
|
23
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { usePathname } from 'next/navigation';
|
|
3
|
+
/**
|
|
4
|
+
* Hook to get the active state of a nav item based on the current pathname.
|
|
5
|
+
* Use this in your custom NavItem component registered via `customComponents.NavItem`.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* 'use client'
|
|
10
|
+
* import { useNavItemState } from '@veiag/payload-enhanced-sidebar'
|
|
11
|
+
*
|
|
12
|
+
* export const MyNavItem = ({ href, label }) => {
|
|
13
|
+
* const { isActive, isCurrentPage } = useNavItemState(href)
|
|
14
|
+
* return (
|
|
15
|
+
* <a href={href} style={{ fontWeight: isActive ? 'bold' : 'normal' }}>
|
|
16
|
+
* {label}
|
|
17
|
+
* </a>
|
|
18
|
+
* )
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/ export const useNavItemState = (href)=>{
|
|
22
|
+
const pathname = usePathname();
|
|
23
|
+
return {
|
|
24
|
+
isActive: pathname.startsWith(href) && [
|
|
25
|
+
'/',
|
|
26
|
+
undefined
|
|
27
|
+
].includes(pathname[href.length]),
|
|
28
|
+
isCurrentPage: pathname === href
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=useNavItemState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/EnhancedSidebar/hooks/useNavItemState.ts"],"sourcesContent":["'use client'\n\nimport { usePathname } from 'next/navigation'\n\n/**\n * Hook to get the active state of a nav item based on the current pathname.\n * Use this in your custom NavItem component registered via `customComponents.NavItem`.\n *\n * @example\n * ```tsx\n * 'use client'\n * import { useNavItemState } from '@veiag/payload-enhanced-sidebar'\n *\n * export const MyNavItem = ({ href, label }) => {\n * const { isActive, isCurrentPage } = useNavItemState(href)\n * return (\n * <a href={href} style={{ fontWeight: isActive ? 'bold' : 'normal' }}>\n * {label}\n * </a>\n * )\n * }\n * ```\n */\nexport const useNavItemState = (href: string): { isActive: boolean; isCurrentPage: boolean } => {\n const pathname = usePathname()\n return {\n isActive: pathname.startsWith(href) && ['/', undefined].includes(pathname[href.length]),\n isCurrentPage: pathname === href,\n }\n}\n"],"names":["usePathname","useNavItemState","href","pathname","isActive","startsWith","undefined","includes","length","isCurrentPage"],"mappings":"AAAA;AAEA,SAASA,WAAW,QAAQ,kBAAiB;AAE7C;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,MAAMC,kBAAkB,CAACC;IAC9B,MAAMC,WAAWH;IACjB,OAAO;QACLI,UAAUD,SAASE,UAAU,CAACH,SAAS;YAAC;YAAKI;SAAU,CAACC,QAAQ,CAACJ,QAAQ,CAACD,KAAKM,MAAM,CAAC;QACtFC,eAAeN,aAAaD;IAC9B;AACF,EAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns whether a sidebar tab is currently active.
|
|
3
|
+
* Use this inside a custom `NavContent` component to show/hide tab content.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* const { isActive } = useTabState('my-tab-id')
|
|
8
|
+
* return <div style={{ display: isActive ? undefined : 'none' }}>{children}</div>
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export declare const useTabState: (id: string) => {
|
|
12
|
+
isActive: boolean;
|
|
13
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEnhancedSidebar } from '../context';
|
|
3
|
+
/**
|
|
4
|
+
* Returns whether a sidebar tab is currently active.
|
|
5
|
+
* Use this inside a custom `NavContent` component to show/hide tab content.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const { isActive } = useTabState('my-tab-id')
|
|
10
|
+
* return <div style={{ display: isActive ? undefined : 'none' }}>{children}</div>
|
|
11
|
+
* ```
|
|
12
|
+
*/ export const useTabState = (id)=>{
|
|
13
|
+
const { activeTabId } = useEnhancedSidebar();
|
|
14
|
+
return {
|
|
15
|
+
isActive: activeTabId === id
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=useTabState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/EnhancedSidebar/hooks/useTabState.ts"],"sourcesContent":["'use client'\n\nimport { useEnhancedSidebar } from '../context'\n\n/**\n * Returns whether a sidebar tab is currently active.\n * Use this inside a custom `NavContent` component to show/hide tab content.\n *\n * @example\n * ```tsx\n * const { isActive } = useTabState('my-tab-id')\n * return <div style={{ display: isActive ? undefined : 'none' }}>{children}</div>\n * ```\n */\nexport const useTabState = (id: string): { isActive: boolean } => {\n const { activeTabId } = useEnhancedSidebar()\n return { isActive: activeTabId === id }\n}\n"],"names":["useEnhancedSidebar","useTabState","id","activeTabId","isActive"],"mappings":"AAAA;AAEA,SAASA,kBAAkB,QAAQ,aAAY;AAE/C;;;;;;;;;CASC,GACD,OAAO,MAAMC,cAAc,CAACC;IAC1B,MAAM,EAAEC,WAAW,EAAE,GAAGH;IACxB,OAAO;QAAEI,UAAUD,gBAAgBD;IAAG;AACxC,EAAC"}
|
|
@@ -1,14 +1,105 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { getTranslation } from '@payloadcms/translations';
|
|
2
3
|
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent';
|
|
4
|
+
import { NavGroup } from '@payloadcms/ui';
|
|
3
5
|
import { EntityType, groupNavItems } from '@payloadcms/ui/shared';
|
|
4
6
|
import { cookies } from 'next/headers';
|
|
5
|
-
import
|
|
7
|
+
import { formatAdminURL } from 'payload/shared';
|
|
8
|
+
import React, { Fragment } from 'react';
|
|
6
9
|
const COOKIE_KEY = 'payload-enhanced-sidebar-active-tab';
|
|
10
|
+
import { extractLocalizedValue, resolveSidebarComponent } from '../../utils';
|
|
7
11
|
import { getNavPrefs } from './getNavPrefs';
|
|
12
|
+
import { Icon } from './Icon';
|
|
13
|
+
import { NavItem } from './NavItem';
|
|
8
14
|
import { SidebarContent } from './SidebarContent';
|
|
9
15
|
import './index.scss';
|
|
16
|
+
/**
|
|
17
|
+
* Computes filtered and merged groups for a specific tab (server-side).
|
|
18
|
+
*/ const computeGroupsForTab = (tab, groups, currentLang)=>{
|
|
19
|
+
const { collections: tabCollections, customItems, globals: tabGlobals } = tab;
|
|
20
|
+
const showAll = !tabCollections && !tabGlobals;
|
|
21
|
+
const allowedSlugs = new Set([
|
|
22
|
+
...tabCollections ?? [],
|
|
23
|
+
...tabGlobals ?? []
|
|
24
|
+
]);
|
|
25
|
+
let result = [];
|
|
26
|
+
if (showAll) {
|
|
27
|
+
result = groups.map((g)=>({
|
|
28
|
+
...g,
|
|
29
|
+
entities: [
|
|
30
|
+
...g.entities
|
|
31
|
+
]
|
|
32
|
+
}));
|
|
33
|
+
} else if (allowedSlugs.size > 0) {
|
|
34
|
+
result = groups.map((group)=>({
|
|
35
|
+
...group,
|
|
36
|
+
entities: group.entities.filter((entity)=>allowedSlugs.has(entity.slug))
|
|
37
|
+
})).filter((group)=>group.entities.length > 0);
|
|
38
|
+
}
|
|
39
|
+
if (customItems && customItems.length > 0) {
|
|
40
|
+
const topAdditions = [];
|
|
41
|
+
const topUngrouped = [];
|
|
42
|
+
const bottomUngrouped = [];
|
|
43
|
+
const toEntity = (item)=>({
|
|
44
|
+
slug: item.slug,
|
|
45
|
+
type: 'custom',
|
|
46
|
+
href: item.href,
|
|
47
|
+
isExternal: item.isExternal,
|
|
48
|
+
label: item.label
|
|
49
|
+
});
|
|
50
|
+
for (const item of customItems){
|
|
51
|
+
if (item.group) {
|
|
52
|
+
const itemGroupLabel = extractLocalizedValue(item.group, currentLang);
|
|
53
|
+
const existingGroup = result.find((g)=>{
|
|
54
|
+
const groupLabel = extractLocalizedValue(g.label, currentLang);
|
|
55
|
+
return groupLabel === itemGroupLabel;
|
|
56
|
+
});
|
|
57
|
+
if (existingGroup) {
|
|
58
|
+
// Merged into existing collection group — position has no effect here
|
|
59
|
+
existingGroup.entities.push(toEntity(item));
|
|
60
|
+
} else {
|
|
61
|
+
// New custom group — position controls top vs bottom
|
|
62
|
+
const newGroup = {
|
|
63
|
+
entities: [
|
|
64
|
+
toEntity(item)
|
|
65
|
+
],
|
|
66
|
+
label: item.group
|
|
67
|
+
};
|
|
68
|
+
if (item.position === 'top') {
|
|
69
|
+
topAdditions.push(newGroup);
|
|
70
|
+
} else {
|
|
71
|
+
result.push(newGroup);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
if (item.position === 'top') {
|
|
76
|
+
topUngrouped.push(item);
|
|
77
|
+
} else {
|
|
78
|
+
bottomUngrouped.push(item);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (topUngrouped.length > 0) {
|
|
83
|
+
topAdditions.unshift({
|
|
84
|
+
entities: topUngrouped.map(toEntity),
|
|
85
|
+
label: ''
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (bottomUngrouped.length > 0) {
|
|
89
|
+
result.push({
|
|
90
|
+
entities: bottomUngrouped.map(toEntity),
|
|
91
|
+
label: ''
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
result = [
|
|
95
|
+
...topAdditions,
|
|
96
|
+
...result
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
};
|
|
10
101
|
export const EnhancedSidebar = async (props)=>{
|
|
11
|
-
const { i18n, locale, params, payload, permissions, req, searchParams, sidebarConfig, user, visibleEntities } = props;
|
|
102
|
+
const { i18n, locale, params, payload, permissions, req, searchParams, sidebarConfig, user, visibleEntities, documentSubViewType, viewType } = props;
|
|
12
103
|
if (!payload?.config) {
|
|
13
104
|
return null;
|
|
14
105
|
}
|
|
@@ -33,23 +124,29 @@ export const EnhancedSidebar = async (props)=>{
|
|
|
33
124
|
searchParams,
|
|
34
125
|
user
|
|
35
126
|
};
|
|
127
|
+
const clientProps = {
|
|
128
|
+
documentSubViewType,
|
|
129
|
+
viewType
|
|
130
|
+
};
|
|
36
131
|
const beforeNavLinksRendered = RenderServerComponent({
|
|
37
132
|
Component: beforeNavLinks,
|
|
38
133
|
importMap: payload.importMap,
|
|
39
|
-
serverProps
|
|
134
|
+
serverProps,
|
|
135
|
+
clientProps
|
|
40
136
|
});
|
|
41
137
|
const afterNavLinksRendered = RenderServerComponent({
|
|
42
138
|
Component: afterNavLinks,
|
|
43
139
|
importMap: payload.importMap,
|
|
44
|
-
serverProps
|
|
140
|
+
serverProps,
|
|
141
|
+
clientProps
|
|
45
142
|
});
|
|
46
143
|
const renderedSettingsMenu = settingsMenu && Array.isArray(settingsMenu) ? settingsMenu.map((item, index)=>RenderServerComponent({
|
|
47
144
|
Component: item,
|
|
48
145
|
importMap: payload.importMap,
|
|
49
146
|
key: `settings-menu-item-${index}`,
|
|
50
|
-
serverProps
|
|
147
|
+
serverProps,
|
|
148
|
+
clientProps
|
|
51
149
|
})) : [];
|
|
52
|
-
// Default config if not provided
|
|
53
150
|
const config = sidebarConfig ?? {
|
|
54
151
|
tabs: [
|
|
55
152
|
{
|
|
@@ -66,14 +163,194 @@ export const EnhancedSidebar = async (props)=>{
|
|
|
66
163
|
const tabs = config.tabs?.filter((t)=>t.type === 'tab') ?? [];
|
|
67
164
|
const defaultTabId = tabs[0]?.id ?? 'default';
|
|
68
165
|
const initialActiveTabId = storedTabId && tabs.some((t)=>t.id === storedTabId) ? storedTabId : defaultTabId;
|
|
166
|
+
const adminRoute = payload.config.routes.admin;
|
|
167
|
+
const currentLang = i18n.language;
|
|
168
|
+
/**
|
|
169
|
+
* Renders a single entity as a NavItem (default or custom).
|
|
170
|
+
*/ const renderEntity = (entity, key)=>{
|
|
171
|
+
const { slug, type } = entity;
|
|
172
|
+
let href;
|
|
173
|
+
let id;
|
|
174
|
+
if (type === 'collection') {
|
|
175
|
+
href = formatAdminURL({
|
|
176
|
+
adminRoute,
|
|
177
|
+
path: `/collections/${slug}`
|
|
178
|
+
});
|
|
179
|
+
id = `nav-${slug}`;
|
|
180
|
+
} else if (type === 'global') {
|
|
181
|
+
href = formatAdminURL({
|
|
182
|
+
adminRoute,
|
|
183
|
+
path: `/globals/${slug}`
|
|
184
|
+
});
|
|
185
|
+
id = `nav-global-${slug}`;
|
|
186
|
+
} else if (type === 'custom' && entity.href) {
|
|
187
|
+
id = `nav-custom-${slug}`;
|
|
188
|
+
href = entity.isExternal ? entity.href : formatAdminURL({
|
|
189
|
+
adminRoute,
|
|
190
|
+
path: entity.href
|
|
191
|
+
});
|
|
192
|
+
} else {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const badgeConfig = config.badges?.[slug];
|
|
196
|
+
if (config.customComponents?.NavItem) {
|
|
197
|
+
const label = getTranslation(entity.label, i18n);
|
|
198
|
+
const { path, clientProps: extraProps } = resolveSidebarComponent(config.customComponents.NavItem);
|
|
199
|
+
return RenderServerComponent({
|
|
200
|
+
Component: path,
|
|
201
|
+
importMap: payload.importMap,
|
|
202
|
+
key,
|
|
203
|
+
clientProps: {
|
|
204
|
+
entity,
|
|
205
|
+
href,
|
|
206
|
+
id,
|
|
207
|
+
badgeConfig,
|
|
208
|
+
label,
|
|
209
|
+
...extraProps
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return /*#__PURE__*/ _jsx(NavItem, {
|
|
214
|
+
badgeConfig: badgeConfig,
|
|
215
|
+
entity: entity,
|
|
216
|
+
href: href,
|
|
217
|
+
id: id
|
|
218
|
+
}, key);
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* Renders a group with its entities (default NavGroup or custom).
|
|
222
|
+
*/ const renderGroup = (group, key)=>{
|
|
223
|
+
const { entities, label } = group;
|
|
224
|
+
const isUngrouped = !label || typeof label === 'string' && label === '';
|
|
225
|
+
const translatedLabel = getTranslation(label || '', i18n);
|
|
226
|
+
const items = entities.map((entity, i)=>renderEntity(entity, `${key}-${i}`));
|
|
227
|
+
if (isUngrouped) {
|
|
228
|
+
return /*#__PURE__*/ _jsx(Fragment, {
|
|
229
|
+
children: items
|
|
230
|
+
}, key);
|
|
231
|
+
}
|
|
232
|
+
if (config.customComponents?.NavGroup) {
|
|
233
|
+
const { path, clientProps: extraProps } = resolveSidebarComponent(config.customComponents.NavGroup);
|
|
234
|
+
return RenderServerComponent({
|
|
235
|
+
Component: path,
|
|
236
|
+
importMap: payload.importMap,
|
|
237
|
+
key,
|
|
238
|
+
clientProps: {
|
|
239
|
+
label: translatedLabel,
|
|
240
|
+
isOpen: navPreferences?.groups?.[translatedLabel]?.open,
|
|
241
|
+
children: items,
|
|
242
|
+
...extraProps
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
return /*#__PURE__*/ _jsx(NavGroup, {
|
|
247
|
+
isOpen: navPreferences?.groups?.[translatedLabel]?.open,
|
|
248
|
+
label: translatedLabel,
|
|
249
|
+
children: items
|
|
250
|
+
}, key);
|
|
251
|
+
};
|
|
252
|
+
// Pre-render content for every tab on the server
|
|
253
|
+
const tabsContent = {};
|
|
254
|
+
for (const tab of tabs){
|
|
255
|
+
const tabGroups = computeGroupsForTab(tab, groups, currentLang);
|
|
256
|
+
tabsContent[tab.id] = /*#__PURE__*/ _jsx(Fragment, {
|
|
257
|
+
children: tabGroups.map((group, i)=>renderGroup(group, `${tab.id}-${i}`))
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
// For the no-tabs fallback
|
|
261
|
+
const allContent = tabs.length === 0 ? /*#__PURE__*/ _jsx(Fragment, {
|
|
262
|
+
children: groups.map((group, i)=>renderGroup(group, `all-${i}`))
|
|
263
|
+
}) : undefined;
|
|
264
|
+
// Build server-side icon and tab button rendering
|
|
265
|
+
const allTabItems = config.tabs ?? [];
|
|
266
|
+
const hasCustomTabButton = !!config.customComponents?.TabButton;
|
|
267
|
+
const hasAnyIconComponent = allTabItems.some((t)=>t.iconComponent);
|
|
268
|
+
// tabIcons: per-id icon node (only built when no custom TabButton, just iconComponent overrides)
|
|
269
|
+
const tabIcons = {};
|
|
270
|
+
// renderedTabItems: fully custom tab button nodes (built when customComponents.TabButton is set)
|
|
271
|
+
const renderedTabItems = [];
|
|
272
|
+
if (hasCustomTabButton || hasAnyIconComponent) {
|
|
273
|
+
for (const item of allTabItems){
|
|
274
|
+
const label = getTranslation(item.label, i18n);
|
|
275
|
+
// Resolve icon: custom iconComponent > default Lucide
|
|
276
|
+
let iconNode;
|
|
277
|
+
if (item.iconComponent) {
|
|
278
|
+
const { path: iconPath, clientProps: iconExtraProps } = resolveSidebarComponent(item.iconComponent);
|
|
279
|
+
iconNode = RenderServerComponent({
|
|
280
|
+
Component: iconPath,
|
|
281
|
+
importMap: payload.importMap,
|
|
282
|
+
clientProps: {
|
|
283
|
+
id: item.id,
|
|
284
|
+
label,
|
|
285
|
+
type: item.type,
|
|
286
|
+
...iconExtraProps
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
} else {
|
|
290
|
+
iconNode = /*#__PURE__*/ _jsx(Icon, {
|
|
291
|
+
name: item.icon,
|
|
292
|
+
size: 20
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
if (hasCustomTabButton) {
|
|
296
|
+
// Compute href for links
|
|
297
|
+
let href;
|
|
298
|
+
if (item.type === 'link') {
|
|
299
|
+
href = item.isExternal ? item.href : formatAdminURL({
|
|
300
|
+
adminRoute,
|
|
301
|
+
path: item.href
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
const { path: tabBtnPath, clientProps: tabBtnExtraProps } = resolveSidebarComponent(config.customComponents.TabButton);
|
|
305
|
+
renderedTabItems.push(RenderServerComponent({
|
|
306
|
+
Component: tabBtnPath,
|
|
307
|
+
importMap: payload.importMap,
|
|
308
|
+
key: item.id,
|
|
309
|
+
clientProps: {
|
|
310
|
+
badge: item.badge,
|
|
311
|
+
href,
|
|
312
|
+
icon: iconNode,
|
|
313
|
+
id: item.id,
|
|
314
|
+
isExternal: item.type === 'link' ? item.isExternal : undefined,
|
|
315
|
+
label,
|
|
316
|
+
type: item.type,
|
|
317
|
+
...tabBtnExtraProps
|
|
318
|
+
}
|
|
319
|
+
}));
|
|
320
|
+
} else if (item.iconComponent) {
|
|
321
|
+
tabIcons[item.id] = iconNode;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const customNavContent = config.customComponents?.NavContent ? (()=>{
|
|
326
|
+
const { path, clientProps: extraProps } = resolveSidebarComponent(config.customComponents.NavContent);
|
|
327
|
+
return RenderServerComponent({
|
|
328
|
+
Component: path,
|
|
329
|
+
importMap: payload.importMap,
|
|
330
|
+
key: 'enhanced-sidebar-nav-content',
|
|
331
|
+
clientProps: {
|
|
332
|
+
afterNavLinks: afterNavLinksRendered,
|
|
333
|
+
allContent,
|
|
334
|
+
beforeNavLinks: beforeNavLinksRendered,
|
|
335
|
+
tabs: tabs.map((t)=>({
|
|
336
|
+
id: t.id
|
|
337
|
+
})),
|
|
338
|
+
tabsContent,
|
|
339
|
+
...extraProps
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
})() : undefined;
|
|
69
343
|
return /*#__PURE__*/ _jsx(SidebarContent, {
|
|
70
344
|
afterNavLinks: afterNavLinksRendered,
|
|
345
|
+
allContent: allContent,
|
|
71
346
|
beforeNavLinks: beforeNavLinksRendered,
|
|
72
|
-
|
|
347
|
+
customNavContent: customNavContent,
|
|
73
348
|
initialActiveTabId: initialActiveTabId,
|
|
74
|
-
|
|
349
|
+
renderedTabItems: renderedTabItems.length > 0 ? renderedTabItems : undefined,
|
|
75
350
|
settingsMenu: renderedSettingsMenu,
|
|
76
|
-
sidebarConfig: config
|
|
351
|
+
sidebarConfig: config,
|
|
352
|
+
tabIcons: Object.keys(tabIcons).length > 0 ? tabIcons : undefined,
|
|
353
|
+
tabsContent: tabsContent
|
|
77
354
|
});
|
|
78
355
|
};
|
|
79
356
|
export default EnhancedSidebar;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/EnhancedSidebar/index.tsx"],"sourcesContent":["import type { EntityToGroup } from '@payloadcms/ui/shared'\nimport type { PayloadRequest, ServerProps } from 'payload'\n\nimport { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'\nimport { EntityType, groupNavItems } from '@payloadcms/ui/shared'\nimport { cookies } from 'next/headers'\nimport React from 'react'\n\nconst COOKIE_KEY = 'payload-enhanced-sidebar-active-tab'\n\nimport type { EnhancedSidebarConfig, ExtendedGroup } from '../../types'\n\nimport { getNavPrefs } from './getNavPrefs'\nimport { SidebarContent } from './SidebarContent'\nimport './index.scss'\n\nexport type EnhancedSidebarProps = {\n req?: PayloadRequest\n sidebarConfig?: EnhancedSidebarConfig\n} & ServerProps\n\nexport const EnhancedSidebar: React.FC<EnhancedSidebarProps> = async (props) => {\n const {\n i18n,\n locale,\n params,\n payload,\n permissions,\n req,\n searchParams,\n sidebarConfig,\n user,\n visibleEntities,\n } = props\n\n if (!payload?.config) {\n return null\n }\n\n const {\n admin: {\n components: { afterNavLinks, beforeNavLinks, settingsMenu },\n },\n collections,\n globals,\n } = payload.config\n\n const groups = groupNavItems(\n [\n ...collections\n .filter(({ slug }) => visibleEntities?.collections.includes(slug))\n .map(\n (collection) =>\n ({\n type: EntityType.collection,\n entity: collection,\n }) satisfies EntityToGroup,\n ),\n ...globals\n .filter(({ slug }) => visibleEntities?.globals.includes(slug))\n .map(\n (global) =>\n ({\n type: EntityType.global,\n entity: global,\n }) satisfies EntityToGroup,\n ),\n ],\n permissions || {},\n i18n,\n ) as unknown as ExtendedGroup[]\n\n const navPreferences = await getNavPrefs(req)\n\n const serverProps = {\n i18n,\n locale,\n params,\n payload,\n permissions,\n searchParams,\n user,\n }\n\n const beforeNavLinksRendered = RenderServerComponent({\n Component: beforeNavLinks,\n importMap: payload.importMap,\n serverProps,\n })\n\n const afterNavLinksRendered = RenderServerComponent({\n Component: afterNavLinks,\n importMap: payload.importMap,\n serverProps,\n })\n\n const renderedSettingsMenu =\n settingsMenu && Array.isArray(settingsMenu)\n ? settingsMenu.map((item, index) =>\n RenderServerComponent({\n Component: item,\n importMap: payload.importMap,\n key: `settings-menu-item-${index}`,\n serverProps,\n }),\n )\n : []\n\n // Default config if not provided\n const config: EnhancedSidebarConfig = sidebarConfig ?? {\n tabs: [\n {\n id: 'default',\n type: 'tab',\n icon: 'LayoutGrid',\n label: 'Collections',\n },\n ],\n }\n\n // Read active tab from cookie\n const cookieStore = await cookies()\n const storedTabId = cookieStore.get(COOKIE_KEY)?.value\n const tabs = config.tabs?.filter((t) => t.type === 'tab') ?? []\n const defaultTabId = tabs[0]?.id ?? 'default'\n const initialActiveTabId =\n storedTabId && tabs.some((t) => t.id === storedTabId) ? storedTabId : defaultTabId\n\n return (\n <SidebarContent\n afterNavLinks={afterNavLinksRendered}\n beforeNavLinks={beforeNavLinksRendered}\n groups={groups}\n initialActiveTabId={initialActiveTabId}\n navPreferences={navPreferences}\n settingsMenu={renderedSettingsMenu}\n sidebarConfig={config}\n />\n )\n}\n\nexport default EnhancedSidebar\n"],"names":["RenderServerComponent","EntityType","groupNavItems","cookies","React","COOKIE_KEY","getNavPrefs","SidebarContent","EnhancedSidebar","props","i18n","locale","params","payload","permissions","req","searchParams","sidebarConfig","user","visibleEntities","config","admin","components","afterNavLinks","beforeNavLinks","settingsMenu","collections","globals","groups","filter","slug","includes","map","collection","type","entity","global","navPreferences","serverProps","beforeNavLinksRendered","Component","importMap","afterNavLinksRendered","renderedSettingsMenu","Array","isArray","item","index","key","tabs","id","icon","label","cookieStore","storedTabId","get","value","t","defaultTabId","initialActiveTabId","some"],"mappings":";AAGA,SAASA,qBAAqB,QAAQ,gDAA+C;AACrF,SAASC,UAAU,EAAEC,aAAa,QAAQ,wBAAuB;AACjE,SAASC,OAAO,QAAQ,eAAc;AACtC,OAAOC,WAAW,QAAO;AAEzB,MAAMC,aAAa;AAInB,SAASC,WAAW,QAAQ,gBAAe;AAC3C,SAASC,cAAc,QAAQ,mBAAkB;AACjD,OAAO,eAAc;AAOrB,OAAO,MAAMC,kBAAkD,OAAOC;IACpE,MAAM,EACJC,IAAI,EACJC,MAAM,EACNC,MAAM,EACNC,OAAO,EACPC,WAAW,EACXC,GAAG,EACHC,YAAY,EACZC,aAAa,EACbC,IAAI,EACJC,eAAe,EAChB,GAAGV;IAEJ,IAAI,CAACI,SAASO,QAAQ;QACpB,OAAO;IACT;IAEA,MAAM,EACJC,OAAO,EACLC,YAAY,EAAEC,aAAa,EAAEC,cAAc,EAAEC,YAAY,EAAE,EAC5D,EACDC,WAAW,EACXC,OAAO,EACR,GAAGd,QAAQO,MAAM;IAElB,MAAMQ,SAAS1B,cACb;WACKwB,YACAG,MAAM,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAKX,iBAAiBO,YAAYK,SAASD,OAC3DE,GAAG,CACF,CAACC,aACE,CAAA;gBACCC,MAAMjC,WAAWgC,UAAU;gBAC3BE,QAAQF;YACV,CAAA;WAEHN,QACAE,MAAM,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAKX,iBAAiBQ,QAAQI,SAASD,OACvDE,GAAG,CACF,CAACI,SACE,CAAA;gBACCF,MAAMjC,WAAWmC,MAAM;gBACvBD,QAAQC;YACV,CAAA;KAEP,EACDtB,eAAe,CAAC,GAChBJ;IAGF,MAAM2B,iBAAiB,MAAM/B,YAAYS;IAEzC,MAAMuB,cAAc;QAClB5B;QACAC;QACAC;QACAC;QACAC;QACAE;QACAE;IACF;IAEA,MAAMqB,yBAAyBvC,sBAAsB;QACnDwC,WAAWhB;QACXiB,WAAW5B,QAAQ4B,SAAS;QAC5BH;IACF;IAEA,MAAMI,wBAAwB1C,sBAAsB;QAClDwC,WAAWjB;QACXkB,WAAW5B,QAAQ4B,SAAS;QAC5BH;IACF;IAEA,MAAMK,uBACJlB,gBAAgBmB,MAAMC,OAAO,CAACpB,gBAC1BA,aAAaO,GAAG,CAAC,CAACc,MAAMC,QACtB/C,sBAAsB;YACpBwC,WAAWM;YACXL,WAAW5B,QAAQ4B,SAAS;YAC5BO,KAAK,CAAC,mBAAmB,EAAED,OAAO;YAClCT;QACF,MAEF,EAAE;IAER,iCAAiC;IACjC,MAAMlB,SAAgCH,iBAAiB;QACrDgC,MAAM;YACJ;gBACEC,IAAI;gBACJhB,MAAM;gBACNiB,MAAM;gBACNC,OAAO;YACT;SACD;IACH;IAEA,8BAA8B;IAC9B,MAAMC,cAAc,MAAMlD;IAC1B,MAAMmD,cAAcD,YAAYE,GAAG,CAAClD,aAAamD;IACjD,MAAMP,OAAO7B,OAAO6B,IAAI,EAAEpB,OAAO,CAAC4B,IAAMA,EAAEvB,IAAI,KAAK,UAAU,EAAE;IAC/D,MAAMwB,eAAeT,IAAI,CAAC,EAAE,EAAEC,MAAM;IACpC,MAAMS,qBACJL,eAAeL,KAAKW,IAAI,CAAC,CAACH,IAAMA,EAAEP,EAAE,KAAKI,eAAeA,cAAcI;IAExE,qBACE,KAACnD;QACCgB,eAAemB;QACflB,gBAAgBe;QAChBX,QAAQA;QACR+B,oBAAoBA;QACpBtB,gBAAgBA;QAChBZ,cAAckB;QACd1B,eAAeG;;AAGrB,EAAC;AAED,eAAeZ,gBAAe"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/EnhancedSidebar/index.tsx"],"sourcesContent":["import type { EntityToGroup } from '@payloadcms/ui/shared'\nimport type { PayloadRequest, ServerProps } from 'payload'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'\nimport { NavGroup } from '@payloadcms/ui'\nimport { EntityType, groupNavItems } from '@payloadcms/ui/shared'\nimport { cookies } from 'next/headers'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { Fragment } from 'react'\n\nconst COOKIE_KEY = 'payload-enhanced-sidebar-active-tab'\n\nimport type {\n EnhancedSidebarConfig,\n ExtendedEntity,\n ExtendedGroup,\n SidebarTab,\n SidebarTabContent as SidebarTabContentType,\n SidebarTabItem,\n} from '../../types'\n\nimport { extractLocalizedValue, resolveSidebarComponent } from '../../utils'\nimport { getNavPrefs } from './getNavPrefs'\nimport { Icon } from './Icon'\nimport { NavItem } from './NavItem'\nimport { SidebarContent } from './SidebarContent'\nimport './index.scss'\n\nexport type EnhancedSidebarProps = {\n req?: PayloadRequest\n sidebarConfig?: EnhancedSidebarConfig\n} & ServerProps\n\n/**\n * Computes filtered and merged groups for a specific tab (server-side).\n */\nconst computeGroupsForTab = (\n tab: SidebarTabContentType,\n groups: ExtendedGroup[],\n currentLang: string,\n): ExtendedGroup[] => {\n const { collections: tabCollections, customItems, globals: tabGlobals } = tab\n\n const showAll = !tabCollections && !tabGlobals\n const allowedSlugs = new Set([...(tabCollections ?? []), ...(tabGlobals ?? [])])\n\n let result: ExtendedGroup[] = []\n\n if (showAll) {\n result = groups.map((g) => ({ ...g, entities: [...g.entities] }))\n } else if (allowedSlugs.size > 0) {\n result = groups\n .map((group) => ({\n ...group,\n entities: group.entities.filter((entity) => allowedSlugs.has(entity.slug)),\n }))\n .filter((group) => group.entities.length > 0)\n }\n\n if (customItems && customItems.length > 0) {\n const topAdditions: ExtendedGroup[] = []\n const topUngrouped: SidebarTabItem[] = []\n const bottomUngrouped: SidebarTabItem[] = []\n\n const toEntity = (item: SidebarTabItem): ExtendedEntity =>\n ({\n slug: item.slug,\n type: 'custom',\n href: item.href,\n isExternal: item.isExternal,\n label: item.label,\n }) as ExtendedEntity\n\n for (const item of customItems) {\n if (item.group) {\n const itemGroupLabel = extractLocalizedValue(item.group, currentLang)\n const existingGroup = result.find((g) => {\n const groupLabel = extractLocalizedValue(g.label, currentLang)\n return groupLabel === itemGroupLabel\n })\n\n if (existingGroup) {\n // Merged into existing collection group — position has no effect here\n existingGroup.entities.push(toEntity(item))\n } else {\n // New custom group — position controls top vs bottom\n const newGroup: ExtendedGroup = { entities: [toEntity(item)], label: item.group }\n if (item.position === 'top') {\n topAdditions.push(newGroup)\n } else {\n result.push(newGroup)\n }\n }\n } else {\n if (item.position === 'top') {\n topUngrouped.push(item)\n } else {\n bottomUngrouped.push(item)\n }\n }\n }\n\n if (topUngrouped.length > 0) {\n topAdditions.unshift({ entities: topUngrouped.map(toEntity), label: '' })\n }\n\n if (bottomUngrouped.length > 0) {\n result.push({ entities: bottomUngrouped.map(toEntity), label: '' })\n }\n\n result = [...topAdditions, ...result]\n }\n\n return result\n}\n\nexport const EnhancedSidebar: React.FC<EnhancedSidebarProps> = async (props) => {\n const {\n i18n,\n locale,\n params,\n payload,\n permissions,\n req,\n searchParams,\n sidebarConfig,\n user,\n visibleEntities,\n documentSubViewType,\n viewType,\n } = props\n\n if (!payload?.config) {\n return null\n }\n\n const {\n admin: {\n components: { afterNavLinks, beforeNavLinks, settingsMenu },\n },\n collections,\n globals,\n } = payload.config\n\n const groups = groupNavItems(\n [\n ...collections\n .filter(({ slug }) => visibleEntities?.collections.includes(slug))\n .map(\n (collection) =>\n ({\n type: EntityType.collection,\n entity: collection,\n }) satisfies EntityToGroup,\n ),\n ...globals\n .filter(({ slug }) => visibleEntities?.globals.includes(slug))\n .map(\n (global) =>\n ({\n type: EntityType.global,\n entity: global,\n }) satisfies EntityToGroup,\n ),\n ],\n permissions || {},\n i18n,\n ) as unknown as ExtendedGroup[]\n\n const navPreferences = await getNavPrefs(req)\n\n const serverProps = {\n i18n,\n locale,\n params,\n payload,\n permissions,\n searchParams,\n user,\n }\n\n const clientProps = {\n documentSubViewType,\n viewType,\n }\n\n const beforeNavLinksRendered = RenderServerComponent({\n Component: beforeNavLinks,\n importMap: payload.importMap,\n serverProps,\n clientProps,\n })\n\n const afterNavLinksRendered = RenderServerComponent({\n Component: afterNavLinks,\n importMap: payload.importMap,\n serverProps,\n clientProps,\n })\n\n const renderedSettingsMenu =\n settingsMenu && Array.isArray(settingsMenu)\n ? settingsMenu.map((item, index) =>\n RenderServerComponent({\n Component: item,\n importMap: payload.importMap,\n key: `settings-menu-item-${index}`,\n serverProps,\n clientProps,\n }),\n )\n : []\n\n const config: EnhancedSidebarConfig = sidebarConfig ?? {\n tabs: [\n {\n id: 'default',\n type: 'tab',\n icon: 'LayoutGrid',\n label: 'Collections',\n },\n ],\n }\n\n // Read active tab from cookie\n const cookieStore = await cookies()\n const storedTabId = cookieStore.get(COOKIE_KEY)?.value\n const tabs = config.tabs?.filter((t) => t.type === 'tab') ?? []\n const defaultTabId = tabs[0]?.id ?? 'default'\n const initialActiveTabId =\n storedTabId && tabs.some((t) => t.id === storedTabId) ? storedTabId : defaultTabId\n\n const adminRoute = payload.config.routes.admin\n const currentLang = i18n.language\n\n /**\n * Renders a single entity as a NavItem (default or custom).\n */\n const renderEntity = (entity: ExtendedEntity, key: string): React.ReactNode => {\n const { slug, type } = entity\n let href: string\n let id: string\n\n if (type === 'collection') {\n href = formatAdminURL({ adminRoute, path: `/collections/${slug}` })\n id = `nav-${slug}`\n } else if (type === 'global') {\n href = formatAdminURL({ adminRoute, path: `/globals/${slug}` })\n id = `nav-global-${slug}`\n } else if (type === 'custom' && entity.href) {\n id = `nav-custom-${slug}`\n href = entity.isExternal ? entity.href : formatAdminURL({ adminRoute, path: entity.href })\n } else {\n return null\n }\n\n const badgeConfig = config.badges?.[slug]\n\n if (config.customComponents?.NavItem) {\n const label = getTranslation(entity.label, i18n)\n const { path, clientProps: extraProps } = resolveSidebarComponent(config.customComponents.NavItem)\n return RenderServerComponent({\n Component: path,\n importMap: payload.importMap,\n key,\n clientProps: { entity, href, id, badgeConfig, label, ...extraProps },\n })\n }\n\n return <NavItem key={key} badgeConfig={badgeConfig} entity={entity} href={href} id={id} />\n }\n\n /**\n * Renders a group with its entities (default NavGroup or custom).\n */\n const renderGroup = (group: ExtendedGroup, key: string): React.ReactNode => {\n const { entities, label } = group\n const isUngrouped = !label || (typeof label === 'string' && label === '')\n const translatedLabel = getTranslation(label || '', i18n)\n\n const items = entities.map((entity, i) => renderEntity(entity, `${key}-${i}`))\n\n if (isUngrouped) {\n return <Fragment key={key}>{items}</Fragment>\n }\n\n if (config.customComponents?.NavGroup) {\n const { path, clientProps: extraProps } = resolveSidebarComponent(config.customComponents.NavGroup)\n return RenderServerComponent({\n Component: path,\n importMap: payload.importMap,\n key,\n clientProps: {\n label: translatedLabel,\n isOpen: navPreferences?.groups?.[translatedLabel]?.open,\n children: items,\n ...extraProps,\n },\n })\n }\n\n return (\n <NavGroup\n isOpen={navPreferences?.groups?.[translatedLabel]?.open}\n key={key}\n label={translatedLabel}\n >\n {items}\n </NavGroup>\n )\n }\n\n // Pre-render content for every tab on the server\n const tabsContent: Record<string, React.ReactNode> = {}\n for (const tab of tabs) {\n const tabGroups = computeGroupsForTab(tab, groups, currentLang)\n tabsContent[tab.id] = (\n <Fragment>{tabGroups.map((group, i) => renderGroup(group, `${tab.id}-${i}`))}</Fragment>\n )\n }\n\n // For the no-tabs fallback\n const allContent =\n tabs.length === 0 ? (\n <Fragment>{groups.map((group, i) => renderGroup(group, `all-${i}`))}</Fragment>\n ) : undefined\n\n // Build server-side icon and tab button rendering\n const allTabItems = config.tabs ?? []\n const hasCustomTabButton = !!config.customComponents?.TabButton\n const hasAnyIconComponent = allTabItems.some((t) => t.iconComponent)\n\n // tabIcons: per-id icon node (only built when no custom TabButton, just iconComponent overrides)\n const tabIcons: Record<string, React.ReactNode> = {}\n // renderedTabItems: fully custom tab button nodes (built when customComponents.TabButton is set)\n const renderedTabItems: React.ReactNode[] = []\n\n if (hasCustomTabButton || hasAnyIconComponent) {\n for (const item of allTabItems) {\n const label = getTranslation(item.label, i18n)\n\n // Resolve icon: custom iconComponent > default Lucide\n let iconNode: React.ReactNode\n if (item.iconComponent) {\n const { path: iconPath, clientProps: iconExtraProps } = resolveSidebarComponent(item.iconComponent)\n iconNode = RenderServerComponent({\n Component: iconPath,\n importMap: payload.importMap,\n clientProps: { id: item.id, label, type: item.type, ...iconExtraProps },\n })\n } else {\n iconNode = <Icon name={item.icon!} size={20} />\n }\n\n if (hasCustomTabButton) {\n // Compute href for links\n let href: string | undefined\n if (item.type === 'link') {\n href = item.isExternal\n ? item.href\n : formatAdminURL({ adminRoute, path: item.href })\n }\n\n const { path: tabBtnPath, clientProps: tabBtnExtraProps } = resolveSidebarComponent(config.customComponents!.TabButton!)\n renderedTabItems.push(\n RenderServerComponent({\n Component: tabBtnPath,\n importMap: payload.importMap,\n key: item.id,\n clientProps: {\n badge: item.badge,\n href,\n icon: iconNode,\n id: item.id,\n isExternal: item.type === 'link' ? item.isExternal : undefined,\n label,\n type: item.type,\n ...tabBtnExtraProps,\n },\n }),\n )\n } else if (item.iconComponent) {\n tabIcons[item.id] = iconNode\n }\n }\n }\n\n const customNavContent = config.customComponents?.NavContent\n ? (() => {\n const { path, clientProps: extraProps } = resolveSidebarComponent(config.customComponents!.NavContent!)\n return RenderServerComponent({\n Component: path,\n importMap: payload.importMap,\n key: 'enhanced-sidebar-nav-content',\n clientProps: {\n afterNavLinks: afterNavLinksRendered,\n allContent,\n beforeNavLinks: beforeNavLinksRendered,\n tabs: tabs.map((t) => ({ id: t.id })),\n tabsContent,\n ...extraProps,\n },\n })\n })()\n : undefined\n\n return (\n <SidebarContent\n afterNavLinks={afterNavLinksRendered}\n allContent={allContent}\n beforeNavLinks={beforeNavLinksRendered}\n customNavContent={customNavContent}\n initialActiveTabId={initialActiveTabId}\n renderedTabItems={renderedTabItems.length > 0 ? renderedTabItems : undefined}\n settingsMenu={renderedSettingsMenu}\n sidebarConfig={config}\n tabIcons={Object.keys(tabIcons).length > 0 ? tabIcons : undefined}\n tabsContent={tabsContent}\n />\n )\n}\n\nexport default EnhancedSidebar\n"],"names":["getTranslation","RenderServerComponent","NavGroup","EntityType","groupNavItems","cookies","formatAdminURL","React","Fragment","COOKIE_KEY","extractLocalizedValue","resolveSidebarComponent","getNavPrefs","Icon","NavItem","SidebarContent","computeGroupsForTab","tab","groups","currentLang","collections","tabCollections","customItems","globals","tabGlobals","showAll","allowedSlugs","Set","result","map","g","entities","size","group","filter","entity","has","slug","length","topAdditions","topUngrouped","bottomUngrouped","toEntity","item","type","href","isExternal","label","itemGroupLabel","existingGroup","find","groupLabel","push","newGroup","position","unshift","EnhancedSidebar","props","i18n","locale","params","payload","permissions","req","searchParams","sidebarConfig","user","visibleEntities","documentSubViewType","viewType","config","admin","components","afterNavLinks","beforeNavLinks","settingsMenu","includes","collection","global","navPreferences","serverProps","clientProps","beforeNavLinksRendered","Component","importMap","afterNavLinksRendered","renderedSettingsMenu","Array","isArray","index","key","tabs","id","icon","cookieStore","storedTabId","get","value","t","defaultTabId","initialActiveTabId","some","adminRoute","routes","language","renderEntity","path","badgeConfig","badges","customComponents","extraProps","renderGroup","isUngrouped","translatedLabel","items","i","isOpen","open","children","tabsContent","tabGroups","allContent","undefined","allTabItems","hasCustomTabButton","TabButton","hasAnyIconComponent","iconComponent","tabIcons","renderedTabItems","iconNode","iconPath","iconExtraProps","name","tabBtnPath","tabBtnExtraProps","badge","customNavContent","NavContent","Object","keys"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,7 @@ import { type Config } from 'payload';
|
|
|
2
2
|
import type { EnhancedSidebarConfig } from './types';
|
|
3
3
|
export declare const payloadEnhancedSidebar: (pluginOptions?: EnhancedSidebarConfig) => (config: Config) => Config;
|
|
4
4
|
export { BadgeProvider, useBadgeContext, useBadgeValue, } from './components/EnhancedSidebar/BadgeProvider';
|
|
5
|
-
export
|
|
5
|
+
export { useEnhancedSidebar } from './components/EnhancedSidebar/context';
|
|
6
|
+
export { useNavItemState } from './components/EnhancedSidebar/hooks/useNavItemState';
|
|
7
|
+
export { useTabState } from './components/EnhancedSidebar/hooks/useTabState';
|
|
8
|
+
export type { BadgeColor, BadgeConfig, BadgeConfigApi, BadgeConfigCollectionCount, BadgeConfigProvider, BadgeValues, CustomNavContentProps, CustomNavGroupProps, CustomNavItemProps, CustomTabButtonProps, CustomTabIconProps, EnhancedSidebarConfig, SidebarComponent, } from './types';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { deepMerge } from 'payload';
|
|
2
2
|
import { sidebarTranslations } from './translations';
|
|
3
|
+
import { resolveSidebarComponent } from './utils';
|
|
3
4
|
/**
|
|
4
5
|
* Default configuration for the enhanced sidebar
|
|
5
6
|
*/ const defaultConfig = {
|
|
@@ -30,7 +31,6 @@ export const payloadEnhancedSidebar = (pluginOptions = {})=>(config)=>{
|
|
|
30
31
|
if (pluginOptions.disabled) {
|
|
31
32
|
return config;
|
|
32
33
|
}
|
|
33
|
-
// Merge user config with defaults
|
|
34
34
|
const sidebarConfig = {
|
|
35
35
|
...defaultConfig,
|
|
36
36
|
...pluginOptions,
|
|
@@ -50,6 +50,35 @@ export const payloadEnhancedSidebar = (pluginOptions = {})=>(config)=>{
|
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
+
// Register custom components and per-tab icons in the import map
|
|
54
|
+
if (!config.admin.dependencies) {
|
|
55
|
+
config.admin.dependencies = {};
|
|
56
|
+
}
|
|
57
|
+
const customComponentSlots = [
|
|
58
|
+
'NavContent',
|
|
59
|
+
'NavGroup',
|
|
60
|
+
'NavItem',
|
|
61
|
+
'TabButton'
|
|
62
|
+
];
|
|
63
|
+
for (const slot of customComponentSlots){
|
|
64
|
+
const component = pluginOptions.customComponents?.[slot];
|
|
65
|
+
if (component) {
|
|
66
|
+
const { path } = resolveSidebarComponent(component);
|
|
67
|
+
config.admin.dependencies[`enhanced-sidebar-${slot.toLowerCase()}`] = {
|
|
68
|
+
type: 'component',
|
|
69
|
+
path
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const tab of sidebarConfig.tabs ?? []){
|
|
74
|
+
if (tab.iconComponent) {
|
|
75
|
+
const { path } = resolveSidebarComponent(tab.iconComponent);
|
|
76
|
+
config.admin.dependencies[`enhanced-sidebar-icon-${tab.id}`] = {
|
|
77
|
+
type: 'component',
|
|
78
|
+
path
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
53
82
|
// Check if we have any badges to fetch (api or collection-count)
|
|
54
83
|
const hasBadgesToFetch = sidebarConfig.badges || sidebarConfig.tabs?.some((tab)=>tab.badge && tab.badge.type !== 'provider');
|
|
55
84
|
// Add InternalBadgeProvider if we have badges to fetch
|
|
@@ -76,5 +105,8 @@ export const payloadEnhancedSidebar = (pluginOptions = {})=>(config)=>{
|
|
|
76
105
|
return config;
|
|
77
106
|
};
|
|
78
107
|
export { BadgeProvider, useBadgeContext, useBadgeValue } from './components/EnhancedSidebar/BadgeProvider';
|
|
108
|
+
export { useEnhancedSidebar } from './components/EnhancedSidebar/context';
|
|
109
|
+
export { useNavItemState } from './components/EnhancedSidebar/hooks/useNavItemState';
|
|
110
|
+
export { useTabState } from './components/EnhancedSidebar/hooks/useTabState';
|
|
79
111
|
|
|
80
112
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { type Config, deepMerge } from 'payload'\n\nimport type { EnhancedSidebarConfig } from './types'\n\nimport { sidebarTranslations } from './translations'\n\n/**\n * Default configuration for the enhanced sidebar\n */\nconst defaultConfig: EnhancedSidebarConfig = {\n showLogout: true,\n tabs: [\n {\n id: 'dashboard',\n type: 'link',\n href: '/',\n icon: 'House',\n label: { en: 'Dashboard', uk: 'Головна' },\n },\n {\n id: 'default',\n type: 'tab',\n icon: 'LayoutGrid',\n label: { en: 'Collections', uk: 'Колекції' },\n },\n ],\n}\n\nexport const payloadEnhancedSidebar =\n (pluginOptions: EnhancedSidebarConfig = {}) =>\n (config: Config): Config => {\n if (pluginOptions.disabled) {\n return config\n }\n\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { type Config, deepMerge } from 'payload'\n\nimport type { EnhancedSidebarConfig } from './types'\n\nimport { sidebarTranslations } from './translations'\nimport { resolveSidebarComponent } from './utils'\n\n/**\n * Default configuration for the enhanced sidebar\n */\nconst defaultConfig: EnhancedSidebarConfig = {\n showLogout: true,\n tabs: [\n {\n id: 'dashboard',\n type: 'link',\n href: '/',\n icon: 'House',\n label: { en: 'Dashboard', uk: 'Головна' },\n },\n {\n id: 'default',\n type: 'tab',\n icon: 'LayoutGrid',\n label: { en: 'Collections', uk: 'Колекції' },\n },\n ],\n}\n\nexport const payloadEnhancedSidebar =\n (pluginOptions: EnhancedSidebarConfig = {}) =>\n (config: Config): Config => {\n if (pluginOptions.disabled) {\n return config\n }\n\n const sidebarConfig: EnhancedSidebarConfig = {\n ...defaultConfig,\n ...pluginOptions,\n tabs: pluginOptions.tabs ?? defaultConfig.tabs,\n }\n\n if (!config.admin) {\n config.admin = {}\n }\n\n if (!config.admin.components) {\n config.admin.components = {}\n }\n\n if (!config.admin.components.Nav) {\n config.admin.components.Nav = {\n path: '@veiag/payload-enhanced-sidebar/rsc#EnhancedSidebar',\n serverProps: {\n sidebarConfig,\n },\n }\n }\n\n // Register custom components and per-tab icons in the import map\n if (!config.admin.dependencies) {\n config.admin.dependencies = {}\n }\n\n const customComponentSlots = ['NavContent', 'NavGroup', 'NavItem', 'TabButton'] as const\n for (const slot of customComponentSlots) {\n const component = pluginOptions.customComponents?.[slot]\n if (component) {\n const { path } = resolveSidebarComponent(component)\n config.admin.dependencies[`enhanced-sidebar-${slot.toLowerCase()}`] = {\n type: 'component',\n path,\n }\n }\n }\n\n for (const tab of sidebarConfig.tabs ?? []) {\n if (tab.iconComponent) {\n const { path } = resolveSidebarComponent(tab.iconComponent)\n config.admin.dependencies[`enhanced-sidebar-icon-${tab.id}`] = {\n type: 'component',\n path,\n }\n }\n }\n\n // Check if we have any badges to fetch (api or collection-count)\n const hasBadgesToFetch =\n sidebarConfig.badges ||\n sidebarConfig.tabs?.some((tab) => tab.badge && tab.badge.type !== 'provider')\n\n // Add InternalBadgeProvider if we have badges to fetch\n if (hasBadgesToFetch) {\n if (!config.admin.components.providers) {\n config.admin.components.providers = []\n }\n\n // Add our internal provider at the beginning (so user providers can override)\n config.admin.components.providers.unshift({\n clientProps: {\n sidebarConfig,\n },\n path: '@veiag/payload-enhanced-sidebar/client#InternalBadgeProvider',\n })\n }\n\n // Adding translations\n if (!config.i18n) {\n config.i18n = {}\n }\n if (!config.i18n.translations) {\n config.i18n.translations = {}\n }\n\n config.i18n.translations = deepMerge(config.i18n.translations, sidebarTranslations)\n\n return config\n }\n\nexport {\n BadgeProvider,\n useBadgeContext,\n useBadgeValue,\n} from './components/EnhancedSidebar/BadgeProvider'\n\nexport { useEnhancedSidebar } from './components/EnhancedSidebar/context'\nexport { useNavItemState } from './components/EnhancedSidebar/hooks/useNavItemState'\nexport { useTabState } from './components/EnhancedSidebar/hooks/useTabState'\n\nexport type {\n BadgeColor,\n BadgeConfig,\n BadgeConfigApi,\n BadgeConfigCollectionCount,\n BadgeConfigProvider,\n BadgeValues,\n CustomNavContentProps,\n CustomNavGroupProps,\n CustomNavItemProps,\n CustomTabButtonProps,\n CustomTabIconProps,\n EnhancedSidebarConfig,\n SidebarComponent,\n} from './types'\n"],"names":["deepMerge","sidebarTranslations","resolveSidebarComponent","defaultConfig","showLogout","tabs","id","type","href","icon","label","en","uk","payloadEnhancedSidebar","pluginOptions","config","disabled","sidebarConfig","admin","components","Nav","path","serverProps","dependencies","customComponentSlots","slot","component","customComponents","toLowerCase","tab","iconComponent","hasBadgesToFetch","badges","some","badge","providers","unshift","clientProps","i18n","translations","BadgeProvider","useBadgeContext","useBadgeValue","useEnhancedSidebar","useNavItemState","useTabState"],"mappings":"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"}
|