@vertebr/react 0.13.0 → 0.16.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.
@@ -1 +1 @@
1
- {"version":3,"file":"AdminSidebar.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminSidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,SAAS,CAAC;AAG7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AA6FF,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,iBAAiB,+BAwBvE"}
1
+ {"version":3,"file":"AdminSidebar.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminSidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,SAAS,CAAC;AAG7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AA+FF,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,iBAAiB,+BAwBvE"}
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
3
  import { AdminPoweredBy } from "./AdminPoweredBy";
4
- import { iconForNavKey } from "../ui/icons";
4
+ import { resolveNavIcon } from "../ui/icons";
5
5
  function SidebarNavItem({ item, collapsed, }) {
6
6
  const hasChildren = Boolean(item.children?.length);
7
7
  const childActive = item.children?.some((child) => child.active) ?? false;
8
8
  const sectionActive = item.active || childActive;
9
9
  const [open, setOpen] = useState(sectionActive);
10
- const Icon = item.icon ?? iconForNavKey(item.key);
10
+ const Icon = item.icon ??
11
+ resolveNavIcon({ key: item.key, label: item.label, group: item.group });
11
12
  useEffect(() => {
12
13
  if (sectionActive)
13
14
  setOpen(true);
@@ -2,6 +2,9 @@ import type { AdminEnvironment, HealthCheck } from "@vertebr/client";
2
2
  import type { VbTheme } from "../../hooks/useVertebrTheme";
3
3
  export type AdminTopBarProps = {
4
4
  brand: string;
5
+ brandLogoUrl?: string;
6
+ /** Optional mark for dark surfaces (skips CSS invert). */
7
+ brandLogoUrlDark?: string;
5
8
  hostName?: string;
6
9
  hostLogoUrl?: string;
7
10
  envList: AdminEnvironment[];
@@ -28,5 +31,5 @@ export type AdminTopBarProps = {
28
31
  healthChecks?: HealthCheck[] | null;
29
32
  onRefreshHealth?: () => Promise<void>;
30
33
  };
31
- export declare function AdminTopBar({ brand, hostName, hostLogoUrl, envList, environment, onEnvironmentChange, authUserLabel, onSignOut, getAccessToken, authViaTokenOnly, authRequired, token, tokenDraft, onTokenDraftChange, onSaveToken, onClearToken, theme, onThemeChange, sidebarCollapsed, onToggleSidebar, syncEnabled, onOpenSync, onOpenSearch, healthChecks, onRefreshHealth, }: AdminTopBarProps): import("react").JSX.Element;
34
+ export declare function AdminTopBar({ brand, brandLogoUrl, brandLogoUrlDark, hostName, hostLogoUrl, envList, environment, onEnvironmentChange, authUserLabel, onSignOut, getAccessToken, authViaTokenOnly, authRequired, token, tokenDraft, onTokenDraftChange, onSaveToken, onClearToken, theme, onThemeChange, sidebarCollapsed, onToggleSidebar, syncEnabled, onOpenSync, onOpenSearch, healthChecks, onRefreshHealth, }: AdminTopBarProps): import("react").JSX.Element;
32
35
  //# sourceMappingURL=AdminTopBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdminTopBar.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminTopBar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAI3D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,cAAc,CAAC,EAAE,MACb,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACvC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,CAAC;AAiBF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,WAAW,EACX,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,KAAK,EACL,UAAU,EACV,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,EAAE,gBAAgB,+BA0JlB"}
1
+ {"version":3,"file":"AdminTopBar.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminTopBar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAI3D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,cAAc,CAAC,EAAE,MACb,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACvC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,CAAC;AAiBF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,YAAY,EACZ,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,KAAK,EACL,UAAU,EACV,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,EAAE,gBAAgB,+BAoLlB"}
@@ -20,11 +20,15 @@ function healthLabel(tone) {
20
20
  return "Attention";
21
21
  return "Degraded";
22
22
  }
23
- export function AdminTopBar({ brand, hostName, hostLogoUrl, envList, environment, onEnvironmentChange, authUserLabel, onSignOut, getAccessToken, authViaTokenOnly, authRequired, token, tokenDraft, onTokenDraftChange, onSaveToken, onClearToken, theme, onThemeChange, sidebarCollapsed, onToggleSidebar, syncEnabled, onOpenSync, onOpenSearch, healthChecks, onRefreshHealth, }) {
23
+ export function AdminTopBar({ brand, brandLogoUrl, brandLogoUrlDark, hostName, hostLogoUrl, envList, environment, onEnvironmentChange, authUserLabel, onSignOut, getAccessToken, authViaTokenOnly, authRequired, token, tokenDraft, onTokenDraftChange, onSaveToken, onClearToken, theme, onThemeChange, sidebarCollapsed, onToggleSidebar, syncEnabled, onOpenSync, onOpenSearch, healthChecks, onRefreshHealth, }) {
24
24
  const [healthOpen, setHealthOpen] = useState(false);
25
25
  const healthTone = healthOverall(healthChecks);
26
26
  const showTokenField = !getAccessToken &&
27
27
  !authViaTokenOnly &&
28
28
  (authRequired || Boolean(token));
29
- return (_jsxs(_Fragment, { children: [_jsxs("header", { className: "vertebr-topbar", children: [_jsxs("div", { className: "vertebr-topbar-start", children: [_jsx("button", { type: "button", className: "vertebr-topbar-toggle", "aria-label": sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar", onClick: onToggleSidebar, children: _jsx(IconMenu, {}) }), _jsx("div", { className: "vertebr-topbar-brand-wrap", children: hostName ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "vertebr-topbar-host", "data-primary": "true", children: [hostLogoUrl ? (_jsx("img", { className: "vertebr-topbar-host-logo", src: hostLogoUrl, alt: "" })) : null, _jsx("strong", { className: "vertebr-topbar-host-label", children: hostName })] }), _jsx("span", { className: "vertebr-topbar-product", children: brand })] })) : (_jsx("strong", { className: "vertebr-topbar-brand", children: brand })) }), envList.length > 1 ? (_jsx("div", { className: "vertebr-topbar-env", children: _jsx(EnvSelect, { environments: envList, value: environment, onChange: onEnvironmentChange }) })) : null] }), _jsx("div", { className: "vertebr-topbar-center", children: _jsxs("button", { type: "button", className: "vertebr-topbar-search", onClick: onOpenSearch, children: [_jsx(IconSearch, {}), _jsx("span", { children: "Search admin" }), _jsx("kbd", { children: "\u2318K" })] }) }), _jsxs("div", { className: "vertebr-topbar-end", children: [_jsxs("div", { className: "vertebr-topbar-cluster", "aria-label": "Operations", children: [healthTone && healthChecks?.length ? (_jsxs("button", { type: "button", className: "vertebr-topbar-health", "data-tone": healthTone, "aria-haspopup": "dialog", "aria-expanded": healthOpen, onClick: () => setHealthOpen(true), children: [_jsx("span", { className: "vertebr-topbar-health-dot", "aria-hidden": true }), _jsx("span", { className: "vertebr-topbar-health-text", children: healthLabel(healthTone) })] })) : null, syncEnabled && onOpenSync ? (_jsxs("button", { type: "button", className: "vertebr-topbar-action", onClick: onOpenSync, children: [_jsx(IconSync, {}), _jsx("span", { children: "Sync" })] })) : null] }), showTokenField ? (_jsxs("div", { className: "vertebr-topbar-token", children: [_jsx("input", { className: "vertebr-auth-input", type: "password", placeholder: "Access token", value: tokenDraft, onChange: (event) => onTokenDraftChange(event.target.value), autoComplete: "off" }), _jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", onClick: onSaveToken, children: "Use" }), token ? (_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", onClick: onClearToken, children: "Clear" })) : null] })) : null, getAccessToken || onSignOut ? (_jsxs("div", { className: "vertebr-topbar-account", children: [getAccessToken && authUserLabel ? (_jsx("span", { className: "vertebr-topbar-user", title: authUserLabel, children: authUserLabel })) : null, onSignOut ? (_jsx("button", { type: "button", className: "vertebr-topbar-signout", onClick: () => void onSignOut(), children: "Sign out" })) : null] })) : null, _jsx(ThemeToggle, { theme: theme, onChange: onThemeChange, compact: true })] })] }), healthOpen && healthChecks?.length ? (_jsx(HealthModal, { checks: healthChecks, environment: environment, onClose: () => setHealthOpen(false), onRefresh: onRefreshHealth })) : null] }));
29
+ return (_jsxs(_Fragment, { children: [_jsxs("header", { className: "vertebr-topbar", children: [_jsxs("div", { className: "vertebr-topbar-start", children: [_jsx("button", { type: "button", className: "vertebr-topbar-toggle", "aria-label": sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar", onClick: onToggleSidebar, children: _jsx(IconMenu, {}) }), _jsx("div", { className: "vertebr-topbar-brand-wrap", children: hostName ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "vertebr-topbar-host", "data-primary": "true", children: [hostLogoUrl ? (_jsx("img", { className: "vertebr-topbar-host-logo", src: hostLogoUrl, alt: "" })) : null, _jsx("strong", { className: "vertebr-topbar-host-label", children: hostName })] }), brandLogoUrl ? (_jsx("span", { className: "vertebr-topbar-product", "data-mark": "true", children: _jsx("img", { className: "vertebr-topbar-brand-mark", src: theme === "light"
30
+ ? brandLogoUrl
31
+ : (brandLogoUrlDark ?? brandLogoUrl), alt: brand }) })) : (_jsx("span", { className: "vertebr-topbar-product", children: brand }))] })) : brandLogoUrl ? (_jsx("span", { className: "vertebr-topbar-brand", children: _jsx("img", { className: "vertebr-topbar-brand-mark", src: theme === "light"
32
+ ? brandLogoUrl
33
+ : (brandLogoUrlDark ?? brandLogoUrl), alt: brand }) })) : (_jsx("strong", { className: "vertebr-topbar-brand", children: brand })) }), envList.length > 1 ? (_jsx("div", { className: "vertebr-topbar-env", children: _jsx(EnvSelect, { environments: envList, value: environment, onChange: onEnvironmentChange }) })) : null] }), _jsx("div", { className: "vertebr-topbar-center", children: _jsxs("button", { type: "button", className: "vertebr-topbar-search", onClick: onOpenSearch, children: [_jsx(IconSearch, {}), _jsx("span", { children: "Search admin" }), _jsx("kbd", { children: "\u2318K" })] }) }), _jsxs("div", { className: "vertebr-topbar-end", children: [_jsxs("div", { className: "vertebr-topbar-cluster", "aria-label": "Operations", children: [healthTone && healthChecks?.length ? (_jsxs("button", { type: "button", className: "vertebr-topbar-health", "data-tone": healthTone, "aria-haspopup": "dialog", "aria-expanded": healthOpen, onClick: () => setHealthOpen(true), children: [_jsx("span", { className: "vertebr-topbar-health-dot", "aria-hidden": true }), _jsx("span", { className: "vertebr-topbar-health-text", children: healthLabel(healthTone) })] })) : null, syncEnabled && onOpenSync ? (_jsxs("button", { type: "button", className: "vertebr-topbar-action", onClick: onOpenSync, children: [_jsx(IconSync, {}), _jsx("span", { children: "Sync" })] })) : null] }), showTokenField ? (_jsxs("div", { className: "vertebr-topbar-token", children: [_jsx("input", { className: "vertebr-auth-input", type: "password", placeholder: "Access token", value: tokenDraft, onChange: (event) => onTokenDraftChange(event.target.value), autoComplete: "off" }), _jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", onClick: onSaveToken, children: "Use" }), token ? (_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", onClick: onClearToken, children: "Clear" })) : null] })) : null, getAccessToken || onSignOut ? (_jsxs("div", { className: "vertebr-topbar-account", children: [getAccessToken && authUserLabel ? (_jsx("span", { className: "vertebr-topbar-user", title: authUserLabel, children: authUserLabel })) : null, onSignOut ? (_jsx("button", { type: "button", className: "vertebr-topbar-signout", onClick: () => void onSignOut(), children: "Sign out" })) : null] })) : null, _jsx(ThemeToggle, { theme: theme, onChange: onThemeChange, compact: true })] })] }), healthOpen && healthChecks?.length ? (_jsx(HealthModal, { checks: healthChecks, environment: environment, onClose: () => setHealthOpen(false), onRefresh: onRefreshHealth })) : null] }));
30
34
  }
@@ -1,4 +1,4 @@
1
1
  import type { VertebrAdminProps } from "./types";
2
2
  export type { VertebrAdminProps } from "./types";
3
- export declare function VertebrAdmin({ apiBase, basePath: basePathProp, title, envStorageKey, tokenStorageKey, themeStorageKey, metricsRangeStorageKey, getAccessToken, authUserLabel, onSignOut, }: VertebrAdminProps): import("react").JSX.Element;
3
+ export declare function VertebrAdmin({ apiBase, basePath: basePathProp, title, envStorageKey, tokenStorageKey, themeStorageKey, metricsRangeStorageKey, getAccessToken, authUserLabel, onSignOut, brandLogoUrl, brandLogoUrlDark, }: VertebrAdminProps): import("react").JSX.Element;
4
4
  //# sourceMappingURL=VertebrAdmin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VertebrAdmin.d.ts","sourceRoot":"","sources":["../../../src/components/admin/VertebrAdmin.tsx"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,wBAAgB,YAAY,CAAC,EAC3B,OAAsB,EACtB,QAAQ,EAAE,YAAY,EACtB,KAAuB,EACvB,aAA6B,EAC7B,eAAiC,EACjC,eAAiC,EACjC,sBAAgD,EAChD,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE,iBAAiB,+BAkuBnB"}
1
+ {"version":3,"file":"VertebrAdmin.d.ts","sourceRoot":"","sources":["../../../src/components/admin/VertebrAdmin.tsx"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,wBAAgB,YAAY,CAAC,EAC3B,OAAsB,EACtB,QAAQ,EAAE,YAAY,EACtB,KAAuB,EACvB,aAA6B,EAC7B,eAAiC,EACjC,eAAiC,EACjC,sBAAgD,EAChD,cAAc,EACd,aAAa,EACb,SAAS,EACT,YAAY,EACZ,gBAAgB,GACjB,EAAE,iBAAiB,+BAiyBnB"}
@@ -17,8 +17,8 @@ import { sidebarGroups } from "./sidebar";
17
17
  import { clearStored, readStored, writeStored } from "./storage";
18
18
  import { SaveBarProvider } from "../../hooks/useSaveBar";
19
19
  import { ToastProvider } from "../../hooks/useToast";
20
- import { iconForNavKey } from "../ui/icons";
21
- export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, title = "Control plane", envStorageKey = "vertebr:env", tokenStorageKey = "vertebr:token", themeStorageKey = "vertebr:theme", metricsRangeStorageKey = "vertebr:metrics-range", getAccessToken, authUserLabel, onSignOut, }) {
20
+ import { resolveNavIcon } from "../ui/icons";
21
+ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, title = "Control plane", envStorageKey = "vertebr:env", tokenStorageKey = "vertebr:token", themeStorageKey = "vertebr:theme", metricsRangeStorageKey = "vertebr:metrics-range", getAccessToken, authUserLabel, onSignOut, brandLogoUrl, brandLogoUrlDark, }) {
22
22
  const basePath = basePathProp ?? adminBaseFromApiBase(apiBase);
23
23
  const { theme, setTheme } = useVertebrTheme(themeStorageKey);
24
24
  const [environment, setEnvironment] = useState(() => readStored(envStorageKey) ?? "");
@@ -457,7 +457,13 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
457
457
  key: "overview",
458
458
  group: catalog.metrics.group ?? "Analytics",
459
459
  label: catalog.metrics.label,
460
- icon: iconForNavKey("overview"),
460
+ icon: resolveNavIcon({
461
+ key: "overview",
462
+ id: catalog.metrics.id,
463
+ label: catalog.metrics.label,
464
+ group: catalog.metrics.group,
465
+ icon: catalog.metrics.icon,
466
+ }),
461
467
  active: selection?.kind === "overview",
462
468
  onSelect: () => setSelection({ kind: "overview" }),
463
469
  });
@@ -467,7 +473,13 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
467
473
  key: "audit",
468
474
  group: catalog.audit.group ?? "Analytics",
469
475
  label: catalog.audit.label,
470
- icon: iconForNavKey("audit"),
476
+ icon: resolveNavIcon({
477
+ key: "audit",
478
+ id: catalog.audit.id,
479
+ label: catalog.audit.label,
480
+ group: catalog.audit.group,
481
+ icon: catalog.audit.icon,
482
+ }),
471
483
  active: selection?.kind === "audit",
472
484
  onSelect: () => setSelection({ kind: "audit" }),
473
485
  });
