@veiag/payload-enhanced-sidebar 0.1.1 → 0.2.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.
Files changed (45) hide show
  1. package/README.md +182 -5
  2. package/dist/components/EnhancedSidebar/Badge/index.d.ts +22 -0
  3. package/dist/components/EnhancedSidebar/Badge/index.js +30 -0
  4. package/dist/components/EnhancedSidebar/Badge/index.js.map +1 -0
  5. package/dist/components/EnhancedSidebar/Badge/index.scss +65 -0
  6. package/dist/components/EnhancedSidebar/BadgeProvider/index.d.ts +64 -0
  7. package/dist/components/EnhancedSidebar/BadgeProvider/index.js +66 -0
  8. package/dist/components/EnhancedSidebar/BadgeProvider/index.js.map +1 -0
  9. package/dist/components/EnhancedSidebar/InternalBadgeProvider/index.d.ts +15 -0
  10. package/dist/components/EnhancedSidebar/InternalBadgeProvider/index.js +132 -0
  11. package/dist/components/EnhancedSidebar/InternalBadgeProvider/index.js.map +1 -0
  12. package/dist/components/EnhancedSidebar/NavItem/index.d.ts +11 -0
  13. package/dist/components/EnhancedSidebar/NavItem/index.js +46 -0
  14. package/dist/components/EnhancedSidebar/NavItem/index.js.map +1 -0
  15. package/dist/components/EnhancedSidebar/SettingsMenuButton/index.d.ts +6 -0
  16. package/dist/components/EnhancedSidebar/SettingsMenuButton/index.js +33 -0
  17. package/dist/components/EnhancedSidebar/SettingsMenuButton/index.js.map +1 -0
  18. package/dist/components/EnhancedSidebar/SettingsMenuButton/index.scss +25 -0
  19. package/dist/components/EnhancedSidebar/SidebarContent.d.ts +2 -0
  20. package/dist/components/EnhancedSidebar/SidebarContent.js +117 -99
  21. package/dist/components/EnhancedSidebar/SidebarContent.js.map +1 -1
  22. package/dist/components/EnhancedSidebar/TabsBar/TabItem.d.ts +15 -0
  23. package/dist/components/EnhancedSidebar/TabsBar/TabItem.js +56 -0
  24. package/dist/components/EnhancedSidebar/TabsBar/TabItem.js.map +1 -0
  25. package/dist/components/EnhancedSidebar/TabsBar/index.d.ts +1 -0
  26. package/dist/components/EnhancedSidebar/TabsBar/index.js +58 -52
  27. package/dist/components/EnhancedSidebar/TabsBar/index.js.map +1 -1
  28. package/dist/components/EnhancedSidebar/TabsBar/index.scss +2 -2
  29. package/dist/components/EnhancedSidebar/hooks/useBadge.d.ts +11 -0
  30. package/dist/components/EnhancedSidebar/hooks/useBadge.js +31 -0
  31. package/dist/components/EnhancedSidebar/hooks/useBadge.js.map +1 -0
  32. package/dist/components/EnhancedSidebar/index.client.d.ts +2 -1
  33. package/dist/components/EnhancedSidebar/index.client.js +18 -31
  34. package/dist/components/EnhancedSidebar/index.client.js.map +1 -1
  35. package/dist/components/EnhancedSidebar/index.js +17 -1
  36. package/dist/components/EnhancedSidebar/index.js.map +1 -1
  37. package/dist/exports/client.d.ts +1 -0
  38. package/dist/exports/client.js +2 -1
  39. package/dist/exports/client.js.map +1 -1
  40. package/dist/index.d.ts +2 -1
  41. package/dist/index.js +16 -0
  42. package/dist/index.js.map +1 -1
  43. package/dist/types.d.ts +104 -1
  44. package/dist/types.js.map +1 -1
  45. package/package.json +10 -10
