@wikex/admin-kit 0.2.0 → 0.2.2
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/CHANGELOG.md +4 -0
- package/dist/admin/before-login.d.ts +5 -0
- package/dist/admin/before-login.js +27 -0
- package/dist/admin/brand.d.ts +19 -0
- package/dist/admin/brand.js +16 -0
- package/dist/admin/header.d.ts +5 -0
- package/dist/admin/header.js +96 -0
- package/dist/admin/logout-button.d.ts +8 -0
- package/dist/admin/logout-button.js +8 -0
- package/dist/admin/nav-client.d.ts +16 -0
- package/dist/admin/nav-client.js +258 -0
- package/dist/admin/nav.d.ts +16 -0
- package/dist/admin/nav.js +31 -0
- package/dist/admin/theme-toggle.d.ts +5 -0
- package/dist/admin/theme-toggle.js +8 -0
- package/dist/admin/view-site.d.ts +5 -0
- package/dist/admin/view-site.js +11 -0
- package/dist/chunk-7FEACJUN.js +151 -0
- package/dist/chunk-BUD6BMFV.js +117 -0
- package/dist/chunk-GMPR6LHH.js +2063 -0
- package/dist/chunk-GZ2B5BTH.js +39 -0
- package/dist/chunk-JJLHSZ3T.js +40 -0
- package/dist/chunk-LC2CP5SR.js +13 -0
- package/dist/chunk-SAI5SWZA.js +29 -0
- package/dist/chunk-SM6CCKQQ.js +62 -0
- package/dist/chunk-VK4EFLWH.js +119 -0
- package/dist/chunk-X7VETFVD.js +52 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +104 -0
- package/dist/live-preview.d.ts +118 -0
- package/dist/live-preview.js +20 -0
- package/dist/project-ClCmpyeX.d.ts +54 -0
- package/dist/project.d.ts +1 -0
- package/dist/project.js +8 -0
- package/dist/rich-text-client.d.ts +5 -0
- package/dist/rich-text-client.js +166 -0
- package/dist/rich-text.d.ts +5 -0
- package/dist/rich-text.js +6 -0
- package/dist/runtimeConfig-BwjQepcW.d.ts +30 -0
- package/dist/starter-client.d.ts +56 -0
- package/dist/starter-client.js +26 -0
- package/dist/starter.d.ts +39 -0
- package/dist/starter.js +62 -0
- package/dist/text-style-runtime.d.ts +5 -0
- package/dist/text-style-runtime.js +74 -0
- package/dist/text-styles.d.ts +86 -0
- package/dist/text-styles.js +22 -0
- package/package.json +24 -19
- package/src/TextStyleRuntime.tsx +0 -90
- package/src/admin/BeforeLogin.tsx +0 -19
- package/src/admin/Brand.tsx +0 -74
- package/src/admin/Header.tsx +0 -87
- package/src/admin/LogoutButton.tsx +0 -41
- package/src/admin/Nav.tsx +0 -35
- package/src/admin/NavClient.tsx +0 -288
- package/src/admin/ThemeToggle.tsx +0 -31
- package/src/admin/ViewSite.tsx +0 -11
- package/src/admin/useAdminBrand.ts +0 -81
- package/src/adminExperience.ts +0 -117
- package/src/index.ts +0 -11
- package/src/live-preview/GlobalInlineInspector.tsx +0 -334
- package/src/live-preview/LivePreviewEditor.tsx +0 -2088
- package/src/live-preview/TextStyleInspector.tsx +0 -289
- package/src/live-preview/index.ts +0 -23
- package/src/live-preview/runtimeConfig.ts +0 -52
- package/src/plugin.ts +0 -70
- package/src/project.ts +0 -82
- package/src/rich-text/client.tsx +0 -202
- package/src/rich-text/index.ts +0 -10
- package/src/starter/client.tsx +0 -22
- package/src/starter.ts +0 -95
- package/src/textStyles.ts +0 -161
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wikex/admin-kit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Reusable Payload CMS admin shell, visual editor and typography tools for Wikex projects",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"**/*.scss"
|
|
10
10
|
],
|
|
11
11
|
"files": [
|
|
12
|
-
"
|
|
12
|
+
"dist",
|
|
13
|
+
"src/styles",
|
|
13
14
|
"CHANGELOG.md",
|
|
14
15
|
"README.md",
|
|
15
16
|
"RELEASING.md"
|
|
@@ -19,26 +20,27 @@
|
|
|
19
20
|
"registry": "https://registry.npmjs.org/"
|
|
20
21
|
},
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@wikex/content-kit": "^0.1.
|
|
23
|
+
"@wikex/content-kit": "^0.1.1"
|
|
23
24
|
},
|
|
24
25
|
"exports": {
|
|
25
|
-
".": "./
|
|
26
|
-
"./admin/before-login": "./
|
|
27
|
-
"./admin/brand": "./
|
|
28
|
-
"./admin/header": "./
|
|
29
|
-
"./admin/logout-button": "./
|
|
30
|
-
"./admin/nav": "./
|
|
31
|
-
"./admin/
|
|
32
|
-
"./admin/
|
|
33
|
-
"./
|
|
34
|
-
"./
|
|
35
|
-
"./
|
|
36
|
-
"./rich-text
|
|
37
|
-
"./
|
|
38
|
-
"./starter
|
|
26
|
+
".": "./dist/index.js",
|
|
27
|
+
"./admin/before-login": "./dist/admin/before-login.js",
|
|
28
|
+
"./admin/brand": "./dist/admin/brand.js",
|
|
29
|
+
"./admin/header": "./dist/admin/header.js",
|
|
30
|
+
"./admin/logout-button": "./dist/admin/logout-button.js",
|
|
31
|
+
"./admin/nav": "./dist/admin/nav.js",
|
|
32
|
+
"./admin/nav-client": "./dist/admin/nav-client.js",
|
|
33
|
+
"./admin/theme-toggle": "./dist/admin/theme-toggle.js",
|
|
34
|
+
"./admin/view-site": "./dist/admin/view-site.js",
|
|
35
|
+
"./live-preview": "./dist/live-preview.js",
|
|
36
|
+
"./project": "./dist/project.js",
|
|
37
|
+
"./rich-text": "./dist/rich-text.js",
|
|
38
|
+
"./rich-text/client": "./dist/rich-text-client.js",
|
|
39
|
+
"./starter": "./dist/starter.js",
|
|
40
|
+
"./starter/client": "./dist/starter-client.js",
|
|
39
41
|
"./styles": "./src/styles/admin.scss",
|
|
40
|
-
"./text-style-runtime": "./
|
|
41
|
-
"./text-styles": "./
|
|
42
|
+
"./text-style-runtime": "./dist/text-style-runtime.js",
|
|
43
|
+
"./text-styles": "./dist/text-styles.js"
|
|
42
44
|
},
|
|
43
45
|
"peerDependencies": {
|
|
44
46
|
"@lexical/react": ">=0.41.0",
|
|
@@ -51,5 +53,8 @@
|
|
|
51
53
|
"payload": ">=3.88.0",
|
|
52
54
|
"react": ">=19.0.0",
|
|
53
55
|
"react-dom": ">=19.0.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsup"
|
|
54
59
|
}
|
|
55
60
|
}
|
package/src/TextStyleRuntime.tsx
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useEffect } from 'react'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
EDITABLE_PREVIEW_SELECTOR,
|
|
7
|
-
getEditableElementStyleKey,
|
|
8
|
-
getTextStyleCSS,
|
|
9
|
-
normalizeTextStyleMap,
|
|
10
|
-
} from './textStyles'
|
|
11
|
-
|
|
12
|
-
type OriginalStyle = {
|
|
13
|
-
boxSizing: string
|
|
14
|
-
fontFamily: string
|
|
15
|
-
lineHeight: string
|
|
16
|
-
marginLeft: string
|
|
17
|
-
marginRight: string
|
|
18
|
-
maxWidth: string
|
|
19
|
-
width: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const TextStyleRuntime = ({ styles }: { styles?: unknown }) => {
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
const normalizedStyles = normalizeTextStyleMap(styles)
|
|
25
|
-
const originals = new Map<HTMLElement, OriginalStyle>()
|
|
26
|
-
let applyFrame = 0
|
|
27
|
-
|
|
28
|
-
const applyStyles = () => {
|
|
29
|
-
const fields = new Set(
|
|
30
|
-
document.querySelectorAll<HTMLElement>(`[data-wikex-field],${EDITABLE_PREVIEW_SELECTOR}`),
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
for (const element of fields) {
|
|
34
|
-
const fieldPath = element.dataset.wikexField || getEditableElementStyleKey(element)
|
|
35
|
-
if (!fieldPath || !normalizedStyles[fieldPath]) continue
|
|
36
|
-
|
|
37
|
-
if (!originals.has(element)) {
|
|
38
|
-
originals.set(element, {
|
|
39
|
-
boxSizing: element.style.boxSizing,
|
|
40
|
-
fontFamily: element.style.fontFamily,
|
|
41
|
-
lineHeight: element.style.lineHeight,
|
|
42
|
-
marginLeft: element.style.marginLeft,
|
|
43
|
-
marginRight: element.style.marginRight,
|
|
44
|
-
maxWidth: element.style.maxWidth,
|
|
45
|
-
width: element.style.width,
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const style = getTextStyleCSS(normalizedStyles[fieldPath])
|
|
50
|
-
element.style.boxSizing = style.boxSizing || ''
|
|
51
|
-
element.style.fontFamily = style.fontFamily || ''
|
|
52
|
-
element.style.lineHeight = style.lineHeight || ''
|
|
53
|
-
element.style.marginLeft = style.marginLeft || ''
|
|
54
|
-
element.style.marginRight = style.marginRight || ''
|
|
55
|
-
element.style.maxWidth = style.maxWidth || ''
|
|
56
|
-
element.style.width = style.width || ''
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const scheduleApplyStyles = () => {
|
|
61
|
-
if (applyFrame) return
|
|
62
|
-
|
|
63
|
-
applyFrame = window.requestAnimationFrame(() => {
|
|
64
|
-
applyFrame = 0
|
|
65
|
-
applyStyles()
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
applyStyles()
|
|
70
|
-
const observer = new MutationObserver(scheduleApplyStyles)
|
|
71
|
-
observer.observe(document.body, { childList: true, subtree: true })
|
|
72
|
-
|
|
73
|
-
return () => {
|
|
74
|
-
observer.disconnect()
|
|
75
|
-
window.cancelAnimationFrame(applyFrame)
|
|
76
|
-
for (const [element, original] of originals) {
|
|
77
|
-
if (!element.isConnected) continue
|
|
78
|
-
element.style.boxSizing = original.boxSizing
|
|
79
|
-
element.style.fontFamily = original.fontFamily
|
|
80
|
-
element.style.lineHeight = original.lineHeight
|
|
81
|
-
element.style.marginLeft = original.marginLeft
|
|
82
|
-
element.style.marginRight = original.marginRight
|
|
83
|
-
element.style.maxWidth = original.maxWidth
|
|
84
|
-
element.style.width = original.width
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}, [styles])
|
|
88
|
-
|
|
89
|
-
return null
|
|
90
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
|
|
5
|
-
import { useAdminBrand } from './useAdminBrand'
|
|
6
|
-
|
|
7
|
-
const BeforeLogin: React.FC = () => {
|
|
8
|
-
const { siteName } = useAdminBrand()
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
<div className="admin-login-intro">
|
|
12
|
-
<span className="admin-login-intro__eyebrow">{siteName} · Trung tâm nội dung</span>
|
|
13
|
-
<h1>Chào mừng trở lại.</h1>
|
|
14
|
-
<p>Đăng nhập để quản lý nội dung, hình ảnh và xuất bản của {siteName}.</p>
|
|
15
|
-
</div>
|
|
16
|
-
)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default BeforeLogin
|
package/src/admin/Brand.tsx
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import Image from 'next/image'
|
|
4
|
-
import React from 'react'
|
|
5
|
-
|
|
6
|
-
import { useAdminBrand } from './useAdminBrand'
|
|
7
|
-
|
|
8
|
-
export type AdminBrandAsset = {
|
|
9
|
-
alt: string
|
|
10
|
-
height: number
|
|
11
|
-
url: string
|
|
12
|
-
width: number
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const BrandLogo = ({
|
|
16
|
-
asset,
|
|
17
|
-
className,
|
|
18
|
-
height,
|
|
19
|
-
maxWidth,
|
|
20
|
-
}: {
|
|
21
|
-
asset: AdminBrandAsset
|
|
22
|
-
className?: string
|
|
23
|
-
height: number
|
|
24
|
-
maxWidth: number
|
|
25
|
-
siteName: string
|
|
26
|
-
}) => (
|
|
27
|
-
<span
|
|
28
|
-
className={['brand-logo', className].filter(Boolean).join(' ')}
|
|
29
|
-
style={{ alignItems: 'center', display: 'inline-flex', height, maxWidth }}
|
|
30
|
-
>
|
|
31
|
-
<Image
|
|
32
|
-
alt=""
|
|
33
|
-
height={asset.height}
|
|
34
|
-
src={asset.url}
|
|
35
|
-
style={{ height: '100%', maxWidth: '100%', objectFit: 'contain', width: 'auto' }}
|
|
36
|
-
unoptimized
|
|
37
|
-
width={asset.width}
|
|
38
|
-
/>
|
|
39
|
-
</span>
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
export const AdminIcon: React.FC = () => {
|
|
43
|
-
const brand = useAdminBrand()
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<span className="aurea-brand aurea-brand--icon">
|
|
47
|
-
<BrandLogo
|
|
48
|
-
asset={brand.logo}
|
|
49
|
-
className="aurea-brand__image"
|
|
50
|
-
height={32}
|
|
51
|
-
maxWidth={32}
|
|
52
|
-
siteName={brand.siteName}
|
|
53
|
-
/>
|
|
54
|
-
</span>
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export const AdminLogo: React.FC = () => {
|
|
59
|
-
const brand = useAdminBrand()
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<span aria-label={brand.siteName} className="aurea-brand aurea-brand--logo" role="img">
|
|
63
|
-
<BrandLogo
|
|
64
|
-
asset={brand.logo}
|
|
65
|
-
className="aurea-brand__image"
|
|
66
|
-
height={42}
|
|
67
|
-
maxWidth={190}
|
|
68
|
-
siteName={brand.siteName}
|
|
69
|
-
/>
|
|
70
|
-
</span>
|
|
71
|
-
)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export { configureAdminBrand, useAdminBrand, type AdminBrandSettings } from './useAdminBrand'
|
package/src/admin/Header.tsx
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { Link, useAuth, useConfig, useNav } from '@payloadcms/ui'
|
|
4
|
-
import { Menu, Settings2 } from 'lucide-react'
|
|
5
|
-
import { formatAdminURL } from 'payload/shared'
|
|
6
|
-
import React from 'react'
|
|
7
|
-
|
|
8
|
-
import { AdminIcon } from './Brand'
|
|
9
|
-
import AdminThemeToggle from './ThemeToggle'
|
|
10
|
-
import AdminViewSite from './ViewSite'
|
|
11
|
-
|
|
12
|
-
type AdminUser = {
|
|
13
|
-
email?: string
|
|
14
|
-
name?: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const getInitials = (name?: string, email?: string) => {
|
|
18
|
-
const source = name?.trim() || email?.split('@')[0] || 'AD'
|
|
19
|
-
|
|
20
|
-
return source
|
|
21
|
-
.split(/\s+/)
|
|
22
|
-
.slice(0, 2)
|
|
23
|
-
.map((part) => part.charAt(0).toUpperCase())
|
|
24
|
-
.join('')
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const AdminHeader = () => {
|
|
28
|
-
const { user } = useAuth<AdminUser>()
|
|
29
|
-
const { setNavOpen } = useNav()
|
|
30
|
-
const {
|
|
31
|
-
config: {
|
|
32
|
-
admin: { routes: adminRoutes },
|
|
33
|
-
routes: { admin: adminRoute },
|
|
34
|
-
},
|
|
35
|
-
} = useConfig()
|
|
36
|
-
|
|
37
|
-
const userLabel = user?.name?.trim() || user?.email?.split('@')[0] || 'Quản trị viên'
|
|
38
|
-
const initials = getInitials(user?.name, user?.email)
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<header className="minimal-admin-header">
|
|
42
|
-
<div className="minimal-admin-header__left">
|
|
43
|
-
<button
|
|
44
|
-
aria-label="Mở menu quản trị"
|
|
45
|
-
className="minimal-admin-header__menu"
|
|
46
|
-
onClick={() => setNavOpen(true)}
|
|
47
|
-
type="button"
|
|
48
|
-
>
|
|
49
|
-
<Menu aria-hidden="true" />
|
|
50
|
-
</button>
|
|
51
|
-
<Link
|
|
52
|
-
aria-label="Về dashboard"
|
|
53
|
-
className="minimal-admin-header__mobile-brand"
|
|
54
|
-
href={adminRoute}
|
|
55
|
-
prefetch={false}
|
|
56
|
-
>
|
|
57
|
-
<AdminIcon />
|
|
58
|
-
</Link>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<div className="minimal-admin-header__actions">
|
|
62
|
-
<AdminViewSite />
|
|
63
|
-
<AdminThemeToggle />
|
|
64
|
-
<Link
|
|
65
|
-
aria-label={`Mở tài khoản ${userLabel}`}
|
|
66
|
-
className="minimal-admin-header__settings"
|
|
67
|
-
href={formatAdminURL({ adminRoute, path: adminRoutes.account })}
|
|
68
|
-
prefetch={false}
|
|
69
|
-
title="Cài đặt tài khoản"
|
|
70
|
-
>
|
|
71
|
-
<Settings2 aria-hidden="true" />
|
|
72
|
-
</Link>
|
|
73
|
-
<Link
|
|
74
|
-
aria-label={`Mở tài khoản ${userLabel}`}
|
|
75
|
-
className="minimal-admin-header__account"
|
|
76
|
-
href={formatAdminURL({ adminRoute, path: adminRoutes.account })}
|
|
77
|
-
prefetch={false}
|
|
78
|
-
title={userLabel}
|
|
79
|
-
>
|
|
80
|
-
<span>{initials}</span>
|
|
81
|
-
</Link>
|
|
82
|
-
</div>
|
|
83
|
-
</header>
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export default AdminHeader
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { Link, useConfig, useTranslation } from '@payloadcms/ui'
|
|
4
|
-
import { LogOut } from 'lucide-react'
|
|
5
|
-
import { formatAdminURL } from 'payload/shared'
|
|
6
|
-
import React from 'react'
|
|
7
|
-
|
|
8
|
-
type AdminLogoutButtonProps = {
|
|
9
|
-
tabIndex?: number
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const AdminLogoutButton: React.FC<AdminLogoutButtonProps> = ({ tabIndex = 0 }) => {
|
|
13
|
-
const {
|
|
14
|
-
config: {
|
|
15
|
-
admin: {
|
|
16
|
-
routes: { logout: logoutRoute },
|
|
17
|
-
},
|
|
18
|
-
routes: { admin: adminRoute },
|
|
19
|
-
},
|
|
20
|
-
} = useConfig()
|
|
21
|
-
const { t } = useTranslation()
|
|
22
|
-
const label = t('authentication:logOut')
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<Link
|
|
26
|
-
aria-label={label}
|
|
27
|
-
className="admin-sign-out"
|
|
28
|
-
href={formatAdminURL({ adminRoute, path: logoutRoute })}
|
|
29
|
-
prefetch={false}
|
|
30
|
-
tabIndex={tabIndex}
|
|
31
|
-
title={label}
|
|
32
|
-
>
|
|
33
|
-
<span aria-hidden="true" className="admin-sign-out__icon">
|
|
34
|
-
<LogOut strokeWidth={2} />
|
|
35
|
-
</span>
|
|
36
|
-
<span className="admin-sign-out__label">{label}</span>
|
|
37
|
-
</Link>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export default AdminLogoutButton
|
package/src/admin/Nav.tsx
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { getNavGroups } from '@payloadcms/ui/shared'
|
|
2
|
-
import type { ServerProps, StaticLabel } from 'payload'
|
|
3
|
-
import React from 'react'
|
|
4
|
-
|
|
5
|
-
import { AdminNavClient, type AdminNavGroup } from './NavClient'
|
|
6
|
-
|
|
7
|
-
const localizeLabel = (label: StaticLabel, language: string): string => {
|
|
8
|
-
if (typeof label === 'string') return label
|
|
9
|
-
|
|
10
|
-
return label[language] || Object.values(label)[0] || ''
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const AdminNav = ({ i18n, payload, permissions, visibleEntities }: ServerProps) => {
|
|
14
|
-
if (!permissions || !visibleEntities) return null
|
|
15
|
-
|
|
16
|
-
const groups: AdminNavGroup[] = getNavGroups(
|
|
17
|
-
permissions,
|
|
18
|
-
visibleEntities,
|
|
19
|
-
payload.config,
|
|
20
|
-
i18n,
|
|
21
|
-
).map((group) => ({
|
|
22
|
-
items: group.entities.map((entity) => ({
|
|
23
|
-
label: localizeLabel(entity.label, i18n.language),
|
|
24
|
-
slug: entity.slug,
|
|
25
|
-
type: entity.type,
|
|
26
|
-
})),
|
|
27
|
-
label: group.label,
|
|
28
|
-
}))
|
|
29
|
-
|
|
30
|
-
return <AdminNavClient groups={groups} />
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default AdminNav
|
|
34
|
-
|
|
35
|
-
export { AdminNavClient, type AdminNavGroup } from './NavClient'
|