@vertebr/react 0.3.0 → 0.5.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.
Files changed (126) hide show
  1. package/dist/components/admin/AdminContent.d.ts +36 -0
  2. package/dist/components/admin/AdminContent.d.ts.map +1 -0
  3. package/dist/components/admin/AdminContent.js +107 -0
  4. package/dist/components/admin/AdminHeader.d.ts +13 -0
  5. package/dist/components/admin/AdminHeader.d.ts.map +1 -0
  6. package/dist/components/admin/AdminHeader.js +32 -0
  7. package/dist/components/admin/AdminSidebar.d.ts +25 -0
  8. package/dist/components/admin/AdminSidebar.d.ts.map +1 -0
  9. package/dist/components/admin/AdminSidebar.js +31 -0
  10. package/dist/components/admin/VertebrAdmin.d.ts +3 -18
  11. package/dist/components/admin/VertebrAdmin.d.ts.map +1 -1
  12. package/dist/components/admin/VertebrAdmin.js +130 -120
  13. package/dist/components/admin/sidebar.d.ts +3 -0
  14. package/dist/components/admin/sidebar.d.ts.map +1 -0
  15. package/dist/components/admin/sidebar.js +13 -0
  16. package/dist/components/admin/storage.d.ts +4 -0
  17. package/dist/components/admin/storage.d.ts.map +1 -0
  18. package/dist/components/admin/storage.js +24 -0
  19. package/dist/components/admin/types.d.ts +53 -0
  20. package/dist/components/admin/types.d.ts.map +1 -0
  21. package/dist/components/admin/types.js +1 -0
  22. package/dist/components/config/EnumInput.d.ts +10 -0
  23. package/dist/components/config/EnumInput.d.ts.map +1 -0
  24. package/dist/components/config/EnumInput.js +19 -0
  25. package/dist/components/config/EnumListInput.d.ts +10 -0
  26. package/dist/components/config/EnumListInput.d.ts.map +1 -0
  27. package/dist/components/config/EnumListInput.js +46 -0
  28. package/dist/components/config/VisibilityEye.d.ts +8 -0
  29. package/dist/components/config/VisibilityEye.d.ts.map +1 -0
  30. package/dist/components/config/VisibilityEye.js +18 -0
  31. package/dist/components/config/form/ConfigField.d.ts +2 -1
  32. package/dist/components/config/form/ConfigField.d.ts.map +1 -1
  33. package/dist/components/config/form/ConfigField.js +9 -4
  34. package/dist/components/config/form/ConfigForm.d.ts +1 -1
  35. package/dist/components/config/form/ConfigForm.d.ts.map +1 -1
  36. package/dist/components/config/form/ConfigForm.js +18 -9
  37. package/dist/components/config/form/ConfigFormActions.d.ts +2 -1
  38. package/dist/components/config/form/ConfigFormActions.d.ts.map +1 -1
  39. package/dist/components/config/form/ConfigFormActions.js +2 -2
  40. package/dist/components/config/form/RecordConfigForm.d.ts +3 -1
  41. package/dist/components/config/form/RecordConfigForm.d.ts.map +1 -1
  42. package/dist/components/config/form/RecordConfigForm.js +16 -8
  43. package/dist/components/config/form/SettingsConfigForm.d.ts +3 -1
  44. package/dist/components/config/form/SettingsConfigForm.d.ts.map +1 -1
  45. package/dist/components/config/form/SettingsConfigForm.js +2 -2
  46. package/dist/components/config/form/helpers/fields.d.ts +7 -0
  47. package/dist/components/config/form/helpers/fields.d.ts.map +1 -0
  48. package/dist/components/config/form/helpers/fields.js +31 -0
  49. package/dist/components/config/form/helpers/groups.d.ts +4 -0
  50. package/dist/components/config/form/helpers/groups.d.ts.map +1 -0
  51. package/dist/components/config/form/helpers/groups.js +107 -0
  52. package/dist/components/config/form/helpers/images.d.ts +4 -0
  53. package/dist/components/config/form/helpers/images.d.ts.map +1 -0
  54. package/dist/components/config/form/helpers/images.js +27 -0
  55. package/dist/components/config/form/helpers/index.d.ts +7 -0
  56. package/dist/components/config/form/helpers/index.d.ts.map +1 -0
  57. package/dist/components/config/form/helpers/index.js +6 -0
  58. package/dist/components/config/form/helpers/labels.d.ts +5 -0
  59. package/dist/components/config/form/helpers/labels.d.ts.map +1 -0
  60. package/dist/components/config/form/helpers/labels.js +28 -0
  61. package/dist/components/config/form/helpers/schema.d.ts +8 -0
  62. package/dist/components/config/form/helpers/schema.d.ts.map +1 -0
  63. package/dist/components/config/form/helpers/schema.js +30 -0
  64. package/dist/components/config/form/helpers/visibility.d.ts +13 -0
  65. package/dist/components/config/form/helpers/visibility.d.ts.map +1 -0
  66. package/dist/components/config/form/helpers/visibility.js +86 -0
  67. package/dist/components/config/form/types.d.ts +6 -0
  68. package/dist/components/config/form/types.d.ts.map +1 -1
  69. package/dist/components/emails/EmailRecipientSelect.d.ts +16 -0
  70. package/dist/components/emails/EmailRecipientSelect.d.ts.map +1 -0
  71. package/dist/components/emails/EmailRecipientSelect.js +10 -0
  72. package/dist/components/emails/EmailsActivityPanel.d.ts +11 -0
  73. package/dist/components/emails/EmailsActivityPanel.d.ts.map +1 -0
  74. package/dist/components/emails/EmailsActivityPanel.js +139 -0
  75. package/dist/components/emails/EmailsBoard.d.ts +47 -0
  76. package/dist/components/emails/EmailsBoard.d.ts.map +1 -0
  77. package/dist/components/emails/EmailsBoard.js +594 -0
  78. package/dist/components/emails/EmailsLibraryPanel.d.ts +25 -0
  79. package/dist/components/emails/EmailsLibraryPanel.d.ts.map +1 -0
  80. package/dist/components/emails/EmailsLibraryPanel.js +379 -0
  81. package/dist/components/emails/EmailsNavSelect.d.ts +18 -0
  82. package/dist/components/emails/EmailsNavSelect.d.ts.map +1 -0
  83. package/dist/components/emails/EmailsNavSelect.js +37 -0
  84. package/dist/components/emails/MultiCheckSelect.d.ts +18 -0
  85. package/dist/components/emails/MultiCheckSelect.d.ts.map +1 -0
  86. package/dist/components/emails/MultiCheckSelect.js +74 -0
  87. package/dist/components/metrics/MetricsBoard.d.ts +8 -2
  88. package/dist/components/metrics/MetricsBoard.d.ts.map +1 -1
  89. package/dist/components/metrics/MetricsBoard.js +55 -2
  90. package/dist/components/metrics/charts.d.ts +14 -0
  91. package/dist/components/metrics/charts.d.ts.map +1 -0
  92. package/dist/components/metrics/charts.js +212 -0
  93. package/dist/components/resources/ResourceActionModal.d.ts +14 -0
  94. package/dist/components/resources/ResourceActionModal.d.ts.map +1 -0
  95. package/dist/components/resources/ResourceActionModal.js +64 -0
  96. package/dist/components/resources/ResourceCell.d.ts.map +1 -1
  97. package/dist/components/resources/ResourceCell.js +25 -9
  98. package/dist/components/resources/ResourceCreateModal.d.ts +18 -0
  99. package/dist/components/resources/ResourceCreateModal.d.ts.map +1 -0
  100. package/dist/components/resources/ResourceCreateModal.js +22 -0
  101. package/dist/components/resources/ResourceMailModal.d.ts +12 -0
  102. package/dist/components/resources/ResourceMailModal.d.ts.map +1 -0
  103. package/dist/components/resources/ResourceMailModal.js +196 -0
  104. package/dist/components/resources/ResourceTable.d.ts +9 -3
  105. package/dist/components/resources/ResourceTable.d.ts.map +1 -1
  106. package/dist/components/resources/ResourceTable.js +241 -35
  107. package/dist/index.d.ts +11 -1
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.js +3 -0
  110. package/dist/lib/metricsRanges.d.ts +20 -0
  111. package/dist/lib/metricsRanges.d.ts.map +1 -0
  112. package/dist/lib/metricsRanges.js +14 -0
  113. package/dist/styles/cells.css +42 -0
  114. package/dist/styles/emails.css +632 -0
  115. package/dist/styles/form.css +145 -0
  116. package/dist/styles/index.css +3 -0
  117. package/dist/styles/mail.css +240 -0
  118. package/dist/styles/metrics.css +633 -0
  119. package/dist/styles/modal.css +18 -0
  120. package/dist/styles/nav.css +103 -1
  121. package/dist/styles/panel.css +8 -68
  122. package/dist/styles/table.css +26 -3
  123. package/package.json +2 -2
  124. package/dist/components/config/form/helpers.d.ts +0 -16
  125. package/dist/components/config/form/helpers.d.ts.map +0 -1
  126. package/dist/components/config/form/helpers.js +0 -186
