@consciousclouds/operator-shell 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 +36 -0
- package/LICENSE +194 -0
- package/README.md +319 -0
- package/dist/chief/ChiefDrawer.d.ts +11 -0
- package/dist/chief/ChiefDrawer.d.ts.map +1 -0
- package/dist/chief/ChiefDrawer.js +49 -0
- package/dist/chief/ChiefDrawer.js.map +1 -0
- package/dist/chief/ChiefPanel.d.ts +10 -0
- package/dist/chief/ChiefPanel.d.ts.map +1 -0
- package/dist/chief/ChiefPanel.js +46 -0
- package/dist/chief/ChiefPanel.js.map +1 -0
- package/dist/chief/ChiefRegion.d.ts +9 -0
- package/dist/chief/ChiefRegion.d.ts.map +1 -0
- package/dist/chief/ChiefRegion.js +55 -0
- package/dist/chief/ChiefRegion.js.map +1 -0
- package/dist/chief/ChiefSession.d.ts +21 -0
- package/dist/chief/ChiefSession.d.ts.map +1 -0
- package/dist/chief/ChiefSession.js +9 -0
- package/dist/chief/ChiefSession.js.map +1 -0
- package/dist/chief/directive.d.ts +15 -0
- package/dist/chief/directive.d.ts.map +1 -0
- package/dist/chief/directive.js +20 -0
- package/dist/chief/directive.js.map +1 -0
- package/dist/chief/turn-adapter.d.ts +52 -0
- package/dist/chief/turn-adapter.d.ts.map +1 -0
- package/dist/chief/turn-adapter.js +23 -0
- package/dist/chief/turn-adapter.js.map +1 -0
- package/dist/chief/use-chief-shortcut.d.ts +17 -0
- package/dist/chief/use-chief-shortcut.d.ts.map +1 -0
- package/dist/chief/use-chief-shortcut.js +61 -0
- package/dist/chief/use-chief-shortcut.js.map +1 -0
- package/dist/chief/use-chief-turn.d.ts +50 -0
- package/dist/chief/use-chief-turn.d.ts.map +1 -0
- package/dist/chief/use-chief-turn.js +99 -0
- package/dist/chief/use-chief-turn.js.map +1 -0
- package/dist/flavor/types.d.ts +189 -0
- package/dist/flavor/types.d.ts.map +1 -0
- package/dist/flavor/types.js +13 -0
- package/dist/flavor/types.js.map +1 -0
- package/dist/frame/OperatorShell.d.ts +91 -0
- package/dist/frame/OperatorShell.d.ts.map +1 -0
- package/dist/frame/OperatorShell.js +54 -0
- package/dist/frame/OperatorShell.js.map +1 -0
- package/dist/guard/PermissionProvider.d.ts +49 -0
- package/dist/guard/PermissionProvider.d.ts.map +1 -0
- package/dist/guard/PermissionProvider.js +103 -0
- package/dist/guard/PermissionProvider.js.map +1 -0
- package/dist/guard/RouteGuard.d.ts +45 -0
- package/dist/guard/RouteGuard.d.ts.map +1 -0
- package/dist/guard/RouteGuard.js +59 -0
- package/dist/guard/RouteGuard.js.map +1 -0
- package/dist/guard/permissions.d.ts +88 -0
- package/dist/guard/permissions.d.ts.map +1 -0
- package/dist/guard/permissions.js +105 -0
- package/dist/guard/permissions.js.map +1 -0
- package/dist/header/EnvironmentSwitcher.d.ts +5 -0
- package/dist/header/EnvironmentSwitcher.d.ts.map +1 -0
- package/dist/header/EnvironmentSwitcher.js +51 -0
- package/dist/header/EnvironmentSwitcher.js.map +1 -0
- package/dist/header/OperatorHeader.d.ts +25 -0
- package/dist/header/OperatorHeader.d.ts.map +1 -0
- package/dist/header/OperatorHeader.js +13 -0
- package/dist/header/OperatorHeader.js.map +1 -0
- package/dist/header/OperatorProfileMenu.d.ts +2 -0
- package/dist/header/OperatorProfileMenu.d.ts.map +1 -0
- package/dist/header/OperatorProfileMenu.js +14 -0
- package/dist/header/OperatorProfileMenu.js.map +1 -0
- package/dist/header/ThemeToggle.d.ts +2 -0
- package/dist/header/ThemeToggle.d.ts.map +1 -0
- package/dist/header/ThemeToggle.js +17 -0
- package/dist/header/ThemeToggle.js.map +1 -0
- package/dist/icons/registry.d.ts +57 -0
- package/dist/icons/registry.d.ts.map +1 -0
- package/dist/icons/registry.js +83 -0
- package/dist/icons/registry.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +129 -0
- package/dist/index.js.map +1 -0
- package/dist/inspector/InspectorProvider.d.ts +41 -0
- package/dist/inspector/InspectorProvider.d.ts.map +1 -0
- package/dist/inspector/InspectorProvider.js +63 -0
- package/dist/inspector/InspectorProvider.js.map +1 -0
- package/dist/inspector/types.d.ts +91 -0
- package/dist/inspector/types.d.ts.map +1 -0
- package/dist/inspector/types.js +40 -0
- package/dist/inspector/types.js.map +1 -0
- package/dist/nav/routes.d.ts +39 -0
- package/dist/nav/routes.d.ts.map +1 -0
- package/dist/nav/routes.js +46 -0
- package/dist/nav/routes.js.map +1 -0
- package/dist/palette/CommandPalette.d.ts +40 -0
- package/dist/palette/CommandPalette.d.ts.map +1 -0
- package/dist/palette/CommandPalette.js +108 -0
- package/dist/palette/CommandPalette.js.map +1 -0
- package/dist/palette/commands.d.ts +58 -0
- package/dist/palette/commands.d.ts.map +1 -0
- package/dist/palette/commands.js +81 -0
- package/dist/palette/commands.js.map +1 -0
- package/dist/palette/search-sources.d.ts +126 -0
- package/dist/palette/search-sources.d.ts.map +1 -0
- package/dist/palette/search-sources.js +101 -0
- package/dist/palette/search-sources.js.map +1 -0
- package/dist/palette/use-search-results.d.ts +4 -0
- package/dist/palette/use-search-results.d.ts.map +1 -0
- package/dist/palette/use-search-results.js +51 -0
- package/dist/palette/use-search-results.js.map +1 -0
- package/dist/sidebar/OperatorSidebar.d.ts +44 -0
- package/dist/sidebar/OperatorSidebar.d.ts.map +1 -0
- package/dist/sidebar/OperatorSidebar.js +30 -0
- package/dist/sidebar/OperatorSidebar.js.map +1 -0
- package/dist/workspace/CanvasWorkspace.d.ts +78 -0
- package/dist/workspace/CanvasWorkspace.d.ts.map +1 -0
- package/dist/workspace/CanvasWorkspace.js +44 -0
- package/dist/workspace/CanvasWorkspace.js.map +1 -0
- package/dist/workspace/DashboardWorkspace.d.ts +91 -0
- package/dist/workspace/DashboardWorkspace.d.ts.map +1 -0
- package/dist/workspace/DashboardWorkspace.js +39 -0
- package/dist/workspace/DashboardWorkspace.js.map +1 -0
- package/dist/workspace/FormWorkspace.d.ts +107 -0
- package/dist/workspace/FormWorkspace.d.ts.map +1 -0
- package/dist/workspace/FormWorkspace.js +38 -0
- package/dist/workspace/FormWorkspace.js.map +1 -0
- package/dist/workspace/GraphWorkspace.d.ts +112 -0
- package/dist/workspace/GraphWorkspace.d.ts.map +1 -0
- package/dist/workspace/GraphWorkspace.js +147 -0
- package/dist/workspace/GraphWorkspace.js.map +1 -0
- package/dist/workspace/TableWorkspace.d.ts +74 -0
- package/dist/workspace/TableWorkspace.d.ts.map +1 -0
- package/dist/workspace/TableWorkspace.js +25 -0
- package/dist/workspace/TableWorkspace.js.map +1 -0
- package/dist/workspace/WorkspaceHost.d.ts +26 -0
- package/dist/workspace/WorkspaceHost.d.ts.map +1 -0
- package/dist/workspace/WorkspaceHost.js +21 -0
- package/dist/workspace/WorkspaceHost.js.map +1 -0
- package/dist/workspace/registry.d.ts +30 -0
- package/dist/workspace/registry.d.ts.map +1 -0
- package/dist/workspace/registry.js +33 -0
- package/dist/workspace/registry.js.map +1 -0
- package/dist/workspace/types.d.ts +79 -0
- package/dist/workspace/types.d.ts.map +1 -0
- package/dist/workspace/types.js +48 -0
- package/dist/workspace/types.js.map +1 -0
- package/package.json +64 -0
- package/styles/source.css +16 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouteGuard.js","sourceRoot":"","sources":["../../src/guard/RouteGuard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EACL,KAAK,EACL,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,UAAU,EACV,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AA0BxD,MAAM,UAAU,UAAU,CAAC,EACzB,UAAU,EACV,QAAQ,EACR,OAAO,EACP,MAAM,EACN,UAAU,EACV,QAAQ,GACQ;IAChB,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAEnD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,4BAAG,QAAQ,GAAI,CAAC;IAEjD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,4BAAG,OAAO,IAAI,KAAC,iBAAiB,KAAG,GAAI,CAAC;IACjD,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,IAAI,KAAC,gBAAgB,KAAG,CAAC;IACnD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,KAAC,gBAAgB,IAAC,EAAE,EAAE,UAAU,YAAG,WAAW,GAAoB,CAAC;IAC5E,CAAC;IACD,OAAO,4BAAG,WAAW,GAAI,CAAC;AAC5B,CAAC;AAED,2EAA2E;AAC3E,SAAS,iBAAiB;IACxB,OAAO,CACL,4BAAe,qBAAqB,EAAC,SAAS,EAAC,WAAW,aACxD,KAAC,QAAQ,IAAC,SAAS,EAAC,UAAU,GAAG,EACjC,KAAC,QAAQ,IAAC,SAAS,EAAC,UAAU,GAAG,EACjC,KAAC,QAAQ,IAAC,SAAS,EAAC,aAAa,GAAG,IAChC,CACP,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,SAAS,gBAAgB;IACvB,OAAO,CACL,KAAC,KAAK,iBAAW,oBAAoB,EAAC,SAAS,EAAC,sBAAsB,YACpE,MAAC,WAAW,eACV,KAAC,UAAU,IAAC,OAAO,EAAC,MAAM,YACxB,KAAC,OAAO,KAAG,GACA,EACb,KAAC,UAAU,gCAA2B,EACtC,KAAC,gBAAgB,qLAIE,IACP,GACR,CACT,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAA6C;IACnF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;IACjB,OAAO,4BAAG,QAAQ,GAAI,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The permission-guard seam, per docs/design/operator-platform-contracts.md §5.
|
|
3
|
+
*
|
|
4
|
+
* The shell owns the fail-closed GATING BEHAVIOR (loading / denied / redirect
|
|
5
|
+
* states); the product injects the RESOLUTION. A Flavor supplies
|
|
6
|
+
* `requiredPermission` reference strings; the product's resolver interprets
|
|
7
|
+
* them against its own governance rail (its verified actor/session — never
|
|
8
|
+
* the Flavor). Designed now so a second adopter cannot reshape the shell.
|
|
9
|
+
*
|
|
10
|
+
* A resolver may be SYNC (a decision) or ASYNC (a promise of one — a real
|
|
11
|
+
* governance rail is a network away). While an async decision is in flight
|
|
12
|
+
* the gate is `loading`: nav shows a skeleton, a guarded route shows its
|
|
13
|
+
* loading state, and the command palette hides the entry (a palette has no
|
|
14
|
+
* useful loading row — fail-closed until resolved). A rejected promise or a
|
|
15
|
+
* throwing resolver is DENIED — failure can never widen access.
|
|
16
|
+
*
|
|
17
|
+
* This module is PURE (no React): the decision vocabulary + the evaluation
|
|
18
|
+
* machinery, provable without a DOM. The React half (PermissionProvider /
|
|
19
|
+
* usePermission / usePermissionDecisions / RouteGuard) lives beside it.
|
|
20
|
+
*/
|
|
21
|
+
/** The three outcomes a resolver may return. Anything but `allowed` gates. */
|
|
22
|
+
export type PermissionDecision = "allowed" | "denied" | "unknown";
|
|
23
|
+
/** A synchronous resolution: reference → decision, immediately. */
|
|
24
|
+
export type SyncPermissionResolver = (permission: string) => PermissionDecision;
|
|
25
|
+
/**
|
|
26
|
+
* Injected by the product: given a permission REFERENCE → a decision, sync or
|
|
27
|
+
* async, resolved from the product's own governance rail. The shell never
|
|
28
|
+
* resolves permissions itself. (Every SyncPermissionResolver is assignable
|
|
29
|
+
* here — the widening is backward compatible.)
|
|
30
|
+
*/
|
|
31
|
+
export type PermissionResolver = (permission: string) => PermissionDecision | Promise<PermissionDecision>;
|
|
32
|
+
/**
|
|
33
|
+
* The permissive default for dev-open postures (CCU passes this in M1). It
|
|
34
|
+
* exercises the seam without inventing governance the product doesn't have.
|
|
35
|
+
*/
|
|
36
|
+
export declare const allowAllPermissions: SyncPermissionResolver;
|
|
37
|
+
/**
|
|
38
|
+
* The shell's own default when NO resolver is injected: everything gated
|
|
39
|
+
* resolves `unknown` ⇒ denied. Fail-closed is the default, permissive is a
|
|
40
|
+
* choice the product makes explicitly.
|
|
41
|
+
*/
|
|
42
|
+
export declare const unknownPermissions: SyncPermissionResolver;
|
|
43
|
+
/**
|
|
44
|
+
* Fail-closed evaluation for SYNC resolvers: an ungated reference is allowed;
|
|
45
|
+
* a gated one passes only on an explicit `allowed` (`unknown` ⇒ denied).
|
|
46
|
+
* The async-capable path goes through `evaluatePermissions` + `gateStatus`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isPermitted(requiredPermission: string | undefined, resolve: SyncPermissionResolver): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* What a gate renders RIGHT NOW for one reference: `loading` while an async
|
|
51
|
+
* decision is in flight, `allowed` on an explicit allow, `denied` otherwise
|
|
52
|
+
* (including `unknown` — fail-closed).
|
|
53
|
+
*/
|
|
54
|
+
export type PermissionGateStatus = "loading" | "allowed" | "denied";
|
|
55
|
+
/** Collapse a resolved decision to its gate status (`unknown` ⇒ denied). */
|
|
56
|
+
export declare function toGateStatus(decision: PermissionDecision): "allowed" | "denied";
|
|
57
|
+
/**
|
|
58
|
+
* The one per-item gate every consumer (sidebar, palette, RouteGuard) reads:
|
|
59
|
+
* an ungated reference is allowed; a gated one reads the decisions map —
|
|
60
|
+
* absent from the map ⇒ DENIED (an unevaluated reference is fail-closed, not
|
|
61
|
+
* fail-open; only an explicit in-flight entry is `loading`).
|
|
62
|
+
*/
|
|
63
|
+
export declare function gateStatus(requiredPermission: string | undefined, decisions: Readonly<Record<string, PermissionGateStatus>>): PermissionGateStatus;
|
|
64
|
+
/** One evaluation pass: current statuses + the async decisions still in flight. */
|
|
65
|
+
export interface PermissionEvaluation {
|
|
66
|
+
statuses: Record<string, PermissionGateStatus>;
|
|
67
|
+
pending: ReadonlyArray<{
|
|
68
|
+
permission: string;
|
|
69
|
+
promise: Promise<PermissionDecision>;
|
|
70
|
+
}>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Evaluate a set of references through a (sync or async) resolver — the pure
|
|
74
|
+
* core of usePermissionDecisions. Each reference is resolved ONCE:
|
|
75
|
+
*
|
|
76
|
+
* - a sync decision lands immediately (no loading flash for sync resolvers),
|
|
77
|
+
* - a promise marks the reference `loading` and joins `pending` for the
|
|
78
|
+
* caller to await,
|
|
79
|
+
* - a THROWING resolver is `denied` (fail-closed — a resolution failure can
|
|
80
|
+
* never widen access; the awaited rejection case is the caller's mirror
|
|
81
|
+
* of this rule).
|
|
82
|
+
*/
|
|
83
|
+
export declare function evaluatePermissions(permissions: readonly string[], resolve: PermissionResolver): PermissionEvaluation;
|
|
84
|
+
/** Collect every `requiredPermission` reference from a gated item list. */
|
|
85
|
+
export declare function collectPermissionRefs(items: ReadonlyArray<{
|
|
86
|
+
requiredPermission?: string;
|
|
87
|
+
}>): string[];
|
|
88
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/guard/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElE,mEAAmE;AACnE,MAAM,MAAM,sBAAsB,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,kBAAkB,CAAC;AAEhF;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,UAAU,EAAE,MAAM,KACf,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,sBAAwC,CAAC;AAE3E;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,sBAAwC,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAGT;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEpE,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,kBAAkB,GAAG,SAAS,GAAG,QAAQ,CAE/E;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,GACxD,oBAAoB,CAKtB;AAED,mFAAmF;AACnF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC/C,OAAO,EAAE,aAAa,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;KACtC,CAAC,CAAC;CACJ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,OAAO,EAAE,kBAAkB,GAC1B,oBAAoB,CAsBtB;AAED,2EAA2E;AAC3E,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,CAAC;IAAE,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACpD,MAAM,EAAE,CAQV"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The permission-guard seam, per docs/design/operator-platform-contracts.md §5.
|
|
3
|
+
*
|
|
4
|
+
* The shell owns the fail-closed GATING BEHAVIOR (loading / denied / redirect
|
|
5
|
+
* states); the product injects the RESOLUTION. A Flavor supplies
|
|
6
|
+
* `requiredPermission` reference strings; the product's resolver interprets
|
|
7
|
+
* them against its own governance rail (its verified actor/session — never
|
|
8
|
+
* the Flavor). Designed now so a second adopter cannot reshape the shell.
|
|
9
|
+
*
|
|
10
|
+
* A resolver may be SYNC (a decision) or ASYNC (a promise of one — a real
|
|
11
|
+
* governance rail is a network away). While an async decision is in flight
|
|
12
|
+
* the gate is `loading`: nav shows a skeleton, a guarded route shows its
|
|
13
|
+
* loading state, and the command palette hides the entry (a palette has no
|
|
14
|
+
* useful loading row — fail-closed until resolved). A rejected promise or a
|
|
15
|
+
* throwing resolver is DENIED — failure can never widen access.
|
|
16
|
+
*
|
|
17
|
+
* This module is PURE (no React): the decision vocabulary + the evaluation
|
|
18
|
+
* machinery, provable without a DOM. The React half (PermissionProvider /
|
|
19
|
+
* usePermission / usePermissionDecisions / RouteGuard) lives beside it.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* The permissive default for dev-open postures (CCU passes this in M1). It
|
|
23
|
+
* exercises the seam without inventing governance the product doesn't have.
|
|
24
|
+
*/
|
|
25
|
+
export const allowAllPermissions = () => "allowed";
|
|
26
|
+
/**
|
|
27
|
+
* The shell's own default when NO resolver is injected: everything gated
|
|
28
|
+
* resolves `unknown` ⇒ denied. Fail-closed is the default, permissive is a
|
|
29
|
+
* choice the product makes explicitly.
|
|
30
|
+
*/
|
|
31
|
+
export const unknownPermissions = () => "unknown";
|
|
32
|
+
/**
|
|
33
|
+
* Fail-closed evaluation for SYNC resolvers: an ungated reference is allowed;
|
|
34
|
+
* a gated one passes only on an explicit `allowed` (`unknown` ⇒ denied).
|
|
35
|
+
* The async-capable path goes through `evaluatePermissions` + `gateStatus`.
|
|
36
|
+
*/
|
|
37
|
+
export function isPermitted(requiredPermission, resolve) {
|
|
38
|
+
if (!requiredPermission)
|
|
39
|
+
return true;
|
|
40
|
+
return resolve(requiredPermission) === "allowed";
|
|
41
|
+
}
|
|
42
|
+
/** Collapse a resolved decision to its gate status (`unknown` ⇒ denied). */
|
|
43
|
+
export function toGateStatus(decision) {
|
|
44
|
+
return decision === "allowed" ? "allowed" : "denied";
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The one per-item gate every consumer (sidebar, palette, RouteGuard) reads:
|
|
48
|
+
* an ungated reference is allowed; a gated one reads the decisions map —
|
|
49
|
+
* absent from the map ⇒ DENIED (an unevaluated reference is fail-closed, not
|
|
50
|
+
* fail-open; only an explicit in-flight entry is `loading`).
|
|
51
|
+
*/
|
|
52
|
+
export function gateStatus(requiredPermission, decisions) {
|
|
53
|
+
if (!requiredPermission)
|
|
54
|
+
return "allowed";
|
|
55
|
+
const status = decisions[requiredPermission];
|
|
56
|
+
if (status === "allowed" || status === "loading")
|
|
57
|
+
return status;
|
|
58
|
+
return "denied";
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Evaluate a set of references through a (sync or async) resolver — the pure
|
|
62
|
+
* core of usePermissionDecisions. Each reference is resolved ONCE:
|
|
63
|
+
*
|
|
64
|
+
* - a sync decision lands immediately (no loading flash for sync resolvers),
|
|
65
|
+
* - a promise marks the reference `loading` and joins `pending` for the
|
|
66
|
+
* caller to await,
|
|
67
|
+
* - a THROWING resolver is `denied` (fail-closed — a resolution failure can
|
|
68
|
+
* never widen access; the awaited rejection case is the caller's mirror
|
|
69
|
+
* of this rule).
|
|
70
|
+
*/
|
|
71
|
+
export function evaluatePermissions(permissions, resolve) {
|
|
72
|
+
const statuses = {};
|
|
73
|
+
const pending = [];
|
|
74
|
+
for (const permission of permissions) {
|
|
75
|
+
if (permission in statuses)
|
|
76
|
+
continue; // each reference resolved once
|
|
77
|
+
let result;
|
|
78
|
+
try {
|
|
79
|
+
result = resolve(permission);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
statuses[permission] = "denied";
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (typeof result === "string") {
|
|
86
|
+
statuses[permission] = toGateStatus(result);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
statuses[permission] = "loading";
|
|
90
|
+
pending.push({ permission, promise: result });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { statuses, pending };
|
|
94
|
+
}
|
|
95
|
+
/** Collect every `requiredPermission` reference from a gated item list. */
|
|
96
|
+
export function collectPermissionRefs(items) {
|
|
97
|
+
const refs = [];
|
|
98
|
+
for (const item of items) {
|
|
99
|
+
if (item.requiredPermission && !refs.includes(item.requiredPermission)) {
|
|
100
|
+
refs.push(item.requiredPermission);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return refs;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/guard/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAkBH;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA2B,GAAG,EAAE,CAAC,SAAS,CAAC;AAE3E;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA2B,GAAG,EAAE,CAAC,SAAS,CAAC;AAE1E;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,kBAAsC,EACtC,OAA+B;IAE/B,IAAI,CAAC,kBAAkB;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,OAAO,CAAC,kBAAkB,CAAC,KAAK,SAAS,CAAC;AACnD,CAAC;AASD,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAC,QAA4B;IACvD,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CACxB,kBAAsC,EACtC,SAAyD;IAEzD,IAAI,CAAC,kBAAkB;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,MAAM,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC7C,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAChE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAWD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAA8B,EAC9B,OAA2B;IAE3B,MAAM,QAAQ,GAAyC,EAAE,CAAC;IAC1D,MAAM,OAAO,GAAwE,EAAE,CAAC;IAExF,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,UAAU,IAAI,QAAQ;YAAE,SAAS,CAAC,+BAA+B;QACrE,IAAI,MAAwD,CAAC;QAC7D,IAAI,CAAC;YACH,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;YAChC,SAAS;QACX,CAAC;QACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,qBAAqB,CACnC,KAAqD;IAErD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvironmentSwitcher.d.ts","sourceRoot":"","sources":["../../src/header/EnvironmentSwitcher.tsx"],"names":[],"mappings":"AAiDA,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,SAAS,EAAE,EAAE,wBAAwB,kDA2F1E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Check, ChevronsUpDown } from "lucide-react";
|
|
4
|
+
import { useRuntimeOptional } from "@consciousclouds/frontend-runtime/react";
|
|
5
|
+
import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, cn, } from "@consciousclouds/ui";
|
|
6
|
+
/** Status-dot classes by runtime connection state (semantic, no URL ever). */
|
|
7
|
+
const CONNECTION_DOT = {
|
|
8
|
+
connected: "bg-emerald-500",
|
|
9
|
+
"health-checking": "bg-emerald-500",
|
|
10
|
+
hydrating: "bg-amber-500 animate-pulse",
|
|
11
|
+
switching: "bg-amber-500 animate-pulse",
|
|
12
|
+
error: "bg-destructive",
|
|
13
|
+
idle: "bg-muted-foreground",
|
|
14
|
+
};
|
|
15
|
+
export function EnvironmentSwitcher({ className }) {
|
|
16
|
+
const runtime = useRuntimeOptional();
|
|
17
|
+
// No RuntimeProvider mounted by the product — no environment context, no
|
|
18
|
+
// chrome. Fail-closed: the shell never invents an environment.
|
|
19
|
+
if (!runtime)
|
|
20
|
+
return null;
|
|
21
|
+
const { state, switchTo, controller } = runtime;
|
|
22
|
+
const targets = controller.getNamedTargets();
|
|
23
|
+
const label = state.envLabel ?? state.target?.label ?? targets[0]?.label ?? null;
|
|
24
|
+
if (!label)
|
|
25
|
+
return null;
|
|
26
|
+
const dot = (_jsx("span", { "aria-hidden": true, className: cn("size-1.5 shrink-0 rounded-full", CONNECTION_DOT[state.connectionState]) }));
|
|
27
|
+
// Single configured environment — render honestly as an indicator, not a
|
|
28
|
+
// menu that pretends there is something to switch to.
|
|
29
|
+
if (targets.length <= 1) {
|
|
30
|
+
return (_jsxs("div", { className: cn("hidden h-8 items-center gap-2 rounded-md border border-input bg-muted/50 px-2.5 text-xs font-medium text-muted-foreground sm:flex", className), title: `Environment: ${label} (${state.connectionState})`, children: [dot, _jsx("span", { suppressHydrationWarning: true, className: "max-w-36 truncate", children: label })] }));
|
|
31
|
+
}
|
|
32
|
+
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", className: cn("hidden h-8 gap-2 border-input bg-muted/50 px-2.5 text-xs font-medium text-muted-foreground shadow-none hover:bg-muted/80 sm:inline-flex", className), "aria-label": `Environment: ${label}`, children: [dot, _jsx("span", { suppressHydrationWarning: true, className: "max-w-36 truncate", children: label }), _jsx(ChevronsUpDown, { className: "size-3.5 opacity-60" })] }) }), _jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [_jsx(DropdownMenuLabel, { children: "Environment" }), _jsx(DropdownMenuSeparator, {}), targets.map((t) => {
|
|
33
|
+
const active = state.target?.kind === "named"
|
|
34
|
+
? state.target.namedId === t.id
|
|
35
|
+
: state.gatewayUrl === t.url;
|
|
36
|
+
return (_jsxs(DropdownMenuItem, { onSelect: () => {
|
|
37
|
+
if (active)
|
|
38
|
+
return;
|
|
39
|
+
// The target's url comes FROM the product's runtime config —
|
|
40
|
+
// the shell only carries it back into the runtime, verbatim.
|
|
41
|
+
void switchTo({
|
|
42
|
+
kind: "named",
|
|
43
|
+
namedId: t.id,
|
|
44
|
+
url: t.url,
|
|
45
|
+
envId: t.id,
|
|
46
|
+
label: t.label,
|
|
47
|
+
});
|
|
48
|
+
}, children: [_jsx("span", { className: "truncate", children: t.label }), active && _jsx(Check, { className: "ml-auto size-4" })] }, t.id));
|
|
49
|
+
})] })] }));
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=EnvironmentSwitcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvironmentSwitcher.js","sourceRoot":"","sources":["../../src/header/EnvironmentSwitcher.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OperatorHeader — the top chrome: brand slot · sidebar trigger · search
|
|
3
|
+
* (the command-palette trigger) · environment switcher · notifications ·
|
|
4
|
+
* theme toggle · profile slot. The brand block renders through the Brand
|
|
5
|
+
* Platform (BrandLogo + useBrand — the shell never bakes an image or a mark
|
|
6
|
+
* string); the environment chrome renders through the published
|
|
7
|
+
* @consciousclouds/frontend-runtime context (the product mounts
|
|
8
|
+
* RuntimeProvider; no provider → no chrome — see EnvironmentSwitcher); the
|
|
9
|
+
* sticky full-width geometry is the open registry's sidebar-16 site-header
|
|
10
|
+
* pattern, and the search button is the registry's docs-search trigger
|
|
11
|
+
* pattern (input-look button + ⌘K kbd hint) — the palette itself is mounted
|
|
12
|
+
* by the frame, which owns the open state so the button and the keybinding
|
|
13
|
+
* open the same instance.
|
|
14
|
+
*/
|
|
15
|
+
import type * as React from "react";
|
|
16
|
+
export interface OperatorHeaderProps {
|
|
17
|
+
/** Product-injected profile dropdown; a neutral operator menu by default. */
|
|
18
|
+
profile?: React.ReactNode;
|
|
19
|
+
/** Search-button copy (the ⌘K hint renders separately as a kbd). */
|
|
20
|
+
searchPlaceholder?: string;
|
|
21
|
+
/** Opens the command palette (wired by the frame). Absent ⇒ inert button. */
|
|
22
|
+
onSearchOpen?: () => void;
|
|
23
|
+
}
|
|
24
|
+
export declare function OperatorHeader({ profile, searchPlaceholder, onSearchOpen, }: OperatorHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=OperatorHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OperatorHeader.d.ts","sourceRoot":"","sources":["../../src/header/OperatorHeader.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAUpC,MAAM,WAAW,mBAAmB;IAClC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,iBAA6B,EAC7B,YAAY,GACb,EAAE,mBAAmB,2CAwDrB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Bell, Search } from "lucide-react";
|
|
4
|
+
import { BrandLogo, useBrand } from "@consciousclouds/brand";
|
|
5
|
+
import { Button, Separator, SidebarTrigger, cn } from "@consciousclouds/ui";
|
|
6
|
+
import { EnvironmentSwitcher } from "./EnvironmentSwitcher.js";
|
|
7
|
+
import { OperatorProfileMenu } from "./OperatorProfileMenu.js";
|
|
8
|
+
import { ThemeToggle } from "./ThemeToggle.js";
|
|
9
|
+
export function OperatorHeader({ profile, searchPlaceholder = "Search…", onSearchOpen, }) {
|
|
10
|
+
const brand = useBrand();
|
|
11
|
+
return (_jsx("header", { className: "sticky top-0 z-50 flex h-(--header-height) w-full shrink-0 items-center border-b border-border bg-background", children: _jsxs("div", { className: "flex w-full items-center gap-2 px-3 sm:px-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: "flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md bg-primary text-sm font-bold text-primary-foreground lowercase", children: [_jsx(BrandLogo, { role: "icon", mode: "light", className: "max-h-full max-w-full dark:hidden" }), _jsx(BrandLogo, { role: "icon", mode: "dark", className: "hidden max-h-full max-w-full dark:block" })] }), _jsxs("div", { className: "leading-tight", children: [_jsx("div", { className: "text-sm font-semibold", children: brand.name }), brand.sub && _jsx("div", { className: "text-[11px] text-muted-foreground", children: brand.sub })] })] }), _jsx(Separator, { orientation: "vertical", className: "mx-1 hidden data-[orientation=vertical]:h-5 md:block" }), _jsx(SidebarTrigger, { className: "text-muted-foreground" }), _jsxs(Button, { type: "button", variant: "outline", onClick: onSearchOpen, className: cn("relative ml-2 hidden h-8 max-w-md flex-1 justify-start border-input bg-muted/50 px-2.5 font-normal text-muted-foreground shadow-none hover:bg-muted/80 md:inline-flex"), children: [_jsx(Search, { className: "size-4" }), _jsx("span", { className: "truncate", children: searchPlaceholder }), _jsxs("kbd", { className: "pointer-events-none absolute top-1/2 right-2 hidden h-5 -translate-y-1/2 items-center gap-1 rounded border bg-background px-1.5 font-mono text-[10px] font-medium select-none sm:inline-flex", children: [_jsx("span", { className: "text-xs", children: "\u2318" }), "K"] })] }), _jsxs("div", { className: "ml-auto flex items-center gap-1", children: [_jsx(EnvironmentSwitcher, { className: "mr-1" }), _jsx(Button, { variant: "ghost", size: "icon", "aria-label": "Notifications", children: _jsx(Bell, { className: "size-4" }) }), _jsx(ThemeToggle, {}), profile ?? _jsx(OperatorProfileMenu, {})] })] }) }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=OperatorHeader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OperatorHeader.js","sourceRoot":"","sources":["../../src/header/OperatorHeader.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAkBb,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAE5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAW/C,MAAM,UAAU,cAAc,CAAC,EAC7B,OAAO,EACP,iBAAiB,GAAG,SAAS,EAC7B,YAAY,GACQ;IACpB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,OAAO,CACL,iBAAQ,SAAS,EAAC,8GAA8G,YAC9H,eAAK,SAAS,EAAC,6CAA6C,aAK1D,eAAK,SAAS,EAAC,yBAAyB,aACtC,eAAK,SAAS,EAAC,4IAA4I,aACzJ,KAAC,SAAS,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,mCAAmC,GAAG,EACpF,KAAC,SAAS,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,MAAM,EAAC,SAAS,EAAC,yCAAyC,GAAG,IACrF,EACN,eAAK,SAAS,EAAC,eAAe,aAC5B,cAAK,SAAS,EAAC,uBAAuB,YAAE,KAAK,CAAC,IAAI,GAAO,EACxD,KAAK,CAAC,GAAG,IAAI,cAAK,SAAS,EAAC,mCAAmC,YAAE,KAAK,CAAC,GAAG,GAAO,IAC9E,IACF,EAEN,KAAC,SAAS,IACR,WAAW,EAAC,UAAU,EACtB,SAAS,EAAC,sDAAsD,GAChE,EACF,KAAC,cAAc,IAAC,SAAS,EAAC,uBAAuB,GAAG,EAGpD,MAAC,MAAM,IACL,IAAI,EAAC,QAAQ,EACb,OAAO,EAAC,SAAS,EACjB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,EAAE,CACX,uKAAuK,CACxK,aAED,KAAC,MAAM,IAAC,SAAS,EAAC,QAAQ,GAAG,EAC7B,eAAM,SAAS,EAAC,UAAU,YAAE,iBAAiB,GAAQ,EACrD,eAAK,SAAS,EAAC,8LAA8L,aAC3M,eAAM,SAAS,EAAC,SAAS,uBAAS,SAC9B,IACC,EAET,eAAK,SAAS,EAAC,iCAAiC,aAG9C,KAAC,mBAAmB,IAAC,SAAS,EAAC,MAAM,GAAG,EACxC,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,MAAM,gBAAY,eAAe,YAC5D,KAAC,IAAI,IAAC,SAAS,EAAC,QAAQ,GAAG,GACpB,EACT,KAAC,WAAW,KAAG,EACd,OAAO,IAAI,KAAC,mBAAmB,KAAG,IAC/B,IACF,GACC,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OperatorProfileMenu.d.ts","sourceRoot":"","sources":["../../src/header/OperatorProfileMenu.tsx"],"names":[],"mappings":"AAuBA,wBAAgB,mBAAmB,4CAoBlC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* OperatorProfileMenu — the header's default profile dropdown (a neutral
|
|
5
|
+
* operator identity). It is the DEFAULT filling of the profile slot; a
|
|
6
|
+
* product injects its own menu (wired to its own session) through the
|
|
7
|
+
* shell's `profile` prop. The shell never resolves who the operator is.
|
|
8
|
+
*/
|
|
9
|
+
import { ChevronsUpDown } from "lucide-react";
|
|
10
|
+
import { Avatar, AvatarFallback, Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@consciousclouds/ui";
|
|
11
|
+
export function OperatorProfileMenu() {
|
|
12
|
+
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", className: "gap-2 pl-1.5", children: [_jsx(Avatar, { className: "size-7", children: _jsx(AvatarFallback, { className: "text-xs", children: "OP" }) }), _jsx("span", { className: "hidden text-sm sm:inline", children: "Operator" }), _jsx(ChevronsUpDown, { className: "size-3.5 text-muted-foreground" })] }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuLabel, { children: "Operator" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { children: "Profile" }), _jsx(DropdownMenuItem, { children: "Settings" })] })] }));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=OperatorProfileMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OperatorProfileMenu.js","sourceRoot":"","sources":["../../src/header/OperatorProfileMenu.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EACL,MAAM,EACN,cAAc,EACd,MAAM,EACN,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,mBAAmB;IACjC,OAAO,CACL,MAAC,YAAY,eACX,KAAC,mBAAmB,IAAC,OAAO,kBAC1B,MAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,SAAS,EAAC,cAAc,aAC9C,KAAC,MAAM,IAAC,SAAS,EAAC,QAAQ,YACxB,KAAC,cAAc,IAAC,SAAS,EAAC,SAAS,mBAAoB,GAChD,EACT,eAAM,SAAS,EAAC,0BAA0B,yBAAgB,EAC1D,KAAC,cAAc,IAAC,SAAS,EAAC,gCAAgC,GAAG,IACtD,GACW,EACtB,MAAC,mBAAmB,IAAC,KAAK,EAAC,KAAK,aAC9B,KAAC,iBAAiB,2BAA6B,EAC/C,KAAC,qBAAqB,KAAG,EACzB,KAAC,gBAAgB,0BAA2B,EAC5C,KAAC,gBAAgB,2BAA4B,IACzB,IACT,CAChB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../src/header/ThemeToggle.tsx"],"names":[],"mappings":"AAeA,wBAAgB,WAAW,4CAgB1B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* ThemeToggle — the shell's light/dark switch. Theme state is token
|
|
5
|
+
* machinery: this consumes the Token System's `useTheme` (the app mounts
|
|
6
|
+
* tokens' ThemeProvider), and the icon swap is CSS-driven off the `.dark`
|
|
7
|
+
* class (the open registry's mode-toggle pattern), so it renders
|
|
8
|
+
* hydration-safe without waiting for the resolved theme.
|
|
9
|
+
*/
|
|
10
|
+
import { Moon, Sun } from "lucide-react";
|
|
11
|
+
import { useTheme } from "@consciousclouds/tokens";
|
|
12
|
+
import { Button } from "@consciousclouds/ui";
|
|
13
|
+
export function ThemeToggle() {
|
|
14
|
+
const { resolvedTheme, setTheme } = useTheme();
|
|
15
|
+
return (_jsxs(Button, { variant: "ghost", size: "icon", className: "relative", "aria-label": "Toggle theme", onClick: () => setTheme(resolvedTheme === "dark" ? "light" : "dark"), children: [_jsx(Sun, { className: "size-4 scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" }), _jsx(Moon, { className: "absolute size-4 scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" }), _jsx("span", { className: "sr-only", children: "Toggle theme" })] }));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=ThemeToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeToggle.js","sourceRoot":"","sources":["../../src/header/ThemeToggle.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,UAAU,WAAW;IACzB,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAAC;IAE/C,OAAO,CACL,MAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,UAAU,gBACT,cAAc,EACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,aAEpE,KAAC,GAAG,IAAC,SAAS,EAAC,uEAAuE,GAAG,EACzF,KAAC,IAAI,IAAC,SAAS,EAAC,+EAA+E,GAAG,EAClG,eAAM,SAAS,EAAC,SAAS,6BAAoB,IACtC,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Icon Platform — the shell's string-name → icon resolution seam.
|
|
3
|
+
*
|
|
4
|
+
* The contract (first-class, per the Declarative-Flavor law):
|
|
5
|
+
*
|
|
6
|
+
* 1. A Flavor declares icons as inert STRING NAMES (`icon: "home"`) —
|
|
7
|
+
* never an imported component (icons stop being product code).
|
|
8
|
+
* 2. The shell resolves names here. The built-in operator vocabulary
|
|
9
|
+
* (`OPERATOR_ICONS`) ships with the shell; the PRODUCT extends the
|
|
10
|
+
* vocabulary through the `icons` prop on `OperatorShell` (an
|
|
11
|
+
* `IconRegistry`: string name → Lucide component). Product extensions
|
|
12
|
+
* take precedence over the built-ins — a product may deliberately
|
|
13
|
+
* re-map a built-in name.
|
|
14
|
+
* 3. Unknown names FAIL CLOSED to `UNKNOWN_ICON` — one deterministic,
|
|
15
|
+
* neutral placeholder (the same glyph for every unresolved name, on
|
|
16
|
+
* every render). Never a crash, never a hole in the nav geometry, and
|
|
17
|
+
* never anything permission-bearing: icons are cosmetic; the guard seam
|
|
18
|
+
* (§5) is the only authority. Lookups are OWN-property only, so
|
|
19
|
+
* prototype names (`"toString"`, `"constructor"`) are unknown too —
|
|
20
|
+
* they render the fallback instead of leaking a non-component.
|
|
21
|
+
* 4. The ICON FAMILY is a Brand-level declaration (`Brand.iconFamily`,
|
|
22
|
+
* @consciousclouds/brand — inert data). The shell ships exactly ONE
|
|
23
|
+
* family — `lucide`, per the license allowlist — so the frame reads the
|
|
24
|
+
* declaration and `resolveIconFamily` read-and-defaults anything else
|
|
25
|
+
* to the shipped family (fail-closed: no dynamic load, no crash). When
|
|
26
|
+
* a second family ships, it registers here and the Brand declaration
|
|
27
|
+
* starts selecting between built-in vocabularies.
|
|
28
|
+
*/
|
|
29
|
+
import { type LucideIcon } from "lucide-react";
|
|
30
|
+
/** A string-name → icon-component map (Lucide vocabulary). */
|
|
31
|
+
export type IconRegistry = Readonly<Record<string, LucideIcon>>;
|
|
32
|
+
/**
|
|
33
|
+
* The deterministic unknown-icon fallback — the guaranteed end of every icon
|
|
34
|
+
* resolution. One neutral glyph (a dashed circle: visibly "unresolved",
|
|
35
|
+
* never mistakable for a real registered icon) for every unknown name.
|
|
36
|
+
*/
|
|
37
|
+
export declare const UNKNOWN_ICON: LucideIcon;
|
|
38
|
+
/**
|
|
39
|
+
* The one icon family this shell ships — Lucide, per the license allowlist
|
|
40
|
+
* (open MIT registry + Radix/CVA/lucide). A Brand may DECLARE another family
|
|
41
|
+
* (`Brand.iconFamily` is an inert preference); the shell honors the families
|
|
42
|
+
* it ships and defaults the rest here.
|
|
43
|
+
*/
|
|
44
|
+
export declare const SHIPPED_ICON_FAMILY: "lucide";
|
|
45
|
+
/** A family this shell can actually render (today: exactly the shipped one). */
|
|
46
|
+
export type ShippedIconFamily = typeof SHIPPED_ICON_FAMILY;
|
|
47
|
+
/** The built-in operator vocabulary (kebab-case Lucide names). */
|
|
48
|
+
export declare const OPERATOR_ICONS: IconRegistry;
|
|
49
|
+
export declare function resolveIconFamily(declared?: string): ShippedIconFamily;
|
|
50
|
+
/**
|
|
51
|
+
* Resolve an icon name: product extensions first (they may override
|
|
52
|
+
* built-ins), then the built-in vocabulary of the resolved family, then the
|
|
53
|
+
* deterministic `UNKNOWN_ICON` fallback. Total — every string returns a
|
|
54
|
+
* renderable component; permissions never resolve here.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveIcon(name: string, extensions?: IconRegistry, family?: string): LucideIcon;
|
|
57
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/icons/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAQL,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,8DAA8D;AAC9D,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAEhE;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,UAAyB,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAG,QAAiB,CAAC;AAErD,gFAAgF;AAChF,MAAM,MAAM,iBAAiB,GAAG,OAAO,mBAAmB,CAAC;AAE3D,kEAAkE;AAClE,eAAO,MAAM,cAAc,EAAE,YAO5B,CAAC;AAiBF,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAItE;AAOD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,YAAY,EACzB,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAGZ"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Icon Platform — the shell's string-name → icon resolution seam.
|
|
3
|
+
*
|
|
4
|
+
* The contract (first-class, per the Declarative-Flavor law):
|
|
5
|
+
*
|
|
6
|
+
* 1. A Flavor declares icons as inert STRING NAMES (`icon: "home"`) —
|
|
7
|
+
* never an imported component (icons stop being product code).
|
|
8
|
+
* 2. The shell resolves names here. The built-in operator vocabulary
|
|
9
|
+
* (`OPERATOR_ICONS`) ships with the shell; the PRODUCT extends the
|
|
10
|
+
* vocabulary through the `icons` prop on `OperatorShell` (an
|
|
11
|
+
* `IconRegistry`: string name → Lucide component). Product extensions
|
|
12
|
+
* take precedence over the built-ins — a product may deliberately
|
|
13
|
+
* re-map a built-in name.
|
|
14
|
+
* 3. Unknown names FAIL CLOSED to `UNKNOWN_ICON` — one deterministic,
|
|
15
|
+
* neutral placeholder (the same glyph for every unresolved name, on
|
|
16
|
+
* every render). Never a crash, never a hole in the nav geometry, and
|
|
17
|
+
* never anything permission-bearing: icons are cosmetic; the guard seam
|
|
18
|
+
* (§5) is the only authority. Lookups are OWN-property only, so
|
|
19
|
+
* prototype names (`"toString"`, `"constructor"`) are unknown too —
|
|
20
|
+
* they render the fallback instead of leaking a non-component.
|
|
21
|
+
* 4. The ICON FAMILY is a Brand-level declaration (`Brand.iconFamily`,
|
|
22
|
+
* @consciousclouds/brand — inert data). The shell ships exactly ONE
|
|
23
|
+
* family — `lucide`, per the license allowlist — so the frame reads the
|
|
24
|
+
* declaration and `resolveIconFamily` read-and-defaults anything else
|
|
25
|
+
* to the shipped family (fail-closed: no dynamic load, no crash). When
|
|
26
|
+
* a second family ships, it registers here and the Brand declaration
|
|
27
|
+
* starts selecting between built-in vocabularies.
|
|
28
|
+
*/
|
|
29
|
+
import { Activity, BarChart3, Bot, CircleDashed, Home, Plug, Waypoints, } from "lucide-react";
|
|
30
|
+
/**
|
|
31
|
+
* The deterministic unknown-icon fallback — the guaranteed end of every icon
|
|
32
|
+
* resolution. One neutral glyph (a dashed circle: visibly "unresolved",
|
|
33
|
+
* never mistakable for a real registered icon) for every unknown name.
|
|
34
|
+
*/
|
|
35
|
+
export const UNKNOWN_ICON = CircleDashed;
|
|
36
|
+
/**
|
|
37
|
+
* The one icon family this shell ships — Lucide, per the license allowlist
|
|
38
|
+
* (open MIT registry + Radix/CVA/lucide). A Brand may DECLARE another family
|
|
39
|
+
* (`Brand.iconFamily` is an inert preference); the shell honors the families
|
|
40
|
+
* it ships and defaults the rest here.
|
|
41
|
+
*/
|
|
42
|
+
export const SHIPPED_ICON_FAMILY = "lucide";
|
|
43
|
+
/** The built-in operator vocabulary (kebab-case Lucide names). */
|
|
44
|
+
export const OPERATOR_ICONS = {
|
|
45
|
+
home: Home,
|
|
46
|
+
bot: Bot,
|
|
47
|
+
plug: Plug,
|
|
48
|
+
activity: Activity,
|
|
49
|
+
"bar-chart-3": BarChart3,
|
|
50
|
+
waypoints: Waypoints,
|
|
51
|
+
};
|
|
52
|
+
/** Built-in vocabularies by family — where a second shipped family registers. */
|
|
53
|
+
const FAMILY_REGISTRIES = {
|
|
54
|
+
[SHIPPED_ICON_FAMILY]: OPERATOR_ICONS,
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Resolve a Brand's icon-family declaration to a family the shell ships.
|
|
58
|
+
* Undeclared, unknown, or unshipped families READ-AND-DEFAULT to the shipped
|
|
59
|
+
* family (deterministic, fail-closed — the declaration is a preference, not
|
|
60
|
+
* a load instruction).
|
|
61
|
+
*/
|
|
62
|
+
/** Own-property test — prototype names never resolve (fail-closed). */
|
|
63
|
+
const hasOwn = (object, key) => Object.prototype.hasOwnProperty.call(object, key);
|
|
64
|
+
export function resolveIconFamily(declared) {
|
|
65
|
+
return declared !== undefined && hasOwn(FAMILY_REGISTRIES, declared)
|
|
66
|
+
? declared
|
|
67
|
+
: SHIPPED_ICON_FAMILY;
|
|
68
|
+
}
|
|
69
|
+
/** Own-property lookup (see hasOwn). */
|
|
70
|
+
function lookup(registry, name) {
|
|
71
|
+
return registry !== undefined && hasOwn(registry, name) ? registry[name] : undefined;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Resolve an icon name: product extensions first (they may override
|
|
75
|
+
* built-ins), then the built-in vocabulary of the resolved family, then the
|
|
76
|
+
* deterministic `UNKNOWN_ICON` fallback. Total — every string returns a
|
|
77
|
+
* renderable component; permissions never resolve here.
|
|
78
|
+
*/
|
|
79
|
+
export function resolveIcon(name, extensions, family) {
|
|
80
|
+
const builtins = FAMILY_REGISTRIES[resolveIconFamily(family)];
|
|
81
|
+
return lookup(extensions, name) ?? lookup(builtins, name) ?? UNKNOWN_ICON;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/icons/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,GAAG,EACH,YAAY,EACZ,IAAI,EACJ,IAAI,EACJ,SAAS,GAEV,MAAM,cAAc,CAAC;AAKtB;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAe,YAAY,CAAC;AAErD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAiB,CAAC;AAKrD,kEAAkE;AAClE,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,GAAG;IACR,IAAI,EAAE,IAAI;IACV,QAAQ,EAAE,QAAQ;IAClB,aAAa,EAAE,SAAS;IACxB,SAAS,EAAE,SAAS;CACrB,CAAC;AAEF,iFAAiF;AACjF,MAAM,iBAAiB,GAAsD;IAC3E,CAAC,mBAAmB,CAAC,EAAE,cAAc;CACtC,CAAC;AAEF;;;;;GAKG;AACH,uEAAuE;AACvE,MAAM,MAAM,GAAG,CAAC,MAAc,EAAE,GAAW,EAAW,EAAE,CACtD,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEpD,MAAM,UAAU,iBAAiB,CAAC,QAAiB;IACjD,OAAO,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,iBAAiB,EAAE,QAAQ,CAAC;QAClE,CAAC,CAAE,QAA8B;QACjC,CAAC,CAAC,mBAAmB,CAAC;AAC1B,CAAC;AAED,wCAAwC;AACxC,SAAS,MAAM,CAAC,QAAkC,EAAE,IAAY;IAC9D,OAAO,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACvF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,IAAY,EACZ,UAAyB,EACzB,MAAe;IAEf,MAAM,QAAQ,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9D,OAAO,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,YAAY,CAAC;AAC5E,CAAC"}
|