@@ -0,0 +1,46 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { getTranslation } from '@payloadcms/translations';
4
+ import { Link, useTranslation } from '@payloadcms/ui';
5
+ import React from 'react';
6
+ import { Badge } from '../Badge';
7
+ import { useBadge } from '../hooks/useBadge';
8
+ const baseClass = 'enhanced-sidebar';
9
+ export const NavItem = ({ id, badgeConfig, entity, href, isActive, isCurrentPage })=>{
10
+ const { i18n } = useTranslation();
11
+ const { value: badgeValue } = useBadge(badgeConfig, entity.slug);
12
+ const Label = /*#__PURE__*/ _jsxs(_Fragment, {
13
+ children: [
14
+ isActive && /*#__PURE__*/ _jsx("div", {
15
+ className: `${baseClass}__link-indicator`
16
+ }),
17
+ /*#__PURE__*/ _jsx("span", {
18
+ className: `${baseClass}__link-label`,
19
+ children: getTranslation(entity.label, i18n)
20
+ }),
21
+ badgeValue !== undefined && /*#__PURE__*/ _jsx(Badge, {
22
+ color: badgeConfig?.color,
23
+ position: "inline",
24
+ value: badgeValue
25
+ })
26
+ ]
27
+ });
28
+ if (isCurrentPage) {
29
+ return /*#__PURE__*/ _jsx("div", {
30
+ className: `${baseClass}__link`,
31
+ id: id,
32
+ children: Label
33
+ });
34
+ }
35
+ return /*#__PURE__*/ _jsx(Link, {
36
+ className: `${baseClass}__link`,
37
+ href: href,
38
+ id: id,
39
+ prefetch: false,
40
+ rel: entity.isExternal ? 'noopener noreferrer' : undefined,
41
+ target: entity.isExternal ? '_blank' : undefined,
42
+ children: Label
43
+ });
44
+ };
45
+
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/EnhancedSidebar/NavItem/index.tsx"],"sourcesContent":["'use client'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { Link, useTranslation } from '@payloadcms/ui'\nimport React from 'react'\n\nimport type { BadgeConfig, ExtendedEntity } from '../../../types'\n\nimport { Badge } from '../Badge'\nimport { useBadge } from '../hooks/useBadge'\n\nconst baseClass = 'enhanced-sidebar'\n\nexport type NavItemProps = {\n badgeConfig?: BadgeConfig\n entity: ExtendedEntity\n href: string\n id: string\n isActive: boolean\n isCurrentPage: boolean\n}\n\nexport const NavItem: React.FC<NavItemProps> = ({\n id,\n badgeConfig,\n entity,\n href,\n isActive,\n isCurrentPage,\n}) => {\n const { i18n } = useTranslation()\n const { value: badgeValue } = useBadge(badgeConfig, entity.slug)\n\n const Label = (\n <>\n {isActive && <div className={`${baseClass}__link-indicator`} />}\n <span className={`${baseClass}__link-label`}>{getTranslation(entity.label, i18n)}</span>\n {badgeValue !== undefined && (\n <Badge color={badgeConfig?.color} position=\"inline\" value={badgeValue} />\n )}\n </>\n )\n\n if (isCurrentPage) {\n return (\n <div className={`${baseClass}__link`} id={id}>\n {Label}\n </div>\n )\n }\n\n return (\n <Link\n className={`${baseClass}__link`}\n href={href}\n id={id}\n prefetch={false}\n rel={entity.isExternal ? 'noopener noreferrer' : undefined}\n target={entity.isExternal ? '_blank' : undefined}\n >\n {Label}\n </Link>\n )\n}\n"],"names":["getTranslation","Link","useTranslation","React","Badge","useBadge","baseClass","NavItem","id","badgeConfig","entity","href","isActive","isCurrentPage","i18n","value","badgeValue","slug","Label","div","className","span","label","undefined","color","position","prefetch","rel","isExternal","target"],"mappings":"AAAA;;AAEA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,IAAI,EAAEC,cAAc,QAAQ,iBAAgB;AACrD,OAAOC,WAAW,QAAO;AAIzB,SAASC,KAAK,QAAQ,WAAU;AAChC,SAASC,QAAQ,QAAQ,oBAAmB;AAE5C,MAAMC,YAAY;AAWlB,OAAO,MAAMC,UAAkC,CAAC,EAC9CC,EAAE,EACFC,WAAW,EACXC,MAAM,EACNC,IAAI,EACJC,QAAQ,EACRC,aAAa,EACd;IACC,MAAM,EAAEC,IAAI,EAAE,GAAGZ;IACjB,MAAM,EAAEa,OAAOC,UAAU,EAAE,GAAGX,SAASI,aAAaC,OAAOO,IAAI;IAE/D,MAAMC,sBACJ;;YACGN,0BAAY,KAACO;gBAAIC,WAAW,GAAGd,UAAU,gBAAgB,CAAC;;0BAC3D,KAACe;gBAAKD,WAAW,GAAGd,UAAU,YAAY,CAAC;0BAAGN,eAAeU,OAAOY,KAAK,EAAER;;YAC1EE,eAAeO,2BACd,KAACnB;gBAAMoB,OAAOf,aAAae;gBAAOC,UAAS;gBAASV,OAAOC;;;;IAKjE,IAAIH,eAAe;QACjB,qBACE,KAACM;YAAIC,WAAW,GAAGd,UAAU,MAAM,CAAC;YAAEE,IAAIA;sBACvCU;;IAGP;IAEA,qBACE,KAACjB;QACCmB,WAAW,GAAGd,UAAU,MAAM,CAAC;QAC/BK,MAAMA;QACNH,IAAIA;QACJkB,UAAU;QACVC,KAAKjB,OAAOkB,UAAU,GAAG,wBAAwBL;QACjDM,QAAQnB,OAAOkB,UAAU,GAAG,WAAWL;kBAEtCL;;AAGP,EAAC"}
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import './index.scss';
3
+ export type SettingsMenuButtonProps = {
4
+ settingsMenu?: React.ReactNode[];
5
+ };
6
+ export declare const SettingsMenuButton: React.FC<SettingsMenuButtonProps>;
@@ -0,0 +1,33 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Popup, useTranslation } from '@payloadcms/ui';
4
+ import React, { Fragment } from 'react';
5
+ import { Icon } from '../Icon';
6
+ import './index.scss';
7
+ const baseClass = 'settings-menu-button';
8
+ export const SettingsMenuButton = ({ settingsMenu })=>{
9
+ const { t } = useTranslation();
10
+ if (!settingsMenu || settingsMenu.length === 0) {
11
+ return null;
12
+ }
13
+ return /*#__PURE__*/ _jsx(Popup, {
14
+ button: /*#__PURE__*/ _jsx("span", {
15
+ "aria-label": t('general:menu'),
16
+ className: `${baseClass}__button`,
17
+ children: /*#__PURE__*/ _jsx(Icon, {
18
+ name: "Settings",
19
+ size: 20
20
+ })
21
+ }),
22
+ className: baseClass,
23
+ horizontalAlign: "right",
24
+ id: "settings-menu",
25
+ size: "small",
26
+ verticalAlign: "top",
27
+ children: settingsMenu.map((item, i)=>/*#__PURE__*/ _jsx(Fragment, {
28
+ children: item
29
+ }, `settings-menu-item-${i}`))
30
+ });
31
+ };
32
+
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/EnhancedSidebar/SettingsMenuButton/index.tsx"],"sourcesContent":["'use client'\nimport { Popup, useTranslation } from '@payloadcms/ui'\nimport React, { Fragment } from 'react'\n\nimport { Icon } from '../Icon'\nimport './index.scss'\n\nconst baseClass = 'settings-menu-button'\n\nexport type SettingsMenuButtonProps = {\n settingsMenu?: React.ReactNode[]\n}\n\nexport const SettingsMenuButton: React.FC<SettingsMenuButtonProps> = ({ settingsMenu }) => {\n const { t } = useTranslation()\n\n if (!settingsMenu || settingsMenu.length === 0) {\n return null\n }\n\n return (\n <Popup\n button={\n <span aria-label={t('general:menu')} className={`${baseClass}__button`}>\n <Icon name=\"Settings\" size={20} />\n </span>\n }\n className={baseClass}\n horizontalAlign=\"right\"\n id=\"settings-menu\"\n size=\"small\"\n verticalAlign=\"top\"\n >\n {settingsMenu.map((item, i) => (\n <Fragment key={`settings-menu-item-${i}`}>{item}</Fragment>\n ))}\n </Popup>\n )\n}\n"],"names":["Popup","useTranslation","React","Fragment","Icon","baseClass","SettingsMenuButton","settingsMenu","t","length","button","span","aria-label","className","name","size","horizontalAlign","id","verticalAlign","map","item","i"],"mappings":"AAAA;;AACA,SAASA,KAAK,EAAEC,cAAc,QAAQ,iBAAgB;AACtD,OAAOC,SAASC,QAAQ,QAAQ,QAAO;AAEvC,SAASC,IAAI,QAAQ,UAAS;AAC9B,OAAO,eAAc;AAErB,MAAMC,YAAY;AAMlB,OAAO,MAAMC,qBAAwD,CAAC,EAAEC,YAAY,EAAE;IACpF,MAAM,EAAEC,CAAC,EAAE,GAAGP;IAEd,IAAI,CAACM,gBAAgBA,aAAaE,MAAM,KAAK,GAAG;QAC9C,OAAO;IACT;IAEA,qBACE,KAACT;QACCU,sBACE,KAACC;YAAKC,cAAYJ,EAAE;YAAiBK,WAAW,GAAGR,UAAU,QAAQ,CAAC;sBACpE,cAAA,KAACD;gBAAKU,MAAK;gBAAWC,MAAM;;;QAGhCF,WAAWR;QACXW,iBAAgB;QAChBC,IAAG;QACHF,MAAK;QACLG,eAAc;kBAEbX,aAAaY,GAAG,CAAC,CAACC,MAAMC,kBACvB,KAAClB;0BAA0CiB;eAA5B,CAAC,mBAAmB,EAAEC,GAAG;;AAIhD,EAAC"}
@@ -0,0 +1,25 @@
1
+ @import '~@payloadcms/ui/scss';
2
+
3
+ @layer payload-default {
4
+ .settings-menu-button {
5
+ &__button {
6
+ display: flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ width: 36px;
10
+ height: 36px;
11
+ border: none;
12
+ border-radius: base(0.25);
13
+ background: transparent;
14
+ color: var(--theme-elevation-500);
15
+ cursor: pointer;
16
+ transition: all 150ms ease;
17
+
18
+ &:hover {
19
+ background: var(--theme-elevation-100);
20
+ color: var(--theme-text);
21
+ }
22
+ }
23
+
24
+ }
25
+ }
@@ -5,7 +5,9 @@ export type SidebarContentProps = {
5
5
  afterNavLinks?: React.ReactNode;
6
6
  beforeNavLinks?: React.ReactNode;
7
7
  groups: ExtendedGroup[];
8
+ initialActiveTabId: string;
8
9
  navPreferences: NavPreferences | null;
10
+ settingsMenu?: React.ReactNode[];
9
11
  sidebarConfig: EnhancedSidebarConfig;
10
12
  };
11
13
  export declare const SidebarContent: React.FC<SidebarContentProps>;
@@ -1,125 +1,127 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useTranslation } from '@payloadcms/ui';
4
- import React, { useEffect, useMemo, useState } from 'react';
4
+ import React, { useCallback, useMemo, useState } from 'react';
5
5
  import { extractLocalizedValue } from '../../utils';
6
6
  import { EnhancedSidebarClient } from './index.client';
7
7
  import { SidebarWrapper } from './SidebarWrapper';
8
8
  import { TabsBar } from './TabsBar';
9
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
10
+ const COOKIE_KEY = 'payload-enhanced-sidebar-active-tab';
11
+ const setTabCookie = (tabId)=>{
12
+ document.cookie = `${COOKIE_KEY}=${tabId}; path=/; max-age=31536000; SameSite=Lax`;
13
+ };
14
+ /**
15
+ * Computes filtered groups for a specific tab
16
+ */ const computeGroupsForTab = (tab, groups, currentLang)=>{
17
+ const { collections: tabCollections, customItems, globals: tabGlobals } = tab;
18
+ // If no specific collections/globals defined, show all
19
+ const showAll = !tabCollections && !tabGlobals;
20
+ const allowedSlugs = new Set([
21
+ ...tabCollections ?? [],
22
+ ...tabGlobals ?? []
30
23
  ]);
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;
24
+ let result = [];
25
+ if (showAll) {
26
+ result = groups.map((g)=>({
27
+ ...g,
28
+ entities: [
29
+ ...g.entities
30
+ ]
31
+ }));
32
+ } else if (allowedSlugs.size > 0) {
33
+ result = groups.map((group)=>({
34
+ ...group,
35
+ entities: group.entities.filter((entity)=>allowedSlugs.has(entity.slug))
36
+ })).filter((group)=>group.entities.length > 0);
37
+ }
38
+ // Merge custom items into groups
39
+ if (customItems && customItems.length > 0) {
40
+ const ungroupedItems = [];
41
+ for (const item of customItems){
42
+ if (item.group) {
43
+ // Get localized group name for comparison
44
+ const itemGroupLabel = extractLocalizedValue(item.group, currentLang);
45
+ // Find existing group by comparing localized labels
46
+ const existingGroup = result.find((g)=>{
47
+ const groupLabel = extractLocalizedValue(g.label, currentLang);
48
+ return groupLabel === itemGroupLabel;
49
+ });
50
+ if (existingGroup) {
51
+ existingGroup.entities.push({
52
+ slug: item.slug,
53
+ type: 'custom',
54
+ href: item.href,
55
+ isExternal: item.isExternal,
56
+ label: item.label
69
57
  });
70
- if (existingGroup) {
71
- existingGroup.entities.push({
72
- slug: item.slug,
73
- type: 'custom',
74
- href: item.href,
75
- isExternal: item.isExternal,
76
- label: item.label
77
- });
78
- } else {
79
- // Create new group
80
- result.push({
81
- entities: [
82
- {
83
- slug: item.slug,
84
- type: 'custom',
85
- href: item.href,
86
- isExternal: item.isExternal,
87
- label: item.label
88
- }
89
- ],
90
- label: item.group
91
- });
92
- }
93
58
  } else {
94
- ungroupedItems.push(item);
59
+ // Create new group
60
+ result.push({
61
+ entities: [
62
+ {
63
+ slug: item.slug,
64
+ type: 'custom',
65
+ href: item.href,
66
+ isExternal: item.isExternal,
67
+ label: item.label
68
+ }
69
+ ],
70
+ label: item.group
71
+ });
95
72
  }
73
+ } else {
74
+ ungroupedItems.push(item);
96
75
  }
97
- // Add ungrouped items at the end
98
- if (ungroupedItems.length > 0) {
99
- result.push({
100
- entities: ungroupedItems.map((item)=>({
101
- slug: item.slug,
102
- type: 'custom',
103
- href: item.href,
104
- isExternal: item.isExternal,
105
- label: item.label
106
- })),
107
- label: ''
108
- });
109
- }
76
+ }
77
+ // Add ungrouped items at the end
78
+ if (ungroupedItems.length > 0) {
79
+ result.push({
80
+ entities: ungroupedItems.map((item)=>({
81
+ slug: item.slug,
82
+ type: 'custom',
83
+ href: item.href,
84
+ isExternal: item.isExternal,
85
+ label: item.label
86
+ })),
87
+ label: ''
88
+ });
89
+ }
90
+ }
91
+ return result;
92
+ };
93
+ export const SidebarContent = ({ afterNavLinks, beforeNavLinks, groups, initialActiveTabId, navPreferences, settingsMenu, sidebarConfig })=>{
94
+ const { i18n } = useTranslation();
95
+ const currentLang = i18n.language;
96
+ const tabs = useMemo(()=>sidebarConfig.tabs?.filter((t)=>t.type === 'tab') ?? [], [
97
+ sidebarConfig.tabs
98
+ ]);
99
+ const [activeTabId, setActiveTabId] = useState(initialActiveTabId);
100
+ const handleTabChange = useCallback((tabId)=>{
101
+ setActiveTabId(tabId);
102
+ setTabCookie(tabId);
103
+ }, []);
104
+ // Build groups for all tabs at once to keep them mounted
105
+ const groupsPerTab = useMemo(()=>{
106
+ const result = {};
107
+ for (const tab of tabs){
108
+ result[tab.id] = computeGroupsForTab(tab, groups, currentLang);
110
109
  }
111
110
  return result;
112
111
  }, [
113
- activeTab,
112
+ tabs,
114
113
  groups,
115
114
  currentLang
116
115
  ]);
116
+ // Fallback: if no tabs defined, show all groups
117
+ const hasTabs = tabs.length > 0;
117
118
  return /*#__PURE__*/ _jsxs(SidebarWrapper, {
118
119
  baseClass: baseClass,
119
120
  children: [
120
121
  /*#__PURE__*/ _jsx(TabsBar, {
121
122
  activeTabId: activeTabId,
122
- onTabChange: setActiveTabId,
123
+ onTabChange: handleTabChange,
124
+ settingsMenu: settingsMenu,
123
125
  sidebarConfig: sidebarConfig
124
126
  }),
125
127
  /*#__PURE__*/ _jsx("nav", {
@@ -128,8 +130,24 @@ export const SidebarContent = ({ afterNavLinks, beforeNavLinks, groups, navPrefe
128
130
  className: `${baseClass}__content-scroll`,
129
131
  children: [
130
132
  beforeNavLinks,
133
+ hasTabs ? // Render all tabs but hide inactive ones to preserve NavGroup state
134
+ tabs.map((tab)=>{
135
+ const isActive = activeTabId === tab.id;
136
+ return /*#__PURE__*/ _jsx("div", {
137
+ "aria-hidden": !isActive,
138
+ style: {
139
+ display: isActive ? undefined : 'none'
140
+ },
141
+ children: /*#__PURE__*/ _jsx(EnhancedSidebarClient, {
142
+ badges: sidebarConfig.badges,
143
+ groups: groupsPerTab[tab.id] ?? [],
144
+ navPreferences: navPreferences
145
+ })
146
+ }, tab.id);
147
+ }) : // No tabs defined - show all groups
131
148
  /*#__PURE__*/ _jsx(EnhancedSidebarClient, {
132
- groups: filteredGroups,
149
+ badges: sidebarConfig.badges,
150
+ groups: groups,
133
151
  navPreferences: navPreferences
134
152
  }),
135
153
  afterNavLinks
@@ -1 +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 ExtendedEntity,\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 isExternal: item.isExternal,\n label: item.label,\n } as ExtendedEntity)\n } else {\n // Create new group\n result.push({\n entities: [\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 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 isExternal: item.isExternal,\n label: item.label,\n })) as ExtendedEntity[],\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","isExternal","onTabChange","nav","className","div"],"mappings":"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"}
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, { useCallback, useMemo, useState } from 'react'\n\nimport type {\n EnhancedSidebarConfig,\n ExtendedEntity,\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 initialActiveTabId: string\n navPreferences: NavPreferences | null\n settingsMenu?: React.ReactNode[]\n sidebarConfig: EnhancedSidebarConfig\n}\n\nconst COOKIE_KEY = 'payload-enhanced-sidebar-active-tab'\n\nconst setTabCookie = (tabId: string) => {\n document.cookie = `${COOKIE_KEY}=${tabId}; path=/; max-age=31536000; SameSite=Lax`\n}\n\n/**\n * Computes filtered groups for a specific tab\n */\nconst computeGroupsForTab = (\n tab: SidebarTabContentType,\n groups: ExtendedGroup[],\n currentLang: string,\n): ExtendedGroup[] => {\n const { collections: tabCollections, customItems, globals: tabGlobals } = tab\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 isExternal: item.isExternal,\n label: item.label,\n } as ExtendedEntity)\n } else {\n // Create new group\n result.push({\n entities: [\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 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 isExternal: item.isExternal,\n label: item.label,\n })) as ExtendedEntity[],\n label: '',\n })\n }\n }\n\n return result\n}\n\nexport const SidebarContent: React.FC<SidebarContentProps> = ({\n afterNavLinks,\n beforeNavLinks,\n groups,\n initialActiveTabId,\n navPreferences,\n settingsMenu,\n sidebarConfig,\n}) => {\n const { i18n } = useTranslation()\n const currentLang = i18n.language\n\n const tabs = useMemo(\n () => sidebarConfig.tabs?.filter((t): t is SidebarTabContentType => t.type === 'tab') ?? [],\n [sidebarConfig.tabs],\n )\n\n const [activeTabId, setActiveTabId] = useState(initialActiveTabId)\n\n const handleTabChange = useCallback((tabId: string) => {\n setActiveTabId(tabId)\n setTabCookie(tabId)\n }, [])\n\n // Build groups for all tabs at once to keep them mounted\n const groupsPerTab = useMemo(() => {\n const result: Record<string, ExtendedGroup[]> = {}\n for (const tab of tabs) {\n result[tab.id] = computeGroupsForTab(tab, groups, currentLang)\n }\n return result\n }, [tabs, groups, currentLang])\n\n // Fallback: if no tabs defined, show all groups\n const hasTabs = tabs.length > 0\n\n return (\n <SidebarWrapper baseClass={baseClass}>\n <TabsBar\n activeTabId={activeTabId}\n onTabChange={handleTabChange}\n settingsMenu={settingsMenu}\n sidebarConfig={sidebarConfig}\n />\n <nav className={`${baseClass}__content`}>\n <div className={`${baseClass}__content-scroll`}>\n {beforeNavLinks}\n {hasTabs ? (\n // Render all tabs but hide inactive ones to preserve NavGroup state\n tabs.map((tab) => {\n const isActive = activeTabId === tab.id\n return (\n <div\n aria-hidden={!isActive}\n key={tab.id}\n style={{ display: isActive ? undefined : 'none' }}\n >\n <EnhancedSidebarClient\n badges={sidebarConfig.badges}\n groups={groupsPerTab[tab.id] ?? []}\n navPreferences={navPreferences}\n />\n </div>\n )\n })\n ) : (\n // No tabs defined - show all groups\n <EnhancedSidebarClient\n badges={sidebarConfig.badges}\n groups={groups}\n navPreferences={navPreferences}\n />\n )}\n {afterNavLinks}\n </div>\n </nav>\n </SidebarWrapper>\n )\n}\n"],"names":["useTranslation","React","useCallback","useMemo","useState","extractLocalizedValue","EnhancedSidebarClient","SidebarWrapper","TabsBar","baseClass","COOKIE_KEY","setTabCookie","tabId","document","cookie","computeGroupsForTab","tab","groups","currentLang","collections","tabCollections","customItems","globals","tabGlobals","showAll","allowedSlugs","Set","result","map","g","entities","size","group","filter","entity","has","slug","length","ungroupedItems","item","itemGroupLabel","existingGroup","find","groupLabel","label","push","type","href","isExternal","SidebarContent","afterNavLinks","beforeNavLinks","initialActiveTabId","navPreferences","settingsMenu","sidebarConfig","i18n","language","tabs","t","activeTabId","setActiveTabId","handleTabChange","groupsPerTab","id","hasTabs","onTabChange","nav","className","div","isActive","aria-hidden","style","display","undefined","badges"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import type { SidebarTabContent, SidebarTabLink } from '../../../types';
3
+ type TabButtonProps = {
4
+ isActive: boolean;
5
+ onTabChange: (tabId: string) => void;
6
+ tab: SidebarTabContent;
7
+ };
8
+ export declare const TabButton: React.FC<TabButtonProps>;
9
+ type TabLinkProps = {
10
+ href: string;
11
+ isActive: boolean;
12
+ link: SidebarTabLink;
13
+ };
14
+ export declare const TabLink: React.FC<TabLinkProps>;
15
+ export {};
@@ -0,0 +1,56 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { getTranslation } from '@payloadcms/translations';
4
+ import { Link, useTranslation } from '@payloadcms/ui';
5
+ import React from 'react';
6
+ import { Badge } from '../Badge';
7
+ import { useBadge } from '../hooks/useBadge';
8
+ import { Icon } from '../Icon';
9
+ const tabsBaseClass = 'tabs-bar';
10
+ export const TabButton = ({ isActive, onTabChange, tab })=>{
11
+ const { i18n } = useTranslation();
12
+ const label = getTranslation(tab.label, i18n);
13
+ const { value } = useBadge(tab.badge, tab.id);
14
+ return /*#__PURE__*/ _jsxs("button", {
15
+ className: `${tabsBaseClass}__tab ${isActive ? `${tabsBaseClass}__tab--active` : ''}`,
16
+ onClick: ()=>onTabChange(tab.id),
17
+ title: label,
18
+ type: "button",
19
+ children: [
20
+ /*#__PURE__*/ _jsx(Icon, {
21
+ name: tab.icon,
22
+ size: 20
23
+ }),
24
+ value !== undefined && /*#__PURE__*/ _jsx(Badge, {
25
+ color: tab.badge?.color,
26
+ position: "absolute",
27
+ value: value
28
+ })
29
+ ]
30
+ });
31
+ };
32
+ export const TabLink = ({ href, isActive, link })=>{
33
+ const { i18n } = useTranslation();
34
+ const label = getTranslation(link.label, i18n);
35
+ const { value } = useBadge(link.badge, link.id);
36
+ return /*#__PURE__*/ _jsxs(Link, {
37
+ className: `${tabsBaseClass}__link ${isActive ? `${tabsBaseClass}__link--active` : ''}`,
38
+ href: href,
39
+ rel: link.isExternal ? 'noopener noreferrer' : undefined,
40
+ target: link.isExternal ? '_blank' : undefined,
41
+ title: label,
42
+ children: [
43
+ /*#__PURE__*/ _jsx(Icon, {
44
+ name: link.icon,
45
+ size: 20
46
+ }),
47
+ value !== undefined && /*#__PURE__*/ _jsx(Badge, {
48
+ color: link.badge?.color,
49
+ position: "absolute",
50
+ value: value
51
+ })
52
+ ]
53
+ });
54
+ };
55
+
56
+ //# sourceMappingURL=TabItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/EnhancedSidebar/TabsBar/TabItem.tsx"],"sourcesContent":["'use client'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { Link, useTranslation } from '@payloadcms/ui'\nimport React from 'react'\n\nimport type { SidebarTabContent, SidebarTabLink } from '../../../types'\n\nimport { Badge } from '../Badge'\nimport { useBadge } from '../hooks/useBadge'\nimport { Icon } from '../Icon'\n\nconst tabsBaseClass = 'tabs-bar'\n\ntype TabButtonProps = {\n isActive: boolean\n onTabChange: (tabId: string) => void\n tab: SidebarTabContent\n}\n\nexport const TabButton: React.FC<TabButtonProps> = ({ isActive, onTabChange, tab }) => {\n const { i18n } = useTranslation()\n const label = getTranslation(tab.label, i18n)\n const { value } = useBadge(tab.badge, tab.id)\n\n return (\n <button\n className={`${tabsBaseClass}__tab ${isActive ? `${tabsBaseClass}__tab--active` : ''}`}\n onClick={() => onTabChange(tab.id)}\n title={label}\n type=\"button\"\n >\n <Icon name={tab.icon} size={20} />\n {value !== undefined && <Badge color={tab.badge?.color} position=\"absolute\" value={value} />}\n </button>\n )\n}\n\ntype TabLinkProps = {\n href: string\n isActive: boolean\n link: SidebarTabLink\n}\n\nexport const TabLink: React.FC<TabLinkProps> = ({ href, isActive, link }) => {\n const { i18n } = useTranslation()\n const label = getTranslation(link.label, i18n)\n const { value } = useBadge(link.badge, link.id)\n\n return (\n <Link\n className={`${tabsBaseClass}__link ${isActive ? `${tabsBaseClass}__link--active` : ''}`}\n href={href}\n rel={link.isExternal ? 'noopener noreferrer' : undefined}\n target={link.isExternal ? '_blank' : undefined}\n title={label}\n >\n <Icon name={link.icon} size={20} />\n {value !== undefined && <Badge color={link.badge?.color} position=\"absolute\" value={value} />}\n </Link>\n )\n}\n"],"names":["getTranslation","Link","useTranslation","React","Badge","useBadge","Icon","tabsBaseClass","TabButton","isActive","onTabChange","tab","i18n","label","value","badge","id","button","className","onClick","title","type","name","icon","size","undefined","color","position","TabLink","href","link","rel","isExternal","target"],"mappings":"AAAA;;AAEA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,IAAI,EAAEC,cAAc,QAAQ,iBAAgB;AACrD,OAAOC,WAAW,QAAO;AAIzB,SAASC,KAAK,QAAQ,WAAU;AAChC,SAASC,QAAQ,QAAQ,oBAAmB;AAC5C,SAASC,IAAI,QAAQ,UAAS;AAE9B,MAAMC,gBAAgB;AAQtB,OAAO,MAAMC,YAAsC,CAAC,EAAEC,QAAQ,EAAEC,WAAW,EAAEC,GAAG,EAAE;IAChF,MAAM,EAAEC,IAAI,EAAE,GAAGV;IACjB,MAAMW,QAAQb,eAAeW,IAAIE,KAAK,EAAED;IACxC,MAAM,EAAEE,KAAK,EAAE,GAAGT,SAASM,IAAII,KAAK,EAAEJ,IAAIK,EAAE;IAE5C,qBACE,MAACC;QACCC,WAAW,GAAGX,cAAc,MAAM,EAAEE,WAAW,GAAGF,cAAc,aAAa,CAAC,GAAG,IAAI;QACrFY,SAAS,IAAMT,YAAYC,IAAIK,EAAE;QACjCI,OAAOP;QACPQ,MAAK;;0BAEL,KAACf;gBAAKgB,MAAMX,IAAIY,IAAI;gBAAEC,MAAM;;YAC3BV,UAAUW,2BAAa,KAACrB;gBAAMsB,OAAOf,IAAII,KAAK,EAAEW;gBAAOC,UAAS;gBAAWb,OAAOA;;;;AAGzF,EAAC;AAQD,OAAO,MAAMc,UAAkC,CAAC,EAAEC,IAAI,EAAEpB,QAAQ,EAAEqB,IAAI,EAAE;IACtE,MAAM,EAAElB,IAAI,EAAE,GAAGV;IACjB,MAAMW,QAAQb,eAAe8B,KAAKjB,KAAK,EAAED;IACzC,MAAM,EAAEE,KAAK,EAAE,GAAGT,SAASyB,KAAKf,KAAK,EAAEe,KAAKd,EAAE;IAE9C,qBACE,MAACf;QACCiB,WAAW,GAAGX,cAAc,OAAO,EAAEE,WAAW,GAAGF,cAAc,cAAc,CAAC,GAAG,IAAI;QACvFsB,MAAMA;QACNE,KAAKD,KAAKE,UAAU,GAAG,wBAAwBP;QAC/CQ,QAAQH,KAAKE,UAAU,GAAG,WAAWP;QACrCL,OAAOP;;0BAEP,KAACP;gBAAKgB,MAAMQ,KAAKP,IAAI;gBAAEC,MAAM;;YAC5BV,UAAUW,2BAAa,KAACrB;gBAAMsB,OAAOI,KAAKf,KAAK,EAAEW;gBAAOC,UAAS;gBAAWb,OAAOA;;;;AAG1F,EAAC"}
@@ -4,6 +4,7 @@ import './index.scss';
4
4
  export type TabsBarProps = {
5
5
  activeTabId: string;
6
6
  onTabChange: (tabId: string) => void;
7
+ settingsMenu?: React.ReactNode[];
7
8
  sidebarConfig: EnhancedSidebarConfig;
8
9
  };
9
10
  export declare const TabsBar: React.FC<TabsBarProps>;