@nubitio/admin 0.5.29 → 0.5.30
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/index.cjs +78 -2
- package/dist/index.d.cts +43 -1
- package/dist/index.d.mts +43 -1
- package/dist/index.mjs +78 -3
- package/dist/style.css +287 -0
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -21,15 +21,90 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
+
let react_router_dom = require("react-router-dom");
|
|
25
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
24
26
|
let react = require("react");
|
|
25
27
|
react = __toESM(react, 1);
|
|
26
|
-
let react_router_dom = require("react-router-dom");
|
|
27
28
|
let _nubitio_ui = require("@nubitio/ui");
|
|
28
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
29
29
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
30
30
|
let _nubitio_core = require("@nubitio/core");
|
|
31
31
|
let _nubitio_crud = require("@nubitio/crud");
|
|
32
32
|
let _nubitio_hydra = require("@nubitio/hydra");
|
|
33
|
+
//#region packages/admin/FeatureHubLayout.tsx
|
|
34
|
+
function normalizeIcon(icon) {
|
|
35
|
+
if (!icon) return void 0;
|
|
36
|
+
if (icon.startsWith("ph ")) return icon;
|
|
37
|
+
if (icon.startsWith("ph-")) return `ph ${icon}`;
|
|
38
|
+
return `ph ph-${icon}`;
|
|
39
|
+
}
|
|
40
|
+
function normalizeBasePath(path) {
|
|
41
|
+
return path.endsWith("/") && path.length > 1 ? path.slice(0, -1) : path;
|
|
42
|
+
}
|
|
43
|
+
function FeatureHubLayout({ title, subtitle, tabs, basePath, defaultPath, banner, tabsAriaLabel = "Secciones", density = "default", className = "" }) {
|
|
44
|
+
const location = (0, react_router_dom.useLocation)();
|
|
45
|
+
const normalizedBase = normalizeBasePath(basePath);
|
|
46
|
+
const visibleTabs = tabs.filter((tab) => tab.visible !== false);
|
|
47
|
+
const compact = density === "compact";
|
|
48
|
+
const densityClass = compact ? " nb-feature-hub--compact" : "";
|
|
49
|
+
const showBanner = banner && banner.visible !== false && (!compact || banner.showInCompact === true);
|
|
50
|
+
if (location.pathname === normalizedBase || location.pathname === `${normalizedBase}/`) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Navigate, {
|
|
51
|
+
to: defaultPath,
|
|
52
|
+
replace: true
|
|
53
|
+
});
|
|
54
|
+
const tabsNav = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
|
|
55
|
+
className: "nb-feature-hub__tabs",
|
|
56
|
+
"aria-label": tabsAriaLabel,
|
|
57
|
+
children: visibleTabs.map((tab) => {
|
|
58
|
+
const iconClass = normalizeIcon(tab.icon);
|
|
59
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.NavLink, {
|
|
60
|
+
to: tab.path,
|
|
61
|
+
className: ({ isActive }) => `nb-feature-hub__tab${isActive ? " nb-feature-hub__tab--active" : ""}`,
|
|
62
|
+
children: [iconClass && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
63
|
+
className: iconClass,
|
|
64
|
+
"aria-hidden": "true"
|
|
65
|
+
}), tab.label]
|
|
66
|
+
}, tab.key);
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
70
|
+
className: `nb-feature-hub${densityClass}${className ? ` ${className}` : ""}`,
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
|
|
73
|
+
className: "nb-feature-hub__header",
|
|
74
|
+
children: compact ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
75
|
+
className: "nb-feature-hub__tabs-card",
|
|
76
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
77
|
+
className: "nb-feature-hub__title",
|
|
78
|
+
children: title
|
|
79
|
+
}), tabsNav]
|
|
80
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
81
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
82
|
+
className: "nb-feature-hub__title",
|
|
83
|
+
children: title
|
|
84
|
+
}),
|
|
85
|
+
subtitle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
86
|
+
className: "nb-feature-hub__subtitle",
|
|
87
|
+
children: subtitle
|
|
88
|
+
}),
|
|
89
|
+
tabsNav
|
|
90
|
+
] })
|
|
91
|
+
}),
|
|
92
|
+
showBanner && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
93
|
+
className: `nb-feature-hub__banner nb-feature-hub__banner--${banner.tone ?? "info"}`,
|
|
94
|
+
role: "status",
|
|
95
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
96
|
+
className: normalizeIcon(banner.icon ?? "ph-info") ?? "ph ph-info",
|
|
97
|
+
"aria-hidden": "true"
|
|
98
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: banner.message })]
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
101
|
+
className: "nb-feature-hub__content",
|
|
102
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Outlet, {})
|
|
103
|
+
})
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
33
108
|
//#region packages/admin/AdminHeader.tsx
|
|
34
109
|
function ActionPopover({ action }) {
|
|
35
110
|
const { open, toggle, setOpen, containerRef } = (0, _nubitio_ui.useFloatingPanel)();
|
|
@@ -1144,6 +1219,7 @@ exports.AdminHeader = AdminHeader;
|
|
|
1144
1219
|
exports.AdminShell = AdminShell;
|
|
1145
1220
|
exports.AdminSidebarMenu = AdminSidebarMenu;
|
|
1146
1221
|
exports.FeatureGate = FeatureGate;
|
|
1222
|
+
exports.FeatureHubLayout = FeatureHubLayout;
|
|
1147
1223
|
exports.LoginPage = LoginPage;
|
|
1148
1224
|
exports.PlanPanel = PlanPanel;
|
|
1149
1225
|
exports.QuotaUsageBanner = QuotaUsageBanner;
|
package/dist/index.d.cts
CHANGED
|
@@ -3,6 +3,48 @@ import { FeatureGateProps as FeatureGateProps$1 } from "@nubitio/ui";
|
|
|
3
3
|
import { CoreRuntime } from "@nubitio/core";
|
|
4
4
|
import { QueryClient } from "@tanstack/react-query";
|
|
5
5
|
|
|
6
|
+
//#region packages/admin/FeatureHubLayout.d.ts
|
|
7
|
+
interface FeatureHubTab {
|
|
8
|
+
key: string;
|
|
9
|
+
label: string;
|
|
10
|
+
path: string;
|
|
11
|
+
icon?: string;
|
|
12
|
+
visible?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface FeatureHubBanner {
|
|
15
|
+
message: ReactNode;
|
|
16
|
+
tone?: 'info' | 'warning';
|
|
17
|
+
icon?: string;
|
|
18
|
+
visible?: boolean;
|
|
19
|
+
/** When false, compact density hides the banner to preserve grid space. Default: false */
|
|
20
|
+
showInCompact?: boolean;
|
|
21
|
+
}
|
|
22
|
+
type FeatureHubDensity = 'default' | 'compact';
|
|
23
|
+
interface FeatureHubLayoutProps {
|
|
24
|
+
title: string;
|
|
25
|
+
subtitle?: ReactNode;
|
|
26
|
+
tabs: FeatureHubTab[];
|
|
27
|
+
/** Redirect here when pathname equals basePath exactly. */
|
|
28
|
+
basePath: string;
|
|
29
|
+
defaultPath: string;
|
|
30
|
+
banner?: FeatureHubBanner;
|
|
31
|
+
tabsAriaLabel?: string;
|
|
32
|
+
/** Compact merges title + tabs on one row and hides the subtitle. */
|
|
33
|
+
density?: FeatureHubDensity;
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
declare function FeatureHubLayout({
|
|
37
|
+
title,
|
|
38
|
+
subtitle,
|
|
39
|
+
tabs,
|
|
40
|
+
basePath,
|
|
41
|
+
defaultPath,
|
|
42
|
+
banner,
|
|
43
|
+
tabsAriaLabel,
|
|
44
|
+
density,
|
|
45
|
+
className
|
|
46
|
+
}: FeatureHubLayoutProps): import("react").JSX.Element;
|
|
47
|
+
//#endregion
|
|
6
48
|
//#region packages/admin/AdminHeader.d.ts
|
|
7
49
|
interface AdminHeaderAction {
|
|
8
50
|
id: string;
|
|
@@ -444,4 +486,4 @@ declare function hasAnyRole(required: string | string[] | undefined, roles: stri
|
|
|
444
486
|
*/
|
|
445
487
|
declare function filterMenuByRoles(items: NubitAppMenuItem[], roles: string[]): AdminMenuItem[];
|
|
446
488
|
//#endregion
|
|
447
|
-
export { AdminHeader, type AdminHeaderAction, type AdminHeaderProps, type AdminMenuItem, type AdminMenuSubItem, AdminShell, type AdminShellProps, AdminSidebarMenu, type AdminSidebarMenuProps, type AdminSidebarMenuSelectEvent, type AppProfile, type CreateNubitAppConfig, FeatureGate, type FeatureGateProps, LoginPage, type LoginPageProps, type NotificationType, type NubitApp, type NubitAppMenuContext, type NubitAppMenuItem, type NubitAppMenuSubItem, type NubitAppRoute, type NubitAppUserMenuContext, type ParsedQuotaError, type PlanDefinition, PlanPanel, type PlanPanelLabels, type PlanPanelProps, QuotaUsageBanner, type QuotaUsageBannerProps, type RegisterField, type RegisterFieldType, RegisterPage, type RegisterPageProps, type RegisterSelectOption, type RuntimeConfig, type RuntimeConfigState, type SessionContextValue, type SessionFeatureEntitlement, type SessionProfile, SessionProvider, type SessionProviderConfig, type SessionState, type SessionTenant, StaticSessionProvider, ToastHost, type ToastHostProps, type ToastItem, type UseQuotaUsageOptions, type UseRuntimeConfigOptions, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
|
489
|
+
export { 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, LoginPage, type LoginPageProps, type NotificationType, type NubitApp, type NubitAppMenuContext, type NubitAppMenuItem, type NubitAppMenuSubItem, type NubitAppRoute, type NubitAppUserMenuContext, type ParsedQuotaError, type PlanDefinition, PlanPanel, type PlanPanelLabels, type PlanPanelProps, QuotaUsageBanner, type QuotaUsageBannerProps, type RegisterField, type RegisterFieldType, RegisterPage, type RegisterPageProps, type RegisterSelectOption, type RuntimeConfig, type RuntimeConfigState, type SessionContextValue, type SessionFeatureEntitlement, type SessionProfile, SessionProvider, type SessionProviderConfig, type SessionState, type SessionTenant, StaticSessionProvider, ToastHost, type ToastHostProps, type ToastItem, type UseQuotaUsageOptions, type UseRuntimeConfigOptions, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,48 @@ import { FeatureGateProps as FeatureGateProps$1 } from "@nubitio/ui";
|
|
|
3
3
|
import { QueryClient } from "@tanstack/react-query";
|
|
4
4
|
import { CoreRuntime } from "@nubitio/core";
|
|
5
5
|
|
|
6
|
+
//#region packages/admin/FeatureHubLayout.d.ts
|
|
7
|
+
interface FeatureHubTab {
|
|
8
|
+
key: string;
|
|
9
|
+
label: string;
|
|
10
|
+
path: string;
|
|
11
|
+
icon?: string;
|
|
12
|
+
visible?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface FeatureHubBanner {
|
|
15
|
+
message: ReactNode;
|
|
16
|
+
tone?: 'info' | 'warning';
|
|
17
|
+
icon?: string;
|
|
18
|
+
visible?: boolean;
|
|
19
|
+
/** When false, compact density hides the banner to preserve grid space. Default: false */
|
|
20
|
+
showInCompact?: boolean;
|
|
21
|
+
}
|
|
22
|
+
type FeatureHubDensity = 'default' | 'compact';
|
|
23
|
+
interface FeatureHubLayoutProps {
|
|
24
|
+
title: string;
|
|
25
|
+
subtitle?: ReactNode;
|
|
26
|
+
tabs: FeatureHubTab[];
|
|
27
|
+
/** Redirect here when pathname equals basePath exactly. */
|
|
28
|
+
basePath: string;
|
|
29
|
+
defaultPath: string;
|
|
30
|
+
banner?: FeatureHubBanner;
|
|
31
|
+
tabsAriaLabel?: string;
|
|
32
|
+
/** Compact merges title + tabs on one row and hides the subtitle. */
|
|
33
|
+
density?: FeatureHubDensity;
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
declare function FeatureHubLayout({
|
|
37
|
+
title,
|
|
38
|
+
subtitle,
|
|
39
|
+
tabs,
|
|
40
|
+
basePath,
|
|
41
|
+
defaultPath,
|
|
42
|
+
banner,
|
|
43
|
+
tabsAriaLabel,
|
|
44
|
+
density,
|
|
45
|
+
className
|
|
46
|
+
}: FeatureHubLayoutProps): import("react").JSX.Element;
|
|
47
|
+
//#endregion
|
|
6
48
|
//#region packages/admin/AdminHeader.d.ts
|
|
7
49
|
interface AdminHeaderAction {
|
|
8
50
|
id: string;
|
|
@@ -444,4 +486,4 @@ declare function hasAnyRole(required: string | string[] | undefined, roles: stri
|
|
|
444
486
|
*/
|
|
445
487
|
declare function filterMenuByRoles(items: NubitAppMenuItem[], roles: string[]): AdminMenuItem[];
|
|
446
488
|
//#endregion
|
|
447
|
-
export { AdminHeader, type AdminHeaderAction, type AdminHeaderProps, type AdminMenuItem, type AdminMenuSubItem, AdminShell, type AdminShellProps, AdminSidebarMenu, type AdminSidebarMenuProps, type AdminSidebarMenuSelectEvent, type AppProfile, type CreateNubitAppConfig, FeatureGate, type FeatureGateProps, LoginPage, type LoginPageProps, type NotificationType, type NubitApp, type NubitAppMenuContext, type NubitAppMenuItem, type NubitAppMenuSubItem, type NubitAppRoute, type NubitAppUserMenuContext, type ParsedQuotaError, type PlanDefinition, PlanPanel, type PlanPanelLabels, type PlanPanelProps, QuotaUsageBanner, type QuotaUsageBannerProps, type RegisterField, type RegisterFieldType, RegisterPage, type RegisterPageProps, type RegisterSelectOption, type RuntimeConfig, type RuntimeConfigState, type SessionContextValue, type SessionFeatureEntitlement, type SessionProfile, SessionProvider, type SessionProviderConfig, type SessionState, type SessionTenant, StaticSessionProvider, ToastHost, type ToastHostProps, type ToastItem, type UseQuotaUsageOptions, type UseRuntimeConfigOptions, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
|
489
|
+
export { 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, LoginPage, type LoginPageProps, type NotificationType, type NubitApp, type NubitAppMenuContext, type NubitAppMenuItem, type NubitAppMenuSubItem, type NubitAppRoute, type NubitAppUserMenuContext, type ParsedQuotaError, type PlanDefinition, PlanPanel, type PlanPanelLabels, type PlanPanelProps, QuotaUsageBanner, type QuotaUsageBannerProps, type RegisterField, type RegisterFieldType, RegisterPage, type RegisterPageProps, type RegisterSelectOption, type RuntimeConfig, type RuntimeConfigState, type SessionContextValue, type SessionFeatureEntitlement, type SessionProfile, SessionProvider, type SessionProviderConfig, type SessionState, type SessionTenant, StaticSessionProvider, ToastHost, type ToastHostProps, type ToastItem, type UseQuotaUsageOptions, type UseRuntimeConfigOptions, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,86 @@
|
|
|
1
|
+
import { BrowserRouter, Link, NavLink, Navigate, Outlet, Route, Routes, useLocation, useNavigate } from "react-router-dom";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
1
3
|
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
2
|
-
import { BrowserRouter, Link, Navigate, Route, Routes, useLocation, useNavigate } from "react-router-dom";
|
|
3
4
|
import { Badge, Button, Card, FeatureGate as FeatureGate$1, IconButton, TextField, ThemeProvider, ThemeSwitcher, useFloatingPanel } from "@nubitio/ui";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
|
|
6
6
|
import { CoreConfigProvider, CoreProvider, MercureProvider, useCoreHttpClient } from "@nubitio/core";
|
|
7
7
|
import { SmartCrudRolesProvider } from "@nubitio/crud";
|
|
8
8
|
import { HydraResourceSchemaProvider, HydraResourceStoreProvider, SchemaProvider } from "@nubitio/hydra";
|
|
9
|
+
//#region packages/admin/FeatureHubLayout.tsx
|
|
10
|
+
function normalizeIcon(icon) {
|
|
11
|
+
if (!icon) return void 0;
|
|
12
|
+
if (icon.startsWith("ph ")) return icon;
|
|
13
|
+
if (icon.startsWith("ph-")) return `ph ${icon}`;
|
|
14
|
+
return `ph ph-${icon}`;
|
|
15
|
+
}
|
|
16
|
+
function normalizeBasePath(path) {
|
|
17
|
+
return path.endsWith("/") && path.length > 1 ? path.slice(0, -1) : path;
|
|
18
|
+
}
|
|
19
|
+
function FeatureHubLayout({ title, subtitle, tabs, basePath, defaultPath, banner, tabsAriaLabel = "Secciones", density = "default", className = "" }) {
|
|
20
|
+
const location = useLocation();
|
|
21
|
+
const normalizedBase = normalizeBasePath(basePath);
|
|
22
|
+
const visibleTabs = tabs.filter((tab) => tab.visible !== false);
|
|
23
|
+
const compact = density === "compact";
|
|
24
|
+
const densityClass = compact ? " nb-feature-hub--compact" : "";
|
|
25
|
+
const showBanner = banner && banner.visible !== false && (!compact || banner.showInCompact === true);
|
|
26
|
+
if (location.pathname === normalizedBase || location.pathname === `${normalizedBase}/`) return /* @__PURE__ */ jsx(Navigate, {
|
|
27
|
+
to: defaultPath,
|
|
28
|
+
replace: true
|
|
29
|
+
});
|
|
30
|
+
const tabsNav = /* @__PURE__ */ jsx("nav", {
|
|
31
|
+
className: "nb-feature-hub__tabs",
|
|
32
|
+
"aria-label": tabsAriaLabel,
|
|
33
|
+
children: visibleTabs.map((tab) => {
|
|
34
|
+
const iconClass = normalizeIcon(tab.icon);
|
|
35
|
+
return /* @__PURE__ */ jsxs(NavLink, {
|
|
36
|
+
to: tab.path,
|
|
37
|
+
className: ({ isActive }) => `nb-feature-hub__tab${isActive ? " nb-feature-hub__tab--active" : ""}`,
|
|
38
|
+
children: [iconClass && /* @__PURE__ */ jsx("i", {
|
|
39
|
+
className: iconClass,
|
|
40
|
+
"aria-hidden": "true"
|
|
41
|
+
}), tab.label]
|
|
42
|
+
}, tab.key);
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
46
|
+
className: `nb-feature-hub${densityClass}${className ? ` ${className}` : ""}`,
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ jsx("header", {
|
|
49
|
+
className: "nb-feature-hub__header",
|
|
50
|
+
children: compact ? /* @__PURE__ */ jsxs("div", {
|
|
51
|
+
className: "nb-feature-hub__tabs-card",
|
|
52
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
53
|
+
className: "nb-feature-hub__title",
|
|
54
|
+
children: title
|
|
55
|
+
}), tabsNav]
|
|
56
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
57
|
+
/* @__PURE__ */ jsx("h2", {
|
|
58
|
+
className: "nb-feature-hub__title",
|
|
59
|
+
children: title
|
|
60
|
+
}),
|
|
61
|
+
subtitle && /* @__PURE__ */ jsx("p", {
|
|
62
|
+
className: "nb-feature-hub__subtitle",
|
|
63
|
+
children: subtitle
|
|
64
|
+
}),
|
|
65
|
+
tabsNav
|
|
66
|
+
] })
|
|
67
|
+
}),
|
|
68
|
+
showBanner && /* @__PURE__ */ jsxs("div", {
|
|
69
|
+
className: `nb-feature-hub__banner nb-feature-hub__banner--${banner.tone ?? "info"}`,
|
|
70
|
+
role: "status",
|
|
71
|
+
children: [/* @__PURE__ */ jsx("i", {
|
|
72
|
+
className: normalizeIcon(banner.icon ?? "ph-info") ?? "ph ph-info",
|
|
73
|
+
"aria-hidden": "true"
|
|
74
|
+
}), /* @__PURE__ */ jsx("span", { children: banner.message })]
|
|
75
|
+
}),
|
|
76
|
+
/* @__PURE__ */ jsx("div", {
|
|
77
|
+
className: "nb-feature-hub__content",
|
|
78
|
+
children: /* @__PURE__ */ jsx(Outlet, {})
|
|
79
|
+
})
|
|
80
|
+
]
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
9
84
|
//#region packages/admin/AdminHeader.tsx
|
|
10
85
|
function ActionPopover({ action }) {
|
|
11
86
|
const { open, toggle, setOpen, containerRef } = useFloatingPanel();
|
|
@@ -1116,4 +1191,4 @@ function createNubitApp(config) {
|
|
|
1116
1191
|
return { App };
|
|
1117
1192
|
}
|
|
1118
1193
|
//#endregion
|
|
1119
|
-
export { AdminHeader, AdminShell, AdminSidebarMenu, FeatureGate, LoginPage, PlanPanel, QuotaUsageBanner, RegisterPage, SessionProvider, StaticSessionProvider, ToastHost, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
|
1194
|
+
export { AdminHeader, AdminShell, AdminSidebarMenu, FeatureGate, FeatureHubLayout, LoginPage, PlanPanel, QuotaUsageBanner, RegisterPage, SessionProvider, StaticSessionProvider, ToastHost, createNubitApp, filterMenuByRoles, hasAnyRole, parseQuotaError, quotaErrorToastMessage, quotaUsageAboveGrid, useAppRuntime, useFeature, useFeatureConfig, useQuotaUsage, useRuntimeConfig, useScreenSize, useScreenSizeClass, useSession };
|
package/dist/style.css
CHANGED
|
@@ -1,3 +1,290 @@
|
|
|
1
|
+
/* stylelint-disable */
|
|
2
|
+
:root {
|
|
3
|
+
--font-family-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
4
|
+
--font-family-mono: 'JetBrains Mono', 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', monospace;
|
|
5
|
+
--font-family-display: 'Syne', var(--font-family-sans);
|
|
6
|
+
--font-size-xxs: 11px;
|
|
7
|
+
--font-size-xs: 12px;
|
|
8
|
+
--font-size-sm: 13px;
|
|
9
|
+
--font-size-md: 14px;
|
|
10
|
+
--font-size-lg: 16px;
|
|
11
|
+
--font-size-xl: 20px;
|
|
12
|
+
--font-size-2xl: 24px;
|
|
13
|
+
--font-size-3xl: 28px;
|
|
14
|
+
--font-size-4xl: 32px;
|
|
15
|
+
--font-size-5xl: 40px;
|
|
16
|
+
--font-weight-regular: 400;
|
|
17
|
+
--font-weight-medium: 500;
|
|
18
|
+
--font-weight-semibold: 600;
|
|
19
|
+
--font-weight-bold: 700;
|
|
20
|
+
--line-height-tight: 1.25;
|
|
21
|
+
--line-height-normal: 1.5;
|
|
22
|
+
--line-height-relaxed: 1.65;
|
|
23
|
+
--space-1: 4px;
|
|
24
|
+
--space-2: 8px;
|
|
25
|
+
--space-3: 12px;
|
|
26
|
+
--space-4: 16px;
|
|
27
|
+
--space-5: 20px;
|
|
28
|
+
--space-6: 24px;
|
|
29
|
+
--space-7: 32px;
|
|
30
|
+
--space-8: 40px;
|
|
31
|
+
--space-9: 48px;
|
|
32
|
+
--space-10: 64px;
|
|
33
|
+
--radius-xs: 3px;
|
|
34
|
+
--radius-sm: 4px;
|
|
35
|
+
--radius-md: 6px;
|
|
36
|
+
--radius-lg: 8px;
|
|
37
|
+
--radius-xl: 14px;
|
|
38
|
+
--toolbar-height: 36px;
|
|
39
|
+
--row-height: 34px;
|
|
40
|
+
--control-height: 28px;
|
|
41
|
+
--control-height-form: 34px;
|
|
42
|
+
--control-icon-size: 20px;
|
|
43
|
+
--footer-height: 48px;
|
|
44
|
+
--side-panel-min-width: 48px;
|
|
45
|
+
--content-padding: 16px;
|
|
46
|
+
--page-padding: 24px;
|
|
47
|
+
--calendar-width: 292px;
|
|
48
|
+
--toolbar-margin-bottom: var(--content-padding);
|
|
49
|
+
--footer-left-padding: calc((var(--side-panel-min-width) - 16px) / 2);
|
|
50
|
+
--grid-header-height: 34px;
|
|
51
|
+
--grid-filter-height: 28px;
|
|
52
|
+
--grid-cell-padding-x: 10px;
|
|
53
|
+
--grid-cell-padding-y: 6px;
|
|
54
|
+
--grid-row-line-height: 1.35;
|
|
55
|
+
--overlay-bg: rgb(0 0 0 / 42%);
|
|
56
|
+
--transition-fast: 100ms ease;
|
|
57
|
+
--transition-base: 150ms ease;
|
|
58
|
+
--transition-slow: 250ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
59
|
+
--z-dropdown: 100;
|
|
60
|
+
--z-sticky: 200;
|
|
61
|
+
--z-overlay: 300;
|
|
62
|
+
--z-modal: 400;
|
|
63
|
+
--z-popover: 500;
|
|
64
|
+
--z-toast: 600;
|
|
65
|
+
--z-shell-panel: 1500;
|
|
66
|
+
--z-shell-scrim: 1499;
|
|
67
|
+
--z-shell-header: 1501;
|
|
68
|
+
--z-shell-popover: 1700;
|
|
69
|
+
--z-shell-dropdown: 1600;
|
|
70
|
+
--z-dialog: 2000;
|
|
71
|
+
--z-picker-panel: 3000;
|
|
72
|
+
--list-padding-left: 8px;
|
|
73
|
+
--list-padding-vertical: 4px;
|
|
74
|
+
--popup-toolbar-item-spacing: 8px;
|
|
75
|
+
--drop-down-gnrc-button-height: 24px;
|
|
76
|
+
--theme-padding: 8px;
|
|
77
|
+
--button-height-theme-difference: calc((var(--theme-padding) - 10px) / 3);
|
|
78
|
+
--button-height: calc(26px + var(--button-height-theme-difference));
|
|
79
|
+
--nb-admin-header-toolbar-vertical-padding: 10px;
|
|
80
|
+
--toolbar-vertical-padding: 16px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
html[data-density=compact] {
|
|
84
|
+
--font-size-xs: 11px;
|
|
85
|
+
--font-size-sm: 12px;
|
|
86
|
+
--font-size-md: 13px;
|
|
87
|
+
--space-1: 2px;
|
|
88
|
+
--space-2: 5px;
|
|
89
|
+
--space-3: 8px;
|
|
90
|
+
--space-4: 12px;
|
|
91
|
+
--space-5: 16px;
|
|
92
|
+
--space-6: 20px;
|
|
93
|
+
--toolbar-height: 30px;
|
|
94
|
+
--row-height: 28px;
|
|
95
|
+
--control-height: 24px;
|
|
96
|
+
--control-height-form: 28px;
|
|
97
|
+
--control-icon-size: 16px;
|
|
98
|
+
--content-padding: 12px;
|
|
99
|
+
--page-padding: 16px;
|
|
100
|
+
--grid-header-height: 28px;
|
|
101
|
+
--grid-filter-height: 24px;
|
|
102
|
+
--grid-cell-padding-x: 8px;
|
|
103
|
+
--grid-cell-padding-y: 4px;
|
|
104
|
+
--grid-row-line-height: 1.3;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
html[data-density=comfortable] {
|
|
108
|
+
--font-size-xs: 13px;
|
|
109
|
+
--font-size-sm: 14px;
|
|
110
|
+
--font-size-md: 15px;
|
|
111
|
+
--space-1: 6px;
|
|
112
|
+
--space-2: 10px;
|
|
113
|
+
--space-3: 16px;
|
|
114
|
+
--space-4: 20px;
|
|
115
|
+
--space-5: 28px;
|
|
116
|
+
--space-6: 36px;
|
|
117
|
+
--toolbar-height: 44px;
|
|
118
|
+
--row-height: 40px;
|
|
119
|
+
--control-height: 34px;
|
|
120
|
+
--control-height-form: 40px;
|
|
121
|
+
--control-icon-size: 22px;
|
|
122
|
+
--content-padding: 20px;
|
|
123
|
+
--page-padding: 28px;
|
|
124
|
+
--grid-header-height: 40px;
|
|
125
|
+
--grid-filter-height: 34px;
|
|
126
|
+
--grid-cell-padding-x: 14px;
|
|
127
|
+
--grid-cell-padding-y: 8px;
|
|
128
|
+
--grid-row-line-height: 1.4;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.nb-feature-hub {
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-direction: column;
|
|
134
|
+
height: 100%;
|
|
135
|
+
min-height: 0;
|
|
136
|
+
background: var(--surface-canvas, var(--surface-0));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.nb-feature-hub__header {
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-direction: column;
|
|
142
|
+
gap: 0.35rem;
|
|
143
|
+
padding: 1.5rem 1.5rem 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.nb-feature-hub__title {
|
|
147
|
+
margin: 0;
|
|
148
|
+
font-size: 1.5rem;
|
|
149
|
+
font-weight: 700;
|
|
150
|
+
letter-spacing: -0.02em;
|
|
151
|
+
color: var(--text-primary);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.nb-feature-hub__subtitle {
|
|
155
|
+
margin: 0;
|
|
156
|
+
font-size: 0.875rem;
|
|
157
|
+
color: var(--text-secondary);
|
|
158
|
+
max-width: 36rem;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.nb-feature-hub__tabs {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-wrap: wrap;
|
|
164
|
+
gap: 0.25rem;
|
|
165
|
+
margin: 1.25rem 1.5rem 0;
|
|
166
|
+
padding: 0.25rem;
|
|
167
|
+
background: var(--surface-1);
|
|
168
|
+
border: 1px solid var(--border-subtle, var(--border-color));
|
|
169
|
+
border-radius: 10px;
|
|
170
|
+
box-shadow: var(--shadow-sm);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.nb-feature-hub__tab {
|
|
174
|
+
display: inline-flex;
|
|
175
|
+
align-items: center;
|
|
176
|
+
gap: 0.45rem;
|
|
177
|
+
padding: 0.55rem 0.9rem;
|
|
178
|
+
font-size: 0.8125rem;
|
|
179
|
+
font-weight: 600;
|
|
180
|
+
color: var(--text-secondary);
|
|
181
|
+
text-decoration: none;
|
|
182
|
+
border: 1px solid transparent;
|
|
183
|
+
border-radius: 7px;
|
|
184
|
+
transition: color 0.15s, background 0.15s, border-color 0.15s;
|
|
185
|
+
}
|
|
186
|
+
.nb-feature-hub__tab .ph {
|
|
187
|
+
font-size: 1rem;
|
|
188
|
+
opacity: 0.75;
|
|
189
|
+
}
|
|
190
|
+
.nb-feature-hub__tab:hover {
|
|
191
|
+
color: var(--text-primary);
|
|
192
|
+
background: var(--surface-2);
|
|
193
|
+
}
|
|
194
|
+
.nb-feature-hub__tab--active {
|
|
195
|
+
color: var(--accent-color);
|
|
196
|
+
background: var(--accent-subtle, color-mix(in srgb, var(--accent-color) 10%, #fff));
|
|
197
|
+
border-color: color-mix(in srgb, var(--accent-color) 22%, transparent);
|
|
198
|
+
box-shadow: var(--shadow-sm);
|
|
199
|
+
}
|
|
200
|
+
.nb-feature-hub__tab--active .ph {
|
|
201
|
+
opacity: 1;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.nb-feature-hub--compact .nb-feature-hub__header {
|
|
205
|
+
padding: 0.65rem 1rem 0;
|
|
206
|
+
}
|
|
207
|
+
.nb-feature-hub--compact .nb-feature-hub__tabs-card {
|
|
208
|
+
align-items: center;
|
|
209
|
+
background: var(--surface-1);
|
|
210
|
+
border: 1px solid var(--border-subtle, var(--border-color));
|
|
211
|
+
border-radius: 10px;
|
|
212
|
+
box-shadow: var(--shadow-sm);
|
|
213
|
+
display: flex;
|
|
214
|
+
flex: 1 1 auto;
|
|
215
|
+
flex-wrap: wrap;
|
|
216
|
+
gap: 0.5rem 1rem;
|
|
217
|
+
justify-content: space-between;
|
|
218
|
+
min-width: 0;
|
|
219
|
+
padding: 0.35rem 0.45rem 0.35rem 0.85rem;
|
|
220
|
+
width: 100%;
|
|
221
|
+
}
|
|
222
|
+
.nb-feature-hub--compact .nb-feature-hub__title {
|
|
223
|
+
font-size: 1.125rem;
|
|
224
|
+
line-height: 1.2;
|
|
225
|
+
margin: 0;
|
|
226
|
+
}
|
|
227
|
+
.nb-feature-hub--compact .nb-feature-hub__tabs {
|
|
228
|
+
flex: 1 1 auto;
|
|
229
|
+
justify-content: flex-end;
|
|
230
|
+
margin: 0;
|
|
231
|
+
padding: 0.15rem;
|
|
232
|
+
border: none;
|
|
233
|
+
border-radius: 8px;
|
|
234
|
+
background: transparent;
|
|
235
|
+
box-shadow: none;
|
|
236
|
+
min-width: min(100%, 520px);
|
|
237
|
+
}
|
|
238
|
+
.nb-feature-hub--compact .nb-feature-hub__tab {
|
|
239
|
+
padding: 0.38rem 0.7rem;
|
|
240
|
+
font-size: 0.75rem;
|
|
241
|
+
}
|
|
242
|
+
.nb-feature-hub--compact .nb-feature-hub__tab .ph {
|
|
243
|
+
font-size: 0.9rem;
|
|
244
|
+
}
|
|
245
|
+
.nb-feature-hub--compact .nb-feature-hub__banner {
|
|
246
|
+
margin: 0.5rem 1rem 0;
|
|
247
|
+
padding: 0.45rem 0.65rem;
|
|
248
|
+
font-size: 0.75rem;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.nb-feature-hub__banner {
|
|
252
|
+
display: flex;
|
|
253
|
+
align-items: flex-start;
|
|
254
|
+
gap: 0.6rem;
|
|
255
|
+
margin: 0.85rem 1.5rem 0;
|
|
256
|
+
padding: 0.7rem 0.9rem;
|
|
257
|
+
font-size: 0.8125rem;
|
|
258
|
+
line-height: 1.45;
|
|
259
|
+
border-radius: 8px;
|
|
260
|
+
}
|
|
261
|
+
.nb-feature-hub__banner .ph {
|
|
262
|
+
flex-shrink: 0;
|
|
263
|
+
margin-top: 0.1rem;
|
|
264
|
+
font-size: 1rem;
|
|
265
|
+
}
|
|
266
|
+
.nb-feature-hub__banner--info {
|
|
267
|
+
color: var(--status-info-text, #0369a1);
|
|
268
|
+
background: var(--status-info-bg, #e0f2fe);
|
|
269
|
+
border: 1px solid var(--status-info-border, #7dd3fc);
|
|
270
|
+
}
|
|
271
|
+
.nb-feature-hub__banner--warning {
|
|
272
|
+
color: var(--status-warning-text, #b45309);
|
|
273
|
+
background: var(--status-warning-bg, #fef3c7);
|
|
274
|
+
border: 1px solid var(--status-warning-border, #fcd34d);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.nb-feature-hub__content {
|
|
278
|
+
flex: 1;
|
|
279
|
+
min-height: 0;
|
|
280
|
+
overflow: auto;
|
|
281
|
+
display: flex;
|
|
282
|
+
flex-direction: column;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.nb-feature-hub--compact .nb-feature-hub__content {
|
|
286
|
+
padding-top: 0.35rem;
|
|
287
|
+
}
|
|
1
288
|
.nb-admin-shell {
|
|
2
289
|
display: flex;
|
|
3
290
|
flex-direction: column;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nubitio/admin",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.30",
|
|
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,9 +53,9 @@
|
|
|
53
53
|
"react": "^19.0.0",
|
|
54
54
|
"react-dom": "^19.0.0",
|
|
55
55
|
"react-router-dom": "^6.0.0",
|
|
56
|
-
"@nubitio/core": "^0.5.
|
|
57
|
-
"@nubitio/crud": "^0.5.
|
|
58
|
-
"@nubitio/hydra": "^0.5.
|
|
59
|
-
"@nubitio/ui": "^0.5.
|
|
56
|
+
"@nubitio/core": "^0.5.30",
|
|
57
|
+
"@nubitio/crud": "^0.5.30",
|
|
58
|
+
"@nubitio/hydra": "^0.5.30",
|
|
59
|
+
"@nubitio/ui": "^0.5.30"
|
|
60
60
|
}
|
|
61
61
|
}
|