@@ -477,7 +489,13 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
477
489
  key: `resource:${resource.id}`,
478
490
  group: resource.group ?? "Resources",
479
491
  label: resource.label,
480
- icon: iconForNavKey(`resource:${resource.id}`),
492
+ icon: resolveNavIcon({
493
+ key: `resource:${resource.id}`,
494
+ id: resource.id,
495
+ label: resource.label,
496
+ group: resource.group,
497
+ icon: resource.icon,
498
+ }),
481
499
  active: selection?.kind === "resource" && selection.id === resource.id,
482
500
  onSelect: () => setSelection({ kind: "resource", id: resource.id }),
483
501
  });
@@ -487,7 +505,13 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
487
505
  key: "gallery",
488
506
  group: catalog.gallery.group ?? "Resources",
489
507
  label: catalog.gallery.label,
490
- icon: iconForNavKey("gallery"),
508
+ icon: resolveNavIcon({
509
+ key: "gallery",
510
+ id: catalog.gallery.id,
511
+ label: catalog.gallery.label,
512
+ group: catalog.gallery.group,
513
+ icon: catalog.gallery.icon,
514
+ }),
491
515
  active: selection?.kind === "gallery",
492
516
  onSelect: () => setSelection({ kind: "gallery" }),
493
517
  });
