@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.
Files changed (53) hide show
  1. package/README.md +231 -0
  2. package/dist/components/EnhancedSidebar/CustomTabContent.d.ts +6 -0
  3. package/dist/components/EnhancedSidebar/CustomTabContent.js +35 -0
  4. package/dist/components/EnhancedSidebar/CustomTabContent.js.map +1 -0
  5. package/dist/components/EnhancedSidebar/Icon.d.ts +8 -0
  6. package/dist/components/EnhancedSidebar/Icon.js +16 -0
  7. package/dist/components/EnhancedSidebar/Icon.js.map +1 -0
  8. package/dist/components/EnhancedSidebar/NavHamburger/index.d.ts +4 -0
  9. package/dist/components/EnhancedSidebar/NavHamburger/index.js +18 -0
  10. package/dist/components/EnhancedSidebar/NavHamburger/index.js.map +1 -0
  11. package/dist/components/EnhancedSidebar/SidebarContent.d.ts +11 -0
  12. package/dist/components/EnhancedSidebar/SidebarContent.js +140 -0
  13. package/dist/components/EnhancedSidebar/SidebarContent.js.map +1 -0
  14. package/dist/components/EnhancedSidebar/SidebarWrapper/index.d.ts +6 -0
  15. package/dist/components/EnhancedSidebar/SidebarWrapper/index.js +33 -0
  16. package/dist/components/EnhancedSidebar/SidebarWrapper/index.js.map +1 -0
  17. package/dist/components/EnhancedSidebar/SidebarWrapper/index.scss +63 -0
  18. package/dist/components/EnhancedSidebar/TabsBar/index.d.ts +9 -0
  19. package/dist/components/EnhancedSidebar/TabsBar/index.js +85 -0
  20. package/dist/components/EnhancedSidebar/TabsBar/index.js.map +1 -0
  21. package/dist/components/EnhancedSidebar/TabsBar/index.scss +108 -0
  22. package/dist/components/EnhancedSidebar/getNavPrefs.d.ts +2 -0
  23. package/dist/components/EnhancedSidebar/getNavPrefs.js +31 -0
  24. package/dist/components/EnhancedSidebar/getNavPrefs.js.map +1 -0
  25. package/dist/components/EnhancedSidebar/index.client.d.ts +7 -0
  26. package/dist/components/EnhancedSidebar/index.client.js +94 -0
  27. package/dist/components/EnhancedSidebar/index.client.js.map +1 -0
  28. package/dist/components/EnhancedSidebar/index.d.ts +10 -0
  29. package/dist/components/EnhancedSidebar/index.js +65 -0
  30. package/dist/components/EnhancedSidebar/index.js.map +1 -0
  31. package/dist/components/EnhancedSidebar/index.scss +101 -0
  32. package/dist/exports/client.d.ts +0 -0
  33. package/dist/exports/client.js +3 -0
  34. package/dist/exports/client.js.map +1 -0
  35. package/dist/exports/rsc.d.ts +1 -0
  36. package/dist/exports/rsc.js +3 -0
  37. package/dist/exports/rsc.js.map +1 -0
  38. package/dist/hooks/useMutationObserver.d.ts +1 -0
  39. package/dist/hooks/useMutationObserver.js +21 -0
  40. package/dist/hooks/useMutationObserver.js.map +1 -0
  41. package/dist/index.d.ts +4 -0
  42. package/dist/index.js +64 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/translations/index.d.ts +22 -0
  45. package/dist/translations/index.js +30 -0
  46. package/dist/translations/index.js.map +1 -0
  47. package/dist/types.d.ts +132 -0
  48. package/dist/types.js +3 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/utils/index.d.ts +3 -0
  51. package/dist/utils/index.js +14 -0
  52. package/dist/utils/index.js.map +1 -0
  53. package/package.json +95 -0
