@aidex/admin-elements
v1.2.0
Published
Aidex Admin Web Components — the framework-agnostic Web Components implementation of the Aidex Admin / AI Control Center (including the aidex-control-center shell and its composed sections) over @aidex/admin's AdminController. Native Custom Elements only
Maintainers
Readme
@aidex/admin-elements
Installation
pnpm add @aidex/admin-elements @aidex/admin @aidex/admin-theme @aidex/connections @aidex/ai-control @aidex/observabilitynpm install @aidex/admin-elements @aidex/admin @aidex/admin-theme @aidex/connections @aidex/ai-control @aidex/observabilityUniversal, framework-independent Admin UI: 17 native Custom
Elements
rendering @aidex/admin's AdminController — no React/Angular/Vue/Lit
dependency. Works from vanilla JS, or from any framework via its own thin
adapter (@aidex/admin-react and friends compose these, or wrap
AdminController directly — see each adapter's own README).
The flagship surface is <aidex-control-center> — a full AI Control Center
application shell (sidebar navigation, 8 sections, a shared Execution
Inspector). Every section it composes, and the shared Inspector itself, also
registers as its own independently-usable element — pick the whole shell, or
just the one piece you need. Style everything by importing
@aidex/admin-theme's tokens.css once, globally; see that
package's README for the light/dark/system theme model.
Requires a DOM (browser, or Node with a DOM shim like jsdom) —
importing this package registers Custom Elements via customElements.define
and extends HTMLElement, so it throws ReferenceError: HTMLElement is not
defined under plain Node.js with no DOM global. Expected for a Custom
Elements package; not an issue in a browser or an SSR framework's
client-side bundle.
Usage
The full AI Control Center shell:
import '@aidex/admin-elements'; // registers all 17 <aidex-*> elements
import '@aidex/admin-theme/tokens.css'; // once, globally
import { AdminController } from '@aidex/admin';
const controller = new AdminController({ connectionManager, aiControl, observability });
const shell = document.querySelector('aidex-control-center');
shell.controller = controller; // a live object, not a string attribute<aidex-control-center></aidex-control-center>Or use any single element standalone — every section of the shell, and the Execution Inspector, registers as its own independently-usable element too:
<aidex-routing-activity></aidex-routing-activity>
<script type="module">
import '@aidex/admin-elements';
document.querySelector('aidex-routing-activity').controller = controller;
</script>Elements
AI Control Center (<aidex-control-center> and its composed sections)
| Element | Renders | Commands |
|---|---|---|
| <aidex-control-center> | The full application shell — sidebar navigation across 8 sections, mobile drawer, and the shared Execution Inspector | — (delegates to the elements it composes) |
| <aidex-overview> | Overview section: operational metric cards plus embedded Recent Executions | — (read-only) |
| <aidex-recent-executions> | Recent executions table with an "Inspect" action per row | — (read-only; dispatches inspect/navigation events) |
| <aidex-execution-inspector> | Detail panel for one inspected execution — overview, metadata, error, routing, and guardrail-denial sections, each shown only when that execution actually has the data | — (read-only) |
| <aidex-routing-activity> | One execution's Gateway routing decision: candidates considered, the ordered attempt sequence, and the selected candidate, with an "Inspect" action | — (read-only) |
| <aidex-guardrail-activity> | Every observed guardrail denial (stage + code only, never the guardrail's free-form reason), with an "Inspect" action per row | — (read-only) |
| <aidex-connections-grid> | Card-based connection listing (identity/provider/enabled state) | — (read-only) |
| <aidex-providers-grid> | Card-based provider capability discovery, including Gateway routing flags | — (read-only) |
| <aidex-ai-control-panel> | Read-only presentation of global AI enabled/disabled and per-feature overrides | — (read-only) |
| <aidex-observability-panel> | Operational summary: tokens, cost, error count, execution count, last activity | — (read-only) |
Standalone building blocks (independent of the Control Center shell)
| Element | Renders | Commands |
|---|---|---|
| <aidex-admin> | A flat, single-screen dashboard — composes the elements below, no navigation | — |
| <aidex-ai-control> | Global AI enabled/disabled + per-feature overrides, interactively | setAIEnabled, setFeatureEnabled, clearFeatureOverride |
| <aidex-connections> | Connections, identity/provider/enabled state | enableConnection, disableConnection, removeConnection |
| <aidex-providers> | Capability discovery per connection (ProviderSummary), including gateway-routing flags | — (read-only) |
| <aidex-health> | Derived health badge (AdminSnapshot.health) | — (read-only) |
| <aidex-observability> | Tokens, cost, error count, last activity — a compact summary line | — (read-only) |
| <aidex-executions> | Recent executions: requested vs. actual model/provider/routing, duration, tokens, cost, success/error | — (read-only) |
These seven elements predate the Control Center shell and remain fully
independent of it — <aidex-admin> is not <aidex-control-center> under a
different name; it's a deliberately separate, minimal, navigation-free
dashboard some existing consumer may already depend on.
Design notes
.controlleris a JS property, not an HTML attribute. AnAdminControlleris a live object (subscribe()/getSnapshot()), not a string — the same reason<video>uses.srcObjectrather than an attribute. Every framework sets it the same way: a React ref callback, an Angular[controller]binding, a Vue:controller, or plainel.controller = xin vanilla JS.- Every element extends
AidexElement(also exported, for building your own), which owns subscribing/unsubscribing/re-rendering — each concrete element'srender(snapshot)is its entire business. - Shadow DOM,
createElement/textContentonly — neverinnerHTMLwith interpolated snapshot data. Connection ids/metadata are application-supplied strings, not Aidex-controlled; building markup by string interpolation would be an XSS vector the same way string-built SQL is an injection vector. Every element's test suite asserts secrets/error messages never reach the DOM. <aidex-admin>and<aidex-control-center>each build their children once (on first controller assignment) and reuse them across snapshot changes — every child already subscribes to the controller itself and re-renders independently; the parent only re-propagatescontrollerwhen its reference changes.<aidex-control-center>shares one<aidex-execution-inspector>instance between its Overview and Executions sections, relocating it (a same-document DOM move, not a teardown/recreate) rather than duplicating it — "Inspect" behaves identically regardless of which section the user started from.- Themed via
@aidex/admin-theme. Each shadow root's stylesheet consumes--aidex-*custom properties viavar(...); import@aidex/admin-theme/tokens.cssonce, globally, in the host application — see that package's README for the light/dark/system model. Omitting it still renders correctly, using each rule's own literal fallback value.