@@ -497,7 +521,13 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
497
521
  key: "fonts",
498
522
  group: catalog.fontLibrary.group ?? "Resources",
499
523
  label: catalog.fontLibrary.label,
500
- icon: iconForNavKey("fonts"),
524
+ icon: resolveNavIcon({
525
+ key: "fonts",
526
+ id: catalog.fontLibrary.id,
527
+ label: catalog.fontLibrary.label,
528
+ group: catalog.fontLibrary.group,
529
+ icon: catalog.fontLibrary.icon,
530
+ }),
501
531
  active: selection?.kind === "fontLibrary",
502
532
  onSelect: () => setSelection({ kind: "fontLibrary" }),
503
533
  });
@@ -508,7 +538,13 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
508
538
  key: "emails",
509
539
  group: catalog.emails.group ?? "Growth",
510
540
  label: catalog.emails.label,
511
- icon: iconForNavKey("emails"),
541
+ icon: resolveNavIcon({
542
+ key: "emails",
543
+ id: catalog.emails.id,
544
+ label: catalog.emails.label,
545
+ group: catalog.emails.group,
546
+ icon: catalog.emails.icon,
547
+ }),
512
548
  active: selection?.kind === "emails",
513
549
  onSelect: () => setSelection({ kind: "emails", tab: "compose" }),
