@djangocfg/nextjs 2.1.251 → 2.1.254
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/dist/config/index.mjs +1 -1
- package/dist/config/index.mjs.map +1 -1
- package/dist/i18n/routing.d.mts +2 -2
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/dist/navigation/index.d.mts +2 -0
- package/dist/navigation/index.mjs +2 -1
- package/dist/navigation/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/navigation/types.ts +2 -0
- package/src/navigation/utils.ts +1 -0
|
@@ -47,7 +47,8 @@ function routesToMenuItems(routes, groupName) {
|
|
|
47
47
|
).sort((a, b) => (a.metadata.order || 0) - (b.metadata.order || 0)).map((r) => ({
|
|
48
48
|
path: r.path,
|
|
49
49
|
label: r.metadata.label,
|
|
50
|
-
icon: r.metadata.icon
|
|
50
|
+
icon: r.metadata.icon,
|
|
51
|
+
...r.metadata.badge !== void 0 && { badge: r.metadata.badge }
|
|
51
52
|
}));
|
|
52
53
|
}
|
|
53
54
|
function groupRoutesByNavGroups(routes, groups) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/navigation/utils.ts"],"sourcesContent":["/**\n * Navigation Utilities\n *\n * Common utilities for route definitions and navigation\n */\n\nimport type { RouteDefinition, RouteMetadata, MenuItem, NavGroup, NavGroupWithRoutes } from './types';\n\n// ─────────────────────────────────────────────────────────────────────────\n// Route Definition Helper\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Define a route with metadata\n *\n * IMPORTANT: Next.js automatically handles basePath for <Link> components when\n * basePath is set in next.config.ts. We should NOT add basePath manually here,\n * as it would cause double-prefixing in static builds.\n *\n * @param path - Route path (e.g., '/dashboard', '/admin/users')\n * @param metadata - Route metadata (label, icon, etc.)\n */\nexport function defineRoute(\n path: string,\n metadata: RouteMetadata,\n): RouteDefinition {\n // Always return path as-is. Next.js will handle basePath automatically\n // for <Link> components when basePath is set in next.config.ts\n return {\n path,\n metadata,\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Route Guards\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Get redirect path for unauthenticated users\n */\nexport function getUnauthenticatedRedirect(\n path: string,\n authPath: string = '/auth',\n): string | null {\n if (path.startsWith('/private') || path.startsWith('/admin')) {\n // Return path as-is. Next.js will handle basePath automatically for router.push()\n // when basePath is set in next.config.ts\n return authPath;\n }\n return null;\n}\n\n/**\n * Get redirect path to auth page\n */\nexport function redirectToAuth(\n authPath: string = '/auth',\n): string {\n // Return path as-is. Next.js will handle basePath automatically for router.push()\n // when basePath is set in next.config.ts\n return authPath;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Route Lookup\n// ─────────────────────────────────────────────────────────────────────────\n\nexport function findRoute(\n routes: RouteDefinition[],\n path: string\n): RouteDefinition | undefined {\n return routes.find((r) => r.path === path);\n}\n\nexport function findRouteByPattern(\n routes: RouteDefinition[],\n path: string\n): RouteDefinition | undefined {\n const exact = findRoute(routes, path);\n if (exact) return exact;\n\n const segments = path.split('/').filter(Boolean);\n for (let i = segments.length; i > 0; i--) {\n const parentPath = '/' + segments.slice(0, i).join('/');\n const parent = findRoute(routes, parentPath);\n if (parent) return parent;\n }\n\n return undefined;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Page Title\n// ─────────────────────────────────────────────────────────────────────────\n\nexport function getPageTitle(\n routes: RouteDefinition[],\n path: string,\n fallback = 'Dashboard'\n): string {\n const route = findRouteByPattern(routes, path);\n return route?.metadata.label || fallback;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Active Route\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Check if a route is active\n *\n * @param current - Current pathname\n * @param target - Target route path to check\n * @param allRoutes - Optional array of all routes to prevent parent paths from being active when child paths are active\n * @returns true if the route is active\n */\nexport function isActive(\n current: string,\n target: string,\n allRoutes?: RouteDefinition[]\n): boolean {\n const matches =\n current === target || (target !== '/' && current.startsWith(target + '/'));\n\n // If allRoutes is provided, check for more specific paths\n if (matches && allRoutes) {\n return !allRoutes.some(\n (otherRoute) =>\n otherRoute.path !== target &&\n otherRoute.path.startsWith(target + '/') &&\n (current === otherRoute.path ||\n current.startsWith(otherRoute.path + '/'))\n );\n }\n\n return matches;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Menu Generation Helper\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Filter and convert routes to menu items\n */\nexport function routesToMenuItems(\n routes: RouteDefinition[],\n groupName: string\n): MenuItem[] {\n return routes\n .filter(\n (r) =>\n r.metadata.group === groupName &&\n r.metadata.icon &&\n (r.metadata.show === undefined || r.metadata.show === true)\n )\n .sort((a, b) => (a.metadata.order || 0) - (b.metadata.order || 0))\n .map((r) => ({\n path: r.path,\n label: r.metadata.label,\n icon: r.metadata.icon!,\n }));\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Navigation Groups Helper\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Group routes by navigation groups\n *\n * @param routes - Array of route definitions\n * @param groups - Array of navigation group definitions\n * @returns Array of groups with their routes, filtered by dynamic flag\n *\n * @example\n * ```ts\n * const navGroups = [\n * { id: 'dashboard', label: 'Dashboard', order: 1 },\n * { id: 'extensions', label: 'Extensions', order: 2, dynamic: true },\n * ];\n *\n * const groupedRoutes = groupRoutesByNavGroups(allRoutes, navGroups);\n * // Returns groups with routes, hiding dynamic groups with no routes\n * ```\n */\nexport function groupRoutesByNavGroups(\n routes: RouteDefinition[],\n groups: NavGroup[]\n): NavGroupWithRoutes[] {\n return groups\n .map((group) => ({\n ...group,\n routes: routes\n .filter(\n (r) =>\n r.metadata.group === group.id &&\n (r.metadata.show === undefined || r.metadata.show === true)\n )\n .sort((a, b) => (a.metadata.order || 0) - (b.metadata.order || 0)),\n }))\n .filter((group) => {\n // Dynamic groups are only shown if they have routes\n if (group.dynamic) {\n return group.routes.length > 0;\n }\n // Non-dynamic groups are always shown\n return true;\n })\n .sort((a, b) => a.order - b.order);\n}\n\n"],"mappings":";AAsBO,SAAS,YACd,MACA,UACiB;AAGjB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AASO,SAAS,2BACd,MACA,WAAmB,SACJ;AACf,MAAI,KAAK,WAAW,UAAU,KAAK,KAAK,WAAW,QAAQ,GAAG;AAG5D,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,eACd,WAAmB,SACX;AAGR,SAAO;AACT;AAMO,SAAS,UACd,QACA,MAC6B;AAC7B,SAAO,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAC3C;AAEO,SAAS,mBACd,QACA,MAC6B;AAC7B,QAAM,QAAQ,UAAU,QAAQ,IAAI;AACpC,MAAI,MAAO,QAAO;AAElB,QAAM,WAAW,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/C,WAAS,IAAI,SAAS,QAAQ,IAAI,GAAG,KAAK;AACxC,UAAM,aAAa,MAAM,SAAS,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG;AACtD,UAAM,SAAS,UAAU,QAAQ,UAAU;AAC3C,QAAI,OAAQ,QAAO;AAAA,EACrB;AAEA,SAAO;AACT;AAMO,SAAS,aACd,QACA,MACA,WAAW,aACH;AACR,QAAM,QAAQ,mBAAmB,QAAQ,IAAI;AAC7C,SAAO,OAAO,SAAS,SAAS;AAClC;AAcO,SAAS,SACd,SACA,QACA,WACS;AACT,QAAM,UACJ,YAAY,UAAW,WAAW,OAAO,QAAQ,WAAW,SAAS,GAAG;AAG1E,MAAI,WAAW,WAAW;AACxB,WAAO,CAAC,UAAU;AAAA,MAChB,CAAC,eACC,WAAW,SAAS,UACpB,WAAW,KAAK,WAAW,SAAS,GAAG,MACtC,YAAY,WAAW,QACtB,QAAQ,WAAW,WAAW,OAAO,GAAG;AAAA,IAC9C;AAAA,EACF;AAEA,SAAO;AACT;AASO,SAAS,kBACd,QACA,WACY;AACZ,SAAO,OACJ;AAAA,IACC,CAAC,MACC,EAAE,SAAS,UAAU,aACrB,EAAE,SAAS,SACV,EAAE,SAAS,SAAS,UAAa,EAAE,SAAS,SAAS;AAAA,EAC1D,EACC,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,SAAS,MAAM,EAAE,SAAS,SAAS,EAAE,EAChE,IAAI,CAAC,OAAO;AAAA,IACX,MAAM,EAAE;AAAA,IACR,OAAO,EAAE,SAAS;AAAA,IAClB,MAAM,EAAE,SAAS;AAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/navigation/utils.ts"],"sourcesContent":["/**\n * Navigation Utilities\n *\n * Common utilities for route definitions and navigation\n */\n\nimport type { RouteDefinition, RouteMetadata, MenuItem, NavGroup, NavGroupWithRoutes } from './types';\n\n// ─────────────────────────────────────────────────────────────────────────\n// Route Definition Helper\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Define a route with metadata\n *\n * IMPORTANT: Next.js automatically handles basePath for <Link> components when\n * basePath is set in next.config.ts. We should NOT add basePath manually here,\n * as it would cause double-prefixing in static builds.\n *\n * @param path - Route path (e.g., '/dashboard', '/admin/users')\n * @param metadata - Route metadata (label, icon, etc.)\n */\nexport function defineRoute(\n path: string,\n metadata: RouteMetadata,\n): RouteDefinition {\n // Always return path as-is. Next.js will handle basePath automatically\n // for <Link> components when basePath is set in next.config.ts\n return {\n path,\n metadata,\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Route Guards\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Get redirect path for unauthenticated users\n */\nexport function getUnauthenticatedRedirect(\n path: string,\n authPath: string = '/auth',\n): string | null {\n if (path.startsWith('/private') || path.startsWith('/admin')) {\n // Return path as-is. Next.js will handle basePath automatically for router.push()\n // when basePath is set in next.config.ts\n return authPath;\n }\n return null;\n}\n\n/**\n * Get redirect path to auth page\n */\nexport function redirectToAuth(\n authPath: string = '/auth',\n): string {\n // Return path as-is. Next.js will handle basePath automatically for router.push()\n // when basePath is set in next.config.ts\n return authPath;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Route Lookup\n// ─────────────────────────────────────────────────────────────────────────\n\nexport function findRoute(\n routes: RouteDefinition[],\n path: string\n): RouteDefinition | undefined {\n return routes.find((r) => r.path === path);\n}\n\nexport function findRouteByPattern(\n routes: RouteDefinition[],\n path: string\n): RouteDefinition | undefined {\n const exact = findRoute(routes, path);\n if (exact) return exact;\n\n const segments = path.split('/').filter(Boolean);\n for (let i = segments.length; i > 0; i--) {\n const parentPath = '/' + segments.slice(0, i).join('/');\n const parent = findRoute(routes, parentPath);\n if (parent) return parent;\n }\n\n return undefined;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Page Title\n// ─────────────────────────────────────────────────────────────────────────\n\nexport function getPageTitle(\n routes: RouteDefinition[],\n path: string,\n fallback = 'Dashboard'\n): string {\n const route = findRouteByPattern(routes, path);\n return route?.metadata.label || fallback;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Active Route\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Check if a route is active\n *\n * @param current - Current pathname\n * @param target - Target route path to check\n * @param allRoutes - Optional array of all routes to prevent parent paths from being active when child paths are active\n * @returns true if the route is active\n */\nexport function isActive(\n current: string,\n target: string,\n allRoutes?: RouteDefinition[]\n): boolean {\n const matches =\n current === target || (target !== '/' && current.startsWith(target + '/'));\n\n // If allRoutes is provided, check for more specific paths\n if (matches && allRoutes) {\n return !allRoutes.some(\n (otherRoute) =>\n otherRoute.path !== target &&\n otherRoute.path.startsWith(target + '/') &&\n (current === otherRoute.path ||\n current.startsWith(otherRoute.path + '/'))\n );\n }\n\n return matches;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Menu Generation Helper\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Filter and convert routes to menu items\n */\nexport function routesToMenuItems(\n routes: RouteDefinition[],\n groupName: string\n): MenuItem[] {\n return routes\n .filter(\n (r) =>\n r.metadata.group === groupName &&\n r.metadata.icon &&\n (r.metadata.show === undefined || r.metadata.show === true)\n )\n .sort((a, b) => (a.metadata.order || 0) - (b.metadata.order || 0))\n .map((r) => ({\n path: r.path,\n label: r.metadata.label,\n icon: r.metadata.icon!,\n ...(r.metadata.badge !== undefined && { badge: r.metadata.badge }),\n }));\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Navigation Groups Helper\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Group routes by navigation groups\n *\n * @param routes - Array of route definitions\n * @param groups - Array of navigation group definitions\n * @returns Array of groups with their routes, filtered by dynamic flag\n *\n * @example\n * ```ts\n * const navGroups = [\n * { id: 'dashboard', label: 'Dashboard', order: 1 },\n * { id: 'extensions', label: 'Extensions', order: 2, dynamic: true },\n * ];\n *\n * const groupedRoutes = groupRoutesByNavGroups(allRoutes, navGroups);\n * // Returns groups with routes, hiding dynamic groups with no routes\n * ```\n */\nexport function groupRoutesByNavGroups(\n routes: RouteDefinition[],\n groups: NavGroup[]\n): NavGroupWithRoutes[] {\n return groups\n .map((group) => ({\n ...group,\n routes: routes\n .filter(\n (r) =>\n r.metadata.group === group.id &&\n (r.metadata.show === undefined || r.metadata.show === true)\n )\n .sort((a, b) => (a.metadata.order || 0) - (b.metadata.order || 0)),\n }))\n .filter((group) => {\n // Dynamic groups are only shown if they have routes\n if (group.dynamic) {\n return group.routes.length > 0;\n }\n // Non-dynamic groups are always shown\n return true;\n })\n .sort((a, b) => a.order - b.order);\n}\n\n"],"mappings":";AAsBO,SAAS,YACd,MACA,UACiB;AAGjB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AASO,SAAS,2BACd,MACA,WAAmB,SACJ;AACf,MAAI,KAAK,WAAW,UAAU,KAAK,KAAK,WAAW,QAAQ,GAAG;AAG5D,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,eACd,WAAmB,SACX;AAGR,SAAO;AACT;AAMO,SAAS,UACd,QACA,MAC6B;AAC7B,SAAO,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAC3C;AAEO,SAAS,mBACd,QACA,MAC6B;AAC7B,QAAM,QAAQ,UAAU,QAAQ,IAAI;AACpC,MAAI,MAAO,QAAO;AAElB,QAAM,WAAW,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/C,WAAS,IAAI,SAAS,QAAQ,IAAI,GAAG,KAAK;AACxC,UAAM,aAAa,MAAM,SAAS,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG;AACtD,UAAM,SAAS,UAAU,QAAQ,UAAU;AAC3C,QAAI,OAAQ,QAAO;AAAA,EACrB;AAEA,SAAO;AACT;AAMO,SAAS,aACd,QACA,MACA,WAAW,aACH;AACR,QAAM,QAAQ,mBAAmB,QAAQ,IAAI;AAC7C,SAAO,OAAO,SAAS,SAAS;AAClC;AAcO,SAAS,SACd,SACA,QACA,WACS;AACT,QAAM,UACJ,YAAY,UAAW,WAAW,OAAO,QAAQ,WAAW,SAAS,GAAG;AAG1E,MAAI,WAAW,WAAW;AACxB,WAAO,CAAC,UAAU;AAAA,MAChB,CAAC,eACC,WAAW,SAAS,UACpB,WAAW,KAAK,WAAW,SAAS,GAAG,MACtC,YAAY,WAAW,QACtB,QAAQ,WAAW,WAAW,OAAO,GAAG;AAAA,IAC9C;AAAA,EACF;AAEA,SAAO;AACT;AASO,SAAS,kBACd,QACA,WACY;AACZ,SAAO,OACJ;AAAA,IACC,CAAC,MACC,EAAE,SAAS,UAAU,aACrB,EAAE,SAAS,SACV,EAAE,SAAS,SAAS,UAAa,EAAE,SAAS,SAAS;AAAA,EAC1D,EACC,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,SAAS,MAAM,EAAE,SAAS,SAAS,EAAE,EAChE,IAAI,CAAC,OAAO;AAAA,IACX,MAAM,EAAE;AAAA,IACR,OAAO,EAAE,SAAS;AAAA,IAClB,MAAM,EAAE,SAAS;AAAA,IACjB,GAAI,EAAE,SAAS,UAAU,UAAa,EAAE,OAAO,EAAE,SAAS,MAAM;AAAA,EAClE,EAAE;AACN;AAwBO,SAAS,uBACd,QACA,QACsB;AACtB,SAAO,OACJ,IAAI,CAAC,WAAW;AAAA,IACf,GAAG;AAAA,IACH,QAAQ,OACL;AAAA,MACC,CAAC,MACC,EAAE,SAAS,UAAU,MAAM,OAC1B,EAAE,SAAS,SAAS,UAAa,EAAE,SAAS,SAAS;AAAA,IAC1D,EACC,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,SAAS,MAAM,EAAE,SAAS,SAAS,EAAE;AAAA,EACrE,EAAE,EACD,OAAO,CAAC,UAAU;AAEjB,QAAI,MAAM,SAAS;AACjB,aAAO,MAAM,OAAO,SAAS;AAAA,IAC/B;AAEA,WAAO;AAAA,EACT,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACrC;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/nextjs",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.254",
|
|
4
4
|
"description": "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nextjs",
|
|
@@ -143,9 +143,9 @@
|
|
|
143
143
|
"ai-docs": "tsx src/ai/cli.ts"
|
|
144
144
|
},
|
|
145
145
|
"peerDependencies": {
|
|
146
|
-
"@djangocfg/i18n": "^2.1.
|
|
147
|
-
"@djangocfg/monitor": "^2.1.
|
|
148
|
-
"@djangocfg/ui-core": "^2.1.
|
|
146
|
+
"@djangocfg/i18n": "^2.1.254",
|
|
147
|
+
"@djangocfg/monitor": "^2.1.254",
|
|
148
|
+
"@djangocfg/ui-core": "^2.1.254",
|
|
149
149
|
"next": "^16.0.10"
|
|
150
150
|
},
|
|
151
151
|
"peerDependenciesMeta": {
|
|
@@ -167,11 +167,11 @@
|
|
|
167
167
|
"serwist": "^9.2.3"
|
|
168
168
|
},
|
|
169
169
|
"devDependencies": {
|
|
170
|
-
"@djangocfg/i18n": "^2.1.
|
|
171
|
-
"@djangocfg/monitor": "^2.1.
|
|
172
|
-
"@djangocfg/ui-core": "^2.1.
|
|
173
|
-
"@djangocfg/layouts": "^2.1.
|
|
174
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
170
|
+
"@djangocfg/i18n": "^2.1.254",
|
|
171
|
+
"@djangocfg/monitor": "^2.1.254",
|
|
172
|
+
"@djangocfg/ui-core": "^2.1.254",
|
|
173
|
+
"@djangocfg/layouts": "^2.1.254",
|
|
174
|
+
"@djangocfg/typescript-config": "^2.1.254",
|
|
175
175
|
"@types/node": "^24.7.2",
|
|
176
176
|
"@types/react": "^19.1.0",
|
|
177
177
|
"@types/react-dom": "^19.1.0",
|
package/src/navigation/types.ts
CHANGED