@xemahq/ui-kernel 0.1.4
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/LICENSE +17 -0
- package/README.md +72 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/biome-host/biome-mode.d.ts +2 -0
- package/dist/lib/biome-host/biome-mode.d.ts.map +1 -0
- package/dist/lib/biome-host/biome-mode.js +3 -0
- package/dist/lib/biome-host/biome-mode.js.map +1 -0
- package/dist/lib/biome-host/biome-registry.d.ts +30 -0
- package/dist/lib/biome-host/biome-registry.d.ts.map +1 -0
- package/dist/lib/biome-host/biome-registry.js +134 -0
- package/dist/lib/biome-host/biome-registry.js.map +1 -0
- package/dist/lib/biome-host/composition-validation.d.ts +22 -0
- package/dist/lib/biome-host/composition-validation.d.ts.map +1 -0
- package/dist/lib/biome-host/composition-validation.js +127 -0
- package/dist/lib/biome-host/composition-validation.js.map +1 -0
- package/dist/lib/biome-host/frontend-biome.d.ts +47 -0
- package/dist/lib/biome-host/frontend-biome.d.ts.map +1 -0
- package/dist/lib/biome-host/frontend-biome.js +3 -0
- package/dist/lib/biome-host/frontend-biome.js.map +1 -0
- package/dist/lib/biome-host/host-bridge.d.ts +55 -0
- package/dist/lib/biome-host/host-bridge.d.ts.map +1 -0
- package/dist/lib/biome-host/host-bridge.js +16 -0
- package/dist/lib/biome-host/host-bridge.js.map +1 -0
- package/dist/lib/biome-host/host-sources.d.ts +12 -0
- package/dist/lib/biome-host/host-sources.d.ts.map +1 -0
- package/dist/lib/biome-host/host-sources.js +3 -0
- package/dist/lib/biome-host/host-sources.js.map +1 -0
- package/dist/lib/biome-host/index.d.ts +10 -0
- package/dist/lib/biome-host/index.d.ts.map +1 -0
- package/dist/lib/biome-host/index.js +26 -0
- package/dist/lib/biome-host/index.js.map +1 -0
- package/dist/lib/biome-host/nav.d.ts +17 -0
- package/dist/lib/biome-host/nav.d.ts.map +1 -0
- package/dist/lib/biome-host/nav.js +52 -0
- package/dist/lib/biome-host/nav.js.map +1 -0
- package/dist/lib/biome-host/session-contributions.d.ts +143 -0
- package/dist/lib/biome-host/session-contributions.d.ts.map +1 -0
- package/dist/lib/biome-host/session-contributions.js +3 -0
- package/dist/lib/biome-host/session-contributions.js.map +1 -0
- package/dist/lib/biome-host/session-profiles.d.ts +18 -0
- package/dist/lib/biome-host/session-profiles.d.ts.map +1 -0
- package/dist/lib/biome-host/session-profiles.js +39 -0
- package/dist/lib/biome-host/session-profiles.js.map +1 -0
- package/dist/lib/system-bus/capability-invoke.d.ts +18 -0
- package/dist/lib/system-bus/capability-invoke.d.ts.map +1 -0
- package/dist/lib/system-bus/capability-invoke.js +3 -0
- package/dist/lib/system-bus/capability-invoke.js.map +1 -0
- package/dist/lib/system-bus/deeplink.d.ts +33 -0
- package/dist/lib/system-bus/deeplink.d.ts.map +1 -0
- package/dist/lib/system-bus/deeplink.js +99 -0
- package/dist/lib/system-bus/deeplink.js.map +1 -0
- package/dist/lib/system-bus/enums.d.ts +27 -0
- package/dist/lib/system-bus/enums.d.ts.map +1 -0
- package/dist/lib/system-bus/enums.js +35 -0
- package/dist/lib/system-bus/enums.js.map +1 -0
- package/dist/lib/system-bus/host-ports.d.ts +24 -0
- package/dist/lib/system-bus/host-ports.d.ts.map +1 -0
- package/dist/lib/system-bus/host-ports.js +3 -0
- package/dist/lib/system-bus/host-ports.js.map +1 -0
- package/dist/lib/system-bus/index.d.ts +11 -0
- package/dist/lib/system-bus/index.d.ts.map +1 -0
- package/dist/lib/system-bus/index.js +27 -0
- package/dist/lib/system-bus/index.js.map +1 -0
- package/dist/lib/system-bus/intent-registry.d.ts +14 -0
- package/dist/lib/system-bus/intent-registry.d.ts.map +1 -0
- package/dist/lib/system-bus/intent-registry.js +66 -0
- package/dist/lib/system-bus/intent-registry.js.map +1 -0
- package/dist/lib/system-bus/intents.d.ts +30 -0
- package/dist/lib/system-bus/intents.d.ts.map +1 -0
- package/dist/lib/system-bus/intents.js +3 -0
- package/dist/lib/system-bus/intents.js.map +1 -0
- package/dist/lib/system-bus/palette.d.ts +25 -0
- package/dist/lib/system-bus/palette.d.ts.map +1 -0
- package/dist/lib/system-bus/palette.js +3 -0
- package/dist/lib/system-bus/palette.js.map +1 -0
- package/dist/lib/system-bus/system-bus-builder.d.ts +10 -0
- package/dist/lib/system-bus/system-bus-builder.d.ts.map +1 -0
- package/dist/lib/system-bus/system-bus-builder.js +82 -0
- package/dist/lib/system-bus/system-bus-builder.js.map +1 -0
- package/dist/lib/system-bus/system-bus.d.ts +13 -0
- package/dist/lib/system-bus/system-bus.d.ts.map +1 -0
- package/dist/lib/system-bus/system-bus.js +3 -0
- package/dist/lib/system-bus/system-bus.js.map +1 -0
- package/dist/lib/system-bus/windows.d.ts +21 -0
- package/dist/lib/system-bus/windows.d.ts.map +1 -0
- package/dist/lib/system-bus/windows.js +3 -0
- package/dist/lib/system-bus/windows.js.map +1 -0
- package/dist/org-db/components/DbResultTable.d.ts +13 -0
- package/dist/org-db/components/DbResultTable.d.ts.map +1 -0
- package/dist/org-db/components/DbResultTable.js +58 -0
- package/dist/org-db/components/DbResultTable.js.map +1 -0
- package/dist/org-db/index.d.ts +2 -0
- package/dist/org-db/index.d.ts.map +1 -0
- package/dist/org-db/index.js +6 -0
- package/dist/org-db/index.js.map +1 -0
- package/dist/registry/index.d.ts +9 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +25 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/lib/biome-slot.d.ts +7 -0
- package/dist/registry/lib/biome-slot.d.ts.map +1 -0
- package/dist/registry/lib/biome-slot.js +18 -0
- package/dist/registry/lib/biome-slot.js.map +1 -0
- package/dist/registry/lib/biomes-enabled-context.d.ts +3 -0
- package/dist/registry/lib/biomes-enabled-context.d.ts.map +1 -0
- package/dist/registry/lib/biomes-enabled-context.js +11 -0
- package/dist/registry/lib/biomes-enabled-context.js.map +1 -0
- package/dist/registry/lib/composition-validation-host.d.ts +3 -0
- package/dist/registry/lib/composition-validation-host.d.ts.map +1 -0
- package/dist/registry/lib/composition-validation-host.js +10 -0
- package/dist/registry/lib/composition-validation-host.js.map +1 -0
- package/dist/registry/lib/extension-points.d.ts +15 -0
- package/dist/registry/lib/extension-points.d.ts.map +1 -0
- package/dist/registry/lib/extension-points.js +17 -0
- package/dist/registry/lib/extension-points.js.map +1 -0
- package/dist/registry/lib/primitives/SessionEventCard.d.ts +14 -0
- package/dist/registry/lib/primitives/SessionEventCard.d.ts.map +1 -0
- package/dist/registry/lib/primitives/SessionEventCard.js +60 -0
- package/dist/registry/lib/primitives/SessionEventCard.js.map +1 -0
- package/dist/registry/lib/primitives/SessionEventTimeline.d.ts +13 -0
- package/dist/registry/lib/primitives/SessionEventTimeline.d.ts.map +1 -0
- package/dist/registry/lib/primitives/SessionEventTimeline.js +35 -0
- package/dist/registry/lib/primitives/SessionEventTimeline.js.map +1 -0
- package/dist/registry/lib/primitives/SessionMutationBar.d.ts +10 -0
- package/dist/registry/lib/primitives/SessionMutationBar.d.ts.map +1 -0
- package/dist/registry/lib/primitives/SessionMutationBar.js +37 -0
- package/dist/registry/lib/primitives/SessionMutationBar.js.map +1 -0
- package/dist/registry/lib/primitives/SessionTabbedDrawer.d.ts +19 -0
- package/dist/registry/lib/primitives/SessionTabbedDrawer.d.ts.map +1 -0
- package/dist/registry/lib/primitives/SessionTabbedDrawer.js +75 -0
- package/dist/registry/lib/primitives/SessionTabbedDrawer.js.map +1 -0
- package/dist/registry/lib/primitives/index.d.ts +5 -0
- package/dist/registry/lib/primitives/index.d.ts.map +1 -0
- package/dist/registry/lib/primitives/index.js +21 -0
- package/dist/registry/lib/primitives/index.js.map +1 -0
- package/dist/registry/lib/session-context-builder.d.ts +13 -0
- package/dist/registry/lib/session-context-builder.d.ts.map +1 -0
- package/dist/registry/lib/session-context-builder.js +39 -0
- package/dist/registry/lib/session-context-builder.js.map +1 -0
- package/dist/registry/lib/session-context-provider.d.ts +10 -0
- package/dist/registry/lib/session-context-provider.d.ts.map +1 -0
- package/dist/registry/lib/session-context-provider.js +24 -0
- package/dist/registry/lib/session-context-provider.js.map +1 -0
- package/dist/registry/lib/session-selectors.d.ts +9 -0
- package/dist/registry/lib/session-selectors.d.ts.map +1 -0
- package/dist/registry/lib/session-selectors.js +149 -0
- package/dist/registry/lib/session-selectors.js.map +1 -0
- package/dist/session/comments/CommentRail.d.ts +20 -0
- package/dist/session/comments/CommentRail.d.ts.map +1 -0
- package/dist/session/comments/CommentRail.js +16 -0
- package/dist/session/comments/CommentRail.js.map +1 -0
- package/dist/session/index.d.ts +4 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +10 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/lib/cn.d.ts +3 -0
- package/dist/session/lib/cn.d.ts.map +1 -0
- package/dist/session/lib/cn.js +9 -0
- package/dist/session/lib/cn.js.map +1 -0
- package/dist/session/shell/SessionWorkspaceShell.d.ts +16 -0
- package/dist/session/shell/SessionWorkspaceShell.d.ts.map +1 -0
- package/dist/session/shell/SessionWorkspaceShell.js +15 -0
- package/dist/session/shell/SessionWorkspaceShell.js.map +1 -0
- package/package.json +84 -0
- package/src/index.ts +2 -0
- package/src/lib/biome-host/biome-mode.ts +6 -0
- package/src/lib/biome-host/biome-registry.ts +245 -0
- package/src/lib/biome-host/composition-validation.ts +215 -0
- package/src/lib/biome-host/frontend-biome.ts +162 -0
- package/src/lib/biome-host/host-bridge.ts +178 -0
- package/src/lib/biome-host/host-sources.ts +41 -0
- package/src/lib/biome-host/index.ts +23 -0
- package/src/lib/biome-host/nav.ts +83 -0
- package/src/lib/biome-host/session-contributions.ts +293 -0
- package/src/lib/biome-host/session-profiles.ts +99 -0
- package/src/lib/system-bus/capability-invoke.ts +92 -0
- package/src/lib/system-bus/deeplink.ts +200 -0
- package/src/lib/system-bus/enums.ts +86 -0
- package/src/lib/system-bus/host-ports.ts +96 -0
- package/src/lib/system-bus/index.ts +16 -0
- package/src/lib/system-bus/intent-registry.ts +106 -0
- package/src/lib/system-bus/intents.ts +109 -0
- package/src/lib/system-bus/palette.ts +77 -0
- package/src/lib/system-bus/system-bus-builder.ts +157 -0
- package/src/lib/system-bus/system-bus.ts +37 -0
- package/src/lib/system-bus/windows.ts +51 -0
- package/src/org-db/components/DbResultTable.tsx +143 -0
- package/src/org-db/index.ts +1 -0
- package/src/registry/index.ts +8 -0
- package/src/registry/lib/biome-slot.tsx +47 -0
- package/src/registry/lib/biomes-enabled-context.ts +20 -0
- package/src/registry/lib/composition-validation-host.ts +37 -0
- package/src/registry/lib/extension-points.ts +134 -0
- package/src/registry/lib/primitives/SessionEventCard.tsx +138 -0
- package/src/registry/lib/primitives/SessionEventTimeline.tsx +89 -0
- package/src/registry/lib/primitives/SessionMutationBar.tsx +76 -0
- package/src/registry/lib/primitives/SessionTabbedDrawer.tsx +155 -0
- package/src/registry/lib/primitives/index.ts +18 -0
- package/src/registry/lib/session-context-builder.ts +68 -0
- package/src/registry/lib/session-context-provider.tsx +50 -0
- package/src/registry/lib/session-selectors.ts +231 -0
- package/src/session/comments/CommentRail.tsx +164 -0
- package/src/session/index.ts +3 -0
- package/src/session/lib/cn.ts +11 -0
- package/src/session/shell/SessionWorkspaceShell.tsx +141 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSessionSlashCommands = useSessionSlashCommands;
|
|
4
|
+
exports.useSessionDrawerTabs = useSessionDrawerTabs;
|
|
5
|
+
exports.useActivityRenderer = useActivityRenderer;
|
|
6
|
+
exports.useToolCallRenderer = useToolCallRenderer;
|
|
7
|
+
exports.useSessionMutationBars = useSessionMutationBars;
|
|
8
|
+
exports.useSessionHeaderChips = useSessionHeaderChips;
|
|
9
|
+
exports.useSessionAttachmentClasses = useSessionAttachmentClasses;
|
|
10
|
+
const react_1 = require("react");
|
|
11
|
+
const index_1 = require("../../index");
|
|
12
|
+
function sortByWeight(items) {
|
|
13
|
+
return [...items].sort((a, b) => {
|
|
14
|
+
const aw = a.weight ?? a.order ?? 100;
|
|
15
|
+
const bw = b.weight ?? b.order ?? 100;
|
|
16
|
+
if (aw !== bw)
|
|
17
|
+
return aw - bw;
|
|
18
|
+
return a.id.localeCompare(b.id);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function applies(item, args) {
|
|
22
|
+
const predicate = item.appliesTo;
|
|
23
|
+
return predicate == null ? true : predicate(...args);
|
|
24
|
+
}
|
|
25
|
+
function useSessionSlashCommands(session) {
|
|
26
|
+
const revision = (0, index_1.useBiomeRegistryRevision)();
|
|
27
|
+
return (0, react_1.useMemo)(() => {
|
|
28
|
+
const out = [];
|
|
29
|
+
for (const biome of index_1.biomeRegistry.list()) {
|
|
30
|
+
for (const cmd of biome.session?.slashCommands ?? []) {
|
|
31
|
+
if (!applies(cmd, [session]))
|
|
32
|
+
continue;
|
|
33
|
+
out.push(cmd);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return Object.freeze(sortByWeight(out));
|
|
37
|
+
}, [revision, session]);
|
|
38
|
+
}
|
|
39
|
+
function useSessionDrawerTabs(session) {
|
|
40
|
+
const revision = (0, index_1.useBiomeRegistryRevision)();
|
|
41
|
+
return (0, react_1.useMemo)(() => {
|
|
42
|
+
const out = [];
|
|
43
|
+
for (const biome of index_1.biomeRegistry.list()) {
|
|
44
|
+
for (const tab of biome.session?.secondaryDrawerTabs ?? []) {
|
|
45
|
+
if (!applies(tab, [session]))
|
|
46
|
+
continue;
|
|
47
|
+
out.push(tab);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return Object.freeze(sortByWeight(out));
|
|
51
|
+
}, [revision, session]);
|
|
52
|
+
}
|
|
53
|
+
function useActivityRenderer(session, event) {
|
|
54
|
+
const revision = (0, index_1.useBiomeRegistryRevision)();
|
|
55
|
+
return (0, react_1.useMemo)(() => {
|
|
56
|
+
const candidates = [];
|
|
57
|
+
for (const biome of index_1.biomeRegistry.list()) {
|
|
58
|
+
for (const r of biome.session?.activityRenderers ?? []) {
|
|
59
|
+
if (r.entryKind !== event.kind)
|
|
60
|
+
continue;
|
|
61
|
+
if (!applies(r, [{ session, event }]))
|
|
62
|
+
continue;
|
|
63
|
+
candidates.push(r);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (candidates.length === 0)
|
|
67
|
+
return null;
|
|
68
|
+
return sortByWeight(candidates)[0] ?? null;
|
|
69
|
+
}, [revision, session, event]);
|
|
70
|
+
}
|
|
71
|
+
function matchToolName(toolName, eventName) {
|
|
72
|
+
if (toolName === eventName)
|
|
73
|
+
return 'exact';
|
|
74
|
+
if (toolName.endsWith('.*') && eventName.startsWith(toolName.slice(0, -1)))
|
|
75
|
+
return 'glob';
|
|
76
|
+
return 'none';
|
|
77
|
+
}
|
|
78
|
+
function collectToolCallCandidates(session, event) {
|
|
79
|
+
const exact = [];
|
|
80
|
+
const glob = [];
|
|
81
|
+
for (const biome of index_1.biomeRegistry.list()) {
|
|
82
|
+
for (const r of biome.session?.toolCallRenderers ?? []) {
|
|
83
|
+
const match = matchToolName(r.toolName, event.name);
|
|
84
|
+
if (match === 'none')
|
|
85
|
+
continue;
|
|
86
|
+
if (!applies(r, [{ session, event }]))
|
|
87
|
+
continue;
|
|
88
|
+
if (match === 'exact')
|
|
89
|
+
exact.push(r);
|
|
90
|
+
else
|
|
91
|
+
glob.push(r);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { exact, glob };
|
|
95
|
+
}
|
|
96
|
+
function useToolCallRenderer(session, event) {
|
|
97
|
+
const revision = (0, index_1.useBiomeRegistryRevision)();
|
|
98
|
+
return (0, react_1.useMemo)(() => {
|
|
99
|
+
const { exact, glob } = collectToolCallCandidates(session, event);
|
|
100
|
+
if (exact.length > 0)
|
|
101
|
+
return sortByWeight(exact)[0] ?? null;
|
|
102
|
+
if (glob.length > 0)
|
|
103
|
+
return sortByWeight(glob)[0] ?? null;
|
|
104
|
+
return null;
|
|
105
|
+
}, [revision, session, event]);
|
|
106
|
+
}
|
|
107
|
+
function useSessionMutationBars(session) {
|
|
108
|
+
const revision = (0, index_1.useBiomeRegistryRevision)();
|
|
109
|
+
return (0, react_1.useMemo)(() => {
|
|
110
|
+
const out = [];
|
|
111
|
+
for (const biome of index_1.biomeRegistry.list()) {
|
|
112
|
+
for (const bar of biome.session?.mutationBars ?? []) {
|
|
113
|
+
if (!applies(bar, [session]))
|
|
114
|
+
continue;
|
|
115
|
+
out.push(bar);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return Object.freeze(sortByWeight(out));
|
|
119
|
+
}, [revision, session]);
|
|
120
|
+
}
|
|
121
|
+
function useSessionHeaderChips(session) {
|
|
122
|
+
const revision = (0, index_1.useBiomeRegistryRevision)();
|
|
123
|
+
return (0, react_1.useMemo)(() => {
|
|
124
|
+
const out = [];
|
|
125
|
+
for (const biome of index_1.biomeRegistry.list()) {
|
|
126
|
+
for (const chip of biome.session?.headerChips ?? []) {
|
|
127
|
+
if (!applies(chip, [session]))
|
|
128
|
+
continue;
|
|
129
|
+
out.push(chip);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return Object.freeze(sortByWeight(out));
|
|
133
|
+
}, [revision, session]);
|
|
134
|
+
}
|
|
135
|
+
function useSessionAttachmentClasses(session) {
|
|
136
|
+
const revision = (0, index_1.useBiomeRegistryRevision)();
|
|
137
|
+
return (0, react_1.useMemo)(() => {
|
|
138
|
+
const out = [];
|
|
139
|
+
for (const biome of index_1.biomeRegistry.list()) {
|
|
140
|
+
for (const cls of biome.session?.attachmentClasses ?? []) {
|
|
141
|
+
if (!applies(cls, [session]))
|
|
142
|
+
continue;
|
|
143
|
+
out.push(cls);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return Object.freeze(sortByWeight(out));
|
|
147
|
+
}, [revision, session]);
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=session-selectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-selectors.js","sourceRoot":"","sources":["../../../src/registry/lib/session-selectors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface RailComment {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly body: string;
|
|
5
|
+
readonly quotedText?: string;
|
|
6
|
+
readonly resolved: boolean;
|
|
7
|
+
readonly authorLabel?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function CommentRail({ comments, title, emptyHint, composerSlot, headerSlot, onResolve, resolvingId, renderResolveIcon, renderResolvedIcon, }: {
|
|
10
|
+
readonly comments: readonly RailComment[];
|
|
11
|
+
readonly title?: string;
|
|
12
|
+
readonly emptyHint?: ReactNode;
|
|
13
|
+
readonly composerSlot?: ReactNode;
|
|
14
|
+
readonly headerSlot?: ReactNode;
|
|
15
|
+
readonly onResolve?: (id: string) => void;
|
|
16
|
+
readonly resolvingId?: string | null;
|
|
17
|
+
readonly renderResolveIcon?: (busy: boolean) => ReactNode;
|
|
18
|
+
readonly renderResolvedIcon?: () => ReactNode;
|
|
19
|
+
}): import("react").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=CommentRail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentRail.d.ts","sourceRoot":"","sources":["../../../src/session/comments/CommentRail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAiBD,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,KAAkB,EAClB,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,kBAAkB,GACnB,EAAE;IACD,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,SAAS,CAAC;IAC1D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,SAAS,CAAC;CAC/C,+BAmDA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CommentRail = CommentRail;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../lib/cn");
|
|
6
|
+
function CommentRail({ comments, title = 'Comments', emptyHint, composerSlot, headerSlot, onResolve, resolvingId, renderResolveIcon, renderResolvedIcon, }) {
|
|
7
|
+
const open = comments.filter((c) => !c.resolved);
|
|
8
|
+
const resolved = comments.filter((c) => c.resolved);
|
|
9
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex h-full min-h-0 flex-col gap-2 bg-paper p-3 text-[12px]", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "font-medium text-ink", children: title }), open.length > 0 && ((0, jsx_runtime_1.jsx)("span", { className: "rounded-full bg-ink/10 px-2 py-0.5 text-[11px] text-ink-2", children: open.length })), headerSlot] }), composerSlot, comments.length === 0 && !composerSlot && emptyHint && ((0, jsx_runtime_1.jsx)("div", { className: "text-ink-3", children: emptyHint })), (0, jsx_runtime_1.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col gap-2 overflow-auto pr-1", children: [open.map((comment) => ((0, jsx_runtime_1.jsx)(CommentRow, { comment: comment, onResolve: onResolve, busy: resolvingId === comment.id, renderResolveIcon: renderResolveIcon, renderResolvedIcon: renderResolvedIcon }, comment.id))), resolved.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "mt-1 text-[11px] uppercase tracking-wide text-ink-3", children: "Resolved" })), resolved.map((comment) => ((0, jsx_runtime_1.jsx)(CommentRow, { comment: comment, onResolve: onResolve, busy: resolvingId === comment.id, renderResolveIcon: renderResolveIcon, renderResolvedIcon: renderResolvedIcon }, comment.id)))] })] }));
|
|
10
|
+
}
|
|
11
|
+
function CommentRow({ comment, onResolve, busy, renderResolveIcon, renderResolvedIcon, }) {
|
|
12
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)('rounded-md border p-2', comment.resolved
|
|
13
|
+
? 'border-rule/60 bg-paper-elev/30 opacity-70'
|
|
14
|
+
: 'border-rule/70 bg-paper-elev/40'), children: [comment.quotedText && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-1 border-l-2 border-[hsl(var(--comment-anchor))] pl-2 text-[11px] italic text-ink-3", children: ["\u201C", comment.quotedText.slice(0, 120), comment.quotedText.length > 120 ? '…' : '', "\u201D"] })), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-0.5", children: [comment.authorLabel && ((0, jsx_runtime_1.jsx)("span", { className: "text-[11px] font-medium text-ink-2", children: comment.authorLabel })), (0, jsx_runtime_1.jsx)("span", { className: "whitespace-pre-wrap text-ink", children: comment.body })] }), !comment.resolved && onResolve && ((0, jsx_runtime_1.jsx)("button", { type: "button", title: "Resolve", disabled: busy, onClick: () => onResolve(comment.id), className: "flex h-6 w-6 shrink-0 items-center justify-center rounded text-ink-3 hover:bg-ink/5 hover:text-ink disabled:opacity-50", children: renderResolveIcon ? renderResolveIcon(busy) : busy ? '…' : '✓' })), comment.resolved && renderResolvedIcon && ((0, jsx_runtime_1.jsx)("span", { className: "shrink-0 text-ink-3", children: renderResolvedIcon() }))] })] }));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=CommentRail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentRail.js","sourceRoot":"","sources":["../../../src/session/comments/CommentRail.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CommentRail = exports.SessionWorkspaceShell = exports.cn = void 0;
|
|
4
|
+
var cn_1 = require("./lib/cn");
|
|
5
|
+
Object.defineProperty(exports, "cn", { enumerable: true, get: function () { return cn_1.cn; } });
|
|
6
|
+
var SessionWorkspaceShell_1 = require("./shell/SessionWorkspaceShell");
|
|
7
|
+
Object.defineProperty(exports, "SessionWorkspaceShell", { enumerable: true, get: function () { return SessionWorkspaceShell_1.SessionWorkspaceShell; } });
|
|
8
|
+
var CommentRail_1 = require("./comments/CommentRail");
|
|
9
|
+
Object.defineProperty(exports, "CommentRail", { enumerable: true, get: function () { return CommentRail_1.CommentRail; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":";;;AAAA,+BAA8B;AAArB,wFAAA,EAAE,OAAA;AACX,uEAAsE;AAA7D,8HAAA,qBAAqB,OAAA;AAC9B,sDAAuE;AAA9D,0GAAA,WAAW,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../../src/session/lib/cn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAQ7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAElD"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cn = cn;
|
|
4
|
+
const clsx_1 = require("clsx");
|
|
5
|
+
const tailwind_merge_1 = require("tailwind-merge");
|
|
6
|
+
function cn(...inputs) {
|
|
7
|
+
return (0, tailwind_merge_1.twMerge)((0, clsx_1.clsx)(inputs));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=cn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cn.js","sourceRoot":"","sources":["../../../src/session/lib/cn.ts"],"names":[],"mappings":";;AAQA,gBAEC;AAVD,+BAA6C;AAC7C,mDAAyC;AAOzC,SAAgB,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,IAAA,wBAAO,EAAC,IAAA,WAAI,EAAC,MAAM,CAAC,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ReactNode, MouseEvent, RefObject } from 'react';
|
|
2
|
+
interface SessionWorkspaceShellProps {
|
|
3
|
+
readonly splitContainerRef: RefObject<HTMLDivElement>;
|
|
4
|
+
readonly chatPanePercent: number;
|
|
5
|
+
readonly isResizing: boolean;
|
|
6
|
+
readonly startResize: (event: MouseEvent<HTMLElement>) => void;
|
|
7
|
+
readonly chatSlot: ReactNode;
|
|
8
|
+
readonly previewSlot: ReactNode;
|
|
9
|
+
readonly rightHeaderSlot?: ReactNode;
|
|
10
|
+
readonly chatFooterSlot?: ReactNode;
|
|
11
|
+
readonly previewFullscreen?: boolean;
|
|
12
|
+
readonly minLeftPaneWidth?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function SessionWorkspaceShell({ splitContainerRef, chatPanePercent, isResizing, startResize, chatSlot, previewSlot, rightHeaderSlot, chatFooterSlot, previewFullscreen, minLeftPaneWidth, }: SessionWorkspaceShellProps): import("react").JSX.Element;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=SessionWorkspaceShell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionWorkspaceShell.d.ts","sourceRoot":"","sources":["../../../src/session/shell/SessionWorkspaceShell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAI9D,UAAU,0BAA0B;IAKlC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IAEtD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAE7B,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAG/D,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAQ7B,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC;IAMhC,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,CAAC;IAMrC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IAMpC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAGrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAiBD,wBAAgB,qBAAqB,CAAC,EACpC,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,WAAW,EACX,QAAQ,EACR,WAAW,EACX,eAAe,EACf,cAAc,EACd,iBAAyB,EACzB,gBAAsB,GACvB,EAAE,0BAA0B,+BAgE5B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SessionWorkspaceShell = SessionWorkspaceShell;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../lib/cn");
|
|
6
|
+
function SessionWorkspaceShell({ splitContainerRef, chatPanePercent, isResizing, startResize, chatSlot, previewSlot, rightHeaderSlot, chatFooterSlot, previewFullscreen = false, minLeftPaneWidth = 320, }) {
|
|
7
|
+
const hasPreviewSlot = previewSlot !== null;
|
|
8
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: splitContainerRef, className: (0, cn_1.cn)('relative flex h-full w-full overflow-hidden', isResizing && 'cursor-col-resize'), children: [!previewFullscreen && ((0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)('flex h-full w-full flex-col overflow-hidden bg-paper', hasPreviewSlot ? 'lg:flex-none' : ''), style: hasPreviewSlot
|
|
9
|
+
? {
|
|
10
|
+
minWidth: `${minLeftPaneWidth}px`,
|
|
11
|
+
width: `${chatPanePercent}%`,
|
|
12
|
+
}
|
|
13
|
+
: undefined, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: [(0, jsx_runtime_1.jsx)("div", { className: "relative min-h-0 flex-1", children: chatSlot }), chatFooterSlot] }) })), !previewFullscreen && hasPreviewSlot && ((0, jsx_runtime_1.jsx)("div", { className: "relative hidden w-px shrink-0 bg-rule/30 lg:block", children: (0, jsx_runtime_1.jsx)("button", { type: "button", onMouseDown: startResize, "aria-label": "Resize chat and preview panels", title: "Drag to resize", className: "group absolute inset-y-0 left-1/2 w-2 -translate-x-1/2 cursor-col-resize", children: (0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-transparent transition-colors group-hover:bg-primary/40" }) }) })), hasPreviewSlot && ((0, jsx_runtime_1.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden bg-paper", children: [rightHeaderSlot, (0, jsx_runtime_1.jsx)("div", { className: "min-h-0 flex-1 overflow-hidden", children: previewSlot })] }))] }));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=SessionWorkspaceShell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionWorkspaceShell.js","sourceRoot":"","sources":["../../../src/session/shell/SessionWorkspaceShell.tsx"],"names":[],"mappings":";;AAiEA,sDA2EC;;AA1ID,kCAA+B;AA+D/B,SAAgB,qBAAqB,CAAC,EACpC,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,WAAW,EACX,QAAQ,EACR,WAAW,EACX,eAAe,EACf,cAAc,EACd,iBAAiB,GAAG,KAAK,EACzB,gBAAgB,GAAG,GAAG,GACK;IAI3B,MAAM,cAAc,GAAG,WAAW,KAAK,IAAI,CAAC;IAC5C,OAAO,CACL,iCACE,GAAG,EAAE,iBAAiB,EACtB,SAAS,EAAE,IAAA,OAAE,EACX,6CAA6C,EAC7C,UAAU,IAAI,mBAAmB,CAClC,aAEA,CAAC,iBAAiB,IAAI,CACrB,gCACE,SAAS,EAAE,IAAA,OAAE,EACX,sDAAsD,EACtD,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CACrC,EACD,KAAK,EACH,cAAc;oBACZ,CAAC,CAAC;wBACE,QAAQ,EAAE,GAAG,gBAAgB,IAAI;wBACjC,KAAK,EAAE,GAAG,eAAe,GAAG;qBAC7B;oBACH,CAAC,CAAC,SAAS,YAGf,iCAAK,SAAS,EAAC,8CAA8C,aAC3D,gCAAK,SAAS,EAAC,yBAAyB,YAAE,QAAQ,GAAO,EACxD,cAAc,IACX,GACF,CACP,EAEA,CAAC,iBAAiB,IAAI,cAAc,IAAI,CACvC,gCAAK,SAAS,EAAC,mDAAmD,YAKhE,mCACE,IAAI,EAAC,QAAQ,EACb,WAAW,EAAE,WAAW,gBACb,gCAAgC,EAC3C,KAAK,EAAC,gBAAgB,EACtB,SAAS,EAAC,0EAA0E,YAEpF,sDAEE,SAAS,EAAC,8GAA8G,GACxH,GACK,GACL,CACP,EAEA,cAAc,IAAI,CACjB,iCAAK,SAAS,EAAC,uDAAuD,aACnE,eAAe,EAChB,gCAAK,SAAS,EAAC,gCAAgC,YAAE,WAAW,GAAO,IAC/D,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xemahq/ui-kernel",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Host-framework-agnostic UI kernel for the Xema OS. Defines the SystemBus orchestration contract (capability.invoke, cross-biome intents, command palette, xema:// deeplinks, window manager) AND the biome-host contract surface (FrontendBiome/FrontendBiomeFactory, HostBridge, the singleton biomeRegistry, session contributions) that every frontend biome composes against. No Vite, Next.js, or React-Router — React itself IS allowed as the shared component model (the contracts traffic in ReactNode/ComponentType and a React context). Concrete host adapters (router/auth/toast wiring) live in separate packages that consume this kernel. The SystemBus is pure orchestration: it never authorizes, the backend capability-router enforces all policy.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"xema",
|
|
7
|
+
"xema-platform",
|
|
8
|
+
"xema-ui-kernel",
|
|
9
|
+
"system-bus",
|
|
10
|
+
"biome",
|
|
11
|
+
"capability",
|
|
12
|
+
"deeplink",
|
|
13
|
+
"intents"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://docs.xema.dev/biomes",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/xema-dev/xema-monorepo/issues"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/xema-dev/xema-monorepo.git",
|
|
22
|
+
"directory": "packages/ui/xema-ui-kernel"
|
|
23
|
+
},
|
|
24
|
+
"license": "Apache-2.0",
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public",
|
|
27
|
+
"registry": "https://registry.npmjs.org/"
|
|
28
|
+
},
|
|
29
|
+
"main": "dist/index.js",
|
|
30
|
+
"types": "dist/index.d.ts",
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"src",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@xemahq/kernel-contracts": "^0.2.0",
|
|
39
|
+
"clsx": "^2.1.1",
|
|
40
|
+
"tailwind-merge": "^2.5.4",
|
|
41
|
+
"@xemahq/registry": "0.1.1"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@tanstack/react-query": "^5.0.0",
|
|
45
|
+
"react": "^18.3.1"
|
|
46
|
+
},
|
|
47
|
+
"peerDependenciesMeta": {
|
|
48
|
+
"@tanstack/react-query": {
|
|
49
|
+
"optional": true
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@tanstack/react-query": "^5.100.13",
|
|
54
|
+
"@types/node": "25.2.3",
|
|
55
|
+
"@types/react": "^18.3.30",
|
|
56
|
+
"prettier": "3.6.2",
|
|
57
|
+
"react": "^18.3.1",
|
|
58
|
+
"typescript": "5.9.3"
|
|
59
|
+
},
|
|
60
|
+
"exports": {
|
|
61
|
+
".": {
|
|
62
|
+
"types": "./dist/index.d.ts",
|
|
63
|
+
"xema-source": "./src/index.ts",
|
|
64
|
+
"default": "./dist/index.js"
|
|
65
|
+
},
|
|
66
|
+
"./*": {
|
|
67
|
+
"types": "./dist/*/index.d.ts",
|
|
68
|
+
"xema-source": "./src/*/index.ts",
|
|
69
|
+
"default": "./dist/*/index.js"
|
|
70
|
+
},
|
|
71
|
+
"./dist/lib/*": {
|
|
72
|
+
"types": "./dist/lib/*.d.ts",
|
|
73
|
+
"default": "./dist/lib/*.js"
|
|
74
|
+
},
|
|
75
|
+
"./package.json": "./package.json"
|
|
76
|
+
},
|
|
77
|
+
"scripts": {
|
|
78
|
+
"clean": "rm -rf dist",
|
|
79
|
+
"build": "tsc -p tsconfig.json",
|
|
80
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|
|
81
|
+
"lint": "tsc -p tsconfig.lint.json --noEmit",
|
|
82
|
+
"typecheck": "tsc -p tsconfig.lint.json --noEmit"
|
|
83
|
+
}
|
|
84
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { Registry } from '@xemahq/registry';
|
|
2
|
+
import { useSyncExternalStore } from 'react';
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
FrontendBiome,
|
|
6
|
+
FrontendBiomeFactory,
|
|
7
|
+
OutputRendererContribution,
|
|
8
|
+
PanelContribution,
|
|
9
|
+
} from './frontend-biome';
|
|
10
|
+
import type { HostBridge } from './host-bridge';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Singleton frontend biome registry. Populated at app bootstrap by
|
|
14
|
+
* `registerFrontendBiome()` (factory form) or `registerFrontendBiomeInstance()`
|
|
15
|
+
* (already-built form). Bootstrap order: fetch enabled biome ids from
|
|
16
|
+
* `GET /platform/biomes/web`, dynamically `import()` each biome module
|
|
17
|
+
* from the auto-generated loader map (`xema:web-biome-loaders`), then
|
|
18
|
+
* call its default export with the host's concrete `HostBridge` and
|
|
19
|
+
* register the result.
|
|
20
|
+
*
|
|
21
|
+
* Reactivity: components consume registry data via `useBiomeRegistryRevision()`
|
|
22
|
+
* (or `<BiomeSlot>` / `useBiomeRoutes()` which use it internally) so a
|
|
23
|
+
* re-render fires automatically when a biome registers or unregisters —
|
|
24
|
+
* no race between Sidebar mount and async bootstrap, no manual subscription
|
|
25
|
+
* wiring per consumer.
|
|
26
|
+
*
|
|
27
|
+
* Master-disable: hosts that embed `@xemahq/ui-kernel` without
|
|
28
|
+
* participating in Xema's biome ecosystem flip
|
|
29
|
+
* `biomeRegistry.setEnabled(false)` (typically via
|
|
30
|
+
* `<BiomeHostProvider biomes="disabled">`). When disabled, every
|
|
31
|
+
* register/unregister/bootstrap call is a no-op — a single flag controls
|
|
32
|
+
* the entire surface.
|
|
33
|
+
*/
|
|
34
|
+
class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: string }> {
|
|
35
|
+
private revisionCount = 0;
|
|
36
|
+
private readonly listeners = new Set<() => void>();
|
|
37
|
+
/**
|
|
38
|
+
* Biome ids whose `init()` callback has been invoked. Tracked
|
|
39
|
+
* separately from the registry entries so `init()` runs exactly once
|
|
40
|
+
* per biome per SPA session even if `registerBiome` is called
|
|
41
|
+
* multiple times (HMR, strict-mode double-mount, retries). Biome
|
|
42
|
+
* authors get an at-most-once execution guarantee.
|
|
43
|
+
*/
|
|
44
|
+
private readonly initialized = new Set<string>();
|
|
45
|
+
private enabled = true;
|
|
46
|
+
|
|
47
|
+
constructor() {
|
|
48
|
+
super({ name: 'FrontendBiomeRegistry' });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
registerBiome(biome: FrontendBiome): void {
|
|
52
|
+
if (!this.enabled) return;
|
|
53
|
+
this.register({ ...biome, key: biome.id });
|
|
54
|
+
this.revisionCount += 1;
|
|
55
|
+
this.notify();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Invoke a biome's `init()` callback exactly once per SPA session.
|
|
60
|
+
* The caller (bootstrap) is responsible for catching/logging promise
|
|
61
|
+
* rejections — the registry intentionally does not swallow them.
|
|
62
|
+
*/
|
|
63
|
+
async runInit(biomeId: string, bridge: HostBridge): Promise<void> {
|
|
64
|
+
const entry = this.get(biomeId);
|
|
65
|
+
if (!entry || !entry.init) return;
|
|
66
|
+
if (this.initialized.has(biomeId)) return;
|
|
67
|
+
this.initialized.add(biomeId);
|
|
68
|
+
await entry.init({ bridge, biomeId });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
unregisterBiome(id: string): boolean {
|
|
72
|
+
if (!this.enabled) return false;
|
|
73
|
+
const entry = this.get(id);
|
|
74
|
+
const removed = this.unregister(id);
|
|
75
|
+
if (removed) {
|
|
76
|
+
this.revisionCount += 1;
|
|
77
|
+
this.initialized.delete(id);
|
|
78
|
+
if (entry?.dispose) {
|
|
79
|
+
// Fire-and-forget; teardown errors are logged by callers but
|
|
80
|
+
// never block the unregister path — disposal is best-effort
|
|
81
|
+
// because the biome is being torn down anyway.
|
|
82
|
+
void Promise.resolve(entry.dispose()).catch((error: unknown) => {
|
|
83
|
+
// Surface for devtools without crashing the unregister flow.
|
|
84
|
+
// eslint-disable-next-line no-console
|
|
85
|
+
console.error(`[xema-ui-kernel] dispose() failed for '${id}':`, error);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
this.notify();
|
|
89
|
+
}
|
|
90
|
+
return removed;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Snapshot of currently-registered biome ids. Useful for the admin UI
|
|
95
|
+
* to detect "registered in this session" vs "enabled in catalog".
|
|
96
|
+
*/
|
|
97
|
+
snapshot(): readonly string[] {
|
|
98
|
+
return this.list().map((b) => b.id);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setEnabled(enabled: boolean): void {
|
|
102
|
+
if (this.enabled === enabled) return;
|
|
103
|
+
this.enabled = enabled;
|
|
104
|
+
if (!enabled) {
|
|
105
|
+
// When master-disabling, drop any previously-registered biomes so
|
|
106
|
+
// BiomeSlot/useBiomeRoutes consumers re-render to empty.
|
|
107
|
+
const had = this.size() > 0;
|
|
108
|
+
this.clear();
|
|
109
|
+
this.initialized.clear();
|
|
110
|
+
if (had) {
|
|
111
|
+
this.revisionCount += 1;
|
|
112
|
+
this.notify();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
isEnabled(): boolean {
|
|
118
|
+
return this.enabled;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
revision(): number {
|
|
122
|
+
return this.revisionCount;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Subscribe to revision-counter changes. Returns an unsubscribe
|
|
127
|
+
* function. Used internally by `useBiomeRegistryRevision()` (via
|
|
128
|
+
* `useSyncExternalStore`) so components automatically re-render when
|
|
129
|
+
* a biome is added or removed.
|
|
130
|
+
*/
|
|
131
|
+
subscribe(listener: () => void): () => void {
|
|
132
|
+
this.listeners.add(listener);
|
|
133
|
+
return () => {
|
|
134
|
+
this.listeners.delete(listener);
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
panelsForSlot(slot: string): readonly PanelContribution[] {
|
|
139
|
+
if (!this.enabled) return [];
|
|
140
|
+
const out: PanelContribution[] = [];
|
|
141
|
+
for (const biome of this.list()) {
|
|
142
|
+
for (const panel of biome.panels ?? []) {
|
|
143
|
+
if (panel.slot === slot) out.push(panel);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return out.sort((a, b) => (a.weight ?? 100) - (b.weight ?? 100));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Flatten every registered biome's `outputRenderers[]` contributions
|
|
151
|
+
* into a `(outputKind → factory)` map. The host's renderer registry
|
|
152
|
+
* overlays this on top of the built-in set so biome-defined kinds
|
|
153
|
+
* light up the moment the biome's frontend loads. Duplicate kinds
|
|
154
|
+
* across biomes are surfaced as a console error and the first
|
|
155
|
+
* registration wins (deterministic + fail-loud, not silent).
|
|
156
|
+
*/
|
|
157
|
+
outputRenderers(): ReadonlyMap<string, OutputRendererContribution> {
|
|
158
|
+
const out = new Map<string, OutputRendererContribution>();
|
|
159
|
+
if (!this.enabled) return out;
|
|
160
|
+
for (const biome of this.list()) {
|
|
161
|
+
for (const entry of biome.outputRenderers ?? []) {
|
|
162
|
+
if (out.has(entry.outputKind)) {
|
|
163
|
+
console.error(
|
|
164
|
+
`[xema-ui-kernel] duplicate outputRenderer for kind '${entry.outputKind}' ` +
|
|
165
|
+
`from biome '${biome.id}'; first registration wins.`,
|
|
166
|
+
);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
out.set(entry.outputKind, entry);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private notify(): void {
|
|
176
|
+
for (const listener of this.listeners) {
|
|
177
|
+
listener();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export const biomeRegistry = new FrontendBiomeRegistry();
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Register an already-built `FrontendBiome` instance. Prefer
|
|
186
|
+
* `registerFrontendBiome(factory, bridge)` for biomes shipped via
|
|
187
|
+
* the factory contract.
|
|
188
|
+
*/
|
|
189
|
+
export function registerFrontendBiomeInstance(biome: FrontendBiome): void {
|
|
190
|
+
biomeRegistry.registerBiome(biome);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Invoke a `FrontendBiomeFactory` with the host's `HostBridge` and
|
|
195
|
+
* register the resulting `FrontendBiome`. This is the standard
|
|
196
|
+
* registration path for biomes shipped as workspace packages.
|
|
197
|
+
*
|
|
198
|
+
* Fail-fast: a factory that returns a non-`FrontendBiome` value, or
|
|
199
|
+
* that produces a duplicate id, propagates the underlying registry
|
|
200
|
+
* error — no swallowing.
|
|
201
|
+
*/
|
|
202
|
+
export function registerFrontendBiome(
|
|
203
|
+
factory: FrontendBiomeFactory,
|
|
204
|
+
bridge: HostBridge,
|
|
205
|
+
): void {
|
|
206
|
+
if (!biomeRegistry.isEnabled()) return;
|
|
207
|
+
const biome = factory(bridge);
|
|
208
|
+
if (!biome || typeof biome !== 'object' || typeof biome.id !== 'string') {
|
|
209
|
+
throw new Error(
|
|
210
|
+
'[xema-ui-kernel] FrontendBiomeFactory returned a non-FrontendBiome value. ' +
|
|
211
|
+
'A biome module must default-export `(bridge) => FrontendBiome`.',
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
biomeRegistry.registerBiome(biome);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Unregister a biome by id. Triggered by the admin UI's runtime
|
|
219
|
+
* disable flow so BiomeSlot / useBiomeRoutes consumers reflow without
|
|
220
|
+
* a page reload. Returns `true` if a registration was removed.
|
|
221
|
+
*/
|
|
222
|
+
export function unregisterFrontendBiome(id: string): boolean {
|
|
223
|
+
return biomeRegistry.unregisterBiome(id);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* React hook that subscribes the calling component to the biome
|
|
228
|
+
* registry's revision counter. Returns the current revision (a number
|
|
229
|
+
* that increments by 1 on every biome registration or unregistration).
|
|
230
|
+
* Use the return value as a `useMemo` dep when computing data derived
|
|
231
|
+
* from the registry — the memo recomputes on every change.
|
|
232
|
+
*
|
|
233
|
+
* Implemented with `useSyncExternalStore` so it integrates cleanly with
|
|
234
|
+
* React 18 concurrent rendering and SSR.
|
|
235
|
+
*
|
|
236
|
+
* `<BiomeSlot>` uses this hook internally so any host page that mounts
|
|
237
|
+
* a slot re-renders automatically when biomes arrive or leave.
|
|
238
|
+
*/
|
|
239
|
+
export function useBiomeRegistryRevision(): number {
|
|
240
|
+
return useSyncExternalStore(
|
|
241
|
+
(listener) => biomeRegistry.subscribe(listener),
|
|
242
|
+
() => biomeRegistry.revision(),
|
|
243
|
+
() => biomeRegistry.revision(),
|
|
244
|
+
);
|
|
245
|
+
}
|