514
550
  children: [
@@ -538,7 +574,12 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
538
574
  key: "addons:overview",
539
575
  group: "Add-ons",
540
576
  label: "Browse add-ons",
541
- icon: iconForNavKey("addons:overview"),
577
+ icon: resolveNavIcon({
578
+ key: "addons:overview",
579
+ id: "addons",
580
+ label: "Browse add-ons",
581
+ group: "Add-ons",
582
+ }),
542
583
  active: selection?.kind === "addons",
543
584
  onSelect: () => setSelection({ kind: "addons" }),
544
585
  });
@@ -548,7 +589,15 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
548
589
  key: `addon:${addon.id}`,
549
590
  group: addon.group ?? "Add-ons",
550
591
  label: addon.label,
551
- icon: iconForNavKey(`addon:${addon.id}`),
592
+ icon: resolveNavIcon({
593
+ key: `addon:${addon.id}`,
594
+ id: addon.id,
595
+ label: addon.label,
596
+ group: addon.group,
597
+ category: addon.category,
598
+ section: "addon",
599
+ icon: addon.icon,
600
+ }),
552
601
  active: selection?.kind === "addon" && selection.id === addon.id,
553
602
  onSelect: () => setSelection({ kind: "addon", id: addon.id }),
554
603
  });
@@ -559,7 +608,14 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
559
608
  key: `config:${config.id}`,
560
609
  group: config.group ?? fallback,
561
610
  label: config.label,
562
- icon: iconForNavKey(`config:${config.id}`),
611
+ icon: resolveNavIcon({
612
+ key: `config:${config.id}`,
613
+ id: config.id,
614
+ label: config.label,
615
+ group: config.group,
616
+ section: config.section === "page" ? "page" : "config",
617
+ icon: config.icon,
618
+ }),
563
619
  active: selection?.kind === "config" && selection.id === config.id,
564
620
  onSelect: () => setSelection({ kind: "config", id: config.id }),
565
621
  });
@@ -569,7 +625,12 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
569
625
  key: "sync",
570
626
  group: "Settings",
571
627
  label: "Sync environments",
572
- icon: iconForNavKey("sync"),
628
+ icon: resolveNavIcon({
629
+ key: "sync",
630
+ id: "sync",
631
+ label: "Sync environments",
632
+ group: "Settings",
633
+ }),
573
634
  active: selection?.kind === "sync",
574
635
  onSelect: () => setSelection({ kind: "sync" }),
575
636
  });
@@ -608,5 +669,5 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
608
669
  : selection?.kind === "addon"
609
670
  ? catalog?.addons?.find((item) => item.id === selection.id)?.description
610
671
  : undefined;
611
- return (_jsx(SaveBarProvider, { children: _jsx(ToastProvider, { children: _jsxs("div", { className: "vertebr-root", "data-env": environment, "data-sidebar-collapsed": sidebarCollapsed || undefined, children: [_jsx(AdminTopBar, { brand: bootstrap?.brand ?? catalog?.brand ?? "Vertebr", hostName: bootstrap?.appearance?.hostName ?? catalog?.appearance?.hostName, hostLogoUrl: bootstrap?.appearance?.hostLogoUrl ?? catalog?.appearance?.hostLogoUrl, envList: envList, environment: environment, onEnvironmentChange: switchEnvironment, authUserLabel: authUserLabel, onSignOut: onSignOut, getAccessToken: getAccessToken, authViaTokenOnly: authViaTokenOnly, authRequired: authRequired, token: token, tokenDraft: tokenDraft, onTokenDraftChange: setTokenDraft, onSaveToken: saveToken, onClearToken: clearToken, theme: theme, onThemeChange: setTheme, sidebarCollapsed: sidebarCollapsed, onToggleSidebar: () => setSidebarCollapsed((prev) => !prev), syncEnabled: syncEnabled, onOpenSync: () => setSelection({ kind: "sync" }), onOpenSearch: () => setSearchOpen(true), healthChecks: healthChecks, onRefreshHealth: catalog?.health ? refreshHealth : undefined }), catalog && searchOpen ? (_jsx(AdminCommandPalette, { catalog: catalog, onClose: () => setSearchOpen(false), onSelect: setSelection })) : null, _jsx(AdminSidebar, { navGroups: navGroups, collapsed: sidebarCollapsed }), _jsxs("main", { className: "vertebr-main", children: [_jsx(AdminHeader, { activeLabel: activeLabel ?? (catalog ? "Dashboard" : "Sign in"), catalogLoaded: Boolean(catalog), authRequired: authRequired, selection: selection, isPageSelection: isPageSelection, hasPagePreview: hasPagePreview, selectionDescription: selectionDescription, error: error, breadcrumbs: breadcrumbsForSelection(selection, catalog) }), _jsx(AdminContent, { client: client, catalog: catalog, selection: selection, onSelectionChange: setSelection, authRequired: authRequired, loading: loading, isPageSelection: isPageSelection, metricsData: metricsData, metricsLoading: metricsLoading, metricsRange: metricsRange, onMetricsRangeChange: changeMetricsRange, onRefreshMetrics: refreshMetrics, galleryData: galleryData, galleryLoading: galleryLoading, onRefreshGallery: refreshGallery, fontLibraryData: fontLibraryData, fontLibraryLoading: fontLibraryLoading, onRefreshFonts: refreshFonts, emailsData: emailsData, emailsLoading: emailsLoading, onRefreshEmails: refreshEmails, resourceData: resourceData, resourceSearch: resourceSearch, onResourceSearchChange: setResourceSearch, onRefreshResource: refreshResource, configData: configData, onConfigSaved: setConfigData, onRefreshConfig: refreshConfig, galleryPicker: galleryPicker, fontLibraryPicker: fontLibraryPicker }), _jsx(AdminSaveBar, {})] }), _jsx(AdminToastStack, {})] }) }) }));
672
+ return (_jsx(SaveBarProvider, { children: _jsx(ToastProvider, { children: _jsxs("div", { className: "vertebr-root", "data-env": environment, "data-sidebar-collapsed": sidebarCollapsed || undefined, children: [_jsx(AdminTopBar, { brand: bootstrap?.brand ?? catalog?.brand ?? "Vertebr", brandLogoUrl: brandLogoUrl, brandLogoUrlDark: brandLogoUrlDark, hostName: bootstrap?.appearance?.hostName ?? catalog?.appearance?.hostName, hostLogoUrl: bootstrap?.appearance?.hostLogoUrl ?? catalog?.appearance?.hostLogoUrl, envList: envList, environment: environment, onEnvironmentChange: switchEnvironment, authUserLabel: authUserLabel, onSignOut: onSignOut, getAccessToken: getAccessToken, authViaTokenOnly: authViaTokenOnly, authRequired: authRequired, token: token, tokenDraft: tokenDraft, onTokenDraftChange: setTokenDraft, onSaveToken: saveToken, onClearToken: clearToken, theme: theme, onThemeChange: setTheme, sidebarCollapsed: sidebarCollapsed, onToggleSidebar: () => setSidebarCollapsed((prev) => !prev), syncEnabled: syncEnabled, onOpenSync: () => setSelection({ kind: "sync" }), onOpenSearch: () => setSearchOpen(true), healthChecks: healthChecks, onRefreshHealth: catalog?.health ? refreshHealth : undefined }), catalog && searchOpen ? (_jsx(AdminCommandPalette, { catalog: catalog, onClose: () => setSearchOpen(false), onSelect: setSelection })) : null, _jsx(AdminSidebar, { navGroups: navGroups, collapsed: sidebarCollapsed }), _jsxs("main", { className: "vertebr-main", children: [_jsx(AdminHeader, { activeLabel: activeLabel ?? (catalog ? "Dashboard" : "Sign in"), catalogLoaded: Boolean(catalog), authRequired: authRequired, selection: selection, isPageSelection: isPageSelection, hasPagePreview: hasPagePreview, selectionDescription: selectionDescription, error: error, breadcrumbs: breadcrumbsForSelection(selection, catalog) }), _jsx(AdminContent, { client: client, catalog: catalog, selection: selection, onSelectionChange: setSelection, authRequired: authRequired, loading: loading, isPageSelection: isPageSelection, metricsData: metricsData, metricsLoading: metricsLoading, metricsRange: metricsRange, onMetricsRangeChange: changeMetricsRange, onRefreshMetrics: refreshMetrics, galleryData: galleryData, galleryLoading: galleryLoading, onRefreshGallery: refreshGallery, fontLibraryData: fontLibraryData, fontLibraryLoading: fontLibraryLoading, onRefreshFonts: refreshFonts, emailsData: emailsData, emailsLoading: emailsLoading, onRefreshEmails: refreshEmails, resourceData: resourceData, resourceSearch: resourceSearch, onResourceSearchChange: setResourceSearch, onRefreshResource: refreshResource, configData: configData, onConfigSaved: setConfigData, onRefreshConfig: refreshConfig, galleryPicker: galleryPicker, fontLibraryPicker: fontLibraryPicker }), _jsx(AdminSaveBar, {})] }), _jsx(AdminToastStack, {})] }) }) }));
612
673
  }
