@veiag/payload-enhanced-sidebar 0.1.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 +231 -0
- package/dist/components/EnhancedSidebar/CustomTabContent.d.ts +6 -0
- package/dist/components/EnhancedSidebar/CustomTabContent.js +35 -0
- package/dist/components/EnhancedSidebar/CustomTabContent.js.map +1 -0
- package/dist/components/EnhancedSidebar/Icon.d.ts +8 -0
- package/dist/components/EnhancedSidebar/Icon.js +16 -0
- package/dist/components/EnhancedSidebar/Icon.js.map +1 -0
- package/dist/components/EnhancedSidebar/NavHamburger/index.d.ts +4 -0
- package/dist/components/EnhancedSidebar/NavHamburger/index.js +18 -0
- package/dist/components/EnhancedSidebar/NavHamburger/index.js.map +1 -0
- package/dist/components/EnhancedSidebar/SidebarContent.d.ts +11 -0
- package/dist/components/EnhancedSidebar/SidebarContent.js +140 -0
- package/dist/components/EnhancedSidebar/SidebarContent.js.map +1 -0
- package/dist/components/EnhancedSidebar/SidebarWrapper/index.d.ts +6 -0
- package/dist/components/EnhancedSidebar/SidebarWrapper/index.js +33 -0
- package/dist/components/EnhancedSidebar/SidebarWrapper/index.js.map +1 -0
- package/dist/components/EnhancedSidebar/SidebarWrapper/index.scss +63 -0
- package/dist/components/EnhancedSidebar/TabsBar/index.d.ts +9 -0
- package/dist/components/EnhancedSidebar/TabsBar/index.js +85 -0
- package/dist/components/EnhancedSidebar/TabsBar/index.js.map +1 -0
- package/dist/components/EnhancedSidebar/TabsBar/index.scss +108 -0
- package/dist/components/EnhancedSidebar/getNavPrefs.d.ts +2 -0
- package/dist/components/EnhancedSidebar/getNavPrefs.js +31 -0
- package/dist/components/EnhancedSidebar/getNavPrefs.js.map +1 -0
- package/dist/components/EnhancedSidebar/index.client.d.ts +7 -0
- package/dist/components/EnhancedSidebar/index.client.js +94 -0
- package/dist/components/EnhancedSidebar/index.client.js.map +1 -0
- package/dist/components/EnhancedSidebar/index.d.ts +10 -0
- package/dist/components/EnhancedSidebar/index.js +65 -0
- package/dist/components/EnhancedSidebar/index.js.map +1 -0
- package/dist/components/EnhancedSidebar/index.scss +101 -0
- package/dist/exports/client.d.ts +0 -0
- package/dist/exports/client.js +3 -0
- package/dist/exports/client.js.map +1 -0
- package/dist/exports/rsc.d.ts +1 -0
- package/dist/exports/rsc.js +3 -0
- package/dist/exports/rsc.js.map +1 -0
- package/dist/hooks/useMutationObserver.d.ts +1 -0
- package/dist/hooks/useMutationObserver.js +21 -0
- package/dist/hooks/useMutationObserver.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/translations/index.d.ts +22 -0
- package/dist/translations/index.js +30 -0
- package/dist/translations/index.js.map +1 -0
- package/dist/types.d.ts +132 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +14 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Payload Enhanced Sidebar
|
|
2
|
+
|
|
3
|
+
An enhanced sidebar plugin for [Payload CMS](https://payloadcms.com) that adds a tabbed navigation system to organize collections and globals into logical groups.
|
|
4
|
+
|
|
5
|
+
> **Note:** This plugin is in early development and has not been extensively tested. Use with caution in production environments.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Tabbed Navigation** - Organize collections into separate tabs for cleaner navigation
|
|
10
|
+
- **Vertical Tab Bar** - Icon-based tabs on the left side of the sidebar
|
|
11
|
+
- **Link Support** - Add navigation links (like Dashboard) alongside tabs
|
|
12
|
+
- **Custom Items** - Add custom navigation items that can be merged into existing groups
|
|
13
|
+
- **i18n Support** - Full localization support for labels and groups
|
|
14
|
+
- **Lucide Icons** - Use any [Lucide icon](https://lucide.dev/icons) for tabs and links
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @veiag/payload-enhanced-sidebar
|
|
20
|
+
# or
|
|
21
|
+
yarn add @veiag/payload-enhanced-sidebar
|
|
22
|
+
# or
|
|
23
|
+
pnpm add @veiag/payload-enhanced-sidebar
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { payloadEnhancedSidebar } from '@veiag/payload-enhanced-sidebar'
|
|
30
|
+
import { buildConfig } from 'payload'
|
|
31
|
+
|
|
32
|
+
export default buildConfig({
|
|
33
|
+
// ... your config
|
|
34
|
+
plugins: [
|
|
35
|
+
payloadEnhancedSidebar({
|
|
36
|
+
// Works with defaults!
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This will add:
|
|
43
|
+
- A Dashboard link at the top
|
|
44
|
+
- A default tab showing all collections and globals
|
|
45
|
+
- A logout button at the bottom
|
|
46
|
+
|
|
47
|
+
## Configuration
|
|
48
|
+
|
|
49
|
+
### Full Configuration Example
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { payloadEnhancedSidebar } from '@veiag/payload-enhanced-sidebar'
|
|
53
|
+
import { buildConfig } from 'payload'
|
|
54
|
+
|
|
55
|
+
export default buildConfig({
|
|
56
|
+
plugins: [
|
|
57
|
+
payloadEnhancedSidebar({
|
|
58
|
+
// Tabs and links in the sidebar
|
|
59
|
+
tabs: [
|
|
60
|
+
// Dashboard link
|
|
61
|
+
{
|
|
62
|
+
id: 'dashboard',
|
|
63
|
+
type: 'link',
|
|
64
|
+
href: '/',
|
|
65
|
+
icon: 'House',
|
|
66
|
+
label: { en: 'Dashboard', uk: 'Головна' },
|
|
67
|
+
},
|
|
68
|
+
// Content tab - shows specific collections
|
|
69
|
+
{
|
|
70
|
+
id: 'content',
|
|
71
|
+
type: 'tab',
|
|
72
|
+
icon: 'FileText',
|
|
73
|
+
label: { en: 'Content', uk: 'Контент' },
|
|
74
|
+
collections: ['posts', 'pages', 'categories'],
|
|
75
|
+
},
|
|
76
|
+
// E-commerce tab with custom items
|
|
77
|
+
{
|
|
78
|
+
id: 'ecommerce',
|
|
79
|
+
type: 'tab',
|
|
80
|
+
icon: 'ShoppingCart',
|
|
81
|
+
label: { en: 'E-commerce', uk: 'E-commerce' },
|
|
82
|
+
collections: ['products', 'orders', 'customers'],
|
|
83
|
+
customItems: [
|
|
84
|
+
{
|
|
85
|
+
slug: 'analytics',
|
|
86
|
+
href: '/analytics',
|
|
87
|
+
label: { en: 'Analytics', uk: 'Аналітика' },
|
|
88
|
+
group: 'E-commerce', // Merge into existing group
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
// Settings tab with globals
|
|
93
|
+
{
|
|
94
|
+
id: 'settings',
|
|
95
|
+
type: 'tab',
|
|
96
|
+
icon: 'Settings',
|
|
97
|
+
label: { en: 'Settings', uk: 'Налаштування' },
|
|
98
|
+
collections: ['users'],
|
|
99
|
+
globals: ['site-settings', 'footer-settings'],
|
|
100
|
+
customItems: [
|
|
101
|
+
{
|
|
102
|
+
slug: 'api-keys',
|
|
103
|
+
href: '/api-keys',
|
|
104
|
+
label: { en: 'API Keys', uk: 'API Ключі' },
|
|
105
|
+
// No group - will appear at the bottom
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
|
|
111
|
+
// Show/hide logout button (default: true)
|
|
112
|
+
showLogout: true,
|
|
113
|
+
|
|
114
|
+
// Disable the plugin
|
|
115
|
+
disabled: false,
|
|
116
|
+
}),
|
|
117
|
+
],
|
|
118
|
+
})
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Configuration Options
|
|
122
|
+
|
|
123
|
+
### `tabs`
|
|
124
|
+
|
|
125
|
+
Array of tabs and links to show in the sidebar.
|
|
126
|
+
|
|
127
|
+
**Tab (`type: 'tab'`)**
|
|
128
|
+
|
|
129
|
+
| Property | Type | Required | Description |
|
|
130
|
+
|----------|------|----------|-------------|
|
|
131
|
+
| `id` | `string` | Yes | Unique identifier |
|
|
132
|
+
| `type` | `'tab'` | Yes | Tab type |
|
|
133
|
+
| `icon` | `string` | Yes | Lucide icon name |
|
|
134
|
+
| `label` | `LocalizedString` | Yes | Tab tooltip/label |
|
|
135
|
+
| `collections` | `CollectionSlug[]` | No | Collections to show in this tab |
|
|
136
|
+
| `globals` | `GlobalSlug[]` | No | Globals to show in this tab |
|
|
137
|
+
| `customItems` | `SidebarTabItem[]` | No | Custom navigation items |
|
|
138
|
+
|
|
139
|
+
> If neither `collections` nor `globals` are specified, the tab shows all collections and globals.
|
|
140
|
+
|
|
141
|
+
**Link (`type: 'link'`)**
|
|
142
|
+
|
|
143
|
+
| Property | Type | Required | Description |
|
|
144
|
+
|----------|------|----------|-------------|
|
|
145
|
+
| `id` | `string` | Yes | Unique identifier |
|
|
146
|
+
| `type` | `'link'` | Yes | Link type |
|
|
147
|
+
| `icon` | `string` | Yes | Lucide icon name |
|
|
148
|
+
| `label` | `LocalizedString` | Yes | Link tooltip/label |
|
|
149
|
+
| `href` | `string` | Yes | URL (relative to admin route) |
|
|
150
|
+
|
|
151
|
+
### `customItems`
|
|
152
|
+
|
|
153
|
+
Custom items can be added to any tab:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
{
|
|
157
|
+
slug: 'unique-slug', // Required: unique identifier
|
|
158
|
+
href: '/path', // Required: URL (relative to admin route)
|
|
159
|
+
label: { en: 'Label' }, // Required: display label
|
|
160
|
+
group: { en: 'Group Name' }, // Optional: merge into existing group or create new
|
|
161
|
+
isExternal: true, // Optional: if true, href is absolute URL
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Group behavior:**
|
|
166
|
+
- If `group` matches an existing collection group label, the item is added to that group
|
|
167
|
+
- If `group` doesn't match any existing group, a new group is created
|
|
168
|
+
- If `group` is not specified, the item appears at the bottom as ungrouped
|
|
169
|
+
|
|
170
|
+
### `showLogout`
|
|
171
|
+
|
|
172
|
+
Show/hide the logout button at the bottom of the tabs bar.
|
|
173
|
+
|
|
174
|
+
- **Type:** `boolean`
|
|
175
|
+
- **Default:** `true`
|
|
176
|
+
|
|
177
|
+
### `disabled`
|
|
178
|
+
|
|
179
|
+
Completely disable the plugin.
|
|
180
|
+
|
|
181
|
+
- **Type:** `boolean`
|
|
182
|
+
- **Default:** `false`
|
|
183
|
+
|
|
184
|
+
## Localization
|
|
185
|
+
|
|
186
|
+
All labels support localized strings:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
label: 'Simple string'
|
|
190
|
+
// or
|
|
191
|
+
label: {
|
|
192
|
+
en: 'English',
|
|
193
|
+
uk: 'Українська',
|
|
194
|
+
de: 'Deutsch',
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## TODO
|
|
199
|
+
|
|
200
|
+
The following features are planned but not yet implemented:
|
|
201
|
+
|
|
202
|
+
- [ ] **Browse by Folder Button** - Support for the folder view button (requires Payload v3.41.0+)
|
|
203
|
+
- [ ] **Settings Menu Items** - Support for Payload's SettingsMenu items (requires Payload v3.60.0+)
|
|
204
|
+
|
|
205
|
+
## Contributing
|
|
206
|
+
|
|
207
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
208
|
+
|
|
209
|
+
1. Fork the repository
|
|
210
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
211
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
212
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
213
|
+
5. Open a Pull Request
|
|
214
|
+
|
|
215
|
+
## Issues
|
|
216
|
+
|
|
217
|
+
Found a bug or have a feature request? Please open an issue on [GitHub](https://github.com/VeiaG/payload-enhanced-sidebar/issues).
|
|
218
|
+
|
|
219
|
+
## License
|
|
220
|
+
|
|
221
|
+
MIT © [VeiaG](https://github.com/VeiaG)
|
|
222
|
+
|
|
223
|
+
## Links
|
|
224
|
+
|
|
225
|
+
- [GitHub Repository](https://github.com/VeiaG/payload-enhanced-sidebar)
|
|
226
|
+
- [Payload CMS](https://payloadcms.com)
|
|
227
|
+
- [Lucide Icons](https://lucide.dev/icons)
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
### More plugins and Payload resources at [PayloadCMS Extensions](https://payload.veiag.dev/)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { getTranslation } from '@payloadcms/translations';
|
|
4
|
+
import { Link, useConfig, useTranslation } from '@payloadcms/ui';
|
|
5
|
+
import { usePathname } from 'next/navigation.js';
|
|
6
|
+
import { formatAdminURL } from 'payload/shared';
|
|
7
|
+
import React from 'react';
|
|
8
|
+
const baseClass = 'enhanced-sidebar';
|
|
9
|
+
export const CustomTabContent = ({ items })=>{
|
|
10
|
+
const { i18n } = useTranslation();
|
|
11
|
+
const pathname = usePathname();
|
|
12
|
+
const { config: { routes: { admin: adminRoute } } } = useConfig();
|
|
13
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
14
|
+
className: `${baseClass}__custom-items`,
|
|
15
|
+
children: items.map((item)=>{
|
|
16
|
+
const href = item.isExternal ? item.href : formatAdminURL({
|
|
17
|
+
adminRoute,
|
|
18
|
+
path: item.href
|
|
19
|
+
});
|
|
20
|
+
const label = getTranslation(item.label, i18n);
|
|
21
|
+
const isActive = pathname.startsWith(href);
|
|
22
|
+
return /*#__PURE__*/ _jsx(Link, {
|
|
23
|
+
className: `${baseClass}__link ${isActive ? `${baseClass}__link--active` : ''}`,
|
|
24
|
+
href: href,
|
|
25
|
+
prefetch: false,
|
|
26
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
27
|
+
className: `${baseClass}__link-label`,
|
|
28
|
+
children: label
|
|
29
|
+
})
|
|
30
|
+
}, item.slug);
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=CustomTabContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/EnhancedSidebar/CustomTabContent.tsx"],"sourcesContent":["'use client'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { Link, useConfig, useTranslation } from '@payloadcms/ui'\nimport { usePathname } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport React from 'react'\n\nimport type { SidebarTabItem } from '../../types'\n\nconst baseClass = 'enhanced-sidebar'\n\nexport type CustomTabContentProps = {\n items: SidebarTabItem[]\n}\n\nexport const CustomTabContent: React.FC<CustomTabContentProps> = ({ items }) => {\n const { i18n } = useTranslation()\n const pathname = usePathname()\n\n const {\n config: {\n routes: { admin: adminRoute },\n },\n } = useConfig()\n\n return (\n <div className={`${baseClass}__custom-items`}>\n {items.map((item) => {\n const href = item.isExternal ? item.href : formatAdminURL({ adminRoute, path: item.href })\n const label = getTranslation(item.label, i18n)\n const isActive = pathname.startsWith(href)\n\n return (\n <Link\n className={`${baseClass}__link ${isActive ? `${baseClass}__link--active` : ''}`}\n href={href}\n key={item.slug}\n prefetch={false}\n >\n <span className={`${baseClass}__link-label`}>{label}</span>\n </Link>\n )\n })}\n </div>\n )\n}\n"],"names":["getTranslation","Link","useConfig","useTranslation","usePathname","formatAdminURL","React","baseClass","CustomTabContent","items","i18n","pathname","config","routes","admin","adminRoute","div","className","map","item","href","isExternal","path","label","isActive","startsWith","prefetch","span","slug"],"mappings":"AAAA;;AAEA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,IAAI,EAAEC,SAAS,EAAEC,cAAc,QAAQ,iBAAgB;AAChE,SAASC,WAAW,QAAQ,qBAAoB;AAChD,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,OAAOC,WAAW,QAAO;AAIzB,MAAMC,YAAY;AAMlB,OAAO,MAAMC,mBAAoD,CAAC,EAAEC,KAAK,EAAE;IACzE,MAAM,EAAEC,IAAI,EAAE,GAAGP;IACjB,MAAMQ,WAAWP;IAEjB,MAAM,EACJQ,QAAQ,EACNC,QAAQ,EAAEC,OAAOC,UAAU,EAAE,EAC9B,EACF,GAAGb;IAEJ,qBACE,KAACc;QAAIC,WAAW,GAAGV,UAAU,cAAc,CAAC;kBACzCE,MAAMS,GAAG,CAAC,CAACC;YACV,MAAMC,OAAOD,KAAKE,UAAU,GAAGF,KAAKC,IAAI,GAAGf,eAAe;gBAAEU;gBAAYO,MAAMH,KAAKC,IAAI;YAAC;YACxF,MAAMG,QAAQvB,eAAemB,KAAKI,KAAK,EAAEb;YACzC,MAAMc,WAAWb,SAASc,UAAU,CAACL;YAErC,qBACE,KAACnB;gBACCgB,WAAW,GAAGV,UAAU,OAAO,EAAEiB,WAAW,GAAGjB,UAAU,cAAc,CAAC,GAAG,IAAI;gBAC/Ea,MAAMA;gBAENM,UAAU;0BAEV,cAAA,KAACC;oBAAKV,WAAW,GAAGV,UAAU,YAAY,CAAC;8BAAGgB;;eAHzCJ,KAAKS,IAAI;QAMpB;;AAGN,EAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { icons } from 'lucide-react';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
export const Icon = ({ name, className, size = 20 })=>{
|
|
6
|
+
const LucideIcon = icons[name];
|
|
7
|
+
if (!LucideIcon) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return /*#__PURE__*/ _jsx(LucideIcon, {
|
|
11
|
+
className: className,
|
|
12
|
+
size: size
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=Icon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/EnhancedSidebar/Icon.tsx"],"sourcesContent":["'use client'\n\nimport { icons } from 'lucide-react'\nimport React from 'react'\n\nimport type { IconName } from '../../types'\n\nexport interface IconProps {\n className?: string\n name: IconName\n size?: number\n}\n\nexport const Icon: React.FC<IconProps> = ({ name, className, size = 20 }) => {\n const LucideIcon = icons[name]\n\n if (!LucideIcon) {\n return null\n }\n\n return <LucideIcon className={className} size={size} />\n}\n"],"names":["icons","React","Icon","name","className","size","LucideIcon"],"mappings":"AAAA;;AAEA,SAASA,KAAK,QAAQ,eAAc;AACpC,OAAOC,WAAW,QAAO;AAUzB,OAAO,MAAMC,OAA4B,CAAC,EAAEC,IAAI,EAAEC,SAAS,EAAEC,OAAO,EAAE,EAAE;IACtE,MAAMC,aAAaN,KAAK,CAACG,KAAK;IAE9B,IAAI,CAACG,YAAY;QACf,OAAO;IACT;IAEA,qBAAO,KAACA;QAAWF,WAAWA;QAAWC,MAAMA;;AACjD,EAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Hamburger, useNav } from '@payloadcms/ui';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
export const NavHamburger = ({ baseClass })=>{
|
|
6
|
+
const { navOpen, setNavOpen } = useNav();
|
|
7
|
+
return /*#__PURE__*/ _jsx("button", {
|
|
8
|
+
className: `${baseClass}__mobile-close`,
|
|
9
|
+
onClick: ()=>setNavOpen(false),
|
|
10
|
+
tabIndex: navOpen ? undefined : -1,
|
|
11
|
+
type: "button",
|
|
12
|
+
children: /*#__PURE__*/ _jsx(Hamburger, {
|
|
13
|
+
isActive: true
|
|
14
|
+
})
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/EnhancedSidebar/NavHamburger/index.tsx"],"sourcesContent":["'use client'\n\nimport { Hamburger, useNav } from '@payloadcms/ui'\nimport React from 'react'\n\nexport const NavHamburger: React.FC<{\n baseClass: string\n}> = ({ baseClass }) => {\n const { navOpen, setNavOpen } = useNav()\n\n return (\n <button\n className={`${baseClass}__mobile-close`}\n onClick={() => setNavOpen(false)}\n tabIndex={navOpen ? undefined : -1}\n type=\"button\"\n >\n <Hamburger isActive />\n </button>\n )\n}\n"],"names":["Hamburger","useNav","React","NavHamburger","baseClass","navOpen","setNavOpen","button","className","onClick","tabIndex","undefined","type","isActive"],"mappings":"AAAA;;AAEA,SAASA,SAAS,EAAEC,MAAM,QAAQ,iBAAgB;AAClD,OAAOC,WAAW,QAAO;AAEzB,OAAO,MAAMC,eAER,CAAC,EAAEC,SAAS,EAAE;IACjB,MAAM,EAAEC,OAAO,EAAEC,UAAU,EAAE,GAAGL;IAEhC,qBACE,KAACM;QACCC,WAAW,GAAGJ,UAAU,cAAc,CAAC;QACvCK,SAAS,IAAMH,WAAW;QAC1BI,UAAUL,UAAUM,YAAY,CAAC;QACjCC,MAAK;kBAEL,cAAA,KAACZ;YAAUa,QAAQ;;;AAGzB,EAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { NavPreferences } from 'payload';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { EnhancedSidebarConfig, ExtendedGroup } from '../../types';
|
|
4
|
+
export type SidebarContentProps = {
|
|
5
|
+
afterNavLinks?: React.ReactNode;
|
|
6
|
+
beforeNavLinks?: React.ReactNode;
|
|
7
|
+
groups: ExtendedGroup[];
|
|
8
|
+
navPreferences: NavPreferences | null;
|
|
9
|
+
sidebarConfig: EnhancedSidebarConfig;
|
|
10
|
+
};
|
|
11
|
+
export declare const SidebarContent: React.FC<SidebarContentProps>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation } from '@payloadcms/ui';
|
|
4
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
5
|
+
import { extractLocalizedValue } from '../../utils';
|
|
6
|
+
import { EnhancedSidebarClient } from './index.client';
|
|
7
|
+
import { SidebarWrapper } from './SidebarWrapper';
|
|
8
|
+
import { TabsBar } from './TabsBar';
|
|
9
|
+
const baseClass = 'enhanced-sidebar';
|
|
10
|
+
const STORAGE_KEY = 'payload-enhanced-sidebar-active-tab';
|
|
11
|
+
export const SidebarContent = ({ afterNavLinks, beforeNavLinks, groups, navPreferences, sidebarConfig })=>{
|
|
12
|
+
const { i18n } = useTranslation();
|
|
13
|
+
const currentLang = i18n.language;
|
|
14
|
+
const tabs = sidebarConfig.tabs?.filter((t)=>t.type === 'tab') ?? [];
|
|
15
|
+
const defaultTabId = tabs[0]?.id ?? 'default';
|
|
16
|
+
// Always start with default to match server render
|
|
17
|
+
const [activeTabId, setActiveTabId] = useState(defaultTabId);
|
|
18
|
+
// Read from localStorage only after hydration
|
|
19
|
+
useEffect(()=>{
|
|
20
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
21
|
+
if (stored && tabs.some((t)=>t.id === stored)) {
|
|
22
|
+
setActiveTabId(stored);
|
|
23
|
+
}
|
|
24
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
25
|
+
// Persist to localStorage on change
|
|
26
|
+
useEffect(()=>{
|
|
27
|
+
localStorage.setItem(STORAGE_KEY, activeTabId);
|
|
28
|
+
}, [
|
|
29
|
+
activeTabId
|
|
30
|
+
]);
|
|
31
|
+
const activeTab = tabs.find((tab)=>tab.id === activeTabId);
|
|
32
|
+
// Build groups for the active tab
|
|
33
|
+
const filteredGroups = useMemo(()=>{
|
|
34
|
+
if (!activeTab) {
|
|
35
|
+
return groups;
|
|
36
|
+
}
|
|
37
|
+
const { collections: tabCollections, customItems, globals: tabGlobals } = activeTab;
|
|
38
|
+
// If no specific collections/globals defined, show all
|
|
39
|
+
const showAll = !tabCollections && !tabGlobals;
|
|
40
|
+
const allowedSlugs = new Set([
|
|
41
|
+
...tabCollections ?? [],
|
|
42
|
+
...tabGlobals ?? []
|
|
43
|
+
]);
|
|
44
|
+
let result = [];
|
|
45
|
+
if (showAll) {
|
|
46
|
+
result = groups.map((g)=>({
|
|
47
|
+
...g,
|
|
48
|
+
entities: [
|
|
49
|
+
...g.entities
|
|
50
|
+
]
|
|
51
|
+
}));
|
|
52
|
+
} else if (allowedSlugs.size > 0) {
|
|
53
|
+
result = groups.map((group)=>({
|
|
54
|
+
...group,
|
|
55
|
+
entities: group.entities.filter((entity)=>allowedSlugs.has(entity.slug))
|
|
56
|
+
})).filter((group)=>group.entities.length > 0);
|
|
57
|
+
}
|
|
58
|
+
// Merge custom items into groups
|
|
59
|
+
if (customItems && customItems.length > 0) {
|
|
60
|
+
const ungroupedItems = [];
|
|
61
|
+
for (const item of customItems){
|
|
62
|
+
if (item.group) {
|
|
63
|
+
// Get localized group name for comparison
|
|
64
|
+
const itemGroupLabel = extractLocalizedValue(item.group, currentLang);
|
|
65
|
+
// Find existing group by comparing localized labels
|
|
66
|
+
const existingGroup = result.find((g)=>{
|
|
67
|
+
const groupLabel = extractLocalizedValue(g.label, currentLang);
|
|
68
|
+
return groupLabel === itemGroupLabel;
|
|
69
|
+
});
|
|
70
|
+
if (existingGroup) {
|
|
71
|
+
existingGroup.entities.push({
|
|
72
|
+
slug: item.slug,
|
|
73
|
+
type: 'custom',
|
|
74
|
+
href: item.href,
|
|
75
|
+
label: item.label
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
// Create new group
|
|
79
|
+
result.push({
|
|
80
|
+
entities: [
|
|
81
|
+
{
|
|
82
|
+
slug: item.slug,
|
|
83
|
+
type: 'custom',
|
|
84
|
+
href: item.href,
|
|
85
|
+
label: item.label
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
label: item.group
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
ungroupedItems.push(item);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Add ungrouped items at the end
|
|
96
|
+
if (ungroupedItems.length > 0) {
|
|
97
|
+
result.push({
|
|
98
|
+
entities: ungroupedItems.map((item)=>({
|
|
99
|
+
slug: item.slug,
|
|
100
|
+
type: 'custom',
|
|
101
|
+
href: item.href,
|
|
102
|
+
label: item.label
|
|
103
|
+
})),
|
|
104
|
+
label: ''
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}, [
|
|
110
|
+
activeTab,
|
|
111
|
+
groups,
|
|
112
|
+
currentLang
|
|
113
|
+
]);
|
|
114
|
+
return /*#__PURE__*/ _jsxs(SidebarWrapper, {
|
|
115
|
+
baseClass: baseClass,
|
|
116
|
+
children: [
|
|
117
|
+
/*#__PURE__*/ _jsx(TabsBar, {
|
|
118
|
+
activeTabId: activeTabId,
|
|
119
|
+
onTabChange: setActiveTabId,
|
|
120
|
+
sidebarConfig: sidebarConfig
|
|
121
|
+
}),
|
|
122
|
+
/*#__PURE__*/ _jsx("nav", {
|
|
123
|
+
className: `${baseClass}__content`,
|
|
124
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
125
|
+
className: `${baseClass}__content-scroll`,
|
|
126
|
+
children: [
|
|
127
|
+
beforeNavLinks,
|
|
128
|
+
/*#__PURE__*/ _jsx(EnhancedSidebarClient, {
|
|
129
|
+
groups: filteredGroups,
|
|
130
|
+
navPreferences: navPreferences
|
|
131
|
+
}),
|
|
132
|
+
afterNavLinks
|
|
133
|
+
]
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
]
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
//# sourceMappingURL=SidebarContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/EnhancedSidebar/SidebarContent.tsx"],"sourcesContent":["'use client'\nimport type { NavPreferences } from 'payload'\n\nimport { useTranslation } from '@payloadcms/ui'\nimport React, { useEffect, useMemo, useState } from 'react'\n\nimport type {\n EnhancedSidebarConfig,\n ExtendedGroup,\n SidebarTabContent as SidebarTabContentType,\n SidebarTabItem,\n} from '../../types'\n\nimport { extractLocalizedValue } from '../../utils'\nimport { EnhancedSidebarClient } from './index.client'\nimport { SidebarWrapper } from './SidebarWrapper'\nimport { TabsBar } from './TabsBar'\n\nconst baseClass = 'enhanced-sidebar'\n\nexport type SidebarContentProps = {\n afterNavLinks?: React.ReactNode\n beforeNavLinks?: React.ReactNode\n groups: ExtendedGroup[]\n navPreferences: NavPreferences | null\n sidebarConfig: EnhancedSidebarConfig\n}\n\nconst STORAGE_KEY = 'payload-enhanced-sidebar-active-tab'\n\nexport const SidebarContent: React.FC<SidebarContentProps> = ({\n afterNavLinks,\n beforeNavLinks,\n groups,\n navPreferences,\n sidebarConfig,\n}) => {\n const { i18n } = useTranslation()\n const currentLang = i18n.language\n\n const tabs = sidebarConfig.tabs?.filter((t): t is SidebarTabContentType => t.type === 'tab') ?? []\n const defaultTabId = tabs[0]?.id ?? 'default'\n\n // Always start with default to match server render\n const [activeTabId, setActiveTabId] = useState(defaultTabId)\n\n // Read from localStorage only after hydration\n useEffect(() => {\n const stored = localStorage.getItem(STORAGE_KEY)\n if (stored && tabs.some((t) => t.id === stored)) {\n setActiveTabId(stored)\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Persist to localStorage on change\n useEffect(() => {\n localStorage.setItem(STORAGE_KEY, activeTabId)\n }, [activeTabId])\n\n const activeTab = tabs.find((tab) => tab.id === activeTabId)\n\n // Build groups for the active tab\n const filteredGroups = useMemo(() => {\n if (!activeTab) {\n return groups\n }\n\n const { collections: tabCollections, customItems, globals: tabGlobals } = activeTab\n\n // If no specific collections/globals defined, show all\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 // Merge custom items into groups\n if (customItems && customItems.length > 0) {\n const ungroupedItems: SidebarTabItem[] = []\n\n for (const item of customItems) {\n if (item.group) {\n // Get localized group name for comparison\n const itemGroupLabel = extractLocalizedValue(item.group, currentLang)\n\n // Find existing group by comparing localized labels\n const existingGroup = result.find((g) => {\n const groupLabel = extractLocalizedValue(g.label, currentLang)\n return groupLabel === itemGroupLabel\n })\n\n if (existingGroup) {\n existingGroup.entities.push({\n slug: item.slug,\n type: 'custom',\n href: item.href,\n label: item.label,\n })\n } else {\n // Create new group\n result.push({\n entities: [\n {\n slug: item.slug,\n type: 'custom',\n href: item.href,\n label: item.label,\n },\n ],\n label: item.group,\n })\n }\n } else {\n ungroupedItems.push(item)\n }\n }\n\n // Add ungrouped items at the end\n if (ungroupedItems.length > 0) {\n result.push({\n entities: ungroupedItems.map((item) => ({\n slug: item.slug,\n type: 'custom',\n href: item.href,\n label: item.label,\n })),\n label: '',\n })\n }\n }\n\n return result\n }, [activeTab, groups, currentLang])\n\n return (\n <SidebarWrapper baseClass={baseClass}>\n <TabsBar\n activeTabId={activeTabId}\n onTabChange={setActiveTabId}\n sidebarConfig={sidebarConfig}\n />\n <nav className={`${baseClass}__content`}>\n <div className={`${baseClass}__content-scroll`}>\n {beforeNavLinks}\n <EnhancedSidebarClient groups={filteredGroups} navPreferences={navPreferences} />\n {afterNavLinks}\n </div>\n </nav>\n </SidebarWrapper>\n )\n}\n"],"names":["useTranslation","React","useEffect","useMemo","useState","extractLocalizedValue","EnhancedSidebarClient","SidebarWrapper","TabsBar","baseClass","STORAGE_KEY","SidebarContent","afterNavLinks","beforeNavLinks","groups","navPreferences","sidebarConfig","i18n","currentLang","language","tabs","filter","t","type","defaultTabId","id","activeTabId","setActiveTabId","stored","localStorage","getItem","some","setItem","activeTab","find","tab","filteredGroups","collections","tabCollections","customItems","globals","tabGlobals","showAll","allowedSlugs","Set","result","map","g","entities","size","group","entity","has","slug","length","ungroupedItems","item","itemGroupLabel","existingGroup","groupLabel","label","push","href","onTabChange","nav","className","div"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useNav } from '@payloadcms/ui';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { NavHamburger } from '../NavHamburger';
|
|
6
|
+
import './index.scss';
|
|
7
|
+
export const SidebarWrapper = ({ baseClass, children })=>{
|
|
8
|
+
const { hydrated, navOpen, navRef, shouldAnimate } = useNav();
|
|
9
|
+
return /*#__PURE__*/ _jsxs("aside", {
|
|
10
|
+
className: [
|
|
11
|
+
baseClass,
|
|
12
|
+
navOpen && `${baseClass}--nav-open`,
|
|
13
|
+
shouldAnimate && `${baseClass}--nav-animate`,
|
|
14
|
+
hydrated && `${baseClass}--nav-hydrated`
|
|
15
|
+
].filter(Boolean).join(' '),
|
|
16
|
+
inert: !navOpen ? true : undefined,
|
|
17
|
+
children: [
|
|
18
|
+
/*#__PURE__*/ _jsx("div", {
|
|
19
|
+
className: `${baseClass}__header`,
|
|
20
|
+
children: /*#__PURE__*/ _jsx(NavHamburger, {
|
|
21
|
+
baseClass: baseClass
|
|
22
|
+
})
|
|
23
|
+
}),
|
|
24
|
+
/*#__PURE__*/ _jsx("div", {
|
|
25
|
+
className: `${baseClass}__scroll`,
|
|
26
|
+
ref: navRef,
|
|
27
|
+
children: children
|
|
28
|
+
})
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/EnhancedSidebar/SidebarWrapper/index.tsx"],"sourcesContent":["'use client'\n\nimport { useNav } from '@payloadcms/ui'\nimport React from 'react'\n\nimport { NavHamburger } from '../NavHamburger'\nimport './index.scss'\n\nexport const SidebarWrapper: React.FC<{\n baseClass: string\n children: React.ReactNode\n}> = ({ baseClass, children }) => {\n const { hydrated, navOpen, navRef, shouldAnimate } = useNav()\n\n return (\n <aside\n className={[\n baseClass,\n navOpen && `${baseClass}--nav-open`,\n shouldAnimate && `${baseClass}--nav-animate`,\n hydrated && `${baseClass}--nav-hydrated`,\n ]\n .filter(Boolean)\n .join(' ')}\n inert={!navOpen ? true : undefined}\n >\n <div className={`${baseClass}__header`}>\n <NavHamburger baseClass={baseClass} />\n </div>\n <div className={`${baseClass}__scroll`} ref={navRef}>\n {children}\n </div>\n </aside>\n )\n}\n"],"names":["useNav","React","NavHamburger","SidebarWrapper","baseClass","children","hydrated","navOpen","navRef","shouldAnimate","aside","className","filter","Boolean","join","inert","undefined","div","ref"],"mappings":"AAAA;;AAEA,SAASA,MAAM,QAAQ,iBAAgB;AACvC,OAAOC,WAAW,QAAO;AAEzB,SAASC,YAAY,QAAQ,kBAAiB;AAC9C,OAAO,eAAc;AAErB,OAAO,MAAMC,iBAGR,CAAC,EAAEC,SAAS,EAAEC,QAAQ,EAAE;IAC3B,MAAM,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,MAAM,EAAEC,aAAa,EAAE,GAAGT;IAErD,qBACE,MAACU;QACCC,WAAW;YACTP;YACAG,WAAW,GAAGH,UAAU,UAAU,CAAC;YACnCK,iBAAiB,GAAGL,UAAU,aAAa,CAAC;YAC5CE,YAAY,GAAGF,UAAU,cAAc,CAAC;SACzC,CACEQ,MAAM,CAACC,SACPC,IAAI,CAAC;QACRC,OAAO,CAACR,UAAU,OAAOS;;0BAEzB,KAACC;gBAAIN,WAAW,GAAGP,UAAU,QAAQ,CAAC;0BACpC,cAAA,KAACF;oBAAaE,WAAWA;;;0BAE3B,KAACa;gBAAIN,WAAW,GAAGP,UAAU,QAAQ,CAAC;gBAAEc,KAAKV;0BAC1CH;;;;AAIT,EAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
@import '~@payloadcms/ui/scss';
|
|
2
|
+
|
|
3
|
+
@layer payload-default {
|
|
4
|
+
.enhanced-sidebar {
|
|
5
|
+
position: sticky;
|
|
6
|
+
top: 0;
|
|
7
|
+
left: 0;
|
|
8
|
+
flex-shrink: 0;
|
|
9
|
+
height: 100vh;
|
|
10
|
+
width: var(--nav-width);
|
|
11
|
+
border-right: 1px solid var(--theme-elevation-100);
|
|
12
|
+
opacity: 0;
|
|
13
|
+
|
|
14
|
+
[dir='rtl'] & {
|
|
15
|
+
border-right: none;
|
|
16
|
+
border-left: 1px solid var(--theme-elevation-100);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&--nav-animate {
|
|
20
|
+
transition: opacity var(--nav-trans-time) ease-in-out;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&--nav-open {
|
|
24
|
+
opacity: 1;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&__header {
|
|
28
|
+
position: absolute;
|
|
29
|
+
top: 0;
|
|
30
|
+
width: 100vw;
|
|
31
|
+
height: var(--app-header-height);
|
|
32
|
+
z-index: 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&__mobile-close {
|
|
36
|
+
display: none;
|
|
37
|
+
background: none;
|
|
38
|
+
border: 0;
|
|
39
|
+
outline: 0;
|
|
40
|
+
padding: base(0.8) 0;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&__scroll {
|
|
45
|
+
height: 100%;
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: row;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@include small-break {
|
|
51
|
+
&__mobile-close {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
padding-left: var(--gutter-h);
|
|
55
|
+
|
|
56
|
+
[dir='rtl'] & {
|
|
57
|
+
padding-left: 0;
|
|
58
|
+
padding-right: var(--gutter-h);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { EnhancedSidebarConfig } from '../../../types';
|
|
3
|
+
import './index.scss';
|
|
4
|
+
export type TabsBarProps = {
|
|
5
|
+
activeTabId: string;
|
|
6
|
+
onTabChange: (tabId: string) => void;
|
|
7
|
+
sidebarConfig: EnhancedSidebarConfig;
|
|
8
|
+
};
|
|
9
|
+
export declare const TabsBar: React.FC<TabsBarProps>;
|