@nubitio/admin 1.1.2 → 1.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.
- package/README.md +34 -0
- package/dist/index.cjs +181 -115
- package/dist/index.d.cts +33 -6
- package/dist/index.d.mts +33 -6
- package/dist/index.mjs +181 -116
- package/dist/style.css +167 -4
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -45,6 +45,40 @@ export function App() {
|
|
|
45
45
|
|
|
46
46
|
## Exports
|
|
47
47
|
|
|
48
|
+
### Nubit workspace layout (opt-in)
|
|
49
|
+
|
|
50
|
+
The existing layout remains the default. `variant="workspace"` places the sidebar
|
|
51
|
+
alongside the header on large screens and retains the overlay menu on smaller
|
|
52
|
+
screens. Application-specific search and company/branch selection stay outside
|
|
53
|
+
the library:
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
<AdminShell
|
|
57
|
+
variant="workspace"
|
|
58
|
+
title="Sales"
|
|
59
|
+
menuItems={menu}
|
|
60
|
+
brand={<CompanyLogo />}
|
|
61
|
+
headerContent={<WorkspaceSearch />}
|
|
62
|
+
sidebarContext={<CompanyBranchPicker />}
|
|
63
|
+
bottomNavigation={<AdminBottomNavigation items={mobileDestinations} />}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
</AdminShell>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`brand` and `sidebarContext` are hidden in compact mode. The bottom-navigation
|
|
70
|
+
slot renders only on extra-small screens, reserves its own space (including the
|
|
71
|
+
device safe area), and does not cover the main content. `AdminBottomNavigation`
|
|
72
|
+
uses router links and marks the longest matching destination with `aria-current`.
|
|
73
|
+
Pass only authorized destinations. Its `label` prop names the navigation landmark.
|
|
74
|
+
|
|
75
|
+
All slots and `variant` are also available through `createNubitApp({ shell: … })`.
|
|
76
|
+
Set `visualStyle: 'nubit'` to opt into the Figma token foundation when using the
|
|
77
|
+
app factory; see the UI package README for font setup.
|
|
78
|
+
|
|
79
|
+
Preview in the demo: `/dashboard?visualStyle=nubit`. Search navigates between demo
|
|
80
|
+
pages; the context label is illustrative, not an ERP company selector.
|
|
81
|
+
|
|
48
82
|
- `AdminShell` — full layout: sidebar + header + content area
|
|
49
83
|
- `AdminHeader` — standalone header with action slots
|
|
50
84
|
- `AdminSidebarMenu` — standalone sidebar menu
|
package/dist/index.cjs
CHANGED
|
@@ -166,7 +166,7 @@ function UserMenuPopover({ renderUserMenu }) {
|
|
|
166
166
|
})]
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
|
-
const AdminHeader = ({ title, menuToggleEnabled, toggleMenu, className, actions = [], renderUserMenu, renderThemeSwitcher }) => {
|
|
169
|
+
const AdminHeader = ({ title, menuToggleEnabled, toggleMenu, className, actions = [], content, renderUserMenu, renderThemeSwitcher }) => {
|
|
170
170
|
const strings = (0, _nubitio_ui.useUiStrings)();
|
|
171
171
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
|
|
172
172
|
className: ["nb-admin-header-component", className].filter(Boolean).join(" "),
|
|
@@ -174,25 +174,32 @@ const AdminHeader = ({ title, menuToggleEnabled, toggleMenu, className, actions
|
|
|
174
174
|
className: "nb-admin-header-toolbar",
|
|
175
175
|
role: "toolbar",
|
|
176
176
|
"aria-label": strings.mainToolbar,
|
|
177
|
-
children: [
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
179
|
+
className: "nb-admin-header-toolbar__before",
|
|
180
|
+
children: [menuToggleEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_ui.IconButton, {
|
|
181
|
+
className: "nb-admin-menu-button",
|
|
182
|
+
icon: "ph ph-list",
|
|
183
|
+
label: strings.toggleMenu,
|
|
184
|
+
onClick: toggleMenu
|
|
185
|
+
}), title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
186
|
+
className: "nb-admin-header-title",
|
|
187
|
+
children: title
|
|
188
|
+
})]
|
|
189
|
+
}),
|
|
190
|
+
content && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
191
|
+
className: "nb-admin-header-content",
|
|
192
|
+
children: content
|
|
193
|
+
}),
|
|
194
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
195
|
+
className: "nb-admin-header-toolbar__after",
|
|
196
|
+
children: [
|
|
197
|
+
renderThemeSwitcher?.(),
|
|
198
|
+
actions.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionPopover, { action }, action.id)),
|
|
199
|
+
renderUserMenu && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UserMenuPopover, { renderUserMenu })
|
|
200
|
+
]
|
|
201
|
+
})
|
|
202
|
+
]
|
|
196
203
|
})
|
|
197
204
|
});
|
|
198
205
|
};
|
|
@@ -259,7 +266,7 @@ const getIconClassName = (icon) => {
|
|
|
259
266
|
if (!icon) return "";
|
|
260
267
|
return icon.includes(" ") ? icon : `ph ph-${icon}`;
|
|
261
268
|
};
|
|
262
|
-
const AdminSidebarMenu = ({ items, compactMode = false, selectedItemChanged, openMenu, footer }) => {
|
|
269
|
+
const AdminSidebarMenu = ({ items, compactMode = false, selectedItemChanged, openMenu, footer, brand, context }) => {
|
|
263
270
|
const [expandedItemKeys, setExpandedItemKeys] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
264
271
|
const strings = (0, _nubitio_ui.useUiStrings)();
|
|
265
272
|
const { isLarge } = useScreenSize();
|
|
@@ -308,73 +315,84 @@ const AdminSidebarMenu = ({ items, compactMode = false, selectedItemChanged, ope
|
|
|
308
315
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
309
316
|
className: `nb-admin-menu${compactMode ? " compact" : ""}`,
|
|
310
317
|
onPointerDown: openMenu,
|
|
311
|
-
children: [
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
"aria-hidden": "true"
|
|
348
|
-
})
|
|
349
|
-
]
|
|
350
|
-
}), expanded && (item.items?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
351
|
-
className: "nb-admin-menu__children",
|
|
352
|
-
children: item.items.map((subItem) => {
|
|
353
|
-
const childSelected = isSelected(subItem.path);
|
|
354
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
355
|
-
className: `nb-admin-menu__item nb-admin-menu__item--child${childSelected ? " is-selected" : ""}`,
|
|
356
|
-
type: "button",
|
|
357
|
-
"aria-current": childSelected ? "page" : void 0,
|
|
358
|
-
onClick: (event) => handleSelect(subItem.path, childSelected, event),
|
|
359
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
318
|
+
children: [
|
|
319
|
+
brand && !compactMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
320
|
+
className: "nb-admin-menu__brand",
|
|
321
|
+
children: brand
|
|
322
|
+
}),
|
|
323
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
324
|
+
className: "nb-admin-menu-container theme-dependent",
|
|
325
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
|
|
326
|
+
className: "nb-admin-menu__nav",
|
|
327
|
+
"aria-label": strings.mainNavigation,
|
|
328
|
+
children: items.map((item) => {
|
|
329
|
+
const selected = isSelected(item.path);
|
|
330
|
+
const containsSelected = parentContainsSelected(item);
|
|
331
|
+
const itemKey = item.path || item.text;
|
|
332
|
+
const hasChildren = (item.items?.length ?? 0) > 0;
|
|
333
|
+
const expanded = !compactMode && hasChildren && expandedItemKeys.has(itemKey);
|
|
334
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
335
|
+
className: `nb-admin-menu__section${containsSelected ? " has-selected-child" : ""}`,
|
|
336
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
337
|
+
className: `nb-admin-menu__item nb-admin-menu__item--parent${selected ? " is-selected" : ""}`,
|
|
338
|
+
type: "button",
|
|
339
|
+
"aria-current": selected ? "page" : void 0,
|
|
340
|
+
"aria-expanded": hasChildren ? expanded : void 0,
|
|
341
|
+
onClick: (event) => {
|
|
342
|
+
if (hasChildren) {
|
|
343
|
+
toggleExpanded(itemKey);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
handleSelect(item.path, selected, event);
|
|
347
|
+
},
|
|
348
|
+
children: [
|
|
349
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
350
|
+
className: `nb-admin-menu__icon ${getIconClassName(item.icon)}`,
|
|
351
|
+
"aria-hidden": "true"
|
|
352
|
+
}),
|
|
353
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
360
354
|
className: "nb-admin-menu__text",
|
|
361
|
-
children:
|
|
355
|
+
children: item.text
|
|
356
|
+
}),
|
|
357
|
+
hasChildren && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
358
|
+
className: `nb-admin-menu__chevron${expanded ? " is-expanded" : ""}`,
|
|
359
|
+
"aria-hidden": "true"
|
|
362
360
|
})
|
|
363
|
-
|
|
364
|
-
})
|
|
365
|
-
|
|
366
|
-
|
|
361
|
+
]
|
|
362
|
+
}), expanded && (item.items?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
363
|
+
className: "nb-admin-menu__children",
|
|
364
|
+
children: item.items.map((subItem) => {
|
|
365
|
+
const childSelected = isSelected(subItem.path);
|
|
366
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
367
|
+
className: `nb-admin-menu__item nb-admin-menu__item--child${childSelected ? " is-selected" : ""}`,
|
|
368
|
+
type: "button",
|
|
369
|
+
"aria-current": childSelected ? "page" : void 0,
|
|
370
|
+
onClick: (event) => handleSelect(subItem.path, childSelected, event),
|
|
371
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
372
|
+
className: "nb-admin-menu__text",
|
|
373
|
+
children: subItem.text
|
|
374
|
+
})
|
|
375
|
+
}, subItem.path || subItem.text);
|
|
376
|
+
})
|
|
377
|
+
})]
|
|
378
|
+
}, itemKey);
|
|
379
|
+
})
|
|
367
380
|
})
|
|
381
|
+
}),
|
|
382
|
+
context && !compactMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
383
|
+
className: "nb-admin-menu__context",
|
|
384
|
+
children: context
|
|
385
|
+
}),
|
|
386
|
+
footer && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
|
|
387
|
+
className: "nb-admin-footer",
|
|
388
|
+
children: footer
|
|
368
389
|
})
|
|
369
|
-
|
|
370
|
-
className: "nb-admin-footer",
|
|
371
|
-
children: footer
|
|
372
|
-
})]
|
|
390
|
+
]
|
|
373
391
|
});
|
|
374
392
|
};
|
|
375
393
|
//#endregion
|
|
376
394
|
//#region packages/admin/AdminShell.tsx
|
|
377
|
-
const AdminShell = ({ title, menuItems, headerActions, renderUserMenu, renderThemeSwitcher, footer, children }) => {
|
|
395
|
+
const AdminShell = ({ title, menuItems, headerActions, renderUserMenu, renderThemeSwitcher, footer, variant = "default", brand, headerContent, sidebarContext, bottomNavigation, children }) => {
|
|
378
396
|
const navigate = (0, react_router_dom.useNavigate)();
|
|
379
397
|
const strings = (0, _nubitio_ui.useUiStrings)();
|
|
380
398
|
const { isXSmall, isLarge } = useScreenSize();
|
|
@@ -430,45 +448,92 @@ const AdminShell = ({ title, menuItems, headerActions, renderUserMenu, renderThe
|
|
|
430
448
|
isXSmall ? "is-xsmall" : ""
|
|
431
449
|
].filter(Boolean).join(" ");
|
|
432
450
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
433
|
-
className:
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
451
|
+
className: [
|
|
452
|
+
"nb-admin-shell",
|
|
453
|
+
variant === "workspace" && "nb-admin-shell--workspace",
|
|
454
|
+
variant === "workspace" && isLarge && "is-workspace-desktop",
|
|
455
|
+
variant === "workspace" && isLarge && isCompact && "is-workspace-compact"
|
|
456
|
+
].filter(Boolean).join(" "),
|
|
457
|
+
children: [
|
|
458
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AdminHeader, {
|
|
459
|
+
className: "nb-admin-layout-header",
|
|
460
|
+
menuToggleEnabled: true,
|
|
461
|
+
toggleMenu,
|
|
462
|
+
title,
|
|
463
|
+
actions: headerActions,
|
|
464
|
+
content: headerContent,
|
|
465
|
+
renderUserMenu,
|
|
466
|
+
renderThemeSwitcher
|
|
467
|
+
}),
|
|
468
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
469
|
+
className: bodyClassName,
|
|
470
|
+
children: [
|
|
471
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
|
|
472
|
+
className: "nb-admin-shell__panel",
|
|
473
|
+
"aria-label": strings.mainMenu,
|
|
474
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AdminSidebarMenu, {
|
|
475
|
+
items: menuItems,
|
|
476
|
+
compactMode: isCompact,
|
|
477
|
+
selectedItemChanged: onNavigationChanged,
|
|
478
|
+
openMenu: temporaryOpenMenu,
|
|
479
|
+
footer,
|
|
480
|
+
brand,
|
|
481
|
+
context: sidebarContext
|
|
482
|
+
})
|
|
483
|
+
}),
|
|
484
|
+
!isLarge && isMenuOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
485
|
+
className: "nb-admin-shell__scrim",
|
|
486
|
+
type: "button",
|
|
487
|
+
"aria-label": strings.closeMenu,
|
|
488
|
+
onClick: closeMenuFromOverlay
|
|
489
|
+
}),
|
|
490
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("main", {
|
|
491
|
+
className: "nb-admin-shell__content content",
|
|
492
|
+
tabIndex: 0,
|
|
493
|
+
"aria-label": title ? `${title} content` : strings.mainContent,
|
|
494
|
+
children
|
|
454
495
|
})
|
|
496
|
+
]
|
|
497
|
+
}),
|
|
498
|
+
isXSmall && bottomNavigation && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
499
|
+
className: "nb-admin-shell__bottom-navigation",
|
|
500
|
+
children: bottomNavigation
|
|
501
|
+
})
|
|
502
|
+
]
|
|
503
|
+
});
|
|
504
|
+
};
|
|
505
|
+
//#endregion
|
|
506
|
+
//#region packages/admin/AdminBottomNavigation.tsx
|
|
507
|
+
function AdminBottomNavigation({ items, label }) {
|
|
508
|
+
const { pathname } = (0, react_router_dom.useLocation)();
|
|
509
|
+
const strings = (0, _nubitio_ui.useUiStrings)();
|
|
510
|
+
const normalize = (path) => path.replace(/\/+$/, "") || "/";
|
|
511
|
+
const currentPath = normalize(pathname);
|
|
512
|
+
const activePath = items.map((item) => normalize(item.path)).filter((path) => currentPath === path || path !== "/" && currentPath.startsWith(`${path}/`)).sort((a, b) => b.length - a.length)[0];
|
|
513
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
|
|
514
|
+
className: "nb-admin-bottom-nav",
|
|
515
|
+
"aria-label": label ?? strings.mainNavigation,
|
|
516
|
+
children: items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Link, {
|
|
517
|
+
to: item.path,
|
|
518
|
+
className: "nb-admin-bottom-nav__item",
|
|
519
|
+
"aria-current": normalize(item.path) === activePath ? "page" : void 0,
|
|
520
|
+
children: [
|
|
521
|
+
item.icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
522
|
+
className: `nb-admin-bottom-nav__icon ${item.icon.includes(" ") ? item.icon : `ph ph-${item.icon}`}`,
|
|
523
|
+
"aria-hidden": "true"
|
|
455
524
|
}),
|
|
456
|
-
|
|
457
|
-
className: "nb-admin-
|
|
458
|
-
|
|
459
|
-
"aria-label": strings.closeMenu,
|
|
460
|
-
onClick: closeMenuFromOverlay
|
|
525
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
526
|
+
className: "nb-admin-bottom-nav__label",
|
|
527
|
+
children: item.text
|
|
461
528
|
}),
|
|
462
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
463
|
-
className: "nb-admin-
|
|
464
|
-
|
|
465
|
-
"aria-label": title ? `${title} content` : strings.mainContent,
|
|
466
|
-
children
|
|
529
|
+
item.badge != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
530
|
+
className: "nb-admin-bottom-nav__badge",
|
|
531
|
+
children: item.badge
|
|
467
532
|
})
|
|
468
533
|
]
|
|
469
|
-
})
|
|
534
|
+
}, item.path))
|
|
470
535
|
});
|
|
471
|
-
}
|
|
536
|
+
}
|
|
472
537
|
//#endregion
|
|
473
538
|
//#region packages/admin/auth/csrfFetch.ts
|
|
474
539
|
const MUTATING_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -2146,8 +2211,7 @@ function NubitAuthenticatedApp({ config }) {
|
|
|
2146
2211
|
const shell = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AdminShell, {
|
|
2147
2212
|
title: config.title,
|
|
2148
2213
|
menuItems,
|
|
2149
|
-
|
|
2150
|
-
footer: config.shell?.footer,
|
|
2214
|
+
...config.shell,
|
|
2151
2215
|
renderThemeSwitcher,
|
|
2152
2216
|
renderUserMenu: ({ close }) => renderUserMenu({
|
|
2153
2217
|
...menuContext,
|
|
@@ -2246,6 +2310,7 @@ function createNubitApp(config) {
|
|
|
2246
2310
|
client: queryClient,
|
|
2247
2311
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_ui.ThemeProvider, {
|
|
2248
2312
|
basePath: config.themeBasePath,
|
|
2313
|
+
visualStyle: config.visualStyle,
|
|
2249
2314
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionProvider, {
|
|
2250
2315
|
apiBaseUrl,
|
|
2251
2316
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NubitAuthenticatedApp, { config })
|
|
@@ -2258,6 +2323,7 @@ function createNubitApp(config) {
|
|
|
2258
2323
|
//#endregion
|
|
2259
2324
|
exports.AcceptInvitationPage = AcceptInvitationPage;
|
|
2260
2325
|
exports.AccountPage = AccountPage;
|
|
2326
|
+
exports.AdminBottomNavigation = AdminBottomNavigation;
|
|
2261
2327
|
exports.AdminHeader = AdminHeader;
|
|
2262
2328
|
exports.AdminShell = AdminShell;
|
|
2263
2329
|
exports.AdminSidebarMenu = AdminSidebarMenu;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React$1, { ReactNode } from "react";
|
|
2
|
-
import { FeatureGateProps as FeatureGateProps$1 } from "@nubitio/ui";
|
|
2
|
+
import { FeatureGateProps as FeatureGateProps$1, ThemeProviderProps } from "@nubitio/ui";
|
|
3
3
|
import { CoreRuntime } from "@nubitio/core";
|
|
4
4
|
import { QueryClient } from "@tanstack/react-query";
|
|
5
5
|
//#region packages/admin/FeatureHubLayout.d.ts
|
|
@@ -52,12 +52,14 @@ interface AdminHeaderProps {
|
|
|
52
52
|
toggleMenu?: (e: React$1.MouseEvent<HTMLButtonElement>) => void;
|
|
53
53
|
className?: string;
|
|
54
54
|
actions?: AdminHeaderAction[];
|
|
55
|
+
/** Search, command trigger or other application-owned header content. */
|
|
56
|
+
content?: React$1.ReactNode;
|
|
55
57
|
renderUserMenu?: (props: {
|
|
56
58
|
close: () => void;
|
|
57
59
|
}) => React$1.ReactNode;
|
|
58
60
|
renderThemeSwitcher?: () => React$1.ReactNode;
|
|
59
61
|
}
|
|
60
|
-
declare const AdminHeader: ({ title, menuToggleEnabled, toggleMenu, className, actions, renderUserMenu, renderThemeSwitcher }: AdminHeaderProps) => React$1.JSX.Element;
|
|
62
|
+
declare const AdminHeader: ({ title, menuToggleEnabled, toggleMenu, className, actions, content, renderUserMenu, renderThemeSwitcher }: AdminHeaderProps) => React$1.JSX.Element;
|
|
61
63
|
//#endregion
|
|
62
64
|
//#region packages/admin/AdminSidebarMenu.d.ts
|
|
63
65
|
interface AdminMenuSubItem {
|
|
@@ -81,8 +83,10 @@ interface AdminSidebarMenuProps {
|
|
|
81
83
|
selectedItemChanged: (e: AdminSidebarMenuSelectEvent) => void;
|
|
82
84
|
openMenu?: (e: React$1.PointerEvent) => void;
|
|
83
85
|
footer?: React$1.ReactNode;
|
|
86
|
+
brand?: React$1.ReactNode;
|
|
87
|
+
context?: React$1.ReactNode;
|
|
84
88
|
}
|
|
85
|
-
declare const AdminSidebarMenu: ({ items, compactMode, selectedItemChanged, openMenu, footer }: AdminSidebarMenuProps) => React$1.JSX.Element;
|
|
89
|
+
declare const AdminSidebarMenu: ({ items, compactMode, selectedItemChanged, openMenu, footer, brand, context }: AdminSidebarMenuProps) => React$1.JSX.Element;
|
|
86
90
|
//#endregion
|
|
87
91
|
//#region packages/admin/AdminShell.d.ts
|
|
88
92
|
interface AdminShellProps {
|
|
@@ -94,9 +98,31 @@ interface AdminShellProps {
|
|
|
94
98
|
}) => React$1.ReactNode;
|
|
95
99
|
renderThemeSwitcher?: () => React$1.ReactNode;
|
|
96
100
|
footer?: React$1.ReactNode;
|
|
101
|
+
/** Workspace places the sidebar alongside the header on large screens. */
|
|
102
|
+
variant?: 'default' | 'workspace';
|
|
103
|
+
brand?: React$1.ReactNode;
|
|
104
|
+
headerContent?: React$1.ReactNode;
|
|
105
|
+
/** Application owns context selection (e.g. company/branch); the shell only hosts it. */
|
|
106
|
+
sidebarContext?: React$1.ReactNode;
|
|
107
|
+
/** Rendered below content on extra-small screens, without covering the scroll area. */
|
|
108
|
+
bottomNavigation?: React$1.ReactNode;
|
|
97
109
|
children: React$1.ReactNode;
|
|
98
110
|
}
|
|
99
|
-
declare const AdminShell: ({ title, menuItems, headerActions, renderUserMenu, renderThemeSwitcher, footer, children }: AdminShellProps) => React$1.JSX.Element;
|
|
111
|
+
declare const AdminShell: ({ title, menuItems, headerActions, renderUserMenu, renderThemeSwitcher, footer, variant, brand, headerContent, sidebarContext, bottomNavigation, children }: AdminShellProps) => React$1.JSX.Element;
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region packages/admin/AdminBottomNavigation.d.ts
|
|
114
|
+
interface AdminBottomNavigationItem {
|
|
115
|
+
text: string;
|
|
116
|
+
path: string;
|
|
117
|
+
icon?: string;
|
|
118
|
+
badge?: ReactNode;
|
|
119
|
+
}
|
|
120
|
+
interface AdminBottomNavigationProps {
|
|
121
|
+
/** Pass only destinations this user may access; authorization stays in the app/API. */
|
|
122
|
+
items: AdminBottomNavigationItem[];
|
|
123
|
+
label?: string;
|
|
124
|
+
}
|
|
125
|
+
declare function AdminBottomNavigation({ items, label }: AdminBottomNavigationProps): import("react").JSX.Element;
|
|
100
126
|
//#endregion
|
|
101
127
|
//#region packages/admin/useScreenSize.d.ts
|
|
102
128
|
declare const useScreenSize: () => {
|
|
@@ -438,6 +464,7 @@ type CreateNubitAppConfig = {
|
|
|
438
464
|
currency?: string;
|
|
439
465
|
/** Base URL for generated theme CSS files. Default `/themes/`. */
|
|
440
466
|
themeBasePath?: string;
|
|
467
|
+
visualStyle?: ThemeProviderProps['visualStyle'];
|
|
441
468
|
menu: NubitAppMenuItem[] | ((ctx: NubitAppMenuContext) => NubitAppMenuItem[]);
|
|
442
469
|
routes: NubitAppRoute[];
|
|
443
470
|
/**
|
|
@@ -454,7 +481,7 @@ type CreateNubitAppConfig = {
|
|
|
454
481
|
label: string;
|
|
455
482
|
}[];
|
|
456
483
|
};
|
|
457
|
-
shell?: Pick<AdminShellProps, 'headerActions' | 'footer'>;
|
|
484
|
+
shell?: Pick<AdminShellProps, 'headerActions' | 'footer' | 'variant' | 'brand' | 'headerContent' | 'sidebarContext' | 'bottomNavigation'>;
|
|
458
485
|
renderThemeSwitcher?: () => ReactNode;
|
|
459
486
|
renderUserMenu?: (ctx: NubitAppUserMenuContext) => ReactNode;
|
|
460
487
|
/** Wraps authenticated shell content (inside Hydra providers). */
|
|
@@ -488,4 +515,4 @@ declare function hasAnyRole(required: string | string[] | undefined, roles: stri
|
|
|
488
515
|
*/
|
|
489
516
|
declare function filterMenuByRoles(items: NubitAppMenuItem[], roles: string[]): AdminMenuItem[];
|
|
490
517
|
//#endregion
|
|
491
|
-
export { AcceptInvitationPage, type AcceptInvitationPageProps, AccountPage, type AccountPageProps, AdminHeader, type AdminHeaderAction, type AdminHeaderProps, type AdminMenuItem, type AdminMenuSubItem, AdminShell, type AdminShellProps, AdminSidebarMenu, type AdminSidebarMenuProps, type AdminSidebarMenuSelectEvent, type AppProfile, type CreateNubitAppConfig, FeatureGate, type FeatureGateProps, type FeatureHubBanner, type FeatureHubDensity, FeatureHubLayout, type FeatureHubLayoutProps, type FeatureHubTab, ForgotPasswordPage, type ForgotPasswordPageProps, type LoginOidcProvider, LoginPage, type LoginPageProps, type NotificationItem, NotificationPanel, type NotificationPanelProps, type NotificationType, type NubitApp, type NubitAppMenuContext, type NubitAppMenuItem, type NubitAppMenuSubItem, type NubitAppRoute, type NubitAppUserMenuContext, NubitDevToolsPanel, type ParsedQuotaError, type PlanDefinition, PlanPanel, type PlanPanelLabels, type PlanPanelProps, QuotaUsageBanner, type QuotaUsageBannerProps, type RegisterField, type RegisterFieldType, RegisterPage, type RegisterPageProps, type RegisterSelectOption, ResetPasswordPage, type ResetPasswordPageProps, type RuntimeConfig, type RuntimeConfigState, type SessionContextValue, type SessionFeatureEntitlement, type SessionPermissionLimit, type SessionProfile, SessionProvider, type SessionProviderConfig, type SessionState, type SessionTenant, StaticSessionProvider, ToastHost, type ToastHostProps, type ToastItem, type UseNotificationsOptions, type UseQuotaUsageOptions, type UseRuntimeConfigOptions, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useNotifications, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
|
518
|
+
export { AcceptInvitationPage, type AcceptInvitationPageProps, AccountPage, type AccountPageProps, AdminBottomNavigation, type AdminBottomNavigationItem, type AdminBottomNavigationProps, AdminHeader, type AdminHeaderAction, type AdminHeaderProps, type AdminMenuItem, type AdminMenuSubItem, AdminShell, type AdminShellProps, AdminSidebarMenu, type AdminSidebarMenuProps, type AdminSidebarMenuSelectEvent, type AppProfile, type CreateNubitAppConfig, FeatureGate, type FeatureGateProps, type FeatureHubBanner, type FeatureHubDensity, FeatureHubLayout, type FeatureHubLayoutProps, type FeatureHubTab, ForgotPasswordPage, type ForgotPasswordPageProps, type LoginOidcProvider, LoginPage, type LoginPageProps, type NotificationItem, NotificationPanel, type NotificationPanelProps, type NotificationType, type NubitApp, type NubitAppMenuContext, type NubitAppMenuItem, type NubitAppMenuSubItem, type NubitAppRoute, type NubitAppUserMenuContext, NubitDevToolsPanel, type ParsedQuotaError, type PlanDefinition, PlanPanel, type PlanPanelLabels, type PlanPanelProps, QuotaUsageBanner, type QuotaUsageBannerProps, type RegisterField, type RegisterFieldType, RegisterPage, type RegisterPageProps, type RegisterSelectOption, ResetPasswordPage, type ResetPasswordPageProps, type RuntimeConfig, type RuntimeConfigState, type SessionContextValue, type SessionFeatureEntitlement, type SessionPermissionLimit, type SessionProfile, SessionProvider, type SessionProviderConfig, type SessionState, type SessionTenant, StaticSessionProvider, ToastHost, type ToastHostProps, type ToastItem, type UseNotificationsOptions, type UseQuotaUsageOptions, type UseRuntimeConfigOptions, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useNotifications, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React$1, { ReactNode } from "react";
|
|
2
|
-
import { FeatureGateProps as FeatureGateProps$1 } from "@nubitio/ui";
|
|
2
|
+
import { FeatureGateProps as FeatureGateProps$1, ThemeProviderProps } from "@nubitio/ui";
|
|
3
3
|
import { CoreRuntime } from "@nubitio/core";
|
|
4
4
|
import { QueryClient } from "@tanstack/react-query";
|
|
5
5
|
//#region packages/admin/FeatureHubLayout.d.ts
|
|
@@ -52,12 +52,14 @@ interface AdminHeaderProps {
|
|
|
52
52
|
toggleMenu?: (e: React$1.MouseEvent<HTMLButtonElement>) => void;
|
|
53
53
|
className?: string;
|
|
54
54
|
actions?: AdminHeaderAction[];
|
|
55
|
+
/** Search, command trigger or other application-owned header content. */
|
|
56
|
+
content?: React$1.ReactNode;
|
|
55
57
|
renderUserMenu?: (props: {
|
|
56
58
|
close: () => void;
|
|
57
59
|
}) => React$1.ReactNode;
|
|
58
60
|
renderThemeSwitcher?: () => React$1.ReactNode;
|
|
59
61
|
}
|
|
60
|
-
declare const AdminHeader: ({ title, menuToggleEnabled, toggleMenu, className, actions, renderUserMenu, renderThemeSwitcher }: AdminHeaderProps) => React$1.JSX.Element;
|
|
62
|
+
declare const AdminHeader: ({ title, menuToggleEnabled, toggleMenu, className, actions, content, renderUserMenu, renderThemeSwitcher }: AdminHeaderProps) => React$1.JSX.Element;
|
|
61
63
|
//#endregion
|
|
62
64
|
//#region packages/admin/AdminSidebarMenu.d.ts
|
|
63
65
|
interface AdminMenuSubItem {
|
|
@@ -81,8 +83,10 @@ interface AdminSidebarMenuProps {
|
|
|
81
83
|
selectedItemChanged: (e: AdminSidebarMenuSelectEvent) => void;
|
|
82
84
|
openMenu?: (e: React$1.PointerEvent) => void;
|
|
83
85
|
footer?: React$1.ReactNode;
|
|
86
|
+
brand?: React$1.ReactNode;
|
|
87
|
+
context?: React$1.ReactNode;
|
|
84
88
|
}
|
|
85
|
-
declare const AdminSidebarMenu: ({ items, compactMode, selectedItemChanged, openMenu, footer }: AdminSidebarMenuProps) => React$1.JSX.Element;
|
|
89
|
+
declare const AdminSidebarMenu: ({ items, compactMode, selectedItemChanged, openMenu, footer, brand, context }: AdminSidebarMenuProps) => React$1.JSX.Element;
|
|
86
90
|
//#endregion
|
|
87
91
|
//#region packages/admin/AdminShell.d.ts
|
|
88
92
|
interface AdminShellProps {
|
|
@@ -94,9 +98,31 @@ interface AdminShellProps {
|
|
|
94
98
|
}) => React$1.ReactNode;
|
|
95
99
|
renderThemeSwitcher?: () => React$1.ReactNode;
|
|
96
100
|
footer?: React$1.ReactNode;
|
|
101
|
+
/** Workspace places the sidebar alongside the header on large screens. */
|
|
102
|
+
variant?: 'default' | 'workspace';
|
|
103
|
+
brand?: React$1.ReactNode;
|
|
104
|
+
headerContent?: React$1.ReactNode;
|
|
105
|
+
/** Application owns context selection (e.g. company/branch); the shell only hosts it. */
|
|
106
|
+
sidebarContext?: React$1.ReactNode;
|
|
107
|
+
/** Rendered below content on extra-small screens, without covering the scroll area. */
|
|
108
|
+
bottomNavigation?: React$1.ReactNode;
|
|
97
109
|
children: React$1.ReactNode;
|
|
98
110
|
}
|
|
99
|
-
declare const AdminShell: ({ title, menuItems, headerActions, renderUserMenu, renderThemeSwitcher, footer, children }: AdminShellProps) => React$1.JSX.Element;
|
|
111
|
+
declare const AdminShell: ({ title, menuItems, headerActions, renderUserMenu, renderThemeSwitcher, footer, variant, brand, headerContent, sidebarContext, bottomNavigation, children }: AdminShellProps) => React$1.JSX.Element;
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region packages/admin/AdminBottomNavigation.d.ts
|
|
114
|
+
interface AdminBottomNavigationItem {
|
|
115
|
+
text: string;
|
|
116
|
+
path: string;
|
|
117
|
+
icon?: string;
|
|
118
|
+
badge?: ReactNode;
|
|
119
|
+
}
|
|
120
|
+
interface AdminBottomNavigationProps {
|
|
121
|
+
/** Pass only destinations this user may access; authorization stays in the app/API. */
|
|
122
|
+
items: AdminBottomNavigationItem[];
|
|
123
|
+
label?: string;
|
|
124
|
+
}
|
|
125
|
+
declare function AdminBottomNavigation({ items, label }: AdminBottomNavigationProps): import("react").JSX.Element;
|
|
100
126
|
//#endregion
|
|
101
127
|
//#region packages/admin/useScreenSize.d.ts
|
|
102
128
|
declare const useScreenSize: () => {
|
|
@@ -438,6 +464,7 @@ type CreateNubitAppConfig = {
|
|
|
438
464
|
currency?: string;
|
|
439
465
|
/** Base URL for generated theme CSS files. Default `/themes/`. */
|
|
440
466
|
themeBasePath?: string;
|
|
467
|
+
visualStyle?: ThemeProviderProps['visualStyle'];
|
|
441
468
|
menu: NubitAppMenuItem[] | ((ctx: NubitAppMenuContext) => NubitAppMenuItem[]);
|
|
442
469
|
routes: NubitAppRoute[];
|
|
443
470
|
/**
|
|
@@ -454,7 +481,7 @@ type CreateNubitAppConfig = {
|
|
|
454
481
|
label: string;
|
|
455
482
|
}[];
|
|
456
483
|
};
|
|
457
|
-
shell?: Pick<AdminShellProps, 'headerActions' | 'footer'>;
|
|
484
|
+
shell?: Pick<AdminShellProps, 'headerActions' | 'footer' | 'variant' | 'brand' | 'headerContent' | 'sidebarContext' | 'bottomNavigation'>;
|
|
458
485
|
renderThemeSwitcher?: () => ReactNode;
|
|
459
486
|
renderUserMenu?: (ctx: NubitAppUserMenuContext) => ReactNode;
|
|
460
487
|
/** Wraps authenticated shell content (inside Hydra providers). */
|
|
@@ -488,4 +515,4 @@ declare function hasAnyRole(required: string | string[] | undefined, roles: stri
|
|
|
488
515
|
*/
|
|
489
516
|
declare function filterMenuByRoles(items: NubitAppMenuItem[], roles: string[]): AdminMenuItem[];
|
|
490
517
|
//#endregion
|
|
491
|
-
export { AcceptInvitationPage, type AcceptInvitationPageProps, AccountPage, type AccountPageProps, AdminHeader, type AdminHeaderAction, type AdminHeaderProps, type AdminMenuItem, type AdminMenuSubItem, AdminShell, type AdminShellProps, AdminSidebarMenu, type AdminSidebarMenuProps, type AdminSidebarMenuSelectEvent, type AppProfile, type CreateNubitAppConfig, FeatureGate, type FeatureGateProps, type FeatureHubBanner, type FeatureHubDensity, FeatureHubLayout, type FeatureHubLayoutProps, type FeatureHubTab, ForgotPasswordPage, type ForgotPasswordPageProps, type LoginOidcProvider, LoginPage, type LoginPageProps, type NotificationItem, NotificationPanel, type NotificationPanelProps, type NotificationType, type NubitApp, type NubitAppMenuContext, type NubitAppMenuItem, type NubitAppMenuSubItem, type NubitAppRoute, type NubitAppUserMenuContext, NubitDevToolsPanel, type ParsedQuotaError, type PlanDefinition, PlanPanel, type PlanPanelLabels, type PlanPanelProps, QuotaUsageBanner, type QuotaUsageBannerProps, type RegisterField, type RegisterFieldType, RegisterPage, type RegisterPageProps, type RegisterSelectOption, ResetPasswordPage, type ResetPasswordPageProps, type RuntimeConfig, type RuntimeConfigState, type SessionContextValue, type SessionFeatureEntitlement, type SessionPermissionLimit, type SessionProfile, SessionProvider, type SessionProviderConfig, type SessionState, type SessionTenant, StaticSessionProvider, ToastHost, type ToastHostProps, type ToastItem, type UseNotificationsOptions, type UseQuotaUsageOptions, type UseRuntimeConfigOptions, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useNotifications, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
|
518
|
+
export { AcceptInvitationPage, type AcceptInvitationPageProps, AccountPage, type AccountPageProps, AdminBottomNavigation, type AdminBottomNavigationItem, type AdminBottomNavigationProps, AdminHeader, type AdminHeaderAction, type AdminHeaderProps, type AdminMenuItem, type AdminMenuSubItem, AdminShell, type AdminShellProps, AdminSidebarMenu, type AdminSidebarMenuProps, type AdminSidebarMenuSelectEvent, type AppProfile, type CreateNubitAppConfig, FeatureGate, type FeatureGateProps, type FeatureHubBanner, type FeatureHubDensity, FeatureHubLayout, type FeatureHubLayoutProps, type FeatureHubTab, ForgotPasswordPage, type ForgotPasswordPageProps, type LoginOidcProvider, LoginPage, type LoginPageProps, type NotificationItem, NotificationPanel, type NotificationPanelProps, type NotificationType, type NubitApp, type NubitAppMenuContext, type NubitAppMenuItem, type NubitAppMenuSubItem, type NubitAppRoute, type NubitAppUserMenuContext, NubitDevToolsPanel, type ParsedQuotaError, type PlanDefinition, PlanPanel, type PlanPanelLabels, type PlanPanelProps, QuotaUsageBanner, type QuotaUsageBannerProps, type RegisterField, type RegisterFieldType, RegisterPage, type RegisterPageProps, type RegisterSelectOption, ResetPasswordPage, type ResetPasswordPageProps, type RuntimeConfig, type RuntimeConfigState, type SessionContextValue, type SessionFeatureEntitlement, type SessionPermissionLimit, type SessionProfile, SessionProvider, type SessionProviderConfig, type SessionState, type SessionTenant, StaticSessionProvider, ToastHost, type ToastHostProps, type ToastItem, type UseNotificationsOptions, type UseQuotaUsageOptions, type UseRuntimeConfigOptions, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useNotifications, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
package/dist/index.mjs
CHANGED
|
@@ -142,7 +142,7 @@ function UserMenuPopover({ renderUserMenu }) {
|
|
|
142
142
|
})]
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
const AdminHeader = ({ title, menuToggleEnabled, toggleMenu, className, actions = [], renderUserMenu, renderThemeSwitcher }) => {
|
|
145
|
+
const AdminHeader = ({ title, menuToggleEnabled, toggleMenu, className, actions = [], content, renderUserMenu, renderThemeSwitcher }) => {
|
|
146
146
|
const strings = useUiStrings();
|
|
147
147
|
return /* @__PURE__ */ jsx("header", {
|
|
148
148
|
className: ["nb-admin-header-component", className].filter(Boolean).join(" "),
|
|
@@ -150,25 +150,32 @@ const AdminHeader = ({ title, menuToggleEnabled, toggleMenu, className, actions
|
|
|
150
150
|
className: "nb-admin-header-toolbar",
|
|
151
151
|
role: "toolbar",
|
|
152
152
|
"aria-label": strings.mainToolbar,
|
|
153
|
-
children: [
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
153
|
+
children: [
|
|
154
|
+
/* @__PURE__ */ jsxs("div", {
|
|
155
|
+
className: "nb-admin-header-toolbar__before",
|
|
156
|
+
children: [menuToggleEnabled && /* @__PURE__ */ jsx(IconButton, {
|
|
157
|
+
className: "nb-admin-menu-button",
|
|
158
|
+
icon: "ph ph-list",
|
|
159
|
+
label: strings.toggleMenu,
|
|
160
|
+
onClick: toggleMenu
|
|
161
|
+
}), title && /* @__PURE__ */ jsx("div", {
|
|
162
|
+
className: "nb-admin-header-title",
|
|
163
|
+
children: title
|
|
164
|
+
})]
|
|
165
|
+
}),
|
|
166
|
+
content && /* @__PURE__ */ jsx("div", {
|
|
167
|
+
className: "nb-admin-header-content",
|
|
168
|
+
children: content
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ jsxs("div", {
|
|
171
|
+
className: "nb-admin-header-toolbar__after",
|
|
172
|
+
children: [
|
|
173
|
+
renderThemeSwitcher?.(),
|
|
174
|
+
actions.map((action) => /* @__PURE__ */ jsx(ActionPopover, { action }, action.id)),
|
|
175
|
+
renderUserMenu && /* @__PURE__ */ jsx(UserMenuPopover, { renderUserMenu })
|
|
176
|
+
]
|
|
177
|
+
})
|
|
178
|
+
]
|
|
172
179
|
})
|
|
173
180
|
});
|
|
174
181
|
};
|
|
@@ -235,7 +242,7 @@ const getIconClassName = (icon) => {
|
|
|
235
242
|
if (!icon) return "";
|
|
236
243
|
return icon.includes(" ") ? icon : `ph ph-${icon}`;
|
|
237
244
|
};
|
|
238
|
-
const AdminSidebarMenu = ({ items, compactMode = false, selectedItemChanged, openMenu, footer }) => {
|
|
245
|
+
const AdminSidebarMenu = ({ items, compactMode = false, selectedItemChanged, openMenu, footer, brand, context }) => {
|
|
239
246
|
const [expandedItemKeys, setExpandedItemKeys] = useState(/* @__PURE__ */ new Set());
|
|
240
247
|
const strings = useUiStrings();
|
|
241
248
|
const { isLarge } = useScreenSize();
|
|
@@ -284,73 +291,84 @@ const AdminSidebarMenu = ({ items, compactMode = false, selectedItemChanged, ope
|
|
|
284
291
|
return /* @__PURE__ */ jsxs("div", {
|
|
285
292
|
className: `nb-admin-menu${compactMode ? " compact" : ""}`,
|
|
286
293
|
onPointerDown: openMenu,
|
|
287
|
-
children: [
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
"aria-hidden": "true"
|
|
324
|
-
})
|
|
325
|
-
]
|
|
326
|
-
}), expanded && (item.items?.length ?? 0) > 0 && /* @__PURE__ */ jsx("div", {
|
|
327
|
-
className: "nb-admin-menu__children",
|
|
328
|
-
children: item.items.map((subItem) => {
|
|
329
|
-
const childSelected = isSelected(subItem.path);
|
|
330
|
-
return /* @__PURE__ */ jsx("button", {
|
|
331
|
-
className: `nb-admin-menu__item nb-admin-menu__item--child${childSelected ? " is-selected" : ""}`,
|
|
332
|
-
type: "button",
|
|
333
|
-
"aria-current": childSelected ? "page" : void 0,
|
|
334
|
-
onClick: (event) => handleSelect(subItem.path, childSelected, event),
|
|
335
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
294
|
+
children: [
|
|
295
|
+
brand && !compactMode && /* @__PURE__ */ jsx("div", {
|
|
296
|
+
className: "nb-admin-menu__brand",
|
|
297
|
+
children: brand
|
|
298
|
+
}),
|
|
299
|
+
/* @__PURE__ */ jsx("div", {
|
|
300
|
+
className: "nb-admin-menu-container theme-dependent",
|
|
301
|
+
children: /* @__PURE__ */ jsx("nav", {
|
|
302
|
+
className: "nb-admin-menu__nav",
|
|
303
|
+
"aria-label": strings.mainNavigation,
|
|
304
|
+
children: items.map((item) => {
|
|
305
|
+
const selected = isSelected(item.path);
|
|
306
|
+
const containsSelected = parentContainsSelected(item);
|
|
307
|
+
const itemKey = item.path || item.text;
|
|
308
|
+
const hasChildren = (item.items?.length ?? 0) > 0;
|
|
309
|
+
const expanded = !compactMode && hasChildren && expandedItemKeys.has(itemKey);
|
|
310
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
311
|
+
className: `nb-admin-menu__section${containsSelected ? " has-selected-child" : ""}`,
|
|
312
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
313
|
+
className: `nb-admin-menu__item nb-admin-menu__item--parent${selected ? " is-selected" : ""}`,
|
|
314
|
+
type: "button",
|
|
315
|
+
"aria-current": selected ? "page" : void 0,
|
|
316
|
+
"aria-expanded": hasChildren ? expanded : void 0,
|
|
317
|
+
onClick: (event) => {
|
|
318
|
+
if (hasChildren) {
|
|
319
|
+
toggleExpanded(itemKey);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
handleSelect(item.path, selected, event);
|
|
323
|
+
},
|
|
324
|
+
children: [
|
|
325
|
+
/* @__PURE__ */ jsx("span", {
|
|
326
|
+
className: `nb-admin-menu__icon ${getIconClassName(item.icon)}`,
|
|
327
|
+
"aria-hidden": "true"
|
|
328
|
+
}),
|
|
329
|
+
/* @__PURE__ */ jsx("span", {
|
|
336
330
|
className: "nb-admin-menu__text",
|
|
337
|
-
children:
|
|
331
|
+
children: item.text
|
|
332
|
+
}),
|
|
333
|
+
hasChildren && /* @__PURE__ */ jsx("span", {
|
|
334
|
+
className: `nb-admin-menu__chevron${expanded ? " is-expanded" : ""}`,
|
|
335
|
+
"aria-hidden": "true"
|
|
338
336
|
})
|
|
339
|
-
|
|
340
|
-
})
|
|
341
|
-
|
|
342
|
-
|
|
337
|
+
]
|
|
338
|
+
}), expanded && (item.items?.length ?? 0) > 0 && /* @__PURE__ */ jsx("div", {
|
|
339
|
+
className: "nb-admin-menu__children",
|
|
340
|
+
children: item.items.map((subItem) => {
|
|
341
|
+
const childSelected = isSelected(subItem.path);
|
|
342
|
+
return /* @__PURE__ */ jsx("button", {
|
|
343
|
+
className: `nb-admin-menu__item nb-admin-menu__item--child${childSelected ? " is-selected" : ""}`,
|
|
344
|
+
type: "button",
|
|
345
|
+
"aria-current": childSelected ? "page" : void 0,
|
|
346
|
+
onClick: (event) => handleSelect(subItem.path, childSelected, event),
|
|
347
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
348
|
+
className: "nb-admin-menu__text",
|
|
349
|
+
children: subItem.text
|
|
350
|
+
})
|
|
351
|
+
}, subItem.path || subItem.text);
|
|
352
|
+
})
|
|
353
|
+
})]
|
|
354
|
+
}, itemKey);
|
|
355
|
+
})
|
|
343
356
|
})
|
|
357
|
+
}),
|
|
358
|
+
context && !compactMode && /* @__PURE__ */ jsx("div", {
|
|
359
|
+
className: "nb-admin-menu__context",
|
|
360
|
+
children: context
|
|
361
|
+
}),
|
|
362
|
+
footer && /* @__PURE__ */ jsx("footer", {
|
|
363
|
+
className: "nb-admin-footer",
|
|
364
|
+
children: footer
|
|
344
365
|
})
|
|
345
|
-
|
|
346
|
-
className: "nb-admin-footer",
|
|
347
|
-
children: footer
|
|
348
|
-
})]
|
|
366
|
+
]
|
|
349
367
|
});
|
|
350
368
|
};
|
|
351
369
|
//#endregion
|
|
352
370
|
//#region packages/admin/AdminShell.tsx
|
|
353
|
-
const AdminShell = ({ title, menuItems, headerActions, renderUserMenu, renderThemeSwitcher, footer, children }) => {
|
|
371
|
+
const AdminShell = ({ title, menuItems, headerActions, renderUserMenu, renderThemeSwitcher, footer, variant = "default", brand, headerContent, sidebarContext, bottomNavigation, children }) => {
|
|
354
372
|
const navigate = useNavigate();
|
|
355
373
|
const strings = useUiStrings();
|
|
356
374
|
const { isXSmall, isLarge } = useScreenSize();
|
|
@@ -406,45 +424,92 @@ const AdminShell = ({ title, menuItems, headerActions, renderUserMenu, renderThe
|
|
|
406
424
|
isXSmall ? "is-xsmall" : ""
|
|
407
425
|
].filter(Boolean).join(" ");
|
|
408
426
|
return /* @__PURE__ */ jsxs("div", {
|
|
409
|
-
className:
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
427
|
+
className: [
|
|
428
|
+
"nb-admin-shell",
|
|
429
|
+
variant === "workspace" && "nb-admin-shell--workspace",
|
|
430
|
+
variant === "workspace" && isLarge && "is-workspace-desktop",
|
|
431
|
+
variant === "workspace" && isLarge && isCompact && "is-workspace-compact"
|
|
432
|
+
].filter(Boolean).join(" "),
|
|
433
|
+
children: [
|
|
434
|
+
/* @__PURE__ */ jsx(AdminHeader, {
|
|
435
|
+
className: "nb-admin-layout-header",
|
|
436
|
+
menuToggleEnabled: true,
|
|
437
|
+
toggleMenu,
|
|
438
|
+
title,
|
|
439
|
+
actions: headerActions,
|
|
440
|
+
content: headerContent,
|
|
441
|
+
renderUserMenu,
|
|
442
|
+
renderThemeSwitcher
|
|
443
|
+
}),
|
|
444
|
+
/* @__PURE__ */ jsxs("div", {
|
|
445
|
+
className: bodyClassName,
|
|
446
|
+
children: [
|
|
447
|
+
/* @__PURE__ */ jsx("aside", {
|
|
448
|
+
className: "nb-admin-shell__panel",
|
|
449
|
+
"aria-label": strings.mainMenu,
|
|
450
|
+
children: /* @__PURE__ */ jsx(AdminSidebarMenu, {
|
|
451
|
+
items: menuItems,
|
|
452
|
+
compactMode: isCompact,
|
|
453
|
+
selectedItemChanged: onNavigationChanged,
|
|
454
|
+
openMenu: temporaryOpenMenu,
|
|
455
|
+
footer,
|
|
456
|
+
brand,
|
|
457
|
+
context: sidebarContext
|
|
458
|
+
})
|
|
459
|
+
}),
|
|
460
|
+
!isLarge && isMenuOpen && /* @__PURE__ */ jsx("button", {
|
|
461
|
+
className: "nb-admin-shell__scrim",
|
|
462
|
+
type: "button",
|
|
463
|
+
"aria-label": strings.closeMenu,
|
|
464
|
+
onClick: closeMenuFromOverlay
|
|
465
|
+
}),
|
|
466
|
+
/* @__PURE__ */ jsx("main", {
|
|
467
|
+
className: "nb-admin-shell__content content",
|
|
468
|
+
tabIndex: 0,
|
|
469
|
+
"aria-label": title ? `${title} content` : strings.mainContent,
|
|
470
|
+
children
|
|
430
471
|
})
|
|
472
|
+
]
|
|
473
|
+
}),
|
|
474
|
+
isXSmall && bottomNavigation && /* @__PURE__ */ jsx("div", {
|
|
475
|
+
className: "nb-admin-shell__bottom-navigation",
|
|
476
|
+
children: bottomNavigation
|
|
477
|
+
})
|
|
478
|
+
]
|
|
479
|
+
});
|
|
480
|
+
};
|
|
481
|
+
//#endregion
|
|
482
|
+
//#region packages/admin/AdminBottomNavigation.tsx
|
|
483
|
+
function AdminBottomNavigation({ items, label }) {
|
|
484
|
+
const { pathname } = useLocation();
|
|
485
|
+
const strings = useUiStrings();
|
|
486
|
+
const normalize = (path) => path.replace(/\/+$/, "") || "/";
|
|
487
|
+
const currentPath = normalize(pathname);
|
|
488
|
+
const activePath = items.map((item) => normalize(item.path)).filter((path) => currentPath === path || path !== "/" && currentPath.startsWith(`${path}/`)).sort((a, b) => b.length - a.length)[0];
|
|
489
|
+
return /* @__PURE__ */ jsx("nav", {
|
|
490
|
+
className: "nb-admin-bottom-nav",
|
|
491
|
+
"aria-label": label ?? strings.mainNavigation,
|
|
492
|
+
children: items.map((item) => /* @__PURE__ */ jsxs(Link, {
|
|
493
|
+
to: item.path,
|
|
494
|
+
className: "nb-admin-bottom-nav__item",
|
|
495
|
+
"aria-current": normalize(item.path) === activePath ? "page" : void 0,
|
|
496
|
+
children: [
|
|
497
|
+
item.icon && /* @__PURE__ */ jsx("span", {
|
|
498
|
+
className: `nb-admin-bottom-nav__icon ${item.icon.includes(" ") ? item.icon : `ph ph-${item.icon}`}`,
|
|
499
|
+
"aria-hidden": "true"
|
|
431
500
|
}),
|
|
432
|
-
|
|
433
|
-
className: "nb-admin-
|
|
434
|
-
|
|
435
|
-
"aria-label": strings.closeMenu,
|
|
436
|
-
onClick: closeMenuFromOverlay
|
|
501
|
+
/* @__PURE__ */ jsx("span", {
|
|
502
|
+
className: "nb-admin-bottom-nav__label",
|
|
503
|
+
children: item.text
|
|
437
504
|
}),
|
|
438
|
-
/* @__PURE__ */ jsx("
|
|
439
|
-
className: "nb-admin-
|
|
440
|
-
|
|
441
|
-
"aria-label": title ? `${title} content` : strings.mainContent,
|
|
442
|
-
children
|
|
505
|
+
item.badge != null && /* @__PURE__ */ jsx("span", {
|
|
506
|
+
className: "nb-admin-bottom-nav__badge",
|
|
507
|
+
children: item.badge
|
|
443
508
|
})
|
|
444
509
|
]
|
|
445
|
-
})
|
|
510
|
+
}, item.path))
|
|
446
511
|
});
|
|
447
|
-
}
|
|
512
|
+
}
|
|
448
513
|
//#endregion
|
|
449
514
|
//#region packages/admin/auth/csrfFetch.ts
|
|
450
515
|
const MUTATING_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -2122,8 +2187,7 @@ function NubitAuthenticatedApp({ config }) {
|
|
|
2122
2187
|
const shell = /* @__PURE__ */ jsx(AdminShell, {
|
|
2123
2188
|
title: config.title,
|
|
2124
2189
|
menuItems,
|
|
2125
|
-
|
|
2126
|
-
footer: config.shell?.footer,
|
|
2190
|
+
...config.shell,
|
|
2127
2191
|
renderThemeSwitcher,
|
|
2128
2192
|
renderUserMenu: ({ close }) => renderUserMenu({
|
|
2129
2193
|
...menuContext,
|
|
@@ -2222,6 +2286,7 @@ function createNubitApp(config) {
|
|
|
2222
2286
|
client: queryClient,
|
|
2223
2287
|
children: /* @__PURE__ */ jsx(ThemeProvider, {
|
|
2224
2288
|
basePath: config.themeBasePath,
|
|
2289
|
+
visualStyle: config.visualStyle,
|
|
2225
2290
|
children: /* @__PURE__ */ jsx(SessionProvider, {
|
|
2226
2291
|
apiBaseUrl,
|
|
2227
2292
|
children: /* @__PURE__ */ jsx(NubitAuthenticatedApp, { config })
|
|
@@ -2232,4 +2297,4 @@ function createNubitApp(config) {
|
|
|
2232
2297
|
return { App };
|
|
2233
2298
|
}
|
|
2234
2299
|
//#endregion
|
|
2235
|
-
export { AcceptInvitationPage, AccountPage, AdminHeader, AdminShell, AdminSidebarMenu, FeatureGate, FeatureHubLayout, ForgotPasswordPage, LoginPage, NotificationPanel, NubitDevToolsPanel, PlanPanel, QuotaUsageBanner, RegisterPage, ResetPasswordPage, SessionProvider, StaticSessionProvider, ToastHost, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useNotifications, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
|
2300
|
+
export { AcceptInvitationPage, AccountPage, AdminBottomNavigation, AdminHeader, AdminShell, AdminSidebarMenu, FeatureGate, FeatureHubLayout, ForgotPasswordPage, LoginPage, NotificationPanel, NubitDevToolsPanel, PlanPanel, QuotaUsageBanner, RegisterPage, ResetPasswordPage, SessionProvider, StaticSessionProvider, ToastHost, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useNotifications, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
package/dist/style.css
CHANGED
|
@@ -314,6 +314,169 @@ html[data-density=comfortable] {
|
|
|
314
314
|
.nb-feature-hub--compact .nb-feature-hub__content {
|
|
315
315
|
padding-top: var(--space-3);
|
|
316
316
|
}
|
|
317
|
+
.nb-admin-header-content {
|
|
318
|
+
flex: 0 1 320px;
|
|
319
|
+
min-width: 0;
|
|
320
|
+
}
|
|
321
|
+
.nb-admin-header-content > * {
|
|
322
|
+
max-width: 100%;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.nb-admin-menu__brand {
|
|
326
|
+
align-items: center;
|
|
327
|
+
display: flex;
|
|
328
|
+
flex: 0 0 auto;
|
|
329
|
+
min-height: var(--admin-header-height, 64px);
|
|
330
|
+
padding: var(--space-3) var(--space-6);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.nb-admin-menu__context {
|
|
334
|
+
flex: 0 0 auto;
|
|
335
|
+
padding: var(--space-3);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.nb-admin-shell--workspace .nb-admin-menu-container {
|
|
339
|
+
padding-bottom: 0;
|
|
340
|
+
}
|
|
341
|
+
.nb-admin-shell--workspace .nb-admin-footer {
|
|
342
|
+
flex: 0 0 auto;
|
|
343
|
+
position: static;
|
|
344
|
+
}
|
|
345
|
+
.nb-admin-shell--workspace .nb-admin-shell__content {
|
|
346
|
+
min-width: 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.nb-admin-shell.is-workspace-desktop {
|
|
350
|
+
display: grid;
|
|
351
|
+
grid-template-columns: var(--admin-sidebar-width, 248px) minmax(0, 1fr);
|
|
352
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
353
|
+
}
|
|
354
|
+
.nb-admin-shell.is-workspace-desktop > .nb-admin-layout-header {
|
|
355
|
+
grid-column: 2;
|
|
356
|
+
grid-row: 1;
|
|
357
|
+
}
|
|
358
|
+
.nb-admin-shell.is-workspace-desktop > .nb-admin-shell__body {
|
|
359
|
+
display: contents;
|
|
360
|
+
}
|
|
361
|
+
.nb-admin-shell.is-workspace-desktop > .nb-admin-shell__body > .nb-admin-shell__panel {
|
|
362
|
+
grid-column: 1;
|
|
363
|
+
grid-row: 1/-1;
|
|
364
|
+
height: auto;
|
|
365
|
+
width: 100%;
|
|
366
|
+
}
|
|
367
|
+
.nb-admin-shell.is-workspace-desktop > .nb-admin-shell__body > .nb-admin-shell__content {
|
|
368
|
+
grid-column: 2;
|
|
369
|
+
grid-row: 2;
|
|
370
|
+
}
|
|
371
|
+
.nb-admin-shell.is-workspace-desktop.is-workspace-compact {
|
|
372
|
+
grid-template-columns: var(--side-panel-min-width) minmax(0, 1fr);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.nb-admin-shell__bottom-navigation {
|
|
376
|
+
background: var(--surface-1);
|
|
377
|
+
flex: 0 0 auto;
|
|
378
|
+
padding-bottom: env(safe-area-inset-bottom, 0px);
|
|
379
|
+
z-index: var(--z-shell-panel);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.nb-admin-bottom-nav {
|
|
383
|
+
background: var(--surface-1);
|
|
384
|
+
border-top: 1px solid var(--border-color);
|
|
385
|
+
display: flex;
|
|
386
|
+
padding: var(--space-2);
|
|
387
|
+
}
|
|
388
|
+
.nb-admin-bottom-nav__item {
|
|
389
|
+
align-items: center;
|
|
390
|
+
border-radius: var(--radius-sm);
|
|
391
|
+
color: var(--text-secondary);
|
|
392
|
+
display: flex;
|
|
393
|
+
flex: 1 1 0;
|
|
394
|
+
flex-direction: column;
|
|
395
|
+
gap: var(--space-1);
|
|
396
|
+
justify-content: center;
|
|
397
|
+
min-height: 64px;
|
|
398
|
+
min-width: 0;
|
|
399
|
+
padding: var(--space-2) var(--space-1);
|
|
400
|
+
position: relative;
|
|
401
|
+
text-align: center;
|
|
402
|
+
text-decoration: none;
|
|
403
|
+
}
|
|
404
|
+
.nb-admin-bottom-nav__item[aria-current=page] {
|
|
405
|
+
background: var(--accent-subtle);
|
|
406
|
+
color: var(--accent-on-subtle);
|
|
407
|
+
}
|
|
408
|
+
.nb-admin-bottom-nav__item:hover {
|
|
409
|
+
background: var(--surface-2);
|
|
410
|
+
}
|
|
411
|
+
.nb-admin-bottom-nav__item:focus-visible {
|
|
412
|
+
outline: 2px solid var(--focus-ring-color);
|
|
413
|
+
outline-offset: -2px;
|
|
414
|
+
}
|
|
415
|
+
.nb-admin-bottom-nav__icon {
|
|
416
|
+
font-size: 24px;
|
|
417
|
+
}
|
|
418
|
+
.nb-admin-bottom-nav__label {
|
|
419
|
+
font-size: var(--font-size-xs);
|
|
420
|
+
overflow-wrap: anywhere;
|
|
421
|
+
}
|
|
422
|
+
.nb-admin-bottom-nav__badge {
|
|
423
|
+
background: var(--accent-color);
|
|
424
|
+
border-radius: var(--radius-pill);
|
|
425
|
+
color: var(--on-accent-color);
|
|
426
|
+
font-size: var(--font-size-xxs);
|
|
427
|
+
padding: 0 var(--space-1);
|
|
428
|
+
position: absolute;
|
|
429
|
+
right: var(--space-1);
|
|
430
|
+
top: 0;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
html[data-visual-style=nubit] .nb-admin-header-toolbar {
|
|
434
|
+
gap: var(--space-4);
|
|
435
|
+
min-height: calc(var(--admin-header-height) - 1px);
|
|
436
|
+
padding-right: var(--space-7);
|
|
437
|
+
}
|
|
438
|
+
html[data-visual-style=nubit] .nb-admin-header-title {
|
|
439
|
+
font-size: var(--font-size-xl);
|
|
440
|
+
font-weight: var(--font-weight-semibold);
|
|
441
|
+
}
|
|
442
|
+
html[data-visual-style=nubit] .nb-admin-menu__nav {
|
|
443
|
+
gap: var(--space-1);
|
|
444
|
+
padding: var(--space-3);
|
|
445
|
+
}
|
|
446
|
+
html[data-visual-style=nubit] .nb-admin-menu__section {
|
|
447
|
+
border: 0;
|
|
448
|
+
}
|
|
449
|
+
html[data-visual-style=nubit] .nb-admin-menu__item {
|
|
450
|
+
border-left: 0;
|
|
451
|
+
border-radius: var(--radius-sm);
|
|
452
|
+
min-height: 40px;
|
|
453
|
+
}
|
|
454
|
+
html[data-visual-style=nubit] .nb-admin-menu__item.is-selected {
|
|
455
|
+
background: var(--accent-subtle);
|
|
456
|
+
color: var(--accent-on-subtle);
|
|
457
|
+
}
|
|
458
|
+
html[data-visual-style=nubit] .nb-admin-menu__item--parent {
|
|
459
|
+
color: var(--text-secondary);
|
|
460
|
+
}
|
|
461
|
+
html[data-visual-style=nubit] .nb-admin-menu.compact .nb-admin-menu__nav {
|
|
462
|
+
padding-inline: 0;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
@media (max-width: 575.98px) {
|
|
466
|
+
.nb-admin-header-toolbar:has(.nb-admin-header-content) .nb-admin-header-title {
|
|
467
|
+
display: none;
|
|
468
|
+
}
|
|
469
|
+
.nb-admin-header-toolbar:has(.nb-admin-header-content) .nb-admin-header-toolbar__before {
|
|
470
|
+
flex: 0 0 auto;
|
|
471
|
+
}
|
|
472
|
+
.nb-admin-header-content {
|
|
473
|
+
flex: 1 1 0;
|
|
474
|
+
}
|
|
475
|
+
html[data-visual-style=nubit] .nb-admin-header-toolbar {
|
|
476
|
+
gap: var(--space-1);
|
|
477
|
+
padding-right: var(--space-2);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
317
480
|
.nb-admin-shell {
|
|
318
481
|
display: flex;
|
|
319
482
|
flex-direction: column;
|
|
@@ -340,12 +503,12 @@ html[data-density=comfortable] {
|
|
|
340
503
|
.nb-admin-shell__panel {
|
|
341
504
|
background-color: var(--side-panel-background);
|
|
342
505
|
border-right: 1px solid var(--border-color);
|
|
343
|
-
flex: 0 0 240px;
|
|
506
|
+
flex: 0 0 var(--admin-sidebar-width, 240px);
|
|
344
507
|
height: 100%;
|
|
345
508
|
overflow: hidden;
|
|
346
509
|
position: relative;
|
|
347
510
|
transition: flex-basis var(--transition-slow), transform var(--transition-slow), width var(--transition-slow);
|
|
348
|
-
width: 240px;
|
|
511
|
+
width: var(--admin-sidebar-width, 240px);
|
|
349
512
|
z-index: var(--z-shell-panel);
|
|
350
513
|
}
|
|
351
514
|
|
|
@@ -399,7 +562,7 @@ html[data-density=comfortable] {
|
|
|
399
562
|
align-items: center;
|
|
400
563
|
display: flex;
|
|
401
564
|
gap: var(--space-2);
|
|
402
|
-
min-height: var(--toolbar-height);
|
|
565
|
+
min-height: var(--admin-header-height, var(--toolbar-height));
|
|
403
566
|
padding: 0 var(--space-4) 0 0;
|
|
404
567
|
}
|
|
405
568
|
|
|
@@ -480,7 +643,7 @@ html[data-density=comfortable] {
|
|
|
480
643
|
flex-direction: column;
|
|
481
644
|
height: 100%;
|
|
482
645
|
min-height: 100%;
|
|
483
|
-
width: 240px !important;
|
|
646
|
+
width: var(--admin-sidebar-width, 240px) !important;
|
|
484
647
|
}
|
|
485
648
|
.nb-admin-menu .nb-admin-menu-container {
|
|
486
649
|
background-color: var(--side-panel-background);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nubitio/admin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Admin shell layout components: responsive sidebar, header, and screen size utilities for Nubit apps.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"react": "^18.2.0 || ^19.0.0",
|
|
54
54
|
"react-dom": "^18.2.0 || ^19.0.0",
|
|
55
55
|
"react-router-dom": "^6.0.0 || ^7.0.0",
|
|
56
|
-
"@nubitio/core": "^1.
|
|
57
|
-
"@nubitio/
|
|
58
|
-
"@nubitio/
|
|
59
|
-
"@nubitio/ui": "^1.
|
|
56
|
+
"@nubitio/core": "^1.2.0",
|
|
57
|
+
"@nubitio/hydra": "^1.2.0",
|
|
58
|
+
"@nubitio/crud": "^1.2.0",
|
|
59
|
+
"@nubitio/ui": "^1.2.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"react-router-dom": "^6.30.6"
|