@@ -0,0 +1,85 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { getTranslation } from '@payloadcms/translations';
4
+ import { Link, useConfig, useTranslation } from '@payloadcms/ui';
5
+ import { usePathname } from 'next/navigation';
6
+ import { formatAdminURL } from 'payload/shared';
7
+ import React from 'react';
8
+ import { Icon } from '../Icon';
9
+ import './index.scss';
10
+ const tabsBaseClass = 'tabs-bar';
11
+ export const TabsBar = ({ activeTabId, onTabChange, sidebarConfig })=>{
12
+ const { i18n } = useTranslation();
13
+ const pathname = usePathname();
14
+ const { config: { admin: { routes: { logout: logoutRoute } }, routes: { admin: adminRoute } } } = useConfig();
15
+ const showLogout = sidebarConfig.showLogout !== false;
16
+ const renderTab = (tab)=>{
17
+ const label = getTranslation(tab.label, i18n);
18
+ const isActive = activeTabId === tab.id;
19
+ return /*#__PURE__*/ _jsx("button", {
20
+ className: `${tabsBaseClass}__tab ${isActive ? `${tabsBaseClass}__tab--active` : ''}`,
21
+ onClick: ()=>onTabChange(tab.id),
22
+ title: label,
23
+ type: "button",
24
+ children: /*#__PURE__*/ _jsx(Icon, {
25
+ name: tab.icon,
26
+ size: 20
27
+ })
28
+ }, tab.id);
29
+ };
30
+ const renderLink = (link)=>{
31
+ const label = getTranslation(link.label, i18n);
32
+ const href = formatAdminURL({
33
+ adminRoute,
34
+ path: link.href
35
+ });
36
+ // Check if this link is active
37
+ const isActive = pathname === href || link.href === '/' && pathname === adminRoute;
38
+ return /*#__PURE__*/ _jsx(Link, {
39
+ className: `${tabsBaseClass}__link ${isActive ? `${tabsBaseClass}__link--active` : ''}`,
40
+ href: href,
41
+ title: label,
42
+ children: /*#__PURE__*/ _jsx(Icon, {
43
+ name: link.icon,
44
+ size: 20
45
+ })
46
+ }, link.id);
47
+ };
48
+ const renderTabItem = (item)=>{
49
+ if (item.type === 'tab') {
50
+ return renderTab(item);
51
+ }
52
+ return renderLink(item);
53
+ };
54
+ const tabItems = sidebarConfig.tabs ?? [];
55
+ return /*#__PURE__*/ _jsxs("div", {
56
+ className: tabsBaseClass,
57
+ children: [
58
+ /*#__PURE__*/ _jsx("div", {
59
+ className: `${tabsBaseClass}__tabs`,
60
+ children: tabItems.map(renderTabItem)
61
+ }),
62
+ showLogout && /*#__PURE__*/ _jsx("div", {
63
+ className: `${tabsBaseClass}__actions`,
64
+ children: /*#__PURE__*/ _jsx(Link, {
65
+ className: `${tabsBaseClass}__action`,
66
+ href: formatAdminURL({
67
+ adminRoute,
68
+ path: logoutRoute
69
+ }),
70
+ title: getTranslation({
71
+ en: 'Logout',
72
+ uk: 'Вийти'
73
+ }, i18n),
74
+ type: "button",
75
+ children: /*#__PURE__*/ _jsx(Icon, {
76
+ name: "LogOut",
77
+ size: 20
78
+ })
79
+ })
80
+ })
81
+ ]
82
+ });
83
+ };
84
+
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/EnhancedSidebar/TabsBar/index.tsx"],"sourcesContent":["'use client'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { Link, useConfig, useTranslation } from '@payloadcms/ui'\nimport { usePathname } from 'next/navigation'\nimport { formatAdminURL } from 'payload/shared'\nimport React from 'react'\n\nimport type { EnhancedSidebarConfig, SidebarTabContent, SidebarTabLink } from '../../../types'\n\nimport { Icon } from '../Icon'\nimport './index.scss'\n\nconst tabsBaseClass = 'tabs-bar'\n\nexport type TabsBarProps = {\n activeTabId: string\n onTabChange: (tabId: string) => void\n sidebarConfig: EnhancedSidebarConfig\n}\n\nexport const TabsBar: React.FC<TabsBarProps> = ({ activeTabId, onTabChange, sidebarConfig }) => {\n const { i18n } = useTranslation()\n const pathname = usePathname()\n\n const {\n config: {\n admin: {\n routes: { logout: logoutRoute },\n },\n routes: { admin: adminRoute },\n },\n } = useConfig()\n\n const showLogout = sidebarConfig.showLogout !== false\n\n const renderTab = (tab: SidebarTabContent) => {\n const label = getTranslation(tab.label, i18n)\n const isActive = activeTabId === tab.id\n\n return (\n <button\n className={`${tabsBaseClass}__tab ${isActive ? `${tabsBaseClass}__tab--active` : ''}`}\n key={tab.id}\n onClick={() => onTabChange(tab.id)}\n title={label}\n type=\"button\"\n >\n <Icon name={tab.icon} size={20} />\n </button>\n )\n }\n\n const renderLink = (link: SidebarTabLink) => {\n const label = getTranslation(link.label, i18n)\n const href = formatAdminURL({ adminRoute, path: link.href as `/${string}` })\n\n // Check if this link is active\n const isActive = pathname === href || (link.href === '/' && pathname === adminRoute)\n\n return (\n <Link\n className={`${tabsBaseClass}__link ${isActive ? `${tabsBaseClass}__link--active` : ''}`}\n href={href}\n key={link.id}\n title={label}\n >\n <Icon name={link.icon} size={20} />\n </Link>\n )\n }\n\n const renderTabItem = (item: SidebarTabContent | SidebarTabLink) => {\n if (item.type === 'tab') {\n return renderTab(item)\n }\n return renderLink(item)\n }\n\n const tabItems = sidebarConfig.tabs ?? []\n\n return (\n <div className={tabsBaseClass}>\n <div className={`${tabsBaseClass}__tabs`}>{tabItems.map(renderTabItem)}</div>\n\n {showLogout && (\n <div className={`${tabsBaseClass}__actions`}>\n <Link\n className={`${tabsBaseClass}__action`}\n href={formatAdminURL({\n adminRoute,\n path: logoutRoute,\n })}\n title={getTranslation({ en: 'Logout', uk: 'Вийти' }, i18n)}\n type=\"button\"\n >\n <Icon name=\"LogOut\" size={20} />\n </Link>\n </div>\n )}\n </div>\n )\n}\n"],"names":["getTranslation","Link","useConfig","useTranslation","usePathname","formatAdminURL","React","Icon","tabsBaseClass","TabsBar","activeTabId","onTabChange","sidebarConfig","i18n","pathname","config","admin","routes","logout","logoutRoute","adminRoute","showLogout","renderTab","tab","label","isActive","id","button","className","onClick","title","type","name","icon","size","renderLink","link","href","path","renderTabItem","item","tabItems","tabs","div","map","en","uk"],"mappings":"AAAA;;AAEA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,IAAI,EAAEC,SAAS,EAAEC,cAAc,QAAQ,iBAAgB;AAChE,SAASC,WAAW,QAAQ,kBAAiB;AAC7C,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,OAAOC,WAAW,QAAO;AAIzB,SAASC,IAAI,QAAQ,UAAS;AAC9B,OAAO,eAAc;AAErB,MAAMC,gBAAgB;AAQtB,OAAO,MAAMC,UAAkC,CAAC,EAAEC,WAAW,EAAEC,WAAW,EAAEC,aAAa,EAAE;IACzF,MAAM,EAAEC,IAAI,EAAE,GAAGV;IACjB,MAAMW,WAAWV;IAEjB,MAAM,EACJW,QAAQ,EACNC,OAAO,EACLC,QAAQ,EAAEC,QAAQC,WAAW,EAAE,EAChC,EACDF,QAAQ,EAAED,OAAOI,UAAU,EAAE,EAC9B,EACF,GAAGlB;IAEJ,MAAMmB,aAAaT,cAAcS,UAAU,KAAK;IAEhD,MAAMC,YAAY,CAACC;QACjB,MAAMC,QAAQxB,eAAeuB,IAAIC,KAAK,EAAEX;QACxC,MAAMY,WAAWf,gBAAgBa,IAAIG,EAAE;QAEvC,qBACE,KAACC;YACCC,WAAW,GAAGpB,cAAc,MAAM,EAAEiB,WAAW,GAAGjB,cAAc,aAAa,CAAC,GAAG,IAAI;YAErFqB,SAAS,IAAMlB,YAAYY,IAAIG,EAAE;YACjCI,OAAON;YACPO,MAAK;sBAEL,cAAA,KAACxB;gBAAKyB,MAAMT,IAAIU,IAAI;gBAAEC,MAAM;;WALvBX,IAAIG,EAAE;IAQjB;IAEA,MAAMS,aAAa,CAACC;QAClB,MAAMZ,QAAQxB,eAAeoC,KAAKZ,KAAK,EAAEX;QACzC,MAAMwB,OAAOhC,eAAe;YAAEe;YAAYkB,MAAMF,KAAKC,IAAI;QAAiB;QAE1E,+BAA+B;QAC/B,MAAMZ,WAAWX,aAAauB,QAASD,KAAKC,IAAI,KAAK,OAAOvB,aAAaM;QAEzE,qBACE,KAACnB;YACC2B,WAAW,GAAGpB,cAAc,OAAO,EAAEiB,WAAW,GAAGjB,cAAc,cAAc,CAAC,GAAG,IAAI;YACvF6B,MAAMA;YAENP,OAAON;sBAEP,cAAA,KAACjB;gBAAKyB,MAAMI,KAAKH,IAAI;gBAAEC,MAAM;;WAHxBE,KAAKV,EAAE;IAMlB;IAEA,MAAMa,gBAAgB,CAACC;QACrB,IAAIA,KAAKT,IAAI,KAAK,OAAO;YACvB,OAAOT,UAAUkB;QACnB;QACA,OAAOL,WAAWK;IACpB;IAEA,MAAMC,WAAW7B,cAAc8B,IAAI,IAAI,EAAE;IAEzC,qBACE,MAACC;QAAIf,WAAWpB;;0BACd,KAACmC;gBAAIf,WAAW,GAAGpB,cAAc,MAAM,CAAC;0BAAGiC,SAASG,GAAG,CAACL;;YAEvDlB,4BACC,KAACsB;gBAAIf,WAAW,GAAGpB,cAAc,SAAS,CAAC;0BACzC,cAAA,KAACP;oBACC2B,WAAW,GAAGpB,cAAc,QAAQ,CAAC;oBACrC6B,MAAMhC,eAAe;wBACnBe;wBACAkB,MAAMnB;oBACR;oBACAW,OAAO9B,eAAe;wBAAE6C,IAAI;wBAAUC,IAAI;oBAAQ,GAAGjC;oBACrDkB,MAAK;8BAEL,cAAA,KAACxB;wBAAKyB,MAAK;wBAASE,MAAM;;;;;;AAMtC,EAAC"}
@@ -0,0 +1,108 @@
1
+ @import '~@payloadcms/ui/scss';
2
+
3
+ @layer payload-default {
4
+ .tabs-bar {
5
+ display: flex;
6
+ flex-direction: column;
7
+ justify-content: space-between;
8
+ align-items: center;
9
+ width: 48px;
10
+ min-width: 48px;
11
+ padding: base(0.5) 0;
12
+ border-right: 1px solid var(--theme-elevation-100);
13
+ background: var(--theme-elevation-50);
14
+
15
+ [dir='rtl'] & {
16
+ border-right: none;
17
+ border-left: 1px solid var(--theme-elevation-100);
18
+ }
19
+
20
+ &__tabs {
21
+ display: flex;
22
+ flex-direction: column;
23
+ align-items: center;
24
+ gap: base(0.25);
25
+ padding-top: var(--app-header-height);
26
+ }
27
+
28
+ &__tab,
29
+ &__link {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ width: 36px;
34
+ height: 36px;
35
+ border: none;
36
+ border-radius: base(0.25);
37
+ background: transparent;
38
+ color: var(--theme-elevation-500);
39
+ cursor: pointer;
40
+ transition: all 150ms ease;
41
+ text-decoration: none;
42
+
43
+ &:hover {
44
+ background: var(--theme-elevation-100);
45
+ color: var(--theme-text);
46
+ }
47
+ }
48
+
49
+ &__tab--active {
50
+ background: var(--theme-elevation-150);
51
+ color: var(--theme-text);
52
+ }
53
+
54
+ &__link {
55
+ position: relative;
56
+
57
+ &--active {
58
+ color: var(--theme-text);
59
+
60
+ &::before {
61
+ content: '';
62
+ position: absolute;
63
+ left: -6px;
64
+ top: 50%;
65
+ transform: translateY(-50%);
66
+ width: 3px;
67
+ height: 20px;
68
+ background: var(--theme-text);
69
+ border-radius: 0 2px 2px 0;
70
+
71
+ [dir='rtl'] & {
72
+ left: auto;
73
+ right: -6px;
74
+ border-radius: 2px 0 0 2px;
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ &__actions {
81
+ display: flex;
82
+ flex-direction: column;
83
+ align-items: center;
84
+ gap: base(0.25);
85
+ padding-bottom: base(0.5);
86
+ }
87
+
88
+ &__action {
89
+ display: flex;
90
+ align-items: center;
91
+ justify-content: center;
92
+ width: 36px;
93
+ height: 36px;
94
+ border: none;
95
+ border-radius: base(0.25);
96
+ background: transparent;
97
+ color: var(--theme-elevation-500);
98
+ cursor: pointer;
99
+ transition: all 150ms ease;
100
+ text-decoration: none;
101
+
102
+ &:hover {
103
+ background: var(--theme-elevation-100);
104
+ color: var(--theme-text);
105
+ }
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,2 @@
1
+ import type { NavPreferences, PayloadRequest } from 'payload';
2
+ export declare const getNavPrefs: (req: PayloadRequest | undefined) => Promise<NavPreferences | null>;
@@ -0,0 +1,31 @@
1
+ import { cache } from 'react';
2
+ export const getNavPrefs = cache(async (req)=>{
3
+ return req?.user?.collection ? await req.payload.find({
4
+ collection: 'payload-preferences',
5
+ depth: 0,
6
+ limit: 1,
7
+ pagination: false,
8
+ req,
9
+ where: {
10
+ and: [
11
+ {
12
+ key: {
13
+ equals: 'nav'
14
+ }
15
+ },
16
+ {
17
+ 'user.relationTo': {
18
+ equals: req.user.collection
19
+ }
20
+ },
21
+ {
22
+ 'user.value': {
23
+ equals: req?.user?.id
24
+ }
25
+ }
26
+ ]
27
+ }
28
+ })?.then((res)=>res?.docs?.[0]?.value) : null;
29
+ });
30
+
31
+ //# sourceMappingURL=getNavPrefs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/EnhancedSidebar/getNavPrefs.ts"],"sourcesContent":["import type { NavPreferences, PayloadRequest } from 'payload'\n\nimport { cache } from 'react'\n\nexport const getNavPrefs = cache(\n async (req: PayloadRequest | undefined): Promise<NavPreferences | null> => {\n return req?.user?.collection\n ? await req.payload\n .find({\n collection: 'payload-preferences',\n depth: 0,\n limit: 1,\n pagination: false,\n req,\n where: {\n and: [\n {\n key: {\n equals: 'nav',\n },\n },\n {\n 'user.relationTo': {\n equals: req.user.collection,\n },\n },\n {\n 'user.value': {\n equals: req?.user?.id,\n },\n },\n ],\n },\n })\n ?.then((res) => res?.docs?.[0]?.value)\n : null\n },\n)\n"],"names":["cache","getNavPrefs","req","user","collection","payload","find","depth","limit","pagination","where","and","key","equals","id","then","res","docs","value"],"mappings":"AAEA,SAASA,KAAK,QAAQ,QAAO;AAE7B,OAAO,MAAMC,cAAcD,MACzB,OAAOE;IACL,OAAOA,KAAKC,MAAMC,aACd,MAAMF,IAAIG,OAAO,CACdC,IAAI,CAAC;QACJF,YAAY;QACZG,OAAO;QACPC,OAAO;QACPC,YAAY;QACZP;QACAQ,OAAO;YACLC,KAAK;gBACH;oBACEC,KAAK;wBACHC,QAAQ;oBACV;gBACF;gBACA;oBACE,mBAAmB;wBACjBA,QAAQX,IAAIC,IAAI,CAACC,UAAU;oBAC7B;gBACF;gBACA;oBACE,cAAc;wBACZS,QAAQX,KAAKC,MAAMW;oBACrB;gBACF;aACD;QACH;IACF,IACEC,KAAK,CAACC,MAAQA,KAAKC,MAAM,CAAC,EAAE,EAAEC,SAClC;AACN,GACD"}
@@ -0,0 +1,7 @@
1
+ import type { NavPreferences } from 'payload';
2
+ import type { ExtendedGroup } from 'src/types';
3
+ import React from 'react';
4
+ export declare const EnhancedSidebarClient: React.FC<{
5
+ groups: ExtendedGroup[];
6
+ navPreferences: NavPreferences | null;
7
+ }>;
@@ -0,0 +1,94 @@
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, NavGroup, useConfig, useTranslation } from '@payloadcms/ui';
5
+ import { usePathname } from 'next/navigation.js';
6
+ import { formatAdminURL } from 'payload/shared';
7
+ import React, { Fragment } from 'react';
8
+ const baseClass = 'enhanced-sidebar';
9
+ export const EnhancedSidebarClient = ({ groups, navPreferences })=>{
10
+ const pathname = usePathname();
11
+ const { config: { routes: { admin: adminRoute } } } = useConfig();
12
+ const { i18n } = useTranslation();
13
+ return /*#__PURE__*/ _jsx(Fragment, {
14
+ children: groups.map(({ entities, label }, key)=>{
15
+ // Handle empty label (ungrouped items)
16
+ const groupLabel = label || '';
17
+ const isUngrouped = !label || typeof label === 'string' && label === '';
18
+ const content = entities.map((entity, i)=>{
19
+ const { slug, label: entityLabel } = entity;
20
+ const entityType = entity.type;
21
+ let href;
22
+ let id;
23
+ // Check for collection (Will break if EntityType enum changes)
24
+ if (entityType === 'collection') {
25
+ href = formatAdminURL({
26
+ adminRoute,
27
+ path: `/collections/${slug}`
28
+ });
29
+ id = `nav-${slug}`;
30
+ } else if (entityType === 'global') {
31
+ href = formatAdminURL({
32
+ adminRoute,
33
+ path: `/globals/${slug}`
34
+ });
35
+ id = `nav-global-${slug}`;
36
+ } else if (entityType === 'custom' && entity.href) {
37
+ // Custom item with href
38
+ const customHref = entity.href;
39
+ href = formatAdminURL({
40
+ adminRoute,
41
+ path: customHref
42
+ });
43
+ id = `nav-custom-${slug}`;
44
+ } else {
45
+ return null;
46
+ }
47
+ const isActive = pathname.startsWith(href) && [
48
+ '/',
49
+ undefined
50
+ ].includes(pathname[href.length]);
51
+ const Label = /*#__PURE__*/ _jsxs(_Fragment, {
52
+ children: [
53
+ isActive && /*#__PURE__*/ _jsx("div", {
54
+ className: `${baseClass}__link-indicator`
55
+ }),
56
+ /*#__PURE__*/ _jsx("span", {
57
+ className: `${baseClass}__link-label`,
58
+ children: getTranslation(entityLabel, i18n)
59
+ })
60
+ ]
61
+ });
62
+ if (pathname === href) {
63
+ return /*#__PURE__*/ _jsx("div", {
64
+ className: `${baseClass}__link`,
65
+ id: id,
66
+ children: Label
67
+ }, i);
68
+ }
69
+ return /*#__PURE__*/ _jsx(Link, {
70
+ className: `${baseClass}__link`,
71
+ href: href,
72
+ id: id,
73
+ prefetch: false,
74
+ children: Label
75
+ }, i);
76
+ });
77
+ // For ungrouped items, render without NavGroup wrapper
78
+ if (isUngrouped) {
79
+ return /*#__PURE__*/ _jsx(Fragment, {
80
+ children: content
81
+ }, key);
82
+ }
83
+ // Get translated label for NavGroup
84
+ const translatedLabel = getTranslation(groupLabel, i18n);
85
+ return /*#__PURE__*/ _jsx(NavGroup, {
86
+ isOpen: navPreferences?.groups?.[translatedLabel]?.open,
87
+ label: translatedLabel,
88
+ children: content
89
+ }, key);
90
+ })
91
+ });
92
+ };
93
+
94
+ //# sourceMappingURL=index.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/EnhancedSidebar/index.client.tsx"],"sourcesContent":["'use client'\nimport type { NavPreferences } from 'payload'\nimport type { ExtendedGroup } from 'src/types'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { Link, NavGroup, useConfig, useTranslation } from '@payloadcms/ui'\nimport { usePathname } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { Fragment } from 'react'\n\nconst baseClass = 'enhanced-sidebar'\n\nexport const EnhancedSidebarClient: React.FC<{\n groups: ExtendedGroup[]\n navPreferences: NavPreferences | null\n}> = ({ groups, navPreferences }) => {\n const pathname = usePathname()\n\n const {\n config: {\n routes: { admin: adminRoute },\n },\n } = useConfig()\n\n const { i18n } = useTranslation()\n\n return (\n <Fragment>\n {groups.map(({ entities, label }, key) => {\n // Handle empty label (ungrouped items)\n const groupLabel = label || ''\n const isUngrouped = !label || (typeof label === 'string' && label === '')\n\n const content = entities.map((entity, i) => {\n const { slug, label: entityLabel } = entity\n const entityType = entity.type\n let href: string\n let id: string\n\n // Check for collection (Will break if EntityType enum changes)\n if (entityType === 'collection') {\n href = formatAdminURL({ adminRoute, path: `/collections/${slug}` })\n id = `nav-${slug}`\n } else if (entityType === 'global') {\n href = formatAdminURL({ adminRoute, path: `/globals/${slug}` })\n id = `nav-global-${slug}`\n } else if (entityType === 'custom' && entity.href) {\n // Custom item with href\n const customHref = entity.href\n href = formatAdminURL({ adminRoute, path: customHref as `/${string}` })\n id = `nav-custom-${slug}`\n } else {\n return null\n }\n\n const isActive =\n pathname.startsWith(href) && ['/', undefined].includes(pathname[href.length])\n\n const Label = (\n <>\n {isActive && <div className={`${baseClass}__link-indicator`} />}\n <span className={`${baseClass}__link-label`}>\n {getTranslation(entityLabel, i18n)}\n </span>\n </>\n )\n\n if (pathname === href) {\n return (\n <div className={`${baseClass}__link`} id={id} key={i}>\n {Label}\n </div>\n )\n }\n\n return (\n <Link className={`${baseClass}__link`} href={href} id={id} key={i} prefetch={false}>\n {Label}\n </Link>\n )\n })\n\n // For ungrouped items, render without NavGroup wrapper\n if (isUngrouped) {\n return <Fragment key={key}>{content}</Fragment>\n }\n\n // Get translated label for NavGroup\n const translatedLabel = getTranslation(groupLabel, i18n)\n\n return (\n <NavGroup\n isOpen={navPreferences?.groups?.[translatedLabel]?.open}\n key={key}\n label={translatedLabel}\n >\n {content}\n </NavGroup>\n )\n })}\n </Fragment>\n )\n}\n"],"names":["getTranslation","Link","NavGroup","useConfig","useTranslation","usePathname","formatAdminURL","React","Fragment","baseClass","EnhancedSidebarClient","groups","navPreferences","pathname","config","routes","admin","adminRoute","i18n","map","entities","label","key","groupLabel","isUngrouped","content","entity","i","slug","entityLabel","entityType","type","href","id","path","customHref","isActive","startsWith","undefined","includes","length","Label","div","className","span","prefetch","translatedLabel","isOpen","open"],"mappings":"AAAA;;AAIA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,IAAI,EAAEC,QAAQ,EAAEC,SAAS,EAAEC,cAAc,QAAQ,iBAAgB;AAC1E,SAASC,WAAW,QAAQ,qBAAoB;AAChD,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,OAAOC,SAASC,QAAQ,QAAQ,QAAO;AAEvC,MAAMC,YAAY;AAElB,OAAO,MAAMC,wBAGR,CAAC,EAAEC,MAAM,EAAEC,cAAc,EAAE;IAC9B,MAAMC,WAAWR;IAEjB,MAAM,EACJS,QAAQ,EACNC,QAAQ,EAAEC,OAAOC,UAAU,EAAE,EAC9B,EACF,GAAGd;IAEJ,MAAM,EAAEe,IAAI,EAAE,GAAGd;IAEjB,qBACE,KAACI;kBACEG,OAAOQ,GAAG,CAAC,CAAC,EAAEC,QAAQ,EAAEC,KAAK,EAAE,EAAEC;YAChC,uCAAuC;YACvC,MAAMC,aAAaF,SAAS;YAC5B,MAAMG,cAAc,CAACH,SAAU,OAAOA,UAAU,YAAYA,UAAU;YAEtE,MAAMI,UAAUL,SAASD,GAAG,CAAC,CAACO,QAAQC;gBACpC,MAAM,EAAEC,IAAI,EAAEP,OAAOQ,WAAW,EAAE,GAAGH;gBACrC,MAAMI,aAAaJ,OAAOK,IAAI;gBAC9B,IAAIC;gBACJ,IAAIC;gBAEJ,+DAA+D;gBAC/D,IAAIH,eAAe,cAAc;oBAC/BE,OAAO1B,eAAe;wBAAEW;wBAAYiB,MAAM,CAAC,aAAa,EAAEN,MAAM;oBAAC;oBACjEK,KAAK,CAAC,IAAI,EAAEL,MAAM;gBACpB,OAAO,IAAIE,eAAe,UAAU;oBAClCE,OAAO1B,eAAe;wBAAEW;wBAAYiB,MAAM,CAAC,SAAS,EAAEN,MAAM;oBAAC;oBAC7DK,KAAK,CAAC,WAAW,EAAEL,MAAM;gBAC3B,OAAO,IAAIE,eAAe,YAAYJ,OAAOM,IAAI,EAAE;oBACjD,wBAAwB;oBACxB,MAAMG,aAAaT,OAAOM,IAAI;oBAC9BA,OAAO1B,eAAe;wBAAEW;wBAAYiB,MAAMC;oBAA2B;oBACrEF,KAAK,CAAC,WAAW,EAAEL,MAAM;gBAC3B,OAAO;oBACL,OAAO;gBACT;gBAEA,MAAMQ,WACJvB,SAASwB,UAAU,CAACL,SAAS;oBAAC;oBAAKM;iBAAU,CAACC,QAAQ,CAAC1B,QAAQ,CAACmB,KAAKQ,MAAM,CAAC;gBAE9E,MAAMC,sBACJ;;wBACGL,0BAAY,KAACM;4BAAIC,WAAW,GAAGlC,UAAU,gBAAgB,CAAC;;sCAC3D,KAACmC;4BAAKD,WAAW,GAAGlC,UAAU,YAAY,CAAC;sCACxCT,eAAe6B,aAAaX;;;;gBAKnC,IAAIL,aAAamB,MAAM;oBACrB,qBACE,KAACU;wBAAIC,WAAW,GAAGlC,UAAU,MAAM,CAAC;wBAAEwB,IAAIA;kCACvCQ;uBADgDd;gBAIvD;gBAEA,qBACE,KAAC1B;oBAAK0C,WAAW,GAAGlC,UAAU,MAAM,CAAC;oBAAEuB,MAAMA;oBAAMC,IAAIA;oBAAYY,UAAU;8BAC1EJ;mBAD6Dd;YAIpE;YAEA,uDAAuD;YACvD,IAAIH,aAAa;gBACf,qBAAO,KAAChB;8BAAoBiB;mBAANH;YACxB;YAEA,oCAAoC;YACpC,MAAMwB,kBAAkB9C,eAAeuB,YAAYL;YAEnD,qBACE,KAAChB;gBACC6C,QAAQnC,gBAAgBD,QAAQ,CAACmC,gBAAgB,EAAEE;gBAEnD3B,OAAOyB;0BAENrB;eAHIH;QAMX;;AAGN,EAAC"}
@@ -0,0 +1,10 @@
1
+ import type { PayloadRequest, ServerProps } from 'payload';
2
+ import React from 'react';
3
+ import type { EnhancedSidebarConfig } from '../../types';
4
+ import './index.scss';
5
+ export type EnhancedSidebarProps = {
6
+ req?: PayloadRequest;
7
+ sidebarConfig?: EnhancedSidebarConfig;
8
+ } & ServerProps;
9
+ export declare const EnhancedSidebar: React.FC<EnhancedSidebarProps>;
10
+ export default EnhancedSidebar;
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent';
3
+ import { EntityType, groupNavItems } from '@payloadcms/ui/shared';
4
+ import React from 'react';
5
+ import { getNavPrefs } from './getNavPrefs';
6
+ import { SidebarContent } from './SidebarContent';
7
+ import './index.scss';
8
+ export const EnhancedSidebar = async (props)=>{
9
+ const { i18n, locale, params, payload, permissions, req, searchParams, sidebarConfig, user, visibleEntities } = props;
10
+ if (!payload?.config) {
11
+ return null;
12
+ }
13
+ const { admin: { components: { afterNavLinks, beforeNavLinks } }, collections, globals } = payload.config;
14
+ const groups = groupNavItems([
15
+ ...collections.filter(({ slug })=>visibleEntities?.collections.includes(slug)).map((collection)=>({
16
+ type: EntityType.collection,
17
+ entity: collection
18
+ })),
19
+ ...globals.filter(({ slug })=>visibleEntities?.globals.includes(slug)).map((global)=>({
20
+ type: EntityType.global,
21
+ entity: global
22
+ }))
23
+ ], permissions || {}, i18n);
24
+ const navPreferences = await getNavPrefs(req);
25
+ const serverProps = {
26
+ i18n,
27
+ locale,
28
+ params,
29
+ payload,
30
+ permissions,
31
+ searchParams,
32
+ user
33
+ };
34
+ const beforeNavLinksRendered = RenderServerComponent({
35
+ Component: beforeNavLinks,
36
+ importMap: payload.importMap,
37
+ serverProps
38
+ });
39
+ const afterNavLinksRendered = RenderServerComponent({
40
+ Component: afterNavLinks,
41
+ importMap: payload.importMap,
42
+ serverProps
43
+ });
44
+ // Default config if not provided
45
+ const config = sidebarConfig ?? {
46
+ tabs: [
47
+ {
48
+ id: 'default',
49
+ type: 'tab',
50
+ icon: 'LayoutGrid',
51
+ label: 'Collections'
52
+ }
53
+ ]
54
+ };
55
+ return /*#__PURE__*/ _jsx(SidebarContent, {
56
+ afterNavLinks: afterNavLinksRendered,
57
+ beforeNavLinks: beforeNavLinksRendered,
58
+ groups: groups,
59
+ navPreferences: navPreferences,
60
+ sidebarConfig: config
61
+ });
62
+ };
63
+ export default EnhancedSidebar;
64
+
65
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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 React from 'react'\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 },\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 // 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 return (\n <SidebarContent\n afterNavLinks={afterNavLinksRendered}\n beforeNavLinks={beforeNavLinksRendered}\n groups={groups}\n navPreferences={navPreferences}\n sidebarConfig={config}\n />\n )\n}\n\nexport default EnhancedSidebar\n"],"names":["RenderServerComponent","EntityType","groupNavItems","React","getNavPrefs","SidebarContent","EnhancedSidebar","props","i18n","locale","params","payload","permissions","req","searchParams","sidebarConfig","user","visibleEntities","config","admin","components","afterNavLinks","beforeNavLinks","collections","globals","groups","filter","slug","includes","map","collection","type","entity","global","navPreferences","serverProps","beforeNavLinksRendered","Component","importMap","afterNavLinksRendered","tabs","id","icon","label"],"mappings":";AAGA,SAASA,qBAAqB,QAAQ,gDAA+C;AACrF,SAASC,UAAU,EAAEC,aAAa,QAAQ,wBAAuB;AACjE,OAAOC,WAAW,QAAO;AAIzB,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,EAAE,EAC9C,EACDC,WAAW,EACXC,OAAO,EACR,GAAGb,QAAQO,MAAM;IAElB,MAAMO,SAASvB,cACb;WACKqB,YACAG,MAAM,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAKV,iBAAiBM,YAAYK,SAASD,OAC3DE,GAAG,CACF,CAACC,aACE,CAAA;gBACCC,MAAM9B,WAAW6B,UAAU;gBAC3BE,QAAQF;YACV,CAAA;WAEHN,QACAE,MAAM,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAKV,iBAAiBO,QAAQI,SAASD,OACvDE,GAAG,CACF,CAACI,SACE,CAAA;gBACCF,MAAM9B,WAAWgC,MAAM;gBACvBD,QAAQC;YACV,CAAA;KAEP,EACDrB,eAAe,CAAC,GAChBJ;IAGF,MAAM0B,iBAAiB,MAAM9B,YAAYS;IAEzC,MAAMsB,cAAc;QAClB3B;QACAC;QACAC;QACAC;QACAC;QACAE;QACAE;IACF;IAEA,MAAMoB,yBAAyBpC,sBAAsB;QACnDqC,WAAWf;QACXgB,WAAW3B,QAAQ2B,SAAS;QAC5BH;IACF;IAEA,MAAMI,wBAAwBvC,sBAAsB;QAClDqC,WAAWhB;QACXiB,WAAW3B,QAAQ2B,SAAS;QAC5BH;IACF;IAEA,iCAAiC;IACjC,MAAMjB,SAAgCH,iBAAiB;QACrDyB,MAAM;YACJ;gBACEC,IAAI;gBACJV,MAAM;gBACNW,MAAM;gBACNC,OAAO;YACT;SACD;IACH;IAEA,qBACE,KAACtC;QACCgB,eAAekB;QACfjB,gBAAgBc;QAChBX,QAAQA;QACRS,gBAAgBA;QAChBnB,eAAeG;;AAGrB,EAAC;AAED,eAAeZ,gBAAe"}
@@ -0,0 +1,101 @@
1
+ @import '~@payloadcms/ui/scss';
2
+
3
+ @layer payload-default {
4
+ .enhanced-sidebar {
5
+ &__content {
6
+ flex: 1;
7
+ display: flex;
8
+ flex-direction: column;
9
+ overflow: hidden;
10
+ }
11
+
12
+ &__content-scroll {
13
+ flex: 1;
14
+ display: flex;
15
+ flex-direction: column;
16
+ padding: var(--app-header-height) base(1) base(2) base(1);
17
+ overflow-y: auto;
18
+
19
+ &::-webkit-scrollbar {
20
+ display: none;
21
+ }
22
+ }
23
+
24
+ &__link {
25
+ display: flex;
26
+ align-items: center;
27
+ position: relative;
28
+ padding-block: base(0.125);
29
+ padding-inline-start: 0;
30
+ padding-inline-end: base(1.5);
31
+ text-decoration: none;
32
+
33
+ &:focus:not(:focus-visible) {
34
+ box-shadow: none;
35
+ font-weight: 600;
36
+ }
37
+
38
+ &.active {
39
+ font-weight: 600;
40
+ }
41
+ }
42
+
43
+ a.enhanced-sidebar__link {
44
+ &:hover,
45
+ &:focus-visible {
46
+ text-decoration: underline;
47
+ }
48
+ }
49
+
50
+ &__link:has(.enhanced-sidebar__link-indicator) {
51
+ font-weight: 600;
52
+ }
53
+
54
+ &__link-indicator {
55
+ position: absolute;
56
+ display: block;
57
+ inset-inline-start: base(-1);
58
+ width: 2px;
59
+ height: 16px;
60
+ border-start-end-radius: 2px;
61
+ border-end-end-radius: 2px;
62
+ background: var(--theme-text);
63
+ }
64
+
65
+ // &__link-label {
66
+ // // inherit styles
67
+ // }
68
+
69
+ &__link-icon {
70
+ margin-right: base(0.5);
71
+ flex-shrink: 0;
72
+ }
73
+
74
+ &__link--active {
75
+ font-weight: 600;
76
+ }
77
+
78
+ &__custom-items {
79
+ display: flex;
80
+ flex-direction: column;
81
+ gap: base(0.25);
82
+ }
83
+
84
+ @include mid-break {
85
+ &__content-scroll {
86
+ padding-inline: base(0.5);
87
+ }
88
+ }
89
+
90
+ @include small-break {
91
+ &__content-scroll {
92
+ padding-inline: var(--gutter-h);
93
+ }
94
+
95
+ &__link {
96
+ font-size: base(0.875);
97
+ line-height: base(1.5);
98
+ }
99
+ }
100
+ }
101
+ }
File without changes
@@ -0,0 +1,3 @@
1
+ // Client components will be exported here
2
+
3
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["// Client components will be exported here\n"],"names":[],"mappings":"AAAA,0CAA0C"}
@@ -0,0 +1 @@
1
+ export { default as EnhancedSidebar } from '../components/EnhancedSidebar';
@@ -0,0 +1,3 @@
1
+ export { default as EnhancedSidebar } from '../components/EnhancedSidebar';
2
+
3
+ //# sourceMappingURL=rsc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["export { default as EnhancedSidebar } from '../components/EnhancedSidebar'\n"],"names":["default","EnhancedSidebar"],"mappings":"AAAA,SAASA,WAAWC,eAAe,QAAQ,gCAA+B"}
@@ -0,0 +1 @@
1
+ export declare const useMutationObserver: (ref: React.RefObject<HTMLElement | null>, callback: MutationCallback, options?: MutationObserverInit) => void;
@@ -0,0 +1,21 @@
1
+ import { useEffect } from 'react';
2
+ export const useMutationObserver = (ref, callback, options = {
3
+ attributes: true,
4
+ characterData: true,
5
+ childList: true,
6
+ subtree: true
7
+ })=>{
8
+ useEffect(()=>{
9
+ if (ref.current) {
10
+ const observer = new MutationObserver(callback);
11
+ observer.observe(ref.current, options);
12
+ return ()=>observer.disconnect();
13
+ }
14
+ }, [
15
+ ref,
16
+ callback,
17
+ options
18
+ ]);
19
+ };
20
+
21
+ //# sourceMappingURL=useMutationObserver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useMutationObserver.ts"],"sourcesContent":["import { useEffect } from 'react'\n\nexport const useMutationObserver = (\n ref: React.RefObject<HTMLElement | null>,\n callback: MutationCallback,\n options: MutationObserverInit = {\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n },\n) => {\n useEffect(() => {\n if (ref.current) {\n const observer = new MutationObserver(callback)\n observer.observe(ref.current, options)\n return () => observer.disconnect()\n }\n }, [ref, callback, options])\n}\n"],"names":["useEffect","useMutationObserver","ref","callback","options","attributes","characterData","childList","subtree","current","observer","MutationObserver","observe","disconnect"],"mappings":"AAAA,SAASA,SAAS,QAAQ,QAAO;AAEjC,OAAO,MAAMC,sBAAsB,CACjCC,KACAC,UACAC,UAAgC;IAC9BC,YAAY;IACZC,eAAe;IACfC,WAAW;IACXC,SAAS;AACX,CAAC;IAEDR,UAAU;QACR,IAAIE,IAAIO,OAAO,EAAE;YACf,MAAMC,WAAW,IAAIC,iBAAiBR;YACtCO,SAASE,OAAO,CAACV,IAAIO,OAAO,EAAEL;YAC9B,OAAO,IAAMM,SAASG,UAAU;QAClC;IACF,GAAG;QAACX;QAAKC;QAAUC;KAAQ;AAC7B,EAAC"}
@@ -0,0 +1,4 @@
1
+ import { type Config } from 'payload';
2
+ import type { EnhancedSidebarConfig } from './types';
3
+ export declare const payloadEnhancedSidebar: (pluginOptions?: EnhancedSidebarConfig) => (config: Config) => Config;
4
+ export type { EnhancedSidebarConfig } from './types';