@@ -0,0 +1,36 @@
1
+ import type { CatalogResponse, ConfigResponse, EmailsBoardResponse, GalleryResponse, MetricsResponse, ResourceListResponse, VertebrClient } from "@vertebr/client";
2
+ import type { MetricsRangeId } from "../../lib/metricsRanges";
3
+ import type { Selection } from "./types";
4
+ export type AdminContentProps = {
5
+ client: VertebrClient;
6
+ catalog: CatalogResponse | null;
7
+ selection: Selection;
8
+ authRequired: boolean;
9
+ loading: boolean;
10
+ isPageSelection: boolean;
11
+ metricsData: MetricsResponse | null;
12
+ metricsLoading: boolean;
13
+ metricsRange: MetricsRangeId;
14
+ onMetricsRangeChange: (next: MetricsRangeId) => void;
15
+ onRefreshMetrics: () => Promise<void>;
16
+ galleryData: GalleryResponse | null;
17
+ galleryLoading: boolean;
18
+ onRefreshGallery: () => Promise<void>;
19
+ emailsData: EmailsBoardResponse | null;
20
+ emailsLoading: boolean;
21
+ onRefreshEmails: () => Promise<void>;
22
+ resourceData: ResourceListResponse | null;
23
+ onRefreshResource: () => Promise<void>;
24
+ configData: ConfigResponse | null;
25
+ onConfigSaved: (next: ConfigResponse) => void;
26
+ galleryPicker: {
27
+ galleryUpload?: {
28
+ accept: string[];
29
+ maxBytes: number;
30
+ };
31
+ onListGallery?: () => Promise<GalleryResponse["items"]>;
32
+ onUploadGallery?: (files: File[]) => Promise<GalleryResponse["items"]>;
33
+ };
34
+ };
35
+ export declare function AdminContent({ client, catalog, selection, authRequired, loading, isPageSelection, metricsData, metricsLoading, metricsRange, onMetricsRangeChange, onRefreshMetrics, galleryData, galleryLoading, onRefreshGallery, emailsData, emailsLoading, onRefreshEmails, resourceData, onRefreshResource, configData, onConfigSaved, galleryPicker, }: AdminContentProps): import("react").JSX.Element;
36
+ //# sourceMappingURL=AdminContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminContent.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,aAAa,EACd,MAAM,iBAAiB,CAAC;AAMzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,cAAc,CAAC;IAC7B,oBAAoB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACrD,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACvC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,aAAa,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,aAAa,EAAE;QACb,aAAa,CAAC,EAAE;YACd,MAAM,EAAE,MAAM,EAAE,CAAC;YACjB,QAAQ,EAAE,MAAM,CAAC;SAClB,CAAC;QACF,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QACxD,eAAe,CAAC,EAAE,CAChB,KAAK,EAAE,IAAI,EAAE,KACV,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;KACxC,CAAC;CACH,CAAC;AAEF,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,OAAO,EACP,SAAS,EACT,YAAY,EACZ,OAAO,EACP,eAAe,EACf,WAAW,EACX,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,aAAa,GACd,EAAE,iBAAiB,+BAgPnB"}
@@ -0,0 +1,107 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { ConfigForm } from "../config/ConfigForm";
3
+ import { EmailsBoard } from "../emails/EmailsBoard";
4
+ import { GalleryBoard } from "../gallery/GalleryBoard";
5
+ import { MetricsBoard } from "../metrics/MetricsBoard";
6
+ import { ResourcePanel } from "../resources/ResourceTable";
7
+ export function AdminContent({ client, catalog, selection, authRequired, loading, isPageSelection, metricsData, metricsLoading, metricsRange, onMetricsRangeChange, onRefreshMetrics, galleryData, galleryLoading, onRefreshGallery, emailsData, emailsLoading, onRefreshEmails, resourceData, onRefreshResource, configData, onConfigSaved, galleryPicker, }) {
8
+ if (!catalog) {
9
+ return (_jsx("div", { className: "vertebr-content", children: _jsx("section", { className: "vertebr-panel", children: _jsx("div", { className: "vertebr-empty", children: authRequired
10
+ ? "Authenticated access required for this environment."
11
+ : loading
12
+ ? "Loading…"
13
+ : "Unable to load catalog." }) }) }));
14
+ }
15
+ return (_jsx("div", { className: "vertebr-content", children: _jsxs("section", { className: "vertebr-panel", children: [selection?.kind === "overview" ? (_jsx(MetricsBoard, { label: metricsData?.label ?? catalog.metrics?.label, windowLabel: metricsData?.windowLabel, compareLabel: metricsData?.compareLabel, metrics: metricsData?.metrics ?? [], charts: metricsData?.charts ?? [], range: metricsRange, onRangeChange: onMetricsRangeChange, loading: metricsLoading, onRefresh: () => void onRefreshMetrics() })) : null, selection?.kind === "gallery" && galleryData ? (_jsx(GalleryBoard, { label: galleryData.label, items: galleryData.items, accept: galleryData.accept, maxBytes: galleryData.maxBytes, canDelete: galleryData.canDelete, loading: galleryLoading, onRefresh: () => void onRefreshGallery(), onUpload: async (files) => {
16
+ if (files.length === 1 && files[0]) {
17
+ await client.uploadGalleryFile(files[0]);
18
+ }
19
+ else {
20
+ await client.uploadGalleryFiles(files);
21
+ }
22
+ await onRefreshGallery();
23
+ }, onDelete: galleryData.canDelete
24
+ ? async (id) => {
25
+ await client.deleteGalleryItem(id);
26
+ await onRefreshGallery();
27
+ }
28
+ : undefined })) : null, selection?.kind === "emails" && emailsData ? (_jsx(EmailsBoard, { data: emailsData, loading: emailsLoading, tab: selection.tab ?? "compose", onRefresh: () => void onRefreshEmails(), onLoadRecipients: async (resourceId) => {
29
+ const listed = await client.listResource(resourceId, {
30
+ fresh: true,
31
+ });
32
+ const seen = new Set();
33
+ const options = [];
34
+ for (const item of listed.items) {
35
+ const email = String(item.email ?? "")
36
+ .trim()
37
+ .toLowerCase();
38
+ if (!email.includes("@") || seen.has(email))
39
+ continue;
40
+ seen.add(email);
41
+ const id = String(item.id ?? item.uid ?? item.slug ?? email);
42
+ const label = String(item.displayName ?? item.name ?? "").trim();
43
+ options.push({
44
+ email,
45
+ id,
46
+ ...(label ? { label } : {}),
47
+ });
48
+ }
49
+ options.sort((a, b) => a.email.localeCompare(b.email));
50
+ return options;
51
+ }, onPreview: (payload) => client.previewEmails(payload), onSend: async (payload) => {
52
+ const result = await client.sendEmails(payload);
53
+ return { sent: result.sent, failed: result.failed };
54
+ }, onSchedule: emailsData.canSchedule
55
+ ? async (payload) => {
56
+ await client.scheduleEmails(payload);
57
+ }
58
+ : undefined, onCancel: emailsData.canSchedule
59
+ ? async (id) => {
60
+ await client.cancelEmailCampaign(id);
61
+ }
62
+ : undefined, onSaveLibrary: emailsData.canLibrary
63
+ ? async (template) => {
64
+ await client.saveEmailLibraryTemplate(template);
65
+ }
66
+ : undefined, onDeleteLibrary: emailsData.canLibrary
67
+ ? async (id) => {
68
+ await client.deleteEmailLibraryTemplate(id);
69
+ }
70
+ : undefined })) : null, selection?.kind === "resource" && resourceData ? (_jsx(ResourcePanel, { schema: resourceData.schema, items: resourceData.items, label: resourceData.label, permissions: resourceData.permissions, actions: resourceData.actions, collectionActions: resourceData.collectionActions, uploads: resourceData.uploads, storageKey: resourceData.id, onUpdate: resourceData.permissions.update
71
+ ? async (rowId, value) => {
72
+ await client.updateResource(resourceData.id, rowId, value);
73
+ await onRefreshResource();
74
+ }
75
+ : undefined, onCreate: resourceData.permissions.create
76
+ ? async (value) => {
77
+ await client.createResource(resourceData.id, value);
78
+ await onRefreshResource();
79
+ }
80
+ : undefined, onDelete: resourceData.permissions.delete
81
+ ? async (rowId) => {
82
+ await client.deleteResource(resourceData.id, rowId);
83
+ await onRefreshResource();
84
+ }
85
+ : undefined, onAction: async (rowId, actionId, input) => {
86
+ await client.runResourceAction(resourceData.id, rowId, actionId, input);
87
+ }, onActionDone: onRefreshResource, onPreviewMail: async (rowId, actionId, input) => {
88
+ return client.previewResourceMail(resourceData.id, rowId, actionId, input);
89
+ }, onCollectionAction: async (actionId, input) => {
90
+ await client.runCollectionAction(resourceData.id, actionId, input);
91
+ }, onUpload: resourceData.uploads
92
+ ? async (field, files) => {
93
+ if (files.length === 1 && files[0]) {
94
+ const result = await client.uploadResourceFile(resourceData.id, field, files[0]);
95
+ return [{ url: result.url, name: result.name }];
96
+ }
97
+ const result = await client.uploadResourceFiles(resourceData.id, field, files);
98
+ return result.files;
99
+ }
100
+ : undefined, ...galleryPicker })) : null, selection?.kind === "config" && configData ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "vertebr-panel-head", children: [_jsx("h2", { children: isPageSelection ? "Page content" : "Settings" }), _jsxs("span", { className: "vertebr-count", children: [Object.keys(configData.schema).length, " fields"] })] }), _jsx(ConfigForm, { schema: configData.schema, value: configData.value, onSave: async (next) => {
101
+ const saved = await client.setConfig(configData.id, next);
102
+ onConfigSaved({
103
+ ...configData,
104
+ value: saved.value,
105
+ });
106
+ }, ...galleryPicker })] })) : null] }) }));
107
+ }
@@ -0,0 +1,13 @@
1
+ import type { AdminEnvironment } from "@vertebr/client";
2
+ import type { Selection } from "./types";
3
+ export type AdminHeaderProps = {
4
+ activeLabel: string;
5
+ activeEnv?: AdminEnvironment;
6
+ catalogLoaded: boolean;
7
+ authRequired: boolean;
8
+ selection: Selection;
9
+ isPageSelection: boolean;
10
+ error: string | null;
11
+ };
12
+ export declare function AdminHeader({ activeLabel, activeEnv, catalogLoaded, authRequired, selection, isPageSelection, error, }: AdminHeaderProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=AdminHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminHeader.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAkCF,wBAAgB,WAAW,CAAC,EAC1B,WAAW,EACX,SAAS,EACT,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,EACf,KAAK,GACN,EAAE,gBAAgB,+BA+BlB"}
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ function subtitle({ catalogLoaded, authRequired, selection, isPageSelection, }) {
3
+ if (!catalogLoaded && authRequired) {
4
+ return "Provide an access token to load this environment.";
5
+ }
6
+ if (selection?.kind === "overview") {
7
+ return "Commerce, growth, and catalog for the selected environment.";
8
+ }
9
+ if (selection?.kind === "gallery") {
10
+ return "Browse and upload shared media assets.";
11
+ }
12
+ if (selection?.kind === "emails") {
13
+ return "Send or schedule branded email to a list or specific people.";
14
+ }
15
+ if (selection?.kind === "resource") {
16
+ return "Manage records scoped to the selected environment.";
17
+ }
18
+ if (selection?.kind === "config") {
19
+ return isPageSelection
20
+ ? "Edit content for this page."
21
+ : "Owner-managed config for this environment.";
22
+ }
23
+ return "Select a panel.";
24
+ }
25
+ export function AdminHeader({ activeLabel, activeEnv, catalogLoaded, authRequired, selection, isPageSelection, error, }) {
26
+ return (_jsxs("header", { className: "vertebr-header", children: [_jsxs("div", { children: [_jsxs("div", { className: "vertebr-heading-row", children: [_jsx("h1", { children: activeLabel }), activeEnv ? (_jsx("span", { className: "vertebr-env-badge", "data-tone": activeEnv.tone ?? "neutral", children: activeEnv.label })) : null] }), _jsx("p", { children: subtitle({
27
+ catalogLoaded,
28
+ authRequired,
29
+ selection,
30
+ isPageSelection,
31
+ }) })] }), error ? (_jsx("span", { className: "vertebr-status", "data-tone": "danger", children: error })) : null] }));
32
+ }
@@ -0,0 +1,25 @@
1
+ import type { AdminEnvironment } from "@vertebr/client";
2
+ import type { VbTheme } from "../../hooks/useVertebrTheme";
3
+ import type { SidebarNavGroup } from "./types";
4
+ export type AdminSidebarProps = {
5
+ brand: string;
6
+ title: string;
7
+ envList: AdminEnvironment[];
8
+ environment: string;
9
+ onEnvironmentChange: (nextEnv: string) => void;
10
+ navGroups: SidebarNavGroup[];
11
+ getAccessToken?: () => string | null | undefined | Promise<string | null | undefined>;
12
+ authUserLabel?: string;
13
+ onSignOut?: () => void | Promise<void>;
14
+ authRequired: boolean;
15
+ activeEnv?: AdminEnvironment;
16
+ token: string;
17
+ tokenDraft: string;
18
+ onTokenDraftChange: (value: string) => void;
19
+ onSaveToken: () => void;
20
+ onClearToken: () => void;
21
+ theme: VbTheme;
22
+ onThemeChange: (theme: VbTheme) => void;
23
+ };
24
+ export declare function AdminSidebar({ brand, title, envList, environment, onEnvironmentChange, navGroups, getAccessToken, authUserLabel, onSignOut, authRequired, activeEnv, token, tokenDraft, onTokenDraftChange, onSaveToken, onClearToken, theme, onThemeChange, }: AdminSidebarProps): import("react").JSX.Element;
25
+ //# sourceMappingURL=AdminSidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminSidebar.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminSidebar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,SAAS,CAAC;AAE7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MACb,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,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;CACzC,CAAC;AA2EF,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,KAAK,EACL,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,aAAa,EACb,SAAS,EACT,YAAY,EACZ,SAAS,EACT,KAAK,EACL,UAAU,EACV,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,KAAK,EACL,aAAa,GACd,EAAE,iBAAiB,+BA8FnB"}
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { EnvSelect } from "../env/EnvSelect";
4
+ import { ThemeToggle } from "../theme/ThemeToggle";
5
+ function SidebarNavItem({ item }) {
6
+ const hasChildren = Boolean(item.children?.length);
7
+ const childActive = item.children?.some((child) => child.active) ?? false;
8
+ const sectionActive = item.active || childActive;
9
+ const [open, setOpen] = useState(sectionActive);
10
+ useEffect(() => {
11
+ if (sectionActive)
12
+ setOpen(true);
13
+ }, [sectionActive]);
14
+ if (!hasChildren) {
15
+ return (_jsx("button", { type: "button", "data-active": item.active, onClick: item.onSelect, children: item.label }));
16
+ }
17
+ return (_jsxs("div", { className: "vertebr-nav-item", "data-has-children": "true", "data-open": open || undefined, children: [_jsxs("div", { className: "vertebr-nav-parent", children: [_jsx("button", { type: "button", className: "vertebr-nav-parent-label", "data-active": sectionActive && !childActive, "data-section": sectionActive || undefined, onClick: () => {
18
+ setOpen(true);
19
+ item.onSelect();
20
+ }, children: item.label }), _jsx("button", { type: "button", className: "vertebr-nav-parent-toggle", "aria-label": open ? `Collapse ${item.label}` : `Expand ${item.label}`, "aria-expanded": open, onClick: () => setOpen((prev) => !prev), children: _jsx("span", { "aria-hidden": "true", children: open ? "▾" : "▸" }) })] }), open ? (_jsx("div", { className: "vertebr-nav-sub", role: "group", children: item.children.map((child) => (_jsx("button", { type: "button", className: "vertebr-nav-subitem", "data-active": child.active, onClick: () => {
21
+ setOpen(true);
22
+ child.onSelect();
23
+ }, children: child.label }, child.key))) })) : null] }));
24
+ }
25
+ export function AdminSidebar({ brand, title, envList, environment, onEnvironmentChange, navGroups, getAccessToken, authUserLabel, onSignOut, authRequired, activeEnv, token, tokenDraft, onTokenDraftChange, onSaveToken, onClearToken, theme, onThemeChange, }) {
26
+ return (_jsxs("aside", { className: "vertebr-sidebar", children: [_jsxs("div", { className: "vertebr-sidebar-top", children: [_jsxs("div", { className: "vertebr-brand", children: [_jsx("strong", { children: brand }), _jsx("span", { children: title })] }), envList.length > 0 ? (_jsxs("div", { className: "vertebr-env", children: [_jsx("div", { className: "vertebr-nav-label", children: "Environment" }), _jsx(EnvSelect, { environments: envList, value: environment, onChange: onEnvironmentChange })] })) : null, _jsx("nav", { className: "vertebr-nav", children: navGroups.map((group) => (_jsxs("div", { className: "vertebr-nav-group", children: [_jsx("div", { className: "vertebr-nav-label", children: group.label }), group.items.map((item) => (_jsx(SidebarNavItem, { item: item }, item.key)))] }, group.label))) })] }), _jsxs("div", { className: "vertebr-sidebar-bottom", children: [getAccessToken && authUserLabel ? (_jsxs("div", { className: "vertebr-auth", children: [_jsx("div", { className: "vertebr-nav-label", children: "Signed in" }), _jsx("p", { className: "vertebr-auth-hint", children: authUserLabel }), onSignOut ? (_jsx("button", { type: "button", className: "vertebr-btn", onClick: () => void onSignOut(), children: "Sign out" })) : null] })) : null, !getAccessToken && (authRequired || token) ? (_jsxs("div", { className: "vertebr-auth", children: [_jsx("div", { className: "vertebr-nav-label", children: "Access" }), _jsx("p", { className: "vertebr-auth-hint", children: authRequired
27
+ ? `This environment requires auth${activeEnv?.auth?.claimKey
28
+ ? ` (${activeEnv.auth.claimKey})`
29
+ : ""}.`
30
+ : "Optional access token for protected environments." }), _jsx("input", { className: "vertebr-auth-input", type: "password", placeholder: "Bearer token", value: tokenDraft, onChange: (event) => onTokenDraftChange(event.target.value), autoComplete: "off" }), _jsxs("div", { className: "vertebr-auth-actions", children: [_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-primary", onClick: onSaveToken, children: "Use token" }), token ? (_jsx("button", { type: "button", className: "vertebr-btn", onClick: onClearToken, children: "Clear" })) : null] })] })) : null, _jsx(ThemeToggle, { theme: theme, onChange: onThemeChange })] })] }));
31
+ }
@@ -1,19 +1,4 @@
1
- export type VertebrAdminProps = {
2
- /** Base URL for Vertebr API, e.g. `/admin/api` */
3
- apiBase?: string;
4
- title?: string;
5
- /** localStorage key for remembering the selected environment */
6
- envStorageKey?: string;
7
- /** localStorage key for the access token */
8
- tokenStorageKey?: string;
9
- /** localStorage key for light/dark theme preference */
10
- themeStorageKey?: string;
11
- /** Optional host-provided token getter (Firebase ID token, etc.) */
12
- getAccessToken?: () => string | null | undefined | Promise<string | null | undefined>;
13
- /** Signed-in identity shown in the dashboard. */
14
- authUserLabel?: string;
15
- /** Host-provided sign-out action. */
16
- onSignOut?: () => void | Promise<void>;
17
- };
18
- export declare function VertebrAdmin({ apiBase, title, envStorageKey, tokenStorageKey, themeStorageKey, getAccessToken, authUserLabel, onSignOut, }: VertebrAdminProps): import("react").JSX.Element;
1
+ import type { VertebrAdminProps } from "./types";
2
+ export type { VertebrAdminProps } from "./types";
3
+ export declare function VertebrAdmin({ apiBase, title, envStorageKey, tokenStorageKey, themeStorageKey, metricsRangeStorageKey, getAccessToken, authUserLabel, onSignOut, }: VertebrAdminProps): import("react").JSX.Element;
19
4
  //# sourceMappingURL=VertebrAdmin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VertebrAdmin.d.ts","sourceRoot":"","sources":["../../../src/components/admin/VertebrAdmin.tsx"],"names":[],"mappings":"AAkBA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,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,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACtF,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAiCF,wBAAgB,YAAY,CAAC,EAC3B,OAAsB,EACtB,KAAuB,EACvB,aAA6B,EAC7B,eAAiC,EACjC,eAAiC,EACjC,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE,iBAAiB,+BA+mBnB"}
1
+ {"version":3,"file":"VertebrAdmin.d.ts","sourceRoot":"","sources":["../../../src/components/admin/VertebrAdmin.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,wBAAgB,YAAY,CAAC,EAC3B,OAAsB,EACtB,KAAuB,EACvB,aAA6B,EAC7B,eAAiC,EACjC,eAAiC,EACjC,sBAAgD,EAChD,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE,iBAAiB,+BA6bnB"}