@hollis-labs/kit-admin 0.0.0-stage → 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - 2026-10-03 - first release
4
+
5
+ - Render callback-free Settings as read-only text even for writable declarations,
6
+ using a presentation copy without changing host data or backend capabilities.
7
+
8
+ - Controlled admin navigation/content/standalone composition per the
9
+ [admin shell spec](../../docs/admin-shell-spec.md), over existing dashboard
10
+ layouts, settings provenance/setup and observation components. Host-owned
11
+ data, routes and commands remain controlled inputs.
12
+ - Require design-components, design-tokens and kit-dashboard `^0.4.0`,
13
+ kit-settings `^0.2.0` and kit-observe `^0.1.1`.
14
+ - Keep Dashboard a declaration directory and enforce canonical resource sections,
15
+ unavailable discovery/group states and host-owned context.
16
+ - Include opt-in `/charts` delegation, fixture demos and behavioral/browser evidence.
17
+ - Use optional settings text presentation when the host supplies no settings
18
+ callbacks, so read-only preferences render labelled values without disabled
19
+ editor affordances. Keep source, locks and apply state in canonical Settings.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chrispian Burks / Hollis Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,130 @@
1
- # Temporary Holding Version
1
+ # @hollis-labs/kit-admin
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **0.1.0** is the first release of controlled admin composition, implemented
4
+ from the approved [admin shell spec](../../docs/admin-shell-spec.md). The host
5
+ owns data, routes and commands.
6
+
7
+ `AdminNavigation` projects declared destinations through dashboard `NavRail`.
8
+ `AdminContent` supplies the inner page region for an existing host shell.
9
+ `AdminShell` combines those with the existing base `AppShell`, dashboard
10
+ `PageHeader` and `ListPageLayout`. Use one viewport shell and one page scroll
11
+ owner; embedded apps use `AdminContent` rather than nesting `AdminShell`.
12
+
13
+ | Page | Composition |
14
+ | --- | --- |
15
+ | Dashboard | App identity, declaration revision and links to canonical pages/groups; no config values or runtime KPIs. |
16
+ | Settings | One `SettingsProvenanceRenderer` for the host-selected group; source, locks, scope and pending application stay here. |
17
+ | Settings, `mode: 'setup'` | Existing `SettingsWizard` over the same groups/drafts, replacing the normal editor. Host controls step/checks/results; optional `setupContext` supplies provenance summaries beside it. Group links return to normal Settings. |
18
+ | Status | Existing `HealthSummary` and `StatCollection`; no configuration mutation controls. |
19
+ | Diagnostics | Existing `DiagnosticPanel`; an explicitly supplied series renderer receives existing `SampleSeriesViewProps`. |
20
+
21
+ ## Controlled host inputs
22
+
23
+ ```tsx
24
+ import { AdminShell } from '@hollis-labs/kit-admin'
25
+ import type { AdminContentProps } from '@hollis-labs/kit-admin'
26
+
27
+ // The application supplies validated projections and its own adapters.
28
+ export function AppAdmin({ state }: { state: AdminContentProps }) {
29
+ return <AdminShell {...state} />
30
+ }
31
+ ```
32
+
33
+ The host supplies `contextKey`, discovery phase/manifest, page/group/mode
34
+ selection, `destination(target)` returning either an `href` or `onSelect`,
35
+ per-group settings read states, optional settings callbacks, observation maps
36
+ and `nowMs`. `AdminManifest` is a minimal **presentation projection**, not a wire
37
+ registry or complete manifest validator. Transport fields/endpoints and wire
38
+ identity remain with the host and go-envelopes. `adminManifestProblem` fences
39
+ presentation identity, required arrays, contract version, resource placement
40
+ and observation age; supported settings schemas/provenance are checked by
41
+ kit-settings. The host validates all wire schemas, units, bounds, capabilities,
42
+ auth and diagnostic payloads before supplying these projections.
43
+
44
+ Keep all supplied data scoped to the current authorized `contextKey`; a discovery
45
+ context mismatch hides old content globally. Clear old snapshots/drafts and
46
+ cancel requests on auth/context changes. Host-owned routes/history, fetching,
47
+ retry/poll schedules, clocks, effective permissions, per-group revisions/ETags,
48
+ 409/412 reconciliation and uncertain write outcomes never move into this kit.
49
+ Accept and clear only successful group drafts. Reset means host resolution,
50
+ not a browser-computed fallback. Secret replacements remain transient in host
51
+ memory; never persist/log them or infer their values from declarations.
52
+
53
+ No writes occur on mount. Callbacks receive existing controlled settings intents.
54
+ `onApply` is omitted by default; an authorized host may explicitly supply its own
55
+ workflow. Save/setup completion never implies restart, readiness or health. The
56
+ host preserves per-field pending state independently of this command's
57
+ `restart_required` metadata, including no-op outcomes.
58
+
59
+ Failed initial discovery is globally unavailable. Retained declarations during
60
+ refresh/error are labelled and disable editing and command callbacks. A failed
61
+ individual group read disables only that group; sibling destinations remain
62
+ available. Contradictory sections are rejected, never relocated. Missing arrays
63
+ are malformed; empty arrays omit optional nav items and explain unsupported deep
64
+ links. All-empty Dashboard says “No admin resources declared”. Missing observation
65
+ snapshots stay unavailable, never fabricated healthy or zero values.
66
+
67
+ ## Optional charts and CSS
68
+
69
+ Root imports no chart implementation and re-exports no sibling components.
70
+ Opt in explicitly, or supply another renderer with the same existing props:
71
+
72
+ ```tsx
73
+ import { renderAdminSeries } from '@hollis-labs/kit-admin/charts'
74
+ // <AdminShell {...state} renderSeries={renderAdminSeries} />
75
+ ```
76
+
77
+ The adapter delegates to kit-observe `/charts`, which delegates to dashboard
78
+ `TimestampSampleChart`; it does not copy chart code or synthesize history.
79
+ Dashboard remains a dependency for navigation/layout even without series.
80
+ A host using Tailwind v4 imports the theme and each composition's class sources:
81
+
82
+ ```css
83
+ @import '@hollis-labs/kit-dashboard/theme.css';
84
+ @import '@hollis-labs/kit-settings/source.css';
85
+ @import '@hollis-labs/kit-observe/source.css';
86
+ @import '@hollis-labs/kit-admin/source.css';
87
+ ```
88
+
89
+ Set the host's theme and document shell reset as usual. Style evidence uses
90
+ `sysop-p4-white` and includes dashboard CSS. Internal ranges are components and
91
+ dashboard `^0.4.0`, settings `^0.2.0`, observe `^0.1.1`, tokens `^0.4.0`; React 19,
92
+ Tailwind 4, Base UI and lucide use the workspace's existing peers.
93
+
94
+ ## Local fixture review
95
+
96
+ ```bash
97
+ npm run build --workspace=@hollis-labs/kit-admin
98
+ npm run demo:build --workspace=@hollis-labs/kit-admin
99
+ npm run demo --workspace=@hollis-labs/kit-admin -- --host 127.0.0.1
100
+ ```
101
+
102
+ Package-local `prebuild` builds dashboard/settings/observe prerequisites because
103
+ npm's root workspace order visits kit-admin first. No root build script changes.
104
+ The demo imports the built kit-admin entrypoints. Both approved manifest examples
105
+ render all four pages; `?app=nanite|tachyon|tether&page=...` chooses a fixture.
106
+ `mode=setup`, `failure=first|refresh|group` and `embedded=yes` exercise alternate
107
+ composition/failure modes. The separate `settings-only.html` entry imports root
108
+ only. Build emits a manual module inventory for reviewing chart isolation.
109
+ Fixture settings snapshots are explicit existing kit-settings fixtures, not
110
+ manifest-derived defaults. Command callbacks record intent only, without saved
111
+ outcomes, persistence, actual validation, secret logging or restart.
112
+
113
+ [Browser evidence and reproduction](docs/evidence.md) covers the approved
114
+ examples at 1280/390 and a Tether-style desired-config/runtime split. Unit tests
115
+ exercise fail-closed behavior, controlled callbacks, alternate setup, field
116
+ focus and canonical placement. Fixtures establish page/state mapping,
117
+ independently of the real-backend proof below. App-owned wire adapters, Folio
118
+ wiring and application adoption remain separate work.
119
+
120
+ ## Proof and limits
121
+
122
+ Packed consumers have been exercised in Chromium against fixtures and against
123
+ one real Nanite backend in a **read-only configuration**: the page issues only
124
+ GET requests. The real-backend proof used an isolated scratch instance built
125
+ from production code, not a deployed production instance.
126
+
127
+ Not proven: writes through kit-admin against a real backend; Tachyon integration;
128
+ secret, wizard or conflict flows on a real backend; other browsers; or a shared
129
+ typed read client. Backend atomicity and two-app acceptance are not established
130
+ by the read-only Nanite proof.
package/dist/admin.js ADDED
@@ -0,0 +1,160 @@
1
+ import { jsx as e, jsxs as m, Fragment as $ } from "react/jsx-runtime";
2
+ import { SquareTerminal as j, Activity as O, Settings as V, LayoutDashboard as z } from "lucide-react";
3
+ import { Callout as v, AppShell as I, Button as E } from "@hollis-labs/design-components";
4
+ import { NavRail as M, PageHeader as W } from "@hollis-labs/kit-dashboard/ui";
5
+ import { ListPageLayout as G } from "@hollis-labs/kit-dashboard/layout";
6
+ import { settingsMetadataProblem as D, SettingsProvenanceRenderer as H, SettingsWizard as q } from "@hollis-labs/kit-settings";
7
+ import { HealthSummary as B, ObservationStatus as S, StatCollection as F, DiagnosticPanel as U } from "@hollis-labs/kit-observe";
8
+ import { adminManifestProblem as P, adminPages as R } from "./model.js";
9
+ const y = { dashboard: "Dashboard", settings: "Settings", status: "Status", diagnostics: "Diagnostics" }, J = { dashboard: z, settings: V, status: O, diagnostics: j };
10
+ function K(i) {
11
+ const { discovery: n, contextKey: c } = i;
12
+ if (!(n.contextKey !== c || P(n.manifest)))
13
+ return n.manifest;
14
+ }
15
+ function L({ destination: i, children: n }) {
16
+ return i.href !== void 0 ? /* @__PURE__ */ e("a", { className: "break-words text-control text-primary underline underline-offset-2 focus-visible:outline-ring", href: i.href, children: n }) : /* @__PURE__ */ e(E, { type: "button", size: "sm", variant: "outline", onClick: i.onSelect, children: n });
17
+ }
18
+ function f({ children: i }) {
19
+ return /* @__PURE__ */ e("p", { role: "status", className: "text-control text-fg-secondary", children: i });
20
+ }
21
+ function T({ manifest: i, props: n }) {
22
+ return /* @__PURE__ */ e("nav", { "aria-label": "Settings groups", className: "flex flex-wrap gap-3", children: i.settings.map((c) => /* @__PURE__ */ e(L, { destination: n.destination({ page: "settings", groupId: c.id }), children: c.label }, c.id)) });
23
+ }
24
+ function Q(i) {
25
+ const n = K(i), c = n ? R(n) : ["dashboard"];
26
+ return /* @__PURE__ */ e(M, { logoLabel: (n == null ? void 0 : n.app.label) ?? "Admin", items: c.map((l) => {
27
+ const a = J[l];
28
+ return { key: l, label: y[l], icon: /* @__PURE__ */ e(a, { className: "size-4", "aria-hidden": !0 }), active: i.selection.page === l, ...i.destination({ page: l }) };
29
+ }) });
30
+ }
31
+ function X({ props: i, manifest: n }) {
32
+ var N, A, _, C, k;
33
+ const { selection: c, settings: l = {}, settingsActions: a, setup: p } = i, o = i.discovery.phase === "ready", u = (d) => o && (d == null ? void 0 : d.phase) === "ready" && !!d.state, s = n.settings.find((d) => d.id === c.groupId), g = Object.fromEntries(n.settings.map((d) => {
34
+ var b;
35
+ return [d.id, (b = l[d.id]) == null ? void 0 : b.state];
36
+ })), t = (d, b) => {
37
+ u(l[d]) && (a == null || a.onDraftChange(d, b));
38
+ }, r = c.mode !== "setup";
39
+ let h = s, w = g;
40
+ const x = s && g[s.id];
41
+ return r && !a && s && x && !D(s, x) && (h = { ...s, capabilities: {
42
+ ...s.capabilities,
43
+ can_validate: !1,
44
+ can_update: !1,
45
+ can_reset: !1
46
+ } }, w = { ...g, [s.id]: { ...x, draft: {}, values: Object.fromEntries(
47
+ Object.entries(x.values).map(([d, b]) => [d, b.editable ? { ...b, editable: !1, read_only_reason: "This view has no editing actions." } : b])
48
+ ) } }), n.settings.length ? /* @__PURE__ */ m("section", { "aria-label": "Admin Settings", className: "flex min-w-0 flex-col gap-4", children: [
49
+ /* @__PURE__ */ e(T, { manifest: n, props: i }),
50
+ r && (s != null && s.scope) ? /* @__PURE__ */ m(f, { children: [
51
+ "Scope: ",
52
+ s.scope.kind,
53
+ s.scope.id ? ` / ${s.scope.id}` : ""
54
+ ] }) : null,
55
+ r ? c.groupId ? s ? /* @__PURE__ */ m($, { children: [
56
+ ((N = l[s.id]) == null ? void 0 : N.phase) === "error" ? /* @__PURE__ */ m(v, { tone: "danger", title: "Settings read failed", children: [
57
+ ((A = l[s.id]) == null ? void 0 : A.error) ?? "The host could not read this group.",
58
+ " ",
59
+ (_ = l[s.id]) != null && _.state ? "Previous snapshot retained; writes suspended." : "No successful snapshot is available."
60
+ ] }) : null,
61
+ ((C = l[s.id]) == null ? void 0 : C.phase) === "loading" ? /* @__PURE__ */ e(f, { children: (k = l[s.id]) != null && k.state ? "Refreshing settings snapshot; writes suspended." : "Waiting for a settings snapshot." }) : null,
62
+ /* @__PURE__ */ e("fieldset", { disabled: !u(l[s.id]) || !a, className: "min-w-0 border-0 p-0", children: /* @__PURE__ */ e(
63
+ H,
64
+ {
65
+ contractVersion: n.contract_version,
66
+ groups: [h],
67
+ states: w,
68
+ onDraftChange: t,
69
+ readOnlyContext: !a,
70
+ onSave: u(l[s.id]) && (a != null && a.onSave) ? a.onSave : void 0,
71
+ onReset: u(l[s.id]) && (a != null && a.onReset) ? a.onReset : void 0,
72
+ onValidate: u(l[s.id]) && (a != null && a.onValidate) ? a.onValidate : void 0,
73
+ onApply: u(l[s.id]) && (a != null && a.onApply) ? a.onApply : void 0
74
+ },
75
+ `${i.contextKey}:${n.app.id}:${n.revision}:${s.id}`
76
+ ) })
77
+ ] }) : /* @__PURE__ */ e(v, { tone: "warning", title: "Settings group unavailable", children: "This declaration does not contain the selected group." }) : /* @__PURE__ */ e(f, { children: "Choose a settings group." }) : p ? /* @__PURE__ */ m($, { children: [
78
+ /* @__PURE__ */ e(f, { children: "Setup edits the same Settings groups. Source, locks and pending application remain in canonical Settings." }),
79
+ i.setupContext,
80
+ n.settings.some((d) => !u(l[d.id]) || g[d.id] && D(d, g[d.id])) ? /* @__PURE__ */ e(v, { tone: "warning", title: "Setup unavailable", children: "Every setup group needs a current, supported settings snapshot and provenance. Normal Settings remains available per group." }) : /* @__PURE__ */ e("fieldset", { disabled: !o || !a, className: "min-w-0 border-0 p-0", children: /* @__PURE__ */ e(
81
+ q,
82
+ {
83
+ ...p,
84
+ contractVersion: n.contract_version,
85
+ groups: n.settings,
86
+ states: g,
87
+ onDraftChange: t,
88
+ busy: !o || !a || p.busy,
89
+ onComplete: (d) => {
90
+ o && a && p.onComplete(d);
91
+ },
92
+ onCheck: p.onCheck ? (d) => {
93
+ var b;
94
+ o && a && ((b = p.onCheck) == null || b.call(p, d));
95
+ } : void 0
96
+ },
97
+ `${i.contextKey}:${n.app.id}:${n.revision}:setup`
98
+ ) })
99
+ ] }) : /* @__PURE__ */ e(f, { children: "Setup unavailable: the host has not supplied setup controls." })
100
+ ] }) : /* @__PURE__ */ e(f, { children: "Settings unsupported: no settings groups declared." });
101
+ }
102
+ function Y(i) {
103
+ const { discovery: n, selection: c, observations: l = {}, nowMs: a } = i;
104
+ if (n.contextKey !== i.contextKey) return /* @__PURE__ */ e(v, { tone: "warning", title: "Admin context unavailable", children: "The host must supply discovery and snapshots for the current authorized context." });
105
+ if (!n.manifest) return n.phase === "loading" ? /* @__PURE__ */ e(f, { children: "Loading admin declarations." }) : /* @__PURE__ */ e(v, { tone: "danger", title: "Admin unavailable", children: n.error ?? "No admin declaration is available." });
106
+ const p = P(n.manifest);
107
+ if (p) return /* @__PURE__ */ e(v, { tone: "danger", title: "Admin declaration unavailable", children: p });
108
+ const o = n.manifest, u = (t) => ({ phase: "idle", nowMs: a, staleAfterMs: t }), s = R(o);
109
+ let g;
110
+ return c.page === "dashboard" ? g = /* @__PURE__ */ m("section", { "aria-label": "Admin directory", className: "flex min-w-0 flex-col gap-4", children: [
111
+ /* @__PURE__ */ e("h2", { className: "text-heading text-fg", children: o.app.label }),
112
+ /* @__PURE__ */ m(f, { children: [
113
+ "Declaration revision: ",
114
+ o.revision
115
+ ] }),
116
+ s.length === 1 ? /* @__PURE__ */ e(f, { children: "No admin resources declared" }) : /* @__PURE__ */ e("nav", { "aria-label": "Admin directory links", className: "flex flex-wrap gap-3", children: s.filter((t) => t !== "dashboard").map((t) => /* @__PURE__ */ e(L, { destination: i.destination({ page: t }), children: y[t] }, t)) }),
117
+ o.settings.length ? /* @__PURE__ */ e(T, { manifest: o, props: i }) : null
118
+ ] }) : c.page === "settings" ? g = /* @__PURE__ */ e(X, { props: i, manifest: o }) : c.page === "status" ? g = !o.health.length && !o.stats.length ? /* @__PURE__ */ e(f, { children: "Status unsupported: no health or stats resources declared." }) : /* @__PURE__ */ m("section", { "aria-label": "Admin Status", className: "flex min-w-0 flex-col gap-4", children: [
119
+ o.health.map((t) => {
120
+ var h;
121
+ const r = (h = l.health) == null ? void 0 : h[t.id];
122
+ return r ? /* @__PURE__ */ e(B, { ...r, label: t.label }, t.id) : /* @__PURE__ */ e(S, { label: t.label, observation: u(t.stale_after_ms) }, t.id);
123
+ }),
124
+ o.stats.length ? /* @__PURE__ */ e(F, { label: "Stats", rows: o.stats.map((t) => {
125
+ var h;
126
+ const r = (h = l.stats) == null ? void 0 : h[t.id];
127
+ return { id: t.id, label: t.label, unit: t.unit, kind: t.kind, value: (r == null ? void 0 : r.value) ?? null, observation: (r == null ? void 0 : r.observation) ?? u(t.stale_after_ms) };
128
+ }) }) : null
129
+ ] }) : c.page === "diagnostics" ? g = !o.series.length && !o.diagnostics.length ? /* @__PURE__ */ e(f, { children: "Diagnostics unsupported: no series or diagnostic resources declared." }) : /* @__PURE__ */ m("section", { "aria-label": "Admin Diagnostics", className: "flex min-w-0 flex-col gap-4", children: [
130
+ o.series.map((t) => {
131
+ var h;
132
+ const r = (h = l.series) == null ? void 0 : h[t.id];
133
+ return /* @__PURE__ */ e("section", { className: "min-w-0", children: i.renderSeries ? r ? i.renderSeries({ ...r, label: t.label, unit: t.unit, kind: t.kind, bounds: { maxPoints: t.max_points, maxWindowSeconds: t.max_window_seconds } }) : /* @__PURE__ */ e(S, { label: t.label, observation: u(t.stale_after_ms) }) : /* @__PURE__ */ m(v, { tone: "warning", title: "Series renderer unavailable", children: [
134
+ t.label,
135
+ ": the host has not supplied a series renderer."
136
+ ] }) }, t.id);
137
+ }),
138
+ o.diagnostics.map((t) => {
139
+ var h;
140
+ const r = (h = l.diagnostics) == null ? void 0 : h[t.id];
141
+ return r ? /* @__PURE__ */ e(U, { ...r, label: t.label, schema: t.schema }, t.id) : /* @__PURE__ */ e(S, { label: t.label, observation: u(t.stale_after_ms) }, t.id);
142
+ })
143
+ ] }) : g = /* @__PURE__ */ e(v, { tone: "warning", title: "Admin page unavailable", children: "The host selected an unsupported page." }), /* @__PURE__ */ m("div", { className: "mx-auto flex w-full min-w-0 max-w-5xl flex-col gap-4 p-4 text-control text-fg", children: [
144
+ n.phase !== "ready" ? /* @__PURE__ */ m(v, { tone: "warning", title: "Previous declarations retained", children: [
145
+ n.error ?? "Refreshing admin declarations.",
146
+ " Content uses the last declaration; writes are suspended until discovery succeeds."
147
+ ] }) : null,
148
+ g
149
+ ] }, `${i.contextKey}:${o.app.id}:${o.revision}`);
150
+ }
151
+ function oe(i) {
152
+ const n = K(i);
153
+ return /* @__PURE__ */ e(I, { nav: /* @__PURE__ */ e(Q, { ...i }), children: /* @__PURE__ */ e(G, { header: /* @__PURE__ */ e(W, { title: `${(n == null ? void 0 : n.app.label) ?? "Admin"} / ${y[i.selection.page] ?? "Unavailable"}` }), children: /* @__PURE__ */ e(Y, { ...i }) }) });
154
+ }
155
+ export {
156
+ Y as AdminContent,
157
+ Q as AdminNavigation,
158
+ oe as AdminShell
159
+ };
160
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sources":["../src/admin.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport { Activity, LayoutDashboard, Settings, SquareTerminal } from 'lucide-react'\nimport { AppShell, Button, Callout } from '@hollis-labs/design-components'\nimport { NavRail, PageHeader } from '@hollis-labs/kit-dashboard/ui'\nimport { ListPageLayout } from '@hollis-labs/kit-dashboard/layout'\nimport { SettingsProvenanceRenderer, SettingsWizard, settingsMetadataProblem } from '@hollis-labs/kit-settings'\nimport { DiagnosticPanel, HealthSummary, ObservationStatus, StatCollection } from '@hollis-labs/kit-observe'\nimport type { ObservationState } from '@hollis-labs/kit-observe'\nimport { adminManifestProblem, adminPages } from './model'\nimport type { AdminContentProps, AdminDestination, AdminManifest, AdminPage, AdminSettingsRead } from './types'\n\nconst labels = { dashboard: 'Dashboard', settings: 'Settings', status: 'Status', diagnostics: 'Diagnostics' } as const\nconst icons = { dashboard: LayoutDashboard, settings: Settings, status: Activity, diagnostics: SquareTerminal }\nfunction available(props: AdminContentProps): AdminManifest | undefined {\n const { discovery, contextKey } = props\n if (discovery.contextKey !== contextKey || adminManifestProblem(discovery.manifest)) return undefined\n return discovery.manifest\n}\nfunction Destination({ destination, children }: { destination: AdminDestination; children: ReactNode }) {\n return destination.href !== undefined\n ? <a className=\"break-words text-control text-primary underline underline-offset-2 focus-visible:outline-ring\" href={destination.href}>{children}</a>\n : <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={destination.onSelect}>{children}</Button>\n}\nfunction Notice({ children }: { children: ReactNode }) {\n return <p role=\"status\" className=\"text-control text-fg-secondary\">{children}</p>\n}\nfunction GroupLinks({ manifest, props }: { manifest: AdminManifest; props: AdminContentProps }) {\n return <nav aria-label=\"Settings groups\" className=\"flex flex-wrap gap-3\">{manifest.settings.map(group => <Destination key={group.id} destination={props.destination({ page: 'settings', groupId: group.id })}>{group.label}</Destination>)}</nav>\n}\n\n/** Navigation is only a projection of declared sections; the host owns routing/history. */\nexport function AdminNavigation(props: AdminContentProps) {\n const manifest = available(props)\n const pages: readonly AdminPage[] = manifest ? adminPages(manifest) : ['dashboard']\n return <NavRail logoLabel={manifest?.app.label ?? 'Admin'} items={pages.map(page => {\n const Icon = icons[page]\n return { key: page, label: labels[page], icon: <Icon className=\"size-4\" aria-hidden />, active: props.selection.page === page, ...props.destination({ page }) }\n })} />\n}\n\nfunction SettingsPage({ props, manifest }: { props: AdminContentProps; manifest: AdminManifest }) {\n const { selection, settings = {}, settingsActions: actions, setup } = props\n const contextReady = props.discovery.phase === 'ready'\n const readReady = (read: AdminSettingsRead | undefined) => contextReady && read?.phase === 'ready' && !!read.state\n const selected = manifest.settings.find(group => group.id === selection.groupId)\n const states = Object.fromEntries(manifest.settings.map(group => [group.id, settings[group.id]?.state]))\n const change: NonNullable<AdminContentProps['settingsActions']>['onDraftChange'] = (id, draft) => { if (readReady(settings[id])) actions?.onDraftChange(id, draft) }\n const normal = selection.mode !== 'setup'\n let presentedGroup = selected, presentedStates = states\n const state = selected && states[selected.id]\n // Limit only this view; validate the host inputs before copying so malformed\n // permissions/provenance stay unavailable rather than being repaired here.\n if (normal && !actions && selected && state && !settingsMetadataProblem(selected, state)) {\n presentedGroup = { ...selected, capabilities: {\n ...(selected.capabilities as Record<string, unknown>), can_validate: false, can_update: false, can_reset: false,\n } }\n presentedStates = { ...states, [selected.id]: { ...state, draft: {}, values: Object.fromEntries(\n Object.entries(state.values).map(([key, value]) => [key, value.editable\n ? { ...value, editable: false, read_only_reason: 'This view has no editing actions.' } : value]),\n ) } }\n }\n if (!manifest.settings.length) return <Notice>Settings unsupported: no settings groups declared.</Notice>\n return <section aria-label=\"Admin Settings\" className=\"flex min-w-0 flex-col gap-4\">\n <GroupLinks manifest={manifest} props={props} />\n {normal && selected?.scope ? <Notice>Scope: {selected.scope.kind}{selected.scope.id ? ` / ${selected.scope.id}` : ''}</Notice> : null}\n {normal ? !selection.groupId ? <Notice>Choose a settings group.</Notice> : !selected ? <Callout tone=\"warning\" title=\"Settings group unavailable\">This declaration does not contain the selected group.</Callout> : <>\n {settings[selected.id]?.phase === 'error' ? <Callout tone=\"danger\" title=\"Settings read failed\">{settings[selected.id]?.error ?? 'The host could not read this group.'} {settings[selected.id]?.state ? 'Previous snapshot retained; writes suspended.' : 'No successful snapshot is available.'}</Callout> : null}\n {settings[selected.id]?.phase === 'loading' ? <Notice>{settings[selected.id]?.state ? 'Refreshing settings snapshot; writes suspended.' : 'Waiting for a settings snapshot.'}</Notice> : null}\n <fieldset disabled={!readReady(settings[selected.id]) || !actions} className=\"min-w-0 border-0 p-0\">\n <SettingsProvenanceRenderer key={`${props.contextKey}:${manifest.app.id}:${manifest.revision}:${selected.id}`}\n contractVersion={manifest.contract_version} groups={[presentedGroup!]} states={presentedStates} onDraftChange={change} readOnlyContext={!actions}\n onSave={readReady(settings[selected.id]) && actions?.onSave ? actions.onSave : undefined}\n onReset={readReady(settings[selected.id]) && actions?.onReset ? actions.onReset : undefined}\n onValidate={readReady(settings[selected.id]) && actions?.onValidate ? actions.onValidate : undefined}\n onApply={readReady(settings[selected.id]) && actions?.onApply ? actions.onApply : undefined} />\n </fieldset>\n </> : !setup ? <Notice>Setup unavailable: the host has not supplied setup controls.</Notice> : <>\n <Notice>Setup edits the same Settings groups. Source, locks and pending application remain in canonical Settings.</Notice>\n {props.setupContext}\n {manifest.settings.some(group => !readReady(settings[group.id]) || (states[group.id] && settingsMetadataProblem(group, states[group.id]!))) ? <Callout tone=\"warning\" title=\"Setup unavailable\">Every setup group needs a current, supported settings snapshot and provenance. Normal Settings remains available per group.</Callout> : <fieldset disabled={!contextReady || !actions} className=\"min-w-0 border-0 p-0\">\n <SettingsWizard key={`${props.contextKey}:${manifest.app.id}:${manifest.revision}:setup`} {...setup}\n contractVersion={manifest.contract_version} groups={manifest.settings} states={states} onDraftChange={change}\n busy={!contextReady || !actions || setup.busy}\n onComplete={plan => { if (contextReady && actions) setup.onComplete(plan) }}\n onCheck={setup.onCheck ? id => { if (contextReady && actions) setup.onCheck?.(id) } : undefined} />\n </fieldset>}\n </>}\n </section>\n}\n\n/** Inner region for an existing host shell; no viewport wrapper, effects or local data store. */\nexport function AdminContent(props: AdminContentProps) {\n const { discovery, selection, observations = {}, nowMs } = props\n if (discovery.contextKey !== props.contextKey) return <Callout tone=\"warning\" title=\"Admin context unavailable\">The host must supply discovery and snapshots for the current authorized context.</Callout>\n if (!discovery.manifest) return discovery.phase === 'loading' ? <Notice>Loading admin declarations.</Notice> : <Callout tone=\"danger\" title=\"Admin unavailable\">{discovery.error ?? 'No admin declaration is available.'}</Callout>\n const problem = adminManifestProblem(discovery.manifest)\n if (problem) return <Callout tone=\"danger\" title=\"Admin declaration unavailable\">{problem}</Callout>\n const manifest = discovery.manifest\n const observation = (staleAfterMs: number): ObservationState => ({ phase: 'idle', nowMs, staleAfterMs })\n const pages = adminPages(manifest)\n let content: ReactNode\n if (selection.page === 'dashboard') content = <section aria-label=\"Admin directory\" className=\"flex min-w-0 flex-col gap-4\">\n <h2 className=\"text-heading text-fg\">{manifest.app.label}</h2>\n <Notice>Declaration revision: {manifest.revision}</Notice>\n {pages.length === 1 ? <Notice>No admin resources declared</Notice> : <nav aria-label=\"Admin directory links\" className=\"flex flex-wrap gap-3\">{pages.filter(page => page !== 'dashboard').map(page => <Destination key={page} destination={props.destination({ page })}>{labels[page]}</Destination>)}</nav>}\n {manifest.settings.length ? <GroupLinks manifest={manifest} props={props} /> : null}\n </section>\n else if (selection.page === 'settings') content = <SettingsPage props={props} manifest={manifest} />\n else if (selection.page === 'status') content = !manifest.health.length && !manifest.stats.length ? <Notice>Status unsupported: no health or stats resources declared.</Notice> : <section aria-label=\"Admin Status\" className=\"flex min-w-0 flex-col gap-4\">\n {manifest.health.map(resource => {\n const state = observations.health?.[resource.id]\n return state ? <HealthSummary key={resource.id} {...state} label={resource.label} /> : <ObservationStatus key={resource.id} label={resource.label} observation={observation(resource.stale_after_ms)} />\n })}\n {manifest.stats.length ? <StatCollection label=\"Stats\" rows={manifest.stats.map(resource => {\n const state = observations.stats?.[resource.id]\n return { id: resource.id, label: resource.label, unit: resource.unit, kind: resource.kind, value: state?.value ?? null, observation: state?.observation ?? observation(resource.stale_after_ms) }\n })} /> : null}\n </section>\n else if (selection.page === 'diagnostics') content = !manifest.series.length && !manifest.diagnostics.length ? <Notice>Diagnostics unsupported: no series or diagnostic resources declared.</Notice> : <section aria-label=\"Admin Diagnostics\" className=\"flex min-w-0 flex-col gap-4\">\n {manifest.series.map(resource => {\n const state = observations.series?.[resource.id]\n return <section key={resource.id} className=\"min-w-0\">{!props.renderSeries ? <Callout tone=\"warning\" title=\"Series renderer unavailable\">{resource.label}: the host has not supplied a series renderer.</Callout> : !state ? <ObservationStatus label={resource.label} observation={observation(resource.stale_after_ms)} /> : props.renderSeries({ ...state, label: resource.label, unit: resource.unit, kind: resource.kind, bounds: { maxPoints: resource.max_points, maxWindowSeconds: resource.max_window_seconds } })}</section>\n })}\n {manifest.diagnostics.map(resource => {\n const state = observations.diagnostics?.[resource.id]\n return state ? <DiagnosticPanel key={resource.id} {...state} label={resource.label} schema={resource.schema} /> : <ObservationStatus key={resource.id} label={resource.label} observation={observation(resource.stale_after_ms)} />\n })}\n </section>\n else content = <Callout tone=\"warning\" title=\"Admin page unavailable\">The host selected an unsupported page.</Callout>\n return <div key={`${props.contextKey}:${manifest.app.id}:${manifest.revision}`} className=\"mx-auto flex w-full min-w-0 max-w-5xl flex-col gap-4 p-4 text-control text-fg\">\n {discovery.phase !== 'ready' ? <Callout tone=\"warning\" title=\"Previous declarations retained\">{discovery.error ?? 'Refreshing admin declarations.'} Content uses the last declaration; writes are suspended until discovery succeeds.</Callout> : null}\n {content}\n </div>\n}\n\n/** Standalone viewport composition. Use AdminContent inside an existing AppShell instead. */\nexport function AdminShell(props: AdminContentProps) {\n const manifest = available(props)\n return <AppShell nav={<AdminNavigation {...props} />}>\n <ListPageLayout header={<PageHeader title={`${manifest?.app.label ?? 'Admin'} / ${labels[props.selection.page] ?? 'Unavailable'}`} />}>\n <AdminContent {...props} />\n </ListPageLayout>\n </AppShell>\n}\n"],"names":["labels","icons","LayoutDashboard","Settings","Activity","SquareTerminal","available","props","discovery","contextKey","adminManifestProblem","Destination","destination","children","jsx","Button","Notice","GroupLinks","manifest","group","AdminNavigation","pages","adminPages","NavRail","page","Icon","SettingsPage","selection","settings","actions","setup","contextReady","readReady","read","selected","states","_a","change","id","draft","normal","presentedGroup","presentedStates","state","settingsMetadataProblem","key","value","jsxs","Fragment","Callout","_b","_c","_d","_e","SettingsProvenanceRenderer","SettingsWizard","plan","AdminContent","observations","nowMs","problem","observation","staleAfterMs","content","resource","HealthSummary","ObservationStatus","StatCollection","DiagnosticPanel","AdminShell","AppShell","ListPageLayout","PageHeader"],"mappings":"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"}
package/dist/charts.js ADDED
@@ -0,0 +1,9 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { SampleSeriesView as i } from "@hollis-labs/kit-observe/charts";
3
+ function n(r) {
4
+ return /* @__PURE__ */ e(i, { ...r });
5
+ }
6
+ export {
7
+ n as renderAdminSeries
8
+ };
9
+ //# sourceMappingURL=charts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"charts.js","sources":["../src/charts.tsx"],"sourcesContent":["import { SampleSeriesView, type SampleSeriesViewProps } from '@hollis-labs/kit-observe/charts'\n\n/** Supply to AdminContent/AdminShell renderSeries. The root never imports this module. */\nexport function renderAdminSeries(props: SampleSeriesViewProps) {\n return <SampleSeriesView {...props} />\n}\n"],"names":["renderAdminSeries","props","jsx","SampleSeriesView"],"mappings":";;AAGO,SAASA,EAAkBC,GAA8B;AAC9D,SAAO,gBAAAC,EAACC,GAAA,EAAkB,GAAGF,EAAA,CAAO;AACtC;"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import { AdminContent as m, AdminNavigation as e, AdminShell as o } from "./admin.js";
2
+ import { adminManifestProblem as t, adminPages as d } from "./model.js";
3
+ export {
4
+ m as AdminContent,
5
+ e as AdminNavigation,
6
+ o as AdminShell,
7
+ t as adminManifestProblem,
8
+ d as adminPages
9
+ };
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
package/dist/model.js ADDED
@@ -0,0 +1,24 @@
1
+ const n = (t) => typeof t == "object" && t !== null && !Array.isArray(t), r = (t) => typeof t == "string" && t.trim().length > 0, d = { settings: "settings", health: "status", stats: "status", series: "diagnostics", diagnostics: "diagnostics" };
2
+ function c(t) {
3
+ if (!n(t)) return "Malformed admin manifest.";
4
+ if (t.contract_version !== 1) return "Unsupported admin contract version.";
5
+ if (!n(t.app) || !r(t.app.id) || !r(t.app.label) || !r(t.revision)) return "Malformed admin identity or declaration revision.";
6
+ for (const [e, i] of Object.entries(d)) {
7
+ const o = t[e];
8
+ if (!Array.isArray(o)) return `Malformed admin manifest: missing ${e} array.`;
9
+ const a = /* @__PURE__ */ new Set();
10
+ for (const s of o) {
11
+ if (!n(s) || !r(s.id) || !r(s.label) || a.has(s.id)) return `Malformed ${e} resource identity.`;
12
+ if (a.add(s.id), s.section !== i) return `Contradictory ${e} section: resources must declare ${i}.`;
13
+ if (e !== "settings" && (typeof s.stale_after_ms != "number" || !Number.isFinite(s.stale_after_ms) || s.stale_after_ms <= 0)) return `Unsupported ${e} observation age declaration.`;
14
+ }
15
+ }
16
+ }
17
+ function f(t) {
18
+ return ["dashboard", ...t.settings.length ? ["settings"] : [], ...t.health.length || t.stats.length ? ["status"] : [], ...t.series.length || t.diagnostics.length ? ["diagnostics"] : []];
19
+ }
20
+ export {
21
+ c as adminManifestProblem,
22
+ f as adminPages
23
+ };
24
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sources":["../src/model.ts"],"sourcesContent":["import type { AdminManifest, AdminPage } from './types'\n\nconst record = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v)\nconst text = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0\nconst sections = { settings: 'settings', health: 'status', stats: 'status', series: 'diagnostics', diagnostics: 'diagnostics' } as const\n\n/** Presentation fence, not a wire validator. Never relocate a contradictory resource. */\nexport function adminManifestProblem(value: unknown): string | undefined {\n if (!record(value)) return 'Malformed admin manifest.'\n if (value.contract_version !== 1) return 'Unsupported admin contract version.'\n if (!record(value.app) || !text(value.app.id) || !text(value.app.label) || !text(value.revision)) return 'Malformed admin identity or declaration revision.'\n for (const [kind, section] of Object.entries(sections)) {\n const resources = value[kind]\n if (!Array.isArray(resources)) return `Malformed admin manifest: missing ${kind} array.`\n const ids = new Set<string>()\n for (const resource of resources) {\n if (!record(resource) || !text(resource.id) || !text(resource.label) || ids.has(resource.id)) return `Malformed ${kind} resource identity.`\n ids.add(resource.id)\n if (resource.section !== section) return `Contradictory ${kind} section: resources must declare ${section}.`\n if (kind !== 'settings' && (typeof resource.stale_after_ms !== 'number' || !Number.isFinite(resource.stale_after_ms) || resource.stale_after_ms <= 0)) return `Unsupported ${kind} observation age declaration.`\n }\n }\n}\nexport function adminPages(manifest: AdminManifest): readonly AdminPage[] {\n return ['dashboard', ...(manifest.settings.length ? ['settings' as const] : []), ...(manifest.health.length || manifest.stats.length ? ['status' as const] : []), ...(manifest.series.length || manifest.diagnostics.length ? ['diagnostics' as const] : [])]\n}\n"],"names":["record","v","text","sections","adminManifestProblem","value","kind","section","resources","ids","resource","adminPages","manifest"],"mappings":"AAEA,MAAMA,IAAS,CAACC,MAA6C,OAAOA,KAAM,YAAYA,MAAM,QAAQ,CAAC,MAAM,QAAQA,CAAC,GAC9GC,IAAO,CAACD,MAA4B,OAAOA,KAAM,YAAYA,EAAE,OAAO,SAAS,GAC/EE,IAAW,EAAE,UAAU,YAAY,QAAQ,UAAU,OAAO,UAAU,QAAQ,eAAe,aAAa,cAAA;AAGzG,SAASC,EAAqBC,GAAoC;AACvE,MAAI,CAACL,EAAOK,CAAK,EAAG,QAAO;AAC3B,MAAIA,EAAM,qBAAqB,EAAG,QAAO;AACzC,MAAI,CAACL,EAAOK,EAAM,GAAG,KAAK,CAACH,EAAKG,EAAM,IAAI,EAAE,KAAK,CAACH,EAAKG,EAAM,IAAI,KAAK,KAAK,CAACH,EAAKG,EAAM,QAAQ,EAAG,QAAO;AACzG,aAAW,CAACC,GAAMC,CAAO,KAAK,OAAO,QAAQJ,CAAQ,GAAG;AACtD,UAAMK,IAAYH,EAAMC,CAAI;AAC5B,QAAI,CAAC,MAAM,QAAQE,CAAS,EAAG,QAAO,qCAAqCF,CAAI;AAC/E,UAAMG,wBAAU,IAAA;AAChB,eAAWC,KAAYF,GAAW;AAChC,UAAI,CAACR,EAAOU,CAAQ,KAAK,CAACR,EAAKQ,EAAS,EAAE,KAAK,CAACR,EAAKQ,EAAS,KAAK,KAAKD,EAAI,IAAIC,EAAS,EAAE,EAAG,QAAO,aAAaJ,CAAI;AAEtH,UADAG,EAAI,IAAIC,EAAS,EAAE,GACfA,EAAS,YAAYH,UAAgB,iBAAiBD,CAAI,oCAAoCC,CAAO;AACzG,UAAID,MAAS,eAAe,OAAOI,EAAS,kBAAmB,YAAY,CAAC,OAAO,SAASA,EAAS,cAAc,KAAKA,EAAS,kBAAkB,GAAI,QAAO,eAAeJ,CAAI;AAAA,IACnL;AAAA,EACF;AACF;AACO,SAASK,EAAWC,GAA+C;AACxE,SAAO,CAAC,aAAa,GAAIA,EAAS,SAAS,SAAS,CAAC,UAAmB,IAAI,CAAA,GAAK,GAAIA,EAAS,OAAO,UAAUA,EAAS,MAAM,SAAS,CAAC,QAAiB,IAAI,IAAK,GAAIA,EAAS,OAAO,UAAUA,EAAS,YAAY,SAAS,CAAC,aAAsB,IAAI,CAAA,CAAG;AAC9P;"}
@@ -0,0 +1,7 @@
1
+ import { AdminContentProps } from './types';
2
+ /** Navigation is only a projection of declared sections; the host owns routing/history. */
3
+ export declare function AdminNavigation(props: AdminContentProps): import("react").JSX.Element;
4
+ /** Inner region for an existing host shell; no viewport wrapper, effects or local data store. */
5
+ export declare function AdminContent(props: AdminContentProps): import("react").JSX.Element;
6
+ /** Standalone viewport composition. Use AdminContent inside an existing AppShell instead. */
7
+ export declare function AdminShell(props: AdminContentProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import { SampleSeriesViewProps } from '@hollis-labs/kit-observe/charts';
2
+ /** Supply to AdminContent/AdminShell renderSeries. The root never imports this module. */
3
+ export declare function renderAdminSeries(props: SampleSeriesViewProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ export { AdminContent, AdminNavigation, AdminShell } from './admin';
2
+ export { adminManifestProblem, adminPages } from './model';
3
+ export type { AdminContentProps, AdminDeclaration, AdminObservationDeclaration, AdminSettingsDeclaration, AdminStatDeclaration, AdminSeriesDeclaration, AdminDiagnosticDeclaration, AdminManifest, AdminPage, AdminTarget, AdminDestination, AdminSelection, AdminDiscovery, AdminSettingsRead, AdminObservations } from './types';
@@ -0,0 +1,4 @@
1
+ import { AdminManifest, AdminPage } from './types';
2
+ /** Presentation fence, not a wire validator. Never relocate a contradictory resource. */
3
+ export declare function adminManifestProblem(value: unknown): string | undefined;
4
+ export declare function adminPages(manifest: AdminManifest): readonly AdminPage[];
@@ -0,0 +1,93 @@
1
+ import { ReactNode } from 'react';
2
+ import { SettingsGroup, SettingsProvenanceRendererProps, SettingsProvenanceState, SettingsWizardProps } from '@hollis-labs/kit-settings';
3
+ import { HealthSummaryProps, StatObservation, DiagnosticPanelProps, ObservationUnit, ObservationKind } from '@hollis-labs/kit-observe';
4
+ import { SampleSeriesViewProps } from '@hollis-labs/kit-observe/charts';
5
+ /** View projections only. The host validates wire schemas, endpoints, auth and bounds. */
6
+ export interface AdminDeclaration {
7
+ readonly id: string;
8
+ readonly label: string;
9
+ readonly section: string;
10
+ }
11
+ export interface AdminObservationDeclaration extends AdminDeclaration {
12
+ readonly stale_after_ms: number;
13
+ }
14
+ export interface AdminSettingsDeclaration extends SettingsGroup {
15
+ readonly section: string;
16
+ readonly scope?: {
17
+ readonly kind: string;
18
+ readonly id?: string;
19
+ };
20
+ }
21
+ export interface AdminStatDeclaration extends AdminObservationDeclaration {
22
+ readonly unit: ObservationUnit;
23
+ readonly kind: ObservationKind;
24
+ }
25
+ export interface AdminSeriesDeclaration extends AdminStatDeclaration {
26
+ readonly max_points: number;
27
+ readonly max_window_seconds: number;
28
+ }
29
+ export interface AdminDiagnosticDeclaration extends AdminObservationDeclaration {
30
+ readonly schema: DiagnosticPanelProps['schema'];
31
+ }
32
+ export interface AdminManifest {
33
+ readonly contract_version: number;
34
+ readonly app: {
35
+ readonly id: string;
36
+ readonly label: string;
37
+ };
38
+ readonly revision: string;
39
+ readonly settings: readonly AdminSettingsDeclaration[];
40
+ readonly health: readonly AdminObservationDeclaration[];
41
+ readonly stats: readonly AdminStatDeclaration[];
42
+ readonly series: readonly AdminSeriesDeclaration[];
43
+ readonly diagnostics: readonly AdminDiagnosticDeclaration[];
44
+ }
45
+ export type AdminPage = 'dashboard' | 'settings' | 'status' | 'diagnostics';
46
+ export interface AdminTarget {
47
+ readonly page: AdminPage;
48
+ readonly groupId?: string;
49
+ }
50
+ export type AdminDestination = {
51
+ readonly href: string;
52
+ readonly onSelect?: never;
53
+ } | {
54
+ readonly onSelect: () => void;
55
+ readonly href?: never;
56
+ };
57
+ export interface AdminSelection extends AdminTarget {
58
+ readonly mode?: 'edit' | 'setup';
59
+ }
60
+ export interface AdminDiscovery {
61
+ readonly phase: 'loading' | 'ready' | 'error';
62
+ /** Must match the active authorized host context; never retain a prior principal. */
63
+ readonly contextKey: string;
64
+ readonly manifest?: AdminManifest;
65
+ readonly error?: string;
66
+ }
67
+ export interface AdminSettingsRead {
68
+ readonly phase: 'loading' | 'ready' | 'error';
69
+ readonly state?: SettingsProvenanceState;
70
+ readonly error?: string;
71
+ }
72
+ export interface AdminObservations {
73
+ readonly health?: Readonly<Record<string, Omit<HealthSummaryProps, 'label'> | undefined>>;
74
+ readonly stats?: Readonly<Record<string, Pick<StatObservation, 'value' | 'observation'> | undefined>>;
75
+ readonly series?: Readonly<Record<string, Omit<SampleSeriesViewProps, 'label' | 'unit' | 'kind' | 'bounds'> | undefined>>;
76
+ readonly diagnostics?: Readonly<Record<string, Omit<DiagnosticPanelProps, 'label' | 'schema'> | undefined>>;
77
+ }
78
+ export interface AdminContentProps {
79
+ readonly contextKey: string;
80
+ readonly discovery: AdminDiscovery;
81
+ readonly selection: AdminSelection;
82
+ /** Host maps canonical targets to its routes or controlled navigation callbacks. */
83
+ readonly destination: (target: AdminTarget) => AdminDestination;
84
+ readonly settings?: Readonly<Record<string, AdminSettingsRead | undefined>>;
85
+ readonly settingsActions?: Pick<SettingsProvenanceRendererProps, 'onDraftChange' | 'onSave' | 'onReset' | 'onValidate' | 'onApply'>;
86
+ readonly setup?: Omit<SettingsWizardProps, 'contractVersion' | 'groups' | 'states' | 'onDraftChange'>;
87
+ /** Context/metadata beside the Wizard; never a second editable form. */
88
+ readonly setupContext?: ReactNode;
89
+ readonly observations?: AdminObservations;
90
+ readonly nowMs: number;
91
+ /** Explicit opt-in: root imports no chart implementation. See /charts. */
92
+ readonly renderSeries?: (props: SampleSeriesViewProps) => ReactNode;
93
+ }
package/package.json CHANGED
@@ -1,6 +1,95 @@
1
1
  {
2
2
  "name": "@hollis-labs/kit-admin",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "publishConfig": {
5
+ "access": "public",
6
+ "registry": "https://registry.npmjs.org/"
7
+ },
8
+ "description": "Controlled manifest-driven admin navigation and page composition; host-owned data, routes and commands.",
9
+ "keywords": [
10
+ "react",
11
+ "admin",
12
+ "design-system"
13
+ ],
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/hollis-labs/design-kit.git",
18
+ "directory": "packages/kit-admin"
19
+ },
20
+ "homepage": "https://github.com/hollis-labs/design-kit/tree/main/packages/kit-admin#readme",
21
+ "bugs": {
22
+ "url": "https://github.com/hollis-labs/design-kit/issues"
23
+ },
24
+ "type": "module",
25
+ "sideEffects": [
26
+ "**/*.css"
27
+ ],
28
+ "files": [
29
+ "dist",
30
+ "src/styles",
31
+ "CHANGELOG.md"
32
+ ],
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/src/index.d.ts",
36
+ "import": "./dist/index.js"
37
+ },
38
+ "./source.css": "./src/styles/source.css",
39
+ "./charts": {
40
+ "types": "./dist/src/charts.d.ts",
41
+ "import": "./dist/charts.js"
42
+ }
43
+ },
44
+ "main": "./dist/index.js",
45
+ "module": "./dist/index.js",
46
+ "types": "./dist/src/index.d.ts",
47
+ "scripts": {
48
+ "build": "tsc -p tsconfig.build.json && vite build",
49
+ "prepack": "npm run build",
50
+ "typecheck": "tsc --noEmit -p tsconfig.json",
51
+ "lint": "eslint .",
52
+ "test": "vitest",
53
+ "test:run": "vitest run",
54
+ "demo": "vite --config demo/vite.config.ts",
55
+ "demo:build": "vite build --config demo/vite.config.ts",
56
+ "prebuild": "node scripts/build-dependencies.mjs"
57
+ },
58
+ "peerDependencies": {
59
+ "tailwindcss": "^4.0.0",
60
+ "@base-ui/react": "^1.3.0",
61
+ "lucide-react": "^1.7.0",
62
+ "react": "^19.0.0",
63
+ "react-dom": "^19.0.0"
64
+ },
65
+ "dependencies": {
66
+ "@hollis-labs/design-components": "^0.4.0",
67
+ "@hollis-labs/design-tokens": "^0.4.0",
68
+ "@hollis-labs/kit-dashboard": "^0.4.0",
69
+ "@hollis-labs/kit-settings": "^0.2.0",
70
+ "@hollis-labs/kit-observe": "^0.1.1"
71
+ },
72
+ "devDependencies": {
73
+ "@base-ui/react": "^1.3.0",
74
+ "@eslint/js": "^9.39.4",
75
+ "@testing-library/react": "^16.3.2",
76
+ "@types/node": "^24.12.2",
77
+ "@types/react": "^19.2.14",
78
+ "@types/react-dom": "^19.2.3",
79
+ "@vitejs/plugin-react": "4.7.0",
80
+ "eslint": "^9.39.4",
81
+ "eslint-plugin-react-hooks": "^7.0.1",
82
+ "eslint-plugin-react-refresh": "^0.5.2",
83
+ "globals": "^17.4.0",
84
+ "jsdom": "^25.0.1",
85
+ "lucide-react": "^1.7.0",
86
+ "react": "^19.2.4",
87
+ "react-dom": "^19.2.4",
88
+ "typescript": "~6.0.2",
89
+ "vite": "5.4.21",
90
+ "vite-plugin-dts": "^4.5.4",
91
+ "vitest": "^2.1.9",
92
+ "@tailwindcss/vite": "^4.0.0",
93
+ "typescript-eslint": "^8.58.0"
94
+ }
95
+ }
@@ -0,0 +1 @@
1
+ @source "../../dist";