@@ -21,6 +21,15 @@ export type VertebrAdminProps = {
21
21
  authUserLabel?: string;
22
22
  /** Host-provided sign-out action. */
23
23
  onSignOut?: () => void | Promise<void>;
24
+ /**
25
+ * Optional product mark for light UI (dark ink on transparent).
26
+ */
27
+ brandLogoUrl?: string;
28
+ /**
29
+ * Optional product mark for dark UI (light ink on transparent).
30
+ * Falls back to `brandLogoUrl` when omitted.
31
+ */
32
+ brandLogoUrlDark?: string;
24
33
  };
25
34
  import type { ReactElement } from "react";
26
35
  export type EmailsTab = "compose" | "templates" | "activity";
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/admin/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,oEAAoE;IACpE,cAAc,CAAC,EAAE,MACb,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACvC,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAEF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AAE7D,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,YAAY,CAAC;AAEtE,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,CAAC,EAAE,SAAS,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC9B,IAAI,CAAC;AAET,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,OAAO,CAAC;QAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;KACtB,CAAC,CAAC;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/admin/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,oEAAoE;IACpE,cAAc,CAAC,EAAE,MACb,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACvC,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AAE7D,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,YAAY,CAAC;AAEtE,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,CAAC,EAAE,SAAS,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC9B,IAAI,CAAC;AAET,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,OAAO,CAAC;QAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;KACtB,CAAC,CAAC;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB,CAAC"}
@@ -1,11 +1,24 @@
1
- import type { SVGProps } from "react";
1
+ import type { ReactElement, SVGProps } from "react";
2
+ import type { CatalogAddonCategory, NavIconName } from "@vertebr/client";
2
3
  type IconProps = SVGProps<SVGSVGElement>;
3
4
  export declare function IconHome(props: IconProps): import("react").JSX.Element;
4
5
  export declare function IconProducts(props: IconProps): import("react").JSX.Element;
6
+ export declare function IconInventory(props: IconProps): import("react").JSX.Element;
7
+ export declare function IconUsers(props: IconProps): import("react").JSX.Element;
8
+ export declare function IconCard(props: IconProps): import("react").JSX.Element;
9
+ export declare function IconTag(props: IconProps): import("react").JSX.Element;
10
+ export declare function IconBolt(props: IconProps): import("react").JSX.Element;
5
11
  export declare function IconGallery(props: IconProps): import("react").JSX.Element;
6
12
  export declare function IconFonts(props: IconProps): import("react").JSX.Element;
7
13
  export declare function IconMail(props: IconProps): import("react").JSX.Element;
8
14
  export declare function IconPages(props: IconProps): import("react").JSX.Element;
15
+ export declare function IconPalette(props: IconProps): import("react").JSX.Element;
16
+ export declare function IconTruck(props: IconProps): import("react").JSX.Element;
17
+ export declare function IconClock(props: IconProps): import("react").JSX.Element;
18
+ export declare function IconStar(props: IconProps): import("react").JSX.Element;
19
+ export declare function IconMegaphone(props: IconProps): import("react").JSX.Element;
20
+ export declare function IconLayout(props: IconProps): import("react").JSX.Element;
21
+ export declare function IconList(props: IconProps): import("react").JSX.Element;
9
22
  export declare function IconSettings(props: IconProps): import("react").JSX.Element;
10
23
  export declare function IconChart(props: IconProps): import("react").JSX.Element;
11
24
  export declare function IconChevronLeft(props: IconProps): import("react").JSX.Element;
@@ -13,6 +26,21 @@ export declare function IconSearch(props: IconProps): import("react").JSX.Elemen
13
26
  export declare function IconSync(props: IconProps): import("react").JSX.Element;
14
27
  export declare function IconMenu(props: IconProps): import("react").JSX.Element;
15
28
  export declare function IconAddon(props: IconProps): import("react").JSX.Element;
16
- export declare function iconForNavKey(key: string): typeof IconHome;
29
+ export type NavIconComponent = (props: IconProps) => ReactElement;
30
+ export declare const NAV_ICON_COMPONENTS: Record<NavIconName, NavIconComponent>;
31
+ export type ResolveNavIconInput = {
32
+ key: string;
33
+ id?: string;
34
+ label?: string;
35
+ group?: string;
36
+ category?: CatalogAddonCategory;
37
+ section?: "config" | "page" | "addon";
38
+ icon?: NavIconName | null;
39
+ };
40
+ /** Resolve a stable icon name for a sidebar entry. */
41
+ export declare function resolveNavIconName(input: ResolveNavIconInput): NavIconName;
42
+ export declare function resolveNavIcon(input: ResolveNavIconInput): NavIconComponent;
43
+ /** @deprecated Prefer `resolveNavIcon`. */
44
+ export declare function iconForNavKey(key: string): NavIconComponent;
17
45
  export {};
18
46
  //# sourceMappingURL=icons.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../src/components/ui/icons.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEtC,KAAK,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;AAiBzC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAMxC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,+BAO5C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,+BAQ3C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BAOzC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAOxC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BAOzC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,+BAO5C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BAMzC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,+BAM/C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,+BAO1C;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BASxC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAQxC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BASzC;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,mBAYxC"}
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../src/components/ui/icons.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEzE,KAAK,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;AAiBzC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAMxC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,+BAO5C;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,+BAS7C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BASzC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAQxC;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,+BAOvC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAMxC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,+BAQ3C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BAOzC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAOxC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BAOzC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,+BAS3C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BASzC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BAOzC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAMxC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,+BAQ7C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,+BAO1C;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAOxC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,+BAO5C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BAMzC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,+BAM/C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,+BAO1C;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BASxC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,+BAQxC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,+BASzC;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,YAAY,CAAC;AAElE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAuBrE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,OAAO,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACtC,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAC3B,CAAC;AA8FF,sDAAsD;AACtD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,WAAW,CAY1E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,gBAAgB,CAE3E;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAE3D"}
@@ -19,6 +19,21 @@ export function IconHome(props) {
19
19
  export function IconProducts(props) {
20
20
  return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M3 6.5 10 2.5l7 4v9H3v-9z" }), _jsx("path", { d: "M7 11.5h6M7 14h4" })] }));
21
21
  }
22
+ export function IconInventory(props) {
23
+ return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M3.5 7h13v9.5H3.5z" }), _jsx("path", { d: "M3.5 10.5h13" }), _jsx("path", { d: "M7 7V5.5h6V7" }), _jsx("path", { d: "M7 13h2M11 13h2" })] }));
24
+ }
25
+ export function IconUsers(props) {
26
+ return (_jsxs("svg", { ...base(props), children: [_jsx("circle", { cx: "7.5", cy: "7", r: "2.25" }), _jsx("path", { d: "M3.5 15.5c.4-2.4 2-3.75 4-3.75s3.6 1.35 4 3.75" }), _jsx("circle", { cx: "13.5", cy: "7.25", r: "1.75" }), _jsx("path", { d: "M12.2 11.9c1.35.2 2.55 1.1 2.9 3.1" })] }));
27
+ }
28
+ export function IconCard(props) {
29
+ return (_jsxs("svg", { ...base(props), children: [_jsx("rect", { x: "2.5", y: "5", width: "15", height: "10.5", rx: "1.5" }), _jsx("path", { d: "M2.5 8.5h15" }), _jsx("path", { d: "M5.5 12.5h4" })] }));
30
+ }
31
+ export function IconTag(props) {
32
+ return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M3.5 10.5V4.5H9.5l7 7-5 5-8-6z" }), _jsx("circle", { cx: "7", cy: "7", r: "1", fill: "currentColor", stroke: "none" })] }));
33
+ }
34
+ export function IconBolt(props) {
35
+ return (_jsx("svg", { ...base(props), children: _jsx("path", { d: "M11 2.5 5.5 11h4L9 17.5 14.5 9h-4L11 2.5z" }) }));
36
+ }
22
37
  export function IconGallery(props) {
23
38
  return (_jsxs("svg", { ...base(props), children: [_jsx("rect", { x: "2.5", y: "4.5", width: "15", height: "11", rx: "1.5" }), _jsx("path", { d: "m3.5 13 3.5-3.5 2.5 2.5L12.5 9l4 4.5" }), _jsx("circle", { cx: "7", cy: "7.5", r: "1", fill: "currentColor", stroke: "none" })] }));
24
39
  }
@@ -26,11 +41,32 @@ export function IconFonts(props) {
26
41
  return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M5 16.5V5.5h10M7.5 16.5V9h5v7.5" }), _jsx("path", { d: "M7 5.5h6" })] }));
27
42
  }
28
43
  export function IconMail(props) {
29
- return (_jsxs("svg", { ...base(props), children: [_jsx("rect", { x: "2.5", y: "4.5", width: "15", height: "11", rx: "1.5" }), _jsx("path", { d: "m3.5 6.5 6.5 4.5 3.5 2.5 6.5-2.5 6.5 4.5" })] }));
44
+ return (_jsxs("svg", { ...base(props), children: [_jsx("rect", { x: "2.5", y: "4.5", width: "15", height: "11", rx: "1.5" }), _jsx("path", { d: "m3.5 6.5 6.5 4.5 6.5-4.5" })] }));
30
45
  }
31
46
  export function IconPages(props) {
32
47
  return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M6 3.5h5.5L16 8v8.5a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-12a1 1 0 0 1 1-1z" }), _jsx("path", { d: "M11.5 3.5V8H16" })] }));
33
48
  }
49
+ export function IconPalette(props) {
50
+ return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M10 3a7 7 0 1 0 0 14h1.2a1.8 1.8 0 0 0 0-3.6H10a2 2 0 0 1 0-4h3.5" }), _jsx("circle", { cx: "7.2", cy: "8", r: "0.9", fill: "currentColor", stroke: "none" }), _jsx("circle", { cx: "8.4", cy: "11.2", r: "0.9", fill: "currentColor", stroke: "none" }), _jsx("circle", { cx: "12.2", cy: "7.2", r: "0.9", fill: "currentColor", stroke: "none" })] }));
51
+ }
52
+ export function IconTruck(props) {
53
+ return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M2.5 13.5V6.5h9v7" }), _jsx("path", { d: "M11.5 9.5h4l2 2.5v1.5h-6" }), _jsx("circle", { cx: "6", cy: "14.5", r: "1.5" }), _jsx("circle", { cx: "14.5", cy: "14.5", r: "1.5" })] }));
54
+ }
55
+ export function IconClock(props) {
56
+ return (_jsxs("svg", { ...base(props), children: [_jsx("circle", { cx: "10", cy: "10", r: "6.5" }), _jsx("path", { d: "M10 6.5V10l3 2" })] }));
57
+ }
58
+ export function IconStar(props) {
59
+ return (_jsx("svg", { ...base(props), children: _jsx("path", { d: "m10 3.5 1.8 3.7 4.1.6-3 2.9.7 4.1L10 13.2 6.4 14.8l.7-4.1-3-2.9 4.1-.6L10 3.5z" }) }));
60
+ }
61
+ export function IconMegaphone(props) {
62
+ return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M4.5 11.5v-3l10-3.5v10L4.5 11.5z" }), _jsx("path", { d: "M4.5 8.5v5.5a2 2 0 0 0 2 0V11" }), _jsx("path", { d: "M15.5 7.5v5" })] }));
63
+ }
64
+ export function IconLayout(props) {
65
+ return (_jsxs("svg", { ...base(props), children: [_jsx("rect", { x: "3", y: "3.5", width: "14", height: "13", rx: "1.5" }), _jsx("path", { d: "M3 8h14M9 8v8.5" })] }));
66
+ }
67
+ export function IconList(props) {
68
+ return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M7 5.5h9.5M7 10h9.5M7 14.5h9.5" }), _jsx("path", { d: "M4 5.5h.01M4 10h.01M4 14.5h.01" })] }));
69
+ }
34
70
  export function IconSettings(props) {
35
71
  return (_jsxs("svg", { ...base(props), children: [_jsx("circle", { cx: "10", cy: "10", r: "2.25" }), _jsx("path", { d: "M10 2.5v2M10 15.5v2M3.5 10h2M14.5 10h2M5.4 5.4l1.4 1.4M13.2 13.2l1.4 1.4M5.4 14.6l1.4-1.4M13.2 6.8l1.4-1.4" })] }));
36
72
  }
@@ -52,26 +88,174 @@ export function IconMenu(props) {
52
88
  export function IconAddon(props) {
53
89
  return (_jsxs("svg", { ...base(props), children: [_jsx("path", { d: "M8 3.5h4v4H8z" }), _jsx("path", { d: "M3.5 8h4v4h-4z" }), _jsx("path", { d: "M12.5 8h4v4h-4z" }), _jsx("path", { d: "M8 12.5h4v4H8z" })] }));
54
90
  }
55
- export function iconForNavKey(key) {
91
+ export const NAV_ICON_COMPONENTS = {
92
+ home: IconHome,
93
+ products: IconProducts,
94
+ inventory: IconInventory,
95
+ users: IconUsers,
96
+ card: IconCard,
97
+ tag: IconTag,
98
+ bolt: IconBolt,
99
+ gallery: IconGallery,
100
+ fonts: IconFonts,
101
+ mail: IconMail,
102
+ pages: IconPages,
103
+ palette: IconPalette,
104
+ truck: IconTruck,
105
+ clock: IconClock,
106
+ star: IconStar,
107
+ megaphone: IconMegaphone,
108
+ layout: IconLayout,
109
+ list: IconList,
110
+ chart: IconChart,
111
+ sync: IconSync,
112
+ addon: IconAddon,
113
+ settings: IconSettings,
114
+ };
115
+ function normalize(value) {
116
+ return (value ?? "").trim().toLowerCase().replace(/[_-]+/g, " ");
117
+ }
118
+ function haystack(input) {
119
+ return `${normalize(input.id)} ${normalize(input.label)}`.trim();
120
+ }
121
+ function matchHeuristic(text) {
122
+ if (!text)
123
+ return null;
124
+ if (/\binventory\b|\bstock\b|\bsku\b/.test(text))
125
+ return "inventory";
126
+ if (/\bwaitlist\b|\bsignups?\b|\bcustomers?\b|\bsubscribers?\b/.test(text))
127
+ return "users";
128
+ if (/\bwebhooks?\b|\bhooks?\b/.test(text))
129
+ return "bolt";
130
+ if (/\bdiscounts?\b|\bcoupons?\b|\bpromos?\b|\boffers?\b/.test(text))
131
+ return "tag";
132
+ if (/\bsessions?\b|\bpayments?\b|\bcheckout\b/.test(text))
133
+ return "card";
134
+ if (/\bstripe\b/.test(text))
135
+ return "card";
136
+ if (/\btheme\b|\bbrand(?:ing)?\b|\bappearance\b|\bcolors?\b/.test(text))
137
+ return "palette";
138
+ if (/\bshipping\b|\bfulfill\b|\bdelivery\b|\btruck\b/.test(text))
139
+ return "truck";
140
+ if (/\brefunds?\b|\breturns?\b/.test(text))
141
+ return "sync";
142
+ if (/\bterms\b|\bpolic(?:y|ies)\b|\blegal\b|\bprivacy\b/.test(text))
143
+ return "pages";
144
+ if (/\bproduct page\b|\blayout\b|\bblocks?\b/.test(text))
145
+ return "layout";
146
+ if (/\bpre[- ]?order\b|\bcountdown\b|\bschedule\b|\brelease\b/.test(text))
147
+ return "clock";
148
+ if (/\breviews?\b|\bratings?\b|\btestimonials?\b/.test(text))
149
+ return "star";
150
+ if (/\bannouncements?\b|\bbanners?\b|\bmegaphone\b|\balerts?\b/.test(text))
151
+ return "megaphone";
152
+ if (/\blookbook\b|\bpress\b|\blogos?\b|\bsize guide\b|\bguide\b/.test(text))
153
+ return "list";
154
+ if (/\bback in stock\b|\bfree shipping\b|\bthreshold\b/.test(text))
155
+ return "tag";
156
+ if (/\bemails?\b|\bmail\b|\bcampaigns?\b/.test(text))
157
+ return "mail";
158
+ if (/\bfonts?\b|\btypography\b/.test(text))
159
+ return "fonts";
160
+ if (/\bgallery\b|\bfiles?\b|\bmedia\b|\bimages?\b/.test(text))
161
+ return "gallery";
162
+ if (/\baudit\b|\bmetrics?\b|\banalytics\b/.test(text))
163
+ return "chart";
164
+ if (/\bsync\b|\benvironments?\b/.test(text))
165
+ return "sync";
166
+ if (/\bgeneral\b|\bsettings?\b/.test(text))
167
+ return "settings";
168
+ if (/\bproducts?\b|\bcatalog\b/.test(text))
169
+ return "products";
170
+ if (/\bhome\b|\boverview\b/.test(text))
171
+ return "home";
172
+ if (/\bnav(?:igation)?\b|\bmenu\b/.test(text))
173
+ return "list";
174
+ if (/\babout\b|\bcoming soon\b|\bpages?\b/.test(text))
175
+ return "pages";
176
+ return null;
177
+ }
178
+ function matchGroup(group) {
179
+ const g = normalize(group);
180
+ if (!g)
181
+ return null;
182
+ if (g.includes("payment"))
183
+ return "card";
184
+ if (g.includes("marketing") || g.includes("growth") || g.includes("customer"))
185
+ return "users";
186
+ if (g.includes("product") || g.includes("catalog"))
187
+ return "products";
188
+ if (g.includes("online store") ||
189
+ g.includes("pages") ||
190
+ g.includes("storefront"))
191
+ return "pages";
192
+ if (g.includes("setting") || g.includes("general"))
193
+ return "settings";
194
+ if (g.includes("content") || g.includes("media"))
195
+ return "gallery";
196
+ if (g.includes("analytic") || g.includes("home"))
197
+ return "chart";
198
+ if (g.includes("add-on") || g.includes("addon"))
199
+ return "addon";
200
+ return null;
201
+ }
202
+ function matchCategory(category) {
203
+ if (category === "product")
204
+ return "products";
205
+ if (category === "engagement")
206
+ return "megaphone";
207
+ if (category === "sales")
208
+ return "tag";
209
+ return null;
210
+ }
211
+ function kindDefault(key, section) {
56
212
  if (key === "overview")
57
- return IconHome;
213
+ return "home";
58
214
  if (key === "audit")
59
- return IconChart;
60
- if (key.startsWith("resource:"))
61
- return IconProducts;
215
+ return "chart";
62
216
  if (key === "gallery")
63
- return IconGallery;
217
+ return "gallery";
64
218
  if (key === "fonts")
65
- return IconFonts;
219
+ return "fonts";
66
220
  if (key === "emails")
67
- return IconMail;
221
+ return "mail";
68
222
  if (key === "sync")
69
- return IconSync;
223
+ return "sync";
70
224
  if (key === "addons:overview")
71
- return IconAddon;
225
+ return "addon";
72
226
  if (key.startsWith("addon:"))
73
- return IconAddon;
74
- if (key.startsWith("config:"))
75
- return IconPages;
76
- return IconSettings;
227
+ return "addon";
228
+ if (key.startsWith("resource:"))
229
+ return "products";
230
+ if (key.startsWith("config:")) {
231
+ if (section === "page")
232
+ return "pages";
233
+ return "settings";
234
+ }
235
+ return "settings";
236
+ }
237
+ /** Resolve a stable icon name for a sidebar entry. */
238
+ export function resolveNavIconName(input) {
239
+ if (input.icon && input.icon in NAV_ICON_COMPONENTS)
240
+ return input.icon;
241
+ const text = haystack(input);
242
+ const fromText = matchHeuristic(text);
243
+ if (fromText)
244
+ return fromText;
245
+ if (input.key.startsWith("addon:") || input.section === "addon") {
246
+ const fromCategory = matchCategory(input.category);
247
+ if (fromCategory)
248
+ return fromCategory;
249
+ }
250
+ const fromGroup = matchGroup(input.group);
251
+ if (fromGroup)
252
+ return fromGroup;
253
+ return kindDefault(input.key, input.section);
254
+ }
255
+ export function resolveNavIcon(input) {
256
+ return NAV_ICON_COMPONENTS[resolveNavIconName(input)];
257
+ }
258
+ /** @deprecated Prefer `resolveNavIcon`. */
259
+ export function iconForNavKey(key) {
260
+ return resolveNavIcon({ key });
77
261
  }
@@ -91,6 +91,16 @@
91
91
  letter-spacing: -0.01em;
92
92
  white-space: nowrap;
93
93
  color: var(--vb-text);
94
+ display: inline-flex;
95
+ align-items: center;
96
+ line-height: 0;
97
+ }
98
+
99
+ .vertebr-topbar-brand-mark {
100
+ display: block;
101
+ height: 1.55rem;
102
+ width: auto;
103
+ aspect-ratio: 1;
94
104
  }
95
105
 
96
106
  .vertebr-topbar-brand-wrap {
@@ -134,6 +144,16 @@
134
144
  white-space: nowrap;
135
145
  }
136
146
 
147
+ .vertebr-topbar-product[data-mark="true"] {
148
+ line-height: 0;
149
+ letter-spacing: 0;
150
+ text-transform: none;
151
+ }
152
+
153
+ .vertebr-topbar-product[data-mark="true"] .vertebr-topbar-brand-mark {
154
+ height: 1.15rem;
155
+ }
156
+
137
157
  .vertebr-topbar-host-logo {
138
158
  width: 1.15rem;
139
159
  height: 1.15rem;
@@ -64,6 +64,13 @@
64
64
  padding: 0.15rem 0.55rem 0.35rem;
65
65
  }
66
66
 
67
+ .vertebr-brand-mark {
68
+ display: block;
69
+ width: 2.25rem;
70
+ height: 2.25rem;
71
+ margin-bottom: 0.35rem;
72
+ }
73
+
67
74
  .vertebr-brand strong {
68
75
  font-size: 1.05rem;
69
76
  letter-spacing: 0.14em;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertebr/react",
3
- "version": "0.13.0",
3
+ "version": "0.16.0",
4
4
  "description": "Vertebr admin dashboard UI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,6 +20,7 @@
20
20
  "scripts": {
21
21
  "build": "rm -rf dist && tsc -p tsconfig.json && cp src/styles.css dist/styles.css && cp -R src/styles dist/styles && cp -R src/themes dist/themes",
22
22
  "typecheck": "tsc -p tsconfig.json --noEmit",
23
+ "test": "tsx --test test/*.test.ts",
23
24
  "prepublishOnly": "npm run typecheck && npm run build"
24
25
  },
25
26
  "repository": {
@@ -60,6 +61,7 @@
60
61
  "@types/react-dom": "^19.2.3",
61
62
  "react": "^19.2.8",
62
63
  "react-dom": "^19.2.8",
64
+ "tsx": "^4.20.5",
63
65
  "typescript": "^5.9.2"
64
66
  },
65
67
  "license": "SEE LICENSE IN LICENSE"