@vertebr/react 0.13.0 → 0.15.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/components/admin/AdminSidebar.d.ts.map +1 -1
- package/dist/components/admin/AdminSidebar.js +3 -2
- package/dist/components/admin/VertebrAdmin.d.ts.map +1 -1
- package/dist/components/admin/VertebrAdmin.js +72 -11
- package/dist/components/ui/icons.d.ts +30 -2
- package/dist/components/ui/icons.d.ts.map +1 -1
- package/dist/components/ui/icons.js +199 -15
- package/package.json +3 -1
|
@@ -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;
|
|
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 {
|
|
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 ??
|
|
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);
|
|
@@ -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,+
|
|
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,+BA+xBnB"}
|
|
@@ -17,7 +17,7 @@ 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 {
|
|
20
|
+
import { resolveNavIcon } from "../ui/icons";
|
|
21
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, }) {
|
|
22
22
|
const basePath = basePathProp ?? adminBaseFromApiBase(apiBase);
|
|
23
23
|
const { theme, setTheme } = useVertebrTheme(themeStorageKey);
|
|
@@ -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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
});
|
|
@@ -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
|
|
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;
|
|
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
|
|
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
|
|
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
|
|
213
|
+
return "home";
|
|
58
214
|
if (key === "audit")
|
|
59
|
-
return
|
|
60
|
-
if (key.startsWith("resource:"))
|
|
61
|
-
return IconProducts;
|
|
215
|
+
return "chart";
|
|
62
216
|
if (key === "gallery")
|
|
63
|
-
return
|
|
217
|
+
return "gallery";
|
|
64
218
|
if (key === "fonts")
|
|
65
|
-
return
|
|
219
|
+
return "fonts";
|
|
66
220
|
if (key === "emails")
|
|
67
|
-
return
|
|
221
|
+
return "mail";
|
|
68
222
|
if (key === "sync")
|
|
69
|
-
return
|
|
223
|
+
return "sync";
|
|
70
224
|
if (key === "addons:overview")
|
|
71
|
-
return
|
|
225
|
+
return "addon";
|
|
72
226
|
if (key.startsWith("addon:"))
|
|
73
|
-
return
|
|
74
|
-
if (key.startsWith("
|
|
75
|
-
return
|
|
76
|
-
|
|
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
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertebr/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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"
|