@nubitio/admin 0.5.29 → 0.6.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/dist/index.cjs +257 -20
- package/dist/index.d.cts +51 -1
- package/dist/index.d.mts +51 -1
- package/dist/index.mjs +257 -22
- package/dist/style.css +419 -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)();
|
|
@@ -972,6 +1047,158 @@ function ToastHost({ toasts, onDismiss }) {
|
|
|
972
1047
|
});
|
|
973
1048
|
}
|
|
974
1049
|
//#endregion
|
|
1050
|
+
//#region packages/admin/devtools/NubitDevToolsPanel.tsx
|
|
1051
|
+
const PROVIDER_TREE = [
|
|
1052
|
+
"MercureProvider",
|
|
1053
|
+
"SchemaProvider",
|
|
1054
|
+
"HydraResourceSchemaProvider",
|
|
1055
|
+
"HydraResourceStoreProvider",
|
|
1056
|
+
"SmartCrudRolesProvider",
|
|
1057
|
+
"CoreProvider"
|
|
1058
|
+
];
|
|
1059
|
+
function NubitDevToolsPanel() {
|
|
1060
|
+
const { enabled, resources, clearResources } = (0, _nubitio_crud.useDevTools)();
|
|
1061
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1062
|
+
const [expandedUrl, setExpandedUrl] = (0, react.useState)(null);
|
|
1063
|
+
if (!enabled || !(0, _nubitio_crud.isDevEnvironment)()) return null;
|
|
1064
|
+
const active = expandedUrl ? resources.find((r) => r.apiUrl === expandedUrl) : resources[0];
|
|
1065
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1066
|
+
className: `nb-devtools ${open ? "nb-devtools--open" : ""}`,
|
|
1067
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1068
|
+
type: "button",
|
|
1069
|
+
className: "nb-devtools__toggle",
|
|
1070
|
+
onClick: () => setOpen((v) => !v),
|
|
1071
|
+
"aria-expanded": open,
|
|
1072
|
+
title: "Nubit DevTools",
|
|
1073
|
+
children: "Nubit"
|
|
1074
|
+
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1075
|
+
className: "nb-devtools__panel",
|
|
1076
|
+
role: "complementary",
|
|
1077
|
+
"aria-label": "Nubit DevTools",
|
|
1078
|
+
children: [
|
|
1079
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
1080
|
+
className: "nb-devtools__header",
|
|
1081
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Nubit DevTools" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1082
|
+
type: "button",
|
|
1083
|
+
className: "nb-devtools__clear",
|
|
1084
|
+
onClick: clearResources,
|
|
1085
|
+
children: "Clear"
|
|
1086
|
+
})]
|
|
1087
|
+
}),
|
|
1088
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1089
|
+
className: "nb-devtools__section",
|
|
1090
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", { children: "Provider tree" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1091
|
+
className: "nb-devtools__providers",
|
|
1092
|
+
children: PROVIDER_TREE.map((name) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: name }, name))
|
|
1093
|
+
})]
|
|
1094
|
+
}),
|
|
1095
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1096
|
+
className: "nb-devtools__section",
|
|
1097
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h4", { children: [
|
|
1098
|
+
"Active resources (",
|
|
1099
|
+
resources.length,
|
|
1100
|
+
")"
|
|
1101
|
+
] }), resources.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1102
|
+
className: "nb-devtools__empty",
|
|
1103
|
+
children: "Open a SchemaCrudPage to inspect field resolution."
|
|
1104
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1105
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
1106
|
+
className: "nb-devtools__select",
|
|
1107
|
+
value: active?.apiUrl ?? "",
|
|
1108
|
+
onChange: (e) => setExpandedUrl(e.target.value),
|
|
1109
|
+
children: resources.map((r) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1110
|
+
value: r.apiUrl,
|
|
1111
|
+
children: r.apiUrl
|
|
1112
|
+
}, r.apiUrl))
|
|
1113
|
+
}),
|
|
1114
|
+
active && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
1115
|
+
className: "nb-devtools__meta",
|
|
1116
|
+
children: [
|
|
1117
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Source" }),
|
|
1118
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: active.source }),
|
|
1119
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Operations" }),
|
|
1120
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: active.supportedOperations.join(", ") || "—" }),
|
|
1121
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Permissions" }),
|
|
1122
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: active.permissionsSource ?? "—" })
|
|
1123
|
+
]
|
|
1124
|
+
}),
|
|
1125
|
+
active?.formDetail && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
1126
|
+
className: "nb-devtools__subsection",
|
|
1127
|
+
children: "Form detail (lines)"
|
|
1128
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
1129
|
+
className: "nb-devtools__meta",
|
|
1130
|
+
children: [
|
|
1131
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Line fields" }),
|
|
1132
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: active.formDetail.fieldSource }),
|
|
1133
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Property" }),
|
|
1134
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: active.formDetail.propertyName ?? "—" }),
|
|
1135
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Reload URL" }),
|
|
1136
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
1137
|
+
className: "nb-devtools__mapping",
|
|
1138
|
+
children: active.formDetail.reloadUrl ?? "—"
|
|
1139
|
+
}),
|
|
1140
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Line class" }),
|
|
1141
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: active.formDetail.lineClass ?? "—" }),
|
|
1142
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "x-embedded-lines" }),
|
|
1143
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: active.formDetail.embeddedLinesCount })
|
|
1144
|
+
]
|
|
1145
|
+
})] }),
|
|
1146
|
+
active && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
1147
|
+
className: "nb-devtools__subsection",
|
|
1148
|
+
children: "Grid fields"
|
|
1149
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
1150
|
+
className: "nb-devtools__table",
|
|
1151
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
1152
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Field" }),
|
|
1153
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Type" }),
|
|
1154
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Mapping" })
|
|
1155
|
+
] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: active.fields.filter((f) => !f.isIdentity).map((f) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
1156
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: f.name }),
|
|
1157
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: f.type }),
|
|
1158
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
1159
|
+
className: "nb-devtools__mapping",
|
|
1160
|
+
children: f.mappingReason ?? "—"
|
|
1161
|
+
})
|
|
1162
|
+
] }, f.name)) })]
|
|
1163
|
+
})] }),
|
|
1164
|
+
active?.formDetail && active.formDetail.lineFieldCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h4", {
|
|
1165
|
+
className: "nb-devtools__subsection",
|
|
1166
|
+
children: [
|
|
1167
|
+
"Line fields (",
|
|
1168
|
+
active.formDetail.lineFieldCount,
|
|
1169
|
+
")"
|
|
1170
|
+
]
|
|
1171
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
1172
|
+
className: "nb-devtools__table",
|
|
1173
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
1174
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Field" }),
|
|
1175
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Type" }),
|
|
1176
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Mapping" })
|
|
1177
|
+
] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: active.formDetail.lineFields.filter((f) => !f.isIdentity).map((f) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
1178
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: f.name }),
|
|
1179
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: f.type }),
|
|
1180
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
1181
|
+
className: "nb-devtools__mapping",
|
|
1182
|
+
children: f.mappingReason ?? "—"
|
|
1183
|
+
})
|
|
1184
|
+
] }, f.name)) })]
|
|
1185
|
+
})] })
|
|
1186
|
+
] })]
|
|
1187
|
+
}),
|
|
1188
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
|
|
1189
|
+
className: "nb-devtools__footer",
|
|
1190
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
1191
|
+
href: "https://github.com/nubitio/nubit-react/blob/main/docs/architecture/README.md",
|
|
1192
|
+
target: "_blank",
|
|
1193
|
+
rel: "noreferrer",
|
|
1194
|
+
children: "Architecture docs"
|
|
1195
|
+
})
|
|
1196
|
+
})
|
|
1197
|
+
]
|
|
1198
|
+
})]
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
//#endregion
|
|
975
1202
|
//#region packages/admin/app/filterMenuByRoles.ts
|
|
976
1203
|
function hasAnyRole(required, roles) {
|
|
977
1204
|
if (required === void 0) return true;
|
|
@@ -1092,24 +1319,32 @@ function NubitAuthenticatedApp({ config }) {
|
|
|
1092
1319
|
element: route.element
|
|
1093
1320
|
}, route.path))] })
|
|
1094
1321
|
});
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1322
|
+
const devToolsEnabled = config.devTools ?? (0, _nubitio_crud.isDevEnvironment)();
|
|
1323
|
+
const authenticated = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_crud.DevToolsProvider, {
|
|
1324
|
+
enabled: devToolsEnabled,
|
|
1325
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_core.CoreProvider, {
|
|
1326
|
+
http: {
|
|
1327
|
+
baseUrl: apiBaseUrl,
|
|
1328
|
+
refreshPath: "auth/refresh",
|
|
1329
|
+
loginPath: "auth/login"
|
|
1330
|
+
},
|
|
1331
|
+
runtime,
|
|
1332
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_core.CoreConfigProvider, {
|
|
1333
|
+
apiBaseUrl,
|
|
1334
|
+
locale: config.locale ?? "en",
|
|
1335
|
+
timezone: config.timezone ?? "UTC",
|
|
1336
|
+
currency: config.currency ?? "USD",
|
|
1337
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_nubitio_crud.SmartCrudRolesProvider, {
|
|
1338
|
+
roles: session.roles,
|
|
1339
|
+
children: [
|
|
1340
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.BrowserRouter, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Wrapper, { children: config.hydra === false ? shell : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_core.MercureProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_hydra.SchemaProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_hydra.HydraResourceSchemaProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_hydra.HydraResourceStoreProvider, { children: shell }) }) }) }) }) }),
|
|
1341
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToastHost, {
|
|
1342
|
+
toasts,
|
|
1343
|
+
onDismiss: dismiss
|
|
1344
|
+
}),
|
|
1345
|
+
devToolsEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NubitDevToolsPanel, {})
|
|
1346
|
+
]
|
|
1347
|
+
})
|
|
1113
1348
|
})
|
|
1114
1349
|
})
|
|
1115
1350
|
});
|
|
@@ -1144,7 +1379,9 @@ exports.AdminHeader = AdminHeader;
|
|
|
1144
1379
|
exports.AdminShell = AdminShell;
|
|
1145
1380
|
exports.AdminSidebarMenu = AdminSidebarMenu;
|
|
1146
1381
|
exports.FeatureGate = FeatureGate;
|
|
1382
|
+
exports.FeatureHubLayout = FeatureHubLayout;
|
|
1147
1383
|
exports.LoginPage = LoginPage;
|
|
1384
|
+
exports.NubitDevToolsPanel = NubitDevToolsPanel;
|
|
1148
1385
|
exports.PlanPanel = PlanPanel;
|
|
1149
1386
|
exports.QuotaUsageBanner = QuotaUsageBanner;
|
|
1150
1387
|
exports.RegisterPage = RegisterPage;
|
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;
|
|
@@ -428,6 +470,11 @@ type CreateNubitAppConfig = {
|
|
|
428
470
|
}>;
|
|
429
471
|
queryClient?: QueryClient; /** Register Mercure + Hydra schema/store providers. Default true. */
|
|
430
472
|
hydra?: boolean;
|
|
473
|
+
/**
|
|
474
|
+
* Show the Nubit DevTools panel (field mapping, provider tree).
|
|
475
|
+
* Default true on localhost; set false to disable.
|
|
476
|
+
*/
|
|
477
|
+
devTools?: boolean;
|
|
431
478
|
};
|
|
432
479
|
type NubitApp = {
|
|
433
480
|
App: React.ComponentType;
|
|
@@ -436,6 +483,9 @@ type NubitApp = {
|
|
|
436
483
|
//#region packages/admin/app/createNubitApp.d.ts
|
|
437
484
|
declare function createNubitApp(config: CreateNubitAppConfig): NubitApp;
|
|
438
485
|
//#endregion
|
|
486
|
+
//#region packages/admin/devtools/NubitDevToolsPanel.d.ts
|
|
487
|
+
declare function NubitDevToolsPanel(): React$1.JSX.Element | null;
|
|
488
|
+
//#endregion
|
|
439
489
|
//#region packages/admin/app/filterMenuByRoles.d.ts
|
|
440
490
|
declare function hasAnyRole(required: string | string[] | undefined, roles: string[]): boolean;
|
|
441
491
|
/**
|
|
@@ -444,4 +494,4 @@ declare function hasAnyRole(required: string | string[] | undefined, roles: stri
|
|
|
444
494
|
*/
|
|
445
495
|
declare function filterMenuByRoles(items: NubitAppMenuItem[], roles: string[]): AdminMenuItem[];
|
|
446
496
|
//#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 };
|
|
497
|
+
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, NubitDevToolsPanel, 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;
|
|
@@ -428,6 +470,11 @@ type CreateNubitAppConfig = {
|
|
|
428
470
|
}>;
|
|
429
471
|
queryClient?: QueryClient; /** Register Mercure + Hydra schema/store providers. Default true. */
|
|
430
472
|
hydra?: boolean;
|
|
473
|
+
/**
|
|
474
|
+
* Show the Nubit DevTools panel (field mapping, provider tree).
|
|
475
|
+
* Default true on localhost; set false to disable.
|
|
476
|
+
*/
|
|
477
|
+
devTools?: boolean;
|
|
431
478
|
};
|
|
432
479
|
type NubitApp = {
|
|
433
480
|
App: React.ComponentType;
|
|
@@ -436,6 +483,9 @@ type NubitApp = {
|
|
|
436
483
|
//#region packages/admin/app/createNubitApp.d.ts
|
|
437
484
|
declare function createNubitApp(config: CreateNubitAppConfig): NubitApp;
|
|
438
485
|
//#endregion
|
|
486
|
+
//#region packages/admin/devtools/NubitDevToolsPanel.d.ts
|
|
487
|
+
declare function NubitDevToolsPanel(): React$1.JSX.Element | null;
|
|
488
|
+
//#endregion
|
|
439
489
|
//#region packages/admin/app/filterMenuByRoles.d.ts
|
|
440
490
|
declare function hasAnyRole(required: string | string[] | undefined, roles: string[]): boolean;
|
|
441
491
|
/**
|
|
@@ -444,4 +494,4 @@ declare function hasAnyRole(required: string | string[] | undefined, roles: stri
|
|
|
444
494
|
*/
|
|
445
495
|
declare function filterMenuByRoles(items: NubitAppMenuItem[], roles: string[]): AdminMenuItem[];
|
|
446
496
|
//#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 };
|
|
497
|
+
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, NubitDevToolsPanel, 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
|
-
import { SmartCrudRolesProvider } from "@nubitio/crud";
|
|
7
|
+
import { DevToolsProvider, SmartCrudRolesProvider, isDevEnvironment, useDevTools } 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();
|
|
@@ -948,6 +1023,158 @@ function ToastHost({ toasts, onDismiss }) {
|
|
|
948
1023
|
});
|
|
949
1024
|
}
|
|
950
1025
|
//#endregion
|
|
1026
|
+
//#region packages/admin/devtools/NubitDevToolsPanel.tsx
|
|
1027
|
+
const PROVIDER_TREE = [
|
|
1028
|
+
"MercureProvider",
|
|
1029
|
+
"SchemaProvider",
|
|
1030
|
+
"HydraResourceSchemaProvider",
|
|
1031
|
+
"HydraResourceStoreProvider",
|
|
1032
|
+
"SmartCrudRolesProvider",
|
|
1033
|
+
"CoreProvider"
|
|
1034
|
+
];
|
|
1035
|
+
function NubitDevToolsPanel() {
|
|
1036
|
+
const { enabled, resources, clearResources } = useDevTools();
|
|
1037
|
+
const [open, setOpen] = useState(false);
|
|
1038
|
+
const [expandedUrl, setExpandedUrl] = useState(null);
|
|
1039
|
+
if (!enabled || !isDevEnvironment()) return null;
|
|
1040
|
+
const active = expandedUrl ? resources.find((r) => r.apiUrl === expandedUrl) : resources[0];
|
|
1041
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1042
|
+
className: `nb-devtools ${open ? "nb-devtools--open" : ""}`,
|
|
1043
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
1044
|
+
type: "button",
|
|
1045
|
+
className: "nb-devtools__toggle",
|
|
1046
|
+
onClick: () => setOpen((v) => !v),
|
|
1047
|
+
"aria-expanded": open,
|
|
1048
|
+
title: "Nubit DevTools",
|
|
1049
|
+
children: "Nubit"
|
|
1050
|
+
}), open && /* @__PURE__ */ jsxs("div", {
|
|
1051
|
+
className: "nb-devtools__panel",
|
|
1052
|
+
role: "complementary",
|
|
1053
|
+
"aria-label": "Nubit DevTools",
|
|
1054
|
+
children: [
|
|
1055
|
+
/* @__PURE__ */ jsxs("header", {
|
|
1056
|
+
className: "nb-devtools__header",
|
|
1057
|
+
children: [/* @__PURE__ */ jsx("strong", { children: "Nubit DevTools" }), /* @__PURE__ */ jsx("button", {
|
|
1058
|
+
type: "button",
|
|
1059
|
+
className: "nb-devtools__clear",
|
|
1060
|
+
onClick: clearResources,
|
|
1061
|
+
children: "Clear"
|
|
1062
|
+
})]
|
|
1063
|
+
}),
|
|
1064
|
+
/* @__PURE__ */ jsxs("section", {
|
|
1065
|
+
className: "nb-devtools__section",
|
|
1066
|
+
children: [/* @__PURE__ */ jsx("h4", { children: "Provider tree" }), /* @__PURE__ */ jsx("ul", {
|
|
1067
|
+
className: "nb-devtools__providers",
|
|
1068
|
+
children: PROVIDER_TREE.map((name) => /* @__PURE__ */ jsx("li", { children: name }, name))
|
|
1069
|
+
})]
|
|
1070
|
+
}),
|
|
1071
|
+
/* @__PURE__ */ jsxs("section", {
|
|
1072
|
+
className: "nb-devtools__section",
|
|
1073
|
+
children: [/* @__PURE__ */ jsxs("h4", { children: [
|
|
1074
|
+
"Active resources (",
|
|
1075
|
+
resources.length,
|
|
1076
|
+
")"
|
|
1077
|
+
] }), resources.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
1078
|
+
className: "nb-devtools__empty",
|
|
1079
|
+
children: "Open a SchemaCrudPage to inspect field resolution."
|
|
1080
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1081
|
+
/* @__PURE__ */ jsx("select", {
|
|
1082
|
+
className: "nb-devtools__select",
|
|
1083
|
+
value: active?.apiUrl ?? "",
|
|
1084
|
+
onChange: (e) => setExpandedUrl(e.target.value),
|
|
1085
|
+
children: resources.map((r) => /* @__PURE__ */ jsx("option", {
|
|
1086
|
+
value: r.apiUrl,
|
|
1087
|
+
children: r.apiUrl
|
|
1088
|
+
}, r.apiUrl))
|
|
1089
|
+
}),
|
|
1090
|
+
active && /* @__PURE__ */ jsxs("dl", {
|
|
1091
|
+
className: "nb-devtools__meta",
|
|
1092
|
+
children: [
|
|
1093
|
+
/* @__PURE__ */ jsx("dt", { children: "Source" }),
|
|
1094
|
+
/* @__PURE__ */ jsx("dd", { children: active.source }),
|
|
1095
|
+
/* @__PURE__ */ jsx("dt", { children: "Operations" }),
|
|
1096
|
+
/* @__PURE__ */ jsx("dd", { children: active.supportedOperations.join(", ") || "—" }),
|
|
1097
|
+
/* @__PURE__ */ jsx("dt", { children: "Permissions" }),
|
|
1098
|
+
/* @__PURE__ */ jsx("dd", { children: active.permissionsSource ?? "—" })
|
|
1099
|
+
]
|
|
1100
|
+
}),
|
|
1101
|
+
active?.formDetail && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("h4", {
|
|
1102
|
+
className: "nb-devtools__subsection",
|
|
1103
|
+
children: "Form detail (lines)"
|
|
1104
|
+
}), /* @__PURE__ */ jsxs("dl", {
|
|
1105
|
+
className: "nb-devtools__meta",
|
|
1106
|
+
children: [
|
|
1107
|
+
/* @__PURE__ */ jsx("dt", { children: "Line fields" }),
|
|
1108
|
+
/* @__PURE__ */ jsx("dd", { children: active.formDetail.fieldSource }),
|
|
1109
|
+
/* @__PURE__ */ jsx("dt", { children: "Property" }),
|
|
1110
|
+
/* @__PURE__ */ jsx("dd", { children: active.formDetail.propertyName ?? "—" }),
|
|
1111
|
+
/* @__PURE__ */ jsx("dt", { children: "Reload URL" }),
|
|
1112
|
+
/* @__PURE__ */ jsx("dd", {
|
|
1113
|
+
className: "nb-devtools__mapping",
|
|
1114
|
+
children: active.formDetail.reloadUrl ?? "—"
|
|
1115
|
+
}),
|
|
1116
|
+
/* @__PURE__ */ jsx("dt", { children: "Line class" }),
|
|
1117
|
+
/* @__PURE__ */ jsx("dd", { children: active.formDetail.lineClass ?? "—" }),
|
|
1118
|
+
/* @__PURE__ */ jsx("dt", { children: "x-embedded-lines" }),
|
|
1119
|
+
/* @__PURE__ */ jsx("dd", { children: active.formDetail.embeddedLinesCount })
|
|
1120
|
+
]
|
|
1121
|
+
})] }),
|
|
1122
|
+
active && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("h4", {
|
|
1123
|
+
className: "nb-devtools__subsection",
|
|
1124
|
+
children: "Grid fields"
|
|
1125
|
+
}), /* @__PURE__ */ jsxs("table", {
|
|
1126
|
+
className: "nb-devtools__table",
|
|
1127
|
+
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1128
|
+
/* @__PURE__ */ jsx("th", { children: "Field" }),
|
|
1129
|
+
/* @__PURE__ */ jsx("th", { children: "Type" }),
|
|
1130
|
+
/* @__PURE__ */ jsx("th", { children: "Mapping" })
|
|
1131
|
+
] }) }), /* @__PURE__ */ jsx("tbody", { children: active.fields.filter((f) => !f.isIdentity).map((f) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
1132
|
+
/* @__PURE__ */ jsx("td", { children: f.name }),
|
|
1133
|
+
/* @__PURE__ */ jsx("td", { children: f.type }),
|
|
1134
|
+
/* @__PURE__ */ jsx("td", {
|
|
1135
|
+
className: "nb-devtools__mapping",
|
|
1136
|
+
children: f.mappingReason ?? "—"
|
|
1137
|
+
})
|
|
1138
|
+
] }, f.name)) })]
|
|
1139
|
+
})] }),
|
|
1140
|
+
active?.formDetail && active.formDetail.lineFieldCount > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("h4", {
|
|
1141
|
+
className: "nb-devtools__subsection",
|
|
1142
|
+
children: [
|
|
1143
|
+
"Line fields (",
|
|
1144
|
+
active.formDetail.lineFieldCount,
|
|
1145
|
+
")"
|
|
1146
|
+
]
|
|
1147
|
+
}), /* @__PURE__ */ jsxs("table", {
|
|
1148
|
+
className: "nb-devtools__table",
|
|
1149
|
+
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1150
|
+
/* @__PURE__ */ jsx("th", { children: "Field" }),
|
|
1151
|
+
/* @__PURE__ */ jsx("th", { children: "Type" }),
|
|
1152
|
+
/* @__PURE__ */ jsx("th", { children: "Mapping" })
|
|
1153
|
+
] }) }), /* @__PURE__ */ jsx("tbody", { children: active.formDetail.lineFields.filter((f) => !f.isIdentity).map((f) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
1154
|
+
/* @__PURE__ */ jsx("td", { children: f.name }),
|
|
1155
|
+
/* @__PURE__ */ jsx("td", { children: f.type }),
|
|
1156
|
+
/* @__PURE__ */ jsx("td", {
|
|
1157
|
+
className: "nb-devtools__mapping",
|
|
1158
|
+
children: f.mappingReason ?? "—"
|
|
1159
|
+
})
|
|
1160
|
+
] }, f.name)) })]
|
|
1161
|
+
})] })
|
|
1162
|
+
] })]
|
|
1163
|
+
}),
|
|
1164
|
+
/* @__PURE__ */ jsx("footer", {
|
|
1165
|
+
className: "nb-devtools__footer",
|
|
1166
|
+
children: /* @__PURE__ */ jsx("a", {
|
|
1167
|
+
href: "https://github.com/nubitio/nubit-react/blob/main/docs/architecture/README.md",
|
|
1168
|
+
target: "_blank",
|
|
1169
|
+
rel: "noreferrer",
|
|
1170
|
+
children: "Architecture docs"
|
|
1171
|
+
})
|
|
1172
|
+
})
|
|
1173
|
+
]
|
|
1174
|
+
})]
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
//#endregion
|
|
951
1178
|
//#region packages/admin/app/filterMenuByRoles.ts
|
|
952
1179
|
function hasAnyRole(required, roles) {
|
|
953
1180
|
if (required === void 0) return true;
|
|
@@ -1068,24 +1295,32 @@ function NubitAuthenticatedApp({ config }) {
|
|
|
1068
1295
|
element: route.element
|
|
1069
1296
|
}, route.path))] })
|
|
1070
1297
|
});
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1298
|
+
const devToolsEnabled = config.devTools ?? isDevEnvironment();
|
|
1299
|
+
const authenticated = /* @__PURE__ */ jsx(DevToolsProvider, {
|
|
1300
|
+
enabled: devToolsEnabled,
|
|
1301
|
+
children: /* @__PURE__ */ jsx(CoreProvider, {
|
|
1302
|
+
http: {
|
|
1303
|
+
baseUrl: apiBaseUrl,
|
|
1304
|
+
refreshPath: "auth/refresh",
|
|
1305
|
+
loginPath: "auth/login"
|
|
1306
|
+
},
|
|
1307
|
+
runtime,
|
|
1308
|
+
children: /* @__PURE__ */ jsx(CoreConfigProvider, {
|
|
1309
|
+
apiBaseUrl,
|
|
1310
|
+
locale: config.locale ?? "en",
|
|
1311
|
+
timezone: config.timezone ?? "UTC",
|
|
1312
|
+
currency: config.currency ?? "USD",
|
|
1313
|
+
children: /* @__PURE__ */ jsxs(SmartCrudRolesProvider, {
|
|
1314
|
+
roles: session.roles,
|
|
1315
|
+
children: [
|
|
1316
|
+
/* @__PURE__ */ jsx(BrowserRouter, { children: /* @__PURE__ */ jsx(Wrapper, { children: config.hydra === false ? shell : /* @__PURE__ */ jsx(MercureProvider, { children: /* @__PURE__ */ jsx(SchemaProvider, { children: /* @__PURE__ */ jsx(HydraResourceSchemaProvider, { children: /* @__PURE__ */ jsx(HydraResourceStoreProvider, { children: shell }) }) }) }) }) }),
|
|
1317
|
+
/* @__PURE__ */ jsx(ToastHost, {
|
|
1318
|
+
toasts,
|
|
1319
|
+
onDismiss: dismiss
|
|
1320
|
+
}),
|
|
1321
|
+
devToolsEnabled && /* @__PURE__ */ jsx(NubitDevToolsPanel, {})
|
|
1322
|
+
]
|
|
1323
|
+
})
|
|
1089
1324
|
})
|
|
1090
1325
|
})
|
|
1091
1326
|
});
|
|
@@ -1116,4 +1351,4 @@ function createNubitApp(config) {
|
|
|
1116
1351
|
return { App };
|
|
1117
1352
|
}
|
|
1118
1353
|
//#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 };
|
|
1354
|
+
export { AdminHeader, AdminShell, AdminSidebarMenu, FeatureGate, FeatureHubLayout, LoginPage, NubitDevToolsPanel, 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;
|
|
@@ -560,3 +847,135 @@
|
|
|
560
847
|
line-height: 1;
|
|
561
848
|
padding: 0;
|
|
562
849
|
}
|
|
850
|
+
.nb-devtools {
|
|
851
|
+
position: fixed;
|
|
852
|
+
bottom: 12px;
|
|
853
|
+
right: 12px;
|
|
854
|
+
z-index: 9999;
|
|
855
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
856
|
+
font-size: 12px;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
.nb-devtools__toggle {
|
|
860
|
+
background: #1e293b;
|
|
861
|
+
color: #f8fafc;
|
|
862
|
+
border: 1px solid #334155;
|
|
863
|
+
border-radius: 6px;
|
|
864
|
+
padding: 6px 10px;
|
|
865
|
+
cursor: pointer;
|
|
866
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.nb-devtools__panel {
|
|
870
|
+
position: absolute;
|
|
871
|
+
bottom: 40px;
|
|
872
|
+
right: 0;
|
|
873
|
+
width: min(420px, 100vw - 24px);
|
|
874
|
+
max-height: 70vh;
|
|
875
|
+
overflow: auto;
|
|
876
|
+
background: #0f172a;
|
|
877
|
+
color: #e2e8f0;
|
|
878
|
+
border: 1px solid #334155;
|
|
879
|
+
border-radius: 8px;
|
|
880
|
+
padding: 12px;
|
|
881
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
.nb-devtools__header {
|
|
885
|
+
display: flex;
|
|
886
|
+
justify-content: space-between;
|
|
887
|
+
align-items: center;
|
|
888
|
+
margin-bottom: 8px;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
.nb-devtools__clear {
|
|
892
|
+
background: transparent;
|
|
893
|
+
color: #94a3b8;
|
|
894
|
+
border: none;
|
|
895
|
+
cursor: pointer;
|
|
896
|
+
font-size: 11px;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
.nb-devtools__section {
|
|
900
|
+
margin-bottom: 12px;
|
|
901
|
+
}
|
|
902
|
+
.nb-devtools__section h4 {
|
|
903
|
+
margin: 0 0 6px;
|
|
904
|
+
font-size: 11px;
|
|
905
|
+
text-transform: uppercase;
|
|
906
|
+
letter-spacing: 0.04em;
|
|
907
|
+
color: #94a3b8;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
.nb-devtools__subsection {
|
|
911
|
+
margin: 10px 0 6px;
|
|
912
|
+
font-size: 11px;
|
|
913
|
+
text-transform: uppercase;
|
|
914
|
+
letter-spacing: 0.04em;
|
|
915
|
+
color: #94a3b8;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.nb-devtools__providers {
|
|
919
|
+
margin: 0;
|
|
920
|
+
padding-left: 16px;
|
|
921
|
+
color: #cbd5e1;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
.nb-devtools__empty {
|
|
925
|
+
margin: 0;
|
|
926
|
+
color: #94a3b8;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
.nb-devtools__select {
|
|
930
|
+
width: 100%;
|
|
931
|
+
margin-bottom: 8px;
|
|
932
|
+
background: #1e293b;
|
|
933
|
+
color: #f8fafc;
|
|
934
|
+
border: 1px solid #334155;
|
|
935
|
+
border-radius: 4px;
|
|
936
|
+
padding: 4px 6px;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
.nb-devtools__meta {
|
|
940
|
+
display: grid;
|
|
941
|
+
grid-template-columns: auto 1fr;
|
|
942
|
+
gap: 2px 8px;
|
|
943
|
+
margin: 0 0 8px;
|
|
944
|
+
}
|
|
945
|
+
.nb-devtools__meta dt {
|
|
946
|
+
color: #94a3b8;
|
|
947
|
+
}
|
|
948
|
+
.nb-devtools__meta dd {
|
|
949
|
+
margin: 0;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
.nb-devtools__table {
|
|
953
|
+
width: 100%;
|
|
954
|
+
border-collapse: collapse;
|
|
955
|
+
}
|
|
956
|
+
.nb-devtools__table th,
|
|
957
|
+
.nb-devtools__table td {
|
|
958
|
+
text-align: left;
|
|
959
|
+
padding: 3px 4px;
|
|
960
|
+
border-bottom: 1px solid #1e293b;
|
|
961
|
+
vertical-align: top;
|
|
962
|
+
}
|
|
963
|
+
.nb-devtools__table th {
|
|
964
|
+
color: #94a3b8;
|
|
965
|
+
font-weight: 600;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.nb-devtools__mapping {
|
|
969
|
+
color: #7dd3fc;
|
|
970
|
+
word-break: break-word;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
.nb-devtools__footer {
|
|
974
|
+
margin-top: 8px;
|
|
975
|
+
padding-top: 8px;
|
|
976
|
+
border-top: 1px solid #1e293b;
|
|
977
|
+
}
|
|
978
|
+
.nb-devtools__footer a {
|
|
979
|
+
color: #38bdf8;
|
|
980
|
+
text-decoration: none;
|
|
981
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nubitio/admin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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,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/
|
|
57
|
-
"@nubitio/
|
|
58
|
-
"@nubitio/
|
|
59
|
-
"@nubitio/ui": "^0.
|
|
56
|
+
"@nubitio/crud": "^0.6.0",
|
|
57
|
+
"@nubitio/hydra": "^0.6.0",
|
|
58
|
+
"@nubitio/core": "^0.6.0",
|
|
59
|
+
"@nubitio/ui": "^0.6.0"
|
|
60
60
|
}
|
|
61
61
|
}
|