@elevasis/ui 2.31.0 → 2.32.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/dist/{CoreAuthKitInner-KSEGSB67.js → CoreAuthKitInner-QC62UHTZ.js} +1 -1
- package/dist/api/index.js +3 -3
- package/dist/app/index.css +38 -0
- package/dist/app/index.d.ts +69 -9
- package/dist/app/index.js +7 -6
- package/dist/auth/context.js +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/charts/index.js +5 -6
- package/dist/{chunk-XQHZBA65.js → chunk-2RJMVWFJ.js} +1 -6
- package/dist/{chunk-CW3UNAF2.js → chunk-4DYOXEH6.js} +410 -5
- package/dist/{chunk-HQGF4ATG.js → chunk-4MFNGNHF.js} +118 -141
- package/dist/{chunk-ND42LPY4.js → chunk-4QK76KIF.js} +6 -6
- package/dist/chunk-5FJJ72HU.js +13 -0
- package/dist/chunk-5J4PDX26.js +112 -0
- package/dist/{chunk-QDEETKYT.js → chunk-6DWD423K.js} +9 -9
- package/dist/{chunk-SHQXMW4F.js → chunk-7KZINJLP.js} +46 -28
- package/dist/{chunk-L3BVJWML.js → chunk-EPTHX4VZ.js} +1 -1
- package/dist/{chunk-JKSUN5GN.js → chunk-GCOQ3TBG.js} +81 -746
- package/dist/{chunk-DZTG5IAC.js → chunk-I2KLQ2HA.js} +1 -7
- package/dist/{chunk-L2NVFLXU.js → chunk-IQHU7O5Y.js} +4 -4
- package/dist/{chunk-P55BJZZW.js → chunk-IZWTVFJ2.js} +16 -4
- package/dist/{chunk-QHEWXU7I.js → chunk-JFL3GRD4.js} +1 -1
- package/dist/{chunk-Q6OYNEGR.js → chunk-LLRXA7D7.js} +5 -6
- package/dist/{chunk-7KC4P3AU.js → chunk-MOY4VOHF.js} +2 -12
- package/dist/{chunk-XQQEKWTL.js → chunk-N55DVMAG.js} +6 -2
- package/dist/{chunk-TOIXUWR6.js → chunk-ND5TDV2J.js} +1 -1
- package/dist/{chunk-WF227UBV.js → chunk-QQHOKTJA.js} +4 -4
- package/dist/{chunk-T3IPHEYJ.js → chunk-QTI3KC7D.js} +4335 -554
- package/dist/chunk-QXCDKE2O.js +486 -0
- package/dist/{chunk-3BAPR3KA.js → chunk-RQA2EVN3.js} +5 -15
- package/dist/{chunk-HYNYEBHM.js → chunk-RQTWIXJ5.js} +3 -3
- package/dist/chunk-T35FWDAB.js +4342 -0
- package/dist/{chunk-DWK2QIAK.js → chunk-TYRUKGGD.js} +1 -1
- package/dist/{chunk-GRDLB6LM.js → chunk-UROTM5OR.js} +13 -1
- package/dist/{chunk-6YT4IKJ7.js → chunk-VNAZTCHA.js} +15 -0
- package/dist/{chunk-5LJAEZMA.js → chunk-VRNMNB3O.js} +5 -6
- package/dist/chunk-WQPX44YM.js +1626 -0
- package/dist/{chunk-7HMCB26R.js → chunk-XZGSCABI.js} +1 -1
- package/dist/chunk-YLQEVSOR.js +299 -0
- package/dist/{chunk-Y4FWCG7Y.js → chunk-ZQOKIGZP.js} +8 -7
- package/dist/components/chat/index.js +1 -1
- package/dist/components/index.css +38 -0
- package/dist/components/index.d.ts +152 -50
- package/dist/components/index.js +36 -39
- package/dist/components/navigation/index.css +38 -0
- package/dist/components/navigation/index.js +4 -3
- package/dist/execution/index.d.ts +7 -2
- package/dist/execution/index.js +1 -1
- package/dist/features/auth/index.css +38 -0
- package/dist/features/auth/index.d.ts +91 -14
- package/dist/features/auth/index.js +42 -10
- package/dist/features/clients/index.css +38 -0
- package/dist/features/clients/index.d.ts +1 -1
- package/dist/features/clients/index.js +16 -15
- package/dist/features/crm/index.css +38 -0
- package/dist/features/crm/index.d.ts +80 -18
- package/dist/features/crm/index.js +16 -15
- package/dist/features/dashboard/index.css +38 -0
- package/dist/features/dashboard/index.d.ts +65 -25
- package/dist/features/dashboard/index.js +16 -16
- package/dist/features/delivery/index.css +38 -0
- package/dist/features/delivery/index.d.ts +80 -18
- package/dist/features/delivery/index.js +15 -15
- package/dist/features/knowledge/index.css +38 -0
- package/dist/features/knowledge/index.d.ts +20 -18
- package/dist/features/knowledge/index.js +112 -597
- package/dist/features/lead-gen/index.css +38 -0
- package/dist/features/lead-gen/index.d.ts +45 -43
- package/dist/features/lead-gen/index.js +16 -16
- package/dist/features/monitoring/index.css +38 -0
- package/dist/features/monitoring/index.d.ts +20 -18
- package/dist/features/monitoring/index.js +17 -17
- package/dist/features/monitoring/requests/index.css +38 -0
- package/dist/features/monitoring/requests/index.d.ts +21 -19
- package/dist/features/monitoring/requests/index.js +15 -14
- package/dist/features/operations/index.css +38 -0
- package/dist/features/operations/index.d.ts +930 -66
- package/dist/features/operations/index.js +21 -24
- package/dist/features/seo/index.d.ts +20 -18
- package/dist/features/seo/index.js +2 -2
- package/dist/features/settings/index.css +38 -0
- package/dist/features/settings/index.d.ts +80 -18
- package/dist/features/settings/index.js +16 -15
- package/dist/graph/index.js +1 -1
- package/dist/hooks/delivery/index.css +38 -0
- package/dist/hooks/delivery/index.d.ts +60 -0
- package/dist/hooks/delivery/index.js +3 -3
- package/dist/hooks/index.css +38 -0
- package/dist/hooks/index.d.ts +301 -87
- package/dist/hooks/index.js +14 -13
- package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +143 -33
- package/dist/hooks/operations/command-view/utils/transformCommandViewData.js +1 -1
- package/dist/hooks/published.css +38 -0
- package/dist/hooks/published.d.ts +301 -87
- package/dist/hooks/published.js +14 -13
- package/dist/index.css +38 -0
- package/dist/index.d.ts +976 -1341
- package/dist/index.js +15 -14
- package/dist/initialization/index.d.ts +60 -0
- package/dist/initialization/index.js +1 -1
- package/dist/knowledge/index.d.ts +809 -1160
- package/dist/knowledge/index.js +5988 -2140
- package/dist/{chunk-O2QOPJI5.js → knowledge-search-index-5KYPO746.js} +96 -852
- package/dist/layout/index.js +3 -4
- package/dist/organization/index.css +38 -0
- package/dist/organization/index.js +1 -1
- package/dist/profile/index.d.ts +60 -0
- package/dist/profile/index.js +1 -1
- package/dist/provider/ElevasisServiceContext.js +1 -1
- package/dist/provider/index.css +38 -0
- package/dist/provider/index.d.ts +786 -1249
- package/dist/provider/index.js +11 -10
- package/dist/provider/published.css +38 -0
- package/dist/provider/published.d.ts +783 -1246
- package/dist/provider/published.js +8 -7
- package/dist/router/context.js +1 -1
- package/dist/router/index.js +1 -1
- package/dist/sse/index.js +1 -1
- package/dist/supabase/index.d.ts +117 -0
- package/dist/supabase/index.js +1 -1
- package/dist/test-utils/index.d.ts +16 -9
- package/dist/test-utils/index.js +40 -33
- package/dist/test-utils/setup-integration.js +1 -1
- package/dist/test-utils/setup.js +1 -1
- package/dist/theme/index.js +3 -3
- package/dist/theme/presets/index.js +1 -1
- package/dist/typeform/index.js +1 -1
- package/dist/typeform/schemas.js +1 -1
- package/dist/types/index.d.ts +205 -35
- package/dist/utils/index.d.ts +65 -25
- package/dist/utils/index.js +2 -2
- package/dist/vite/index.js +1 -1
- package/dist/vite-plugin-knowledge/index.js +1 -1
- package/dist/zustand/index.js +1 -1
- package/package.json +39 -38
- package/src/provider/README.md +5 -5
- package/dist/chunk-542WPQU2.js +0 -413
- package/dist/chunk-6IXOKUBC.js +0 -347
- package/dist/chunk-CQZ3DNQY.js +0 -740
- package/dist/chunk-ECNNI3NT.js +0 -6
- package/dist/chunk-JDNEWB5F.js +0 -10
- package/dist/chunk-MVFCLZSK.js +0 -4337
- package/dist/chunk-OAVTMITG.js +0 -13
- package/dist/chunk-TVRQ6AQI.js +0 -476
|
@@ -0,0 +1,1626 @@
|
|
|
1
|
+
import { SemanticIcon } from './chunk-UROTM5OR.js';
|
|
2
|
+
import { buildOrganizationGraph, projectOrganizationSurfaces, getSortedSidebarEntries, getSystem } from './chunk-T35FWDAB.js';
|
|
3
|
+
import { useMemo, useState, useRef, useEffect } from 'react';
|
|
4
|
+
import { useTree, Text, Tree, UnstyledButton, Group, TextInput } from '@mantine/core';
|
|
5
|
+
import { useClipboard } from '@mantine/hooks';
|
|
6
|
+
import { IconChevronDown, IconChevronRight, IconX, IconSearch, IconCheck, IconCopy, IconStarFilled, IconStar } from '@tabler/icons-react';
|
|
7
|
+
import { create } from 'zustand';
|
|
8
|
+
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
9
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
10
|
+
|
|
11
|
+
// src/organization-model/getSharedOrganizationGraph.ts
|
|
12
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
13
|
+
function getSharedOrganizationGraph(organizationModel) {
|
|
14
|
+
const cached = cache.get(organizationModel);
|
|
15
|
+
if (cached) return cached;
|
|
16
|
+
const graph = buildOrganizationGraph({ organizationModel });
|
|
17
|
+
cache.set(organizationModel, graph);
|
|
18
|
+
return graph;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/knowledge/iconTokens.ts
|
|
22
|
+
var KNOWLEDGE_ICON_TOKEN_BY_KIND = {
|
|
23
|
+
playbook: "knowledge.playbook",
|
|
24
|
+
strategy: "knowledge.strategy",
|
|
25
|
+
reference: "knowledge.reference"
|
|
26
|
+
};
|
|
27
|
+
function getKnowledgeIconToken(node) {
|
|
28
|
+
return node.icon ?? KNOWLEDGE_ICON_TOKEN_BY_KIND[node.kind];
|
|
29
|
+
}
|
|
30
|
+
var useKnowledgeFavoritesStore = create()(
|
|
31
|
+
persist(
|
|
32
|
+
(set) => ({
|
|
33
|
+
favorites: {},
|
|
34
|
+
toggleFavorite: (entry) => set((state) => {
|
|
35
|
+
const next = { ...state.favorites };
|
|
36
|
+
if (next[entry.routeId]) {
|
|
37
|
+
delete next[entry.routeId];
|
|
38
|
+
} else {
|
|
39
|
+
next[entry.routeId] = { ...entry, addedAt: Date.now() };
|
|
40
|
+
}
|
|
41
|
+
return { favorites: next };
|
|
42
|
+
}),
|
|
43
|
+
removeFavorite: (routeId) => set((state) => {
|
|
44
|
+
if (!state.favorites[routeId]) return state;
|
|
45
|
+
const next = { ...state.favorites };
|
|
46
|
+
delete next[routeId];
|
|
47
|
+
return { favorites: next };
|
|
48
|
+
}),
|
|
49
|
+
clearFavorites: () => set({ favorites: {} })
|
|
50
|
+
}),
|
|
51
|
+
{
|
|
52
|
+
name: "elevasis-knowledge-favorites",
|
|
53
|
+
storage: createJSONStorage(() => localStorage),
|
|
54
|
+
version: 1
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// src/knowledge/navigationProjection.ts
|
|
60
|
+
function collectSurfaceIds(nodes) {
|
|
61
|
+
return getSortedSidebarEntries(nodes).flatMap(
|
|
62
|
+
([id, node]) => node.type === "group" ? collectSurfaceIds(node.children) : [id]
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function collectGroups(nodes, placement, groups = []) {
|
|
66
|
+
getSortedSidebarEntries(nodes).forEach(([id, node]) => {
|
|
67
|
+
if (node.type !== "group") return;
|
|
68
|
+
groups.push({
|
|
69
|
+
id,
|
|
70
|
+
label: node.label,
|
|
71
|
+
placement,
|
|
72
|
+
surfaceIds: collectSurfaceIds(node.children)
|
|
73
|
+
});
|
|
74
|
+
collectGroups(node.children, placement, groups);
|
|
75
|
+
});
|
|
76
|
+
return groups;
|
|
77
|
+
}
|
|
78
|
+
function projectNavigationSurfaces(model) {
|
|
79
|
+
return projectOrganizationSurfaces(model);
|
|
80
|
+
}
|
|
81
|
+
function projectNavigationGroups(model) {
|
|
82
|
+
return [
|
|
83
|
+
...collectGroups(model.navigation.sidebar.primary, "primary"),
|
|
84
|
+
...collectGroups(model.navigation.sidebar.bottom, "bottom")
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
function toSemanticFallbackKind(kind) {
|
|
88
|
+
switch (kind) {
|
|
89
|
+
case "knowledge":
|
|
90
|
+
case "resource":
|
|
91
|
+
case "action":
|
|
92
|
+
case "entity":
|
|
93
|
+
case "event":
|
|
94
|
+
case "policy":
|
|
95
|
+
return kind;
|
|
96
|
+
case "system":
|
|
97
|
+
return "feature";
|
|
98
|
+
case "role":
|
|
99
|
+
return "unknown";
|
|
100
|
+
case "stage":
|
|
101
|
+
return "status";
|
|
102
|
+
case "organization":
|
|
103
|
+
return "unknown";
|
|
104
|
+
default:
|
|
105
|
+
return "unknown";
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
var QUICK_ACCESS_GROUP_KEY = "quick-access";
|
|
109
|
+
var FAVORITE_PREFIX = "favorite:";
|
|
110
|
+
var QUICK_ACCESS_GROUP_VALUE = `group:${QUICK_ACCESS_GROUP_KEY}`;
|
|
111
|
+
var GROUP_ICON_TOKENS = {
|
|
112
|
+
[QUICK_ACCESS_GROUP_KEY]: "om.quick-access",
|
|
113
|
+
profile: "om.profile",
|
|
114
|
+
"business-model": "om.business-model",
|
|
115
|
+
systems: "om.systems",
|
|
116
|
+
graph: "om.graph",
|
|
117
|
+
"governance-wiring": "om.governance-wiring"
|
|
118
|
+
};
|
|
119
|
+
function findFavoritePathInTree(nodes, favorite) {
|
|
120
|
+
const matchesPrimary = (node) => {
|
|
121
|
+
if (favorite.kind === "knowledge") {
|
|
122
|
+
return node.nodeType === "leaf" && node.knowledgeNodeId === favorite.routeId;
|
|
123
|
+
}
|
|
124
|
+
if (favorite.kind === "graph") {
|
|
125
|
+
return node.graphNodeId === favorite.routeId;
|
|
126
|
+
}
|
|
127
|
+
return typeof node.value === "string" && node.value === favorite.routeId;
|
|
128
|
+
};
|
|
129
|
+
const matchesFallback = (node) => {
|
|
130
|
+
if (favorite.kind !== "knowledge") return false;
|
|
131
|
+
return node.nodeType === "item" && node.domainKey === "knowledge" && node.itemId === favorite.routeId;
|
|
132
|
+
};
|
|
133
|
+
function dfs(node, ancestors, match) {
|
|
134
|
+
if (node.value === QUICK_ACCESS_GROUP_VALUE) return void 0;
|
|
135
|
+
const value = typeof node.value === "string" ? node.value : "";
|
|
136
|
+
const path = [...ancestors, value];
|
|
137
|
+
if (match(node)) return path;
|
|
138
|
+
for (const child of node.children ?? []) {
|
|
139
|
+
const found = dfs(child, path, match);
|
|
140
|
+
if (found) return found;
|
|
141
|
+
}
|
|
142
|
+
return void 0;
|
|
143
|
+
}
|
|
144
|
+
for (const root of nodes) {
|
|
145
|
+
const found = dfs(root, [], matchesPrimary);
|
|
146
|
+
if (found) return found;
|
|
147
|
+
}
|
|
148
|
+
for (const root of nodes) {
|
|
149
|
+
const found = dfs(root, [], matchesFallback);
|
|
150
|
+
if (found) return found;
|
|
151
|
+
}
|
|
152
|
+
return void 0;
|
|
153
|
+
}
|
|
154
|
+
var OM_TREE_GROUPS = [
|
|
155
|
+
{ key: "profile", label: "Profile", domains: ["identity", "branding"] },
|
|
156
|
+
{ key: "business-model", label: "Business Model", domains: ["customers", "offerings", "goals"] },
|
|
157
|
+
{ key: "systems", label: "Systems", domains: ["systems", "sales", "prospecting", "projects"] },
|
|
158
|
+
{ key: "graph", label: "Graph", domains: ["resources", "actions", "entities", "events", "stages", "knowledge"] },
|
|
159
|
+
{ key: "governance-wiring", label: "Governance & Wiring", domains: ["roles", "policies", "statuses", "navigation"] }
|
|
160
|
+
];
|
|
161
|
+
var DOMAIN_PREFIX = "domain:";
|
|
162
|
+
var GROUP_PREFIX = "group:";
|
|
163
|
+
var ITEM_PREFIX = "item:";
|
|
164
|
+
function domainKeyForKnowledgeTarget(targetKind) {
|
|
165
|
+
switch (targetKind) {
|
|
166
|
+
case "customer-segment":
|
|
167
|
+
return "customers";
|
|
168
|
+
case "offering":
|
|
169
|
+
return "offerings";
|
|
170
|
+
case "goal":
|
|
171
|
+
return "goals";
|
|
172
|
+
case "role":
|
|
173
|
+
return "roles";
|
|
174
|
+
default:
|
|
175
|
+
return void 0;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function graphNodeIdForKnowledgeTarget(targetKind, targetId) {
|
|
179
|
+
switch (targetKind) {
|
|
180
|
+
case "resource":
|
|
181
|
+
case "action":
|
|
182
|
+
case "entity":
|
|
183
|
+
case "event":
|
|
184
|
+
case "policy":
|
|
185
|
+
case "role":
|
|
186
|
+
case "knowledge":
|
|
187
|
+
case "system":
|
|
188
|
+
case "stage":
|
|
189
|
+
return `${targetKind}:${targetId}`;
|
|
190
|
+
default:
|
|
191
|
+
return void 0;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
var GRAPH_RESOURCE_TYPE_ORDER = [
|
|
195
|
+
"workflow",
|
|
196
|
+
"agent",
|
|
197
|
+
"integration",
|
|
198
|
+
"script",
|
|
199
|
+
"external",
|
|
200
|
+
"trigger",
|
|
201
|
+
"human_checkpoint"
|
|
202
|
+
];
|
|
203
|
+
var GRAPH_RESOURCE_TYPE_LABELS = {
|
|
204
|
+
workflow: "Workflows",
|
|
205
|
+
agent: "Agents",
|
|
206
|
+
integration: "Integrations",
|
|
207
|
+
script: "Scripts",
|
|
208
|
+
external: "External",
|
|
209
|
+
trigger: "Triggers",
|
|
210
|
+
human_checkpoint: "Human Checkpoints"
|
|
211
|
+
};
|
|
212
|
+
var KNOWLEDGE_START_HERE_IDS = [
|
|
213
|
+
"knowledge.org-model-reference",
|
|
214
|
+
"knowledge.org-model-graph-contract",
|
|
215
|
+
"knowledge.org-model-actions",
|
|
216
|
+
"knowledge.org-model-entities",
|
|
217
|
+
"knowledge.org-model-events",
|
|
218
|
+
"knowledge.org-model-policies",
|
|
219
|
+
"knowledge.platform-command-view"
|
|
220
|
+
];
|
|
221
|
+
var SPINE_PREFIX = "spine:";
|
|
222
|
+
var LEAF_PREFIX = "leaf:";
|
|
223
|
+
var FOLDER_PREFIX = "folder:";
|
|
224
|
+
var GROUP_THRESHOLD = 8;
|
|
225
|
+
var SIDEBAR_TREE_ACCENT_COLOR = "var(--color-primary)";
|
|
226
|
+
var DEFAULT_KNOWLEDGE_FACET_STATES = { knowledge: "include" };
|
|
227
|
+
var FOLDER_ORDER = [
|
|
228
|
+
"campaigns",
|
|
229
|
+
"pipeline",
|
|
230
|
+
"targeting",
|
|
231
|
+
"channels",
|
|
232
|
+
"proof",
|
|
233
|
+
"references",
|
|
234
|
+
"playbooks",
|
|
235
|
+
"strategies"
|
|
236
|
+
];
|
|
237
|
+
var FOLDER_LABELS = {
|
|
238
|
+
campaigns: "Campaigns",
|
|
239
|
+
pipeline: "Pipeline",
|
|
240
|
+
targeting: "Targeting and Strategy",
|
|
241
|
+
channels: "Channels",
|
|
242
|
+
proof: "Proof",
|
|
243
|
+
references: "References",
|
|
244
|
+
playbooks: "Playbooks",
|
|
245
|
+
strategies: "Strategies"
|
|
246
|
+
};
|
|
247
|
+
var KNOWLEDGE_DOMAINS_WITH_PANELS = /* @__PURE__ */ new Set([
|
|
248
|
+
"identity",
|
|
249
|
+
"branding",
|
|
250
|
+
"customers",
|
|
251
|
+
"offerings",
|
|
252
|
+
"goals",
|
|
253
|
+
"roles",
|
|
254
|
+
"sales",
|
|
255
|
+
"prospecting",
|
|
256
|
+
"projects",
|
|
257
|
+
"statuses",
|
|
258
|
+
"navigation",
|
|
259
|
+
"policies"
|
|
260
|
+
]);
|
|
261
|
+
var FILTERABLE_DOMAIN_KEYS = /* @__PURE__ */ new Set(["customers", "offerings", "goals", "roles", "statuses", "policies"]);
|
|
262
|
+
function shouldRouteItemToDomainPanel(domainKey) {
|
|
263
|
+
return FILTERABLE_DOMAIN_KEYS.has(domainKey);
|
|
264
|
+
}
|
|
265
|
+
function toBareGraphId(graphNodeId, kind) {
|
|
266
|
+
const prefix = `${kind}:`;
|
|
267
|
+
return graphNodeId.startsWith(prefix) ? graphNodeId.slice(prefix.length) : graphNodeId;
|
|
268
|
+
}
|
|
269
|
+
function topLevelGraphIds(allBareIds) {
|
|
270
|
+
return allBareIds.filter((id) => !id.includes("."));
|
|
271
|
+
}
|
|
272
|
+
function childGraphIds(allBareIds, parentId) {
|
|
273
|
+
const prefix = `${parentId}.`;
|
|
274
|
+
return allBareIds.filter((id) => id.startsWith(prefix) && !id.slice(prefix.length).includes("."));
|
|
275
|
+
}
|
|
276
|
+
function buildTreeContext(graph, knowledgeNodes) {
|
|
277
|
+
const knowledgeByGraphId = /* @__PURE__ */ new Map();
|
|
278
|
+
const nodesById = /* @__PURE__ */ new Map();
|
|
279
|
+
for (const node of graph.nodes) {
|
|
280
|
+
nodesById.set(node.id, node);
|
|
281
|
+
if (node.kind === "knowledge") {
|
|
282
|
+
knowledgeByGraphId.set(node.id, node.sourceId ?? node.id.replace(/^knowledge:/, ""));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const knowledgeById = new Map(knowledgeNodes.map((node) => [node.id, node]));
|
|
286
|
+
const governsRaw = /* @__PURE__ */ new Map();
|
|
287
|
+
const edgesBySource = /* @__PURE__ */ new Map();
|
|
288
|
+
const edgesByTarget = /* @__PURE__ */ new Map();
|
|
289
|
+
for (const edge of graph.edges) {
|
|
290
|
+
const src = edgesBySource.get(edge.sourceId) ?? [];
|
|
291
|
+
src.push(edge);
|
|
292
|
+
edgesBySource.set(edge.sourceId, src);
|
|
293
|
+
const tgt = edgesByTarget.get(edge.targetId) ?? [];
|
|
294
|
+
tgt.push(edge);
|
|
295
|
+
edgesByTarget.set(edge.targetId, tgt);
|
|
296
|
+
if (edge.kind === "governs") {
|
|
297
|
+
const knowledgeId = knowledgeByGraphId.get(edge.sourceId);
|
|
298
|
+
const knowledgeNode = knowledgeId ? knowledgeById.get(knowledgeId) : void 0;
|
|
299
|
+
if (knowledgeNode) {
|
|
300
|
+
const bucket = governsRaw.get(edge.targetId) ?? [];
|
|
301
|
+
bucket.push(knowledgeNode);
|
|
302
|
+
governsRaw.set(edge.targetId, bucket);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const governsEdgesByTarget = /* @__PURE__ */ new Map();
|
|
307
|
+
for (const [targetId, nodes] of governsRaw) {
|
|
308
|
+
governsEdgesByTarget.set(
|
|
309
|
+
targetId,
|
|
310
|
+
nodes.sort((a, b) => a.title.localeCompare(b.title))
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
return { governsEdgesByTarget, nodesById, edgesBySource, edgesByTarget };
|
|
314
|
+
}
|
|
315
|
+
function getKnowledgeByTarget(knowledgeNodes) {
|
|
316
|
+
const map = /* @__PURE__ */ new Map();
|
|
317
|
+
for (const node of knowledgeNodes) {
|
|
318
|
+
for (const link of node.links) {
|
|
319
|
+
const graphNodeId = graphNodeIdForKnowledgeTarget(link.target.kind, link.target.id);
|
|
320
|
+
const domainKey = domainKeyForKnowledgeTarget(link.target.kind);
|
|
321
|
+
const targetKeys = [
|
|
322
|
+
graphNodeId,
|
|
323
|
+
domainKey ? `${domainKey}:${link.target.id}` : void 0,
|
|
324
|
+
domainKey ? domainKey : void 0
|
|
325
|
+
].filter((key) => key !== void 0);
|
|
326
|
+
for (const targetKey of targetKeys) {
|
|
327
|
+
const bucket = map.get(targetKey) ?? [];
|
|
328
|
+
bucket.push(node);
|
|
329
|
+
map.set(targetKey, bucket);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return map;
|
|
334
|
+
}
|
|
335
|
+
function uniqueKnowledgeNodes(nodes) {
|
|
336
|
+
const seen = /* @__PURE__ */ new Set();
|
|
337
|
+
return nodes.sort((left, right) => left.title.localeCompare(right.title)).filter((node) => {
|
|
338
|
+
if (seen.has(node.id)) return false;
|
|
339
|
+
seen.add(node.id);
|
|
340
|
+
return true;
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
function getTargetKnowledge(knowledgeByTarget, targetKey, facetStates) {
|
|
344
|
+
if (facetStates.knowledge === "exclude") return [];
|
|
345
|
+
return uniqueKnowledgeNodes(knowledgeByTarget.get(targetKey) ?? []);
|
|
346
|
+
}
|
|
347
|
+
function sortByOrderThenLabel(items, getLabel) {
|
|
348
|
+
return [...items].sort(
|
|
349
|
+
(left, right) => (left.order ?? 0) - (right.order ?? 0) || getLabel(left).localeCompare(getLabel(right))
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
function modelRecordValues(record, getLabel) {
|
|
353
|
+
return sortByOrderThenLabel(Object.values(record ?? {}), getLabel);
|
|
354
|
+
}
|
|
355
|
+
function spineNodeHasVisibleDescendant(bareId, allBareIds, spine, facetStates, ctx, organizationModel, cache2 = /* @__PURE__ */ new Map()) {
|
|
356
|
+
const cached = cache2.get(bareId);
|
|
357
|
+
if (cached !== void 0) return cached;
|
|
358
|
+
const graphNodeId = `${spine}:${bareId}`;
|
|
359
|
+
const hasContentChildren = spine === "system" && organizationModel !== void 0 && Object.keys(getSystem(organizationModel, bareId)?.content ?? {}).length > 0;
|
|
360
|
+
let result = hasContentChildren || facetStates.knowledge !== "exclude" && (ctx.governsEdgesByTarget.get(graphNodeId)?.length ?? 0) > 0 || getIncludedFacetNodes(graphNodeId, spine, facetStates, ctx).length > 0 || childGraphIds(allBareIds, bareId).some(
|
|
361
|
+
(childId) => spineNodeHasVisibleDescendant(childId, allBareIds, spine, facetStates, ctx, organizationModel, cache2)
|
|
362
|
+
);
|
|
363
|
+
cache2.set(bareId, result);
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
function buildSpineMetaMap(graph, spine) {
|
|
367
|
+
const map = {};
|
|
368
|
+
for (const node of graph.nodes) {
|
|
369
|
+
if (node.kind === spine) {
|
|
370
|
+
map[toBareGraphId(node.id, spine)] = { label: node.label, icon: node.icon, node };
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return map;
|
|
374
|
+
}
|
|
375
|
+
function getKnowledgeReadCommand(nodeId) {
|
|
376
|
+
return `/knowledge read ${nodeId}`;
|
|
377
|
+
}
|
|
378
|
+
function getKnowledgeReadCommands(nodeIds) {
|
|
379
|
+
return [...new Set(nodeIds)].map(getKnowledgeReadCommand).join("\n");
|
|
380
|
+
}
|
|
381
|
+
function getKnowledgeReadSpineFolderCommand(spine, bareId) {
|
|
382
|
+
return `/knowledge read-folder ${spine}:${bareId}`;
|
|
383
|
+
}
|
|
384
|
+
function getKnowledgeReadTreeFolderCommand(treeValue) {
|
|
385
|
+
return `/knowledge read-folder ${treeValue}`;
|
|
386
|
+
}
|
|
387
|
+
function getKnowledgeDirectoryCommand(nodeIds, fallbackCommand) {
|
|
388
|
+
const command = getKnowledgeReadCommands(nodeIds ?? []);
|
|
389
|
+
return command || fallbackCommand;
|
|
390
|
+
}
|
|
391
|
+
function getKnowledgeFolderKey(node) {
|
|
392
|
+
const key = `${node.id} ${node.title}`.toLowerCase();
|
|
393
|
+
if (/\b(stage|booking|discovery|pipeline|communications?)\b/.test(key)) return "pipeline";
|
|
394
|
+
if (/\b(upwork scanning|youtube|obs|recording|reddit|social)\b/.test(key)) return "channels";
|
|
395
|
+
if (/\b(testimonials?|case stud|proof)\b/.test(key)) return "proof";
|
|
396
|
+
if (/\b(target|personalization|vertical|calibration|query|research|strategy)\b/.test(key)) return "targeting";
|
|
397
|
+
if (/\b(outreach|campaign|copy|handoff|bounce|reply|lead-gen playbook)\b/.test(key)) return "campaigns";
|
|
398
|
+
if (node.kind === "reference") return "references";
|
|
399
|
+
if (node.kind === "strategy") return "strategies";
|
|
400
|
+
return "playbooks";
|
|
401
|
+
}
|
|
402
|
+
function sortFolderKeys(left, right) {
|
|
403
|
+
const leftIndex = FOLDER_ORDER.indexOf(left);
|
|
404
|
+
const rightIndex = FOLDER_ORDER.indexOf(right);
|
|
405
|
+
if (leftIndex === -1 && rightIndex === -1) return left.localeCompare(right);
|
|
406
|
+
if (leftIndex === -1) return 1;
|
|
407
|
+
if (rightIndex === -1) return -1;
|
|
408
|
+
return leftIndex - rightIndex;
|
|
409
|
+
}
|
|
410
|
+
function createKnowledgeLeaf(graphNodeId, node) {
|
|
411
|
+
return {
|
|
412
|
+
value: `${LEAF_PREFIX}${graphNodeId}::${node.id}`,
|
|
413
|
+
label: node.title,
|
|
414
|
+
nodeType: "leaf",
|
|
415
|
+
knowledgeNodeId: node.id,
|
|
416
|
+
knowledgeNodeIds: [node.id]
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
function createKnowledgeLeaves(graphNodeId, nodes) {
|
|
420
|
+
if (nodes.length < GROUP_THRESHOLD) {
|
|
421
|
+
return nodes.map((node) => createKnowledgeLeaf(graphNodeId, node));
|
|
422
|
+
}
|
|
423
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
424
|
+
for (const node of nodes) {
|
|
425
|
+
const folderKey = getKnowledgeFolderKey(node);
|
|
426
|
+
const folderNodes = grouped.get(folderKey) ?? [];
|
|
427
|
+
folderNodes.push(node);
|
|
428
|
+
grouped.set(folderKey, folderNodes);
|
|
429
|
+
}
|
|
430
|
+
return [...grouped.entries()].sort(([left], [right]) => sortFolderKeys(left, right)).map(([folderKey, folderNodes]) => ({
|
|
431
|
+
value: `${FOLDER_PREFIX}${graphNodeId}::${folderKey}`,
|
|
432
|
+
label: FOLDER_LABELS[folderKey] ?? folderKey,
|
|
433
|
+
nodeType: "folder",
|
|
434
|
+
icon: "knowledge.playbook",
|
|
435
|
+
knowledgeNodeIds: folderNodes.map((node) => node.id),
|
|
436
|
+
children: folderNodes.map((node) => createKnowledgeLeaf(graphNodeId, node))
|
|
437
|
+
}));
|
|
438
|
+
}
|
|
439
|
+
function collectKnowledgeNodeIds(node) {
|
|
440
|
+
if (node.knowledgeNodeIds) return node.knowledgeNodeIds;
|
|
441
|
+
return (node.children ?? []).flatMap(collectKnowledgeNodeIds);
|
|
442
|
+
}
|
|
443
|
+
function createItemNode({
|
|
444
|
+
domainKey,
|
|
445
|
+
itemId,
|
|
446
|
+
label,
|
|
447
|
+
graphNodeId,
|
|
448
|
+
knowledgeNodes = [],
|
|
449
|
+
children = []
|
|
450
|
+
}) {
|
|
451
|
+
const knowledgeLeaves = knowledgeNodes.length > 0 ? createKnowledgeLeaves(`${ITEM_PREFIX}${domainKey}:${itemId}`, knowledgeNodes) : [];
|
|
452
|
+
const allChildren = [...children, ...knowledgeLeaves];
|
|
453
|
+
return {
|
|
454
|
+
value: `${ITEM_PREFIX}${domainKey}:${itemId}`,
|
|
455
|
+
label,
|
|
456
|
+
nodeType: "item",
|
|
457
|
+
domainKey,
|
|
458
|
+
itemId,
|
|
459
|
+
graphNodeId,
|
|
460
|
+
knowledgeNodeIds: [...knowledgeNodes.map((node) => node.id), ...children.flatMap(collectKnowledgeNodeIds)],
|
|
461
|
+
children: allChildren.length > 0 ? allChildren : void 0
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
function createDomainNode({
|
|
465
|
+
domainKey,
|
|
466
|
+
label,
|
|
467
|
+
knowledgeNodes = [],
|
|
468
|
+
children = []
|
|
469
|
+
}) {
|
|
470
|
+
const knowledgeLeaves = knowledgeNodes.length > 0 ? createKnowledgeLeaves(`${DOMAIN_PREFIX}${domainKey}`, knowledgeNodes) : [];
|
|
471
|
+
const allChildren = [...children, ...knowledgeLeaves];
|
|
472
|
+
return {
|
|
473
|
+
value: `${DOMAIN_PREFIX}${domainKey}`,
|
|
474
|
+
label,
|
|
475
|
+
nodeType: "domain",
|
|
476
|
+
domainKey,
|
|
477
|
+
knowledgeNodeIds: [...knowledgeNodes.map((node) => node.id), ...children.flatMap(collectKnowledgeNodeIds)],
|
|
478
|
+
children: allChildren.length > 0 ? allChildren : void 0
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
function createGroupNode({
|
|
482
|
+
groupKey,
|
|
483
|
+
label,
|
|
484
|
+
children
|
|
485
|
+
}) {
|
|
486
|
+
return {
|
|
487
|
+
value: `${GROUP_PREFIX}${groupKey}`,
|
|
488
|
+
label,
|
|
489
|
+
nodeType: "group",
|
|
490
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
491
|
+
children: children.length > 0 ? children : void 0
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function getIncludedFacetNodes(graphNodeId, spineKind, facetStates, ctx) {
|
|
495
|
+
const includedKinds = new Set(
|
|
496
|
+
Object.entries(facetStates).filter(([kind, state]) => state === "include" && kind !== "knowledge" && kind !== spineKind).map(([kind]) => kind)
|
|
497
|
+
);
|
|
498
|
+
if (includedKinds.size === 0) return [];
|
|
499
|
+
const seen = /* @__PURE__ */ new Set();
|
|
500
|
+
const nodes = [];
|
|
501
|
+
const outgoing = ctx.edgesBySource.get(graphNodeId) ?? [];
|
|
502
|
+
const incoming = ctx.edgesByTarget.get(graphNodeId) ?? [];
|
|
503
|
+
for (const edge of [...outgoing, ...incoming]) {
|
|
504
|
+
const relatedId = edge.sourceId === graphNodeId ? edge.targetId : edge.sourceId;
|
|
505
|
+
const relatedNode = ctx.nodesById.get(relatedId);
|
|
506
|
+
if (!relatedNode || !includedKinds.has(relatedNode.kind) || seen.has(relatedNode.id)) continue;
|
|
507
|
+
seen.add(relatedNode.id);
|
|
508
|
+
nodes.push(relatedNode);
|
|
509
|
+
}
|
|
510
|
+
return nodes.sort((left, right) => left.kind.localeCompare(right.kind) || left.label.localeCompare(right.label));
|
|
511
|
+
}
|
|
512
|
+
function createFacetGraphLeaves(nodes) {
|
|
513
|
+
return nodes.map((node) => ({
|
|
514
|
+
value: `graph:${node.id}`,
|
|
515
|
+
label: node.label,
|
|
516
|
+
nodeType: "graph",
|
|
517
|
+
icon: node.icon,
|
|
518
|
+
graphNodeId: node.id,
|
|
519
|
+
knowledgeNodeIds: []
|
|
520
|
+
}));
|
|
521
|
+
}
|
|
522
|
+
function createGraphNodeItem(node, domainKey) {
|
|
523
|
+
return createItemNode({
|
|
524
|
+
domainKey,
|
|
525
|
+
itemId: node.sourceId ?? node.id,
|
|
526
|
+
label: node.label,
|
|
527
|
+
graphNodeId: node.id
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function createCollectionNode(parentKey, collectionKey, label, children) {
|
|
531
|
+
return {
|
|
532
|
+
value: `${FOLDER_PREFIX}${parentKey}:${collectionKey}`,
|
|
533
|
+
label,
|
|
534
|
+
nodeType: "folder",
|
|
535
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
536
|
+
children: children.length > 0 ? children : void 0
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
var CONTENT_META_KIND_ORDER = ["schema", "config", "knowledge"];
|
|
540
|
+
function contentMetaKindSortKey(kind) {
|
|
541
|
+
const idx = CONTENT_META_KIND_ORDER.indexOf(kind);
|
|
542
|
+
return idx === -1 ? CONTENT_META_KIND_ORDER.length : idx;
|
|
543
|
+
}
|
|
544
|
+
function buildContentKindItems(systemPath, entries) {
|
|
545
|
+
return [...entries].sort(([, a], [, b]) => (a.order ?? 0) - (b.order ?? 0) || (a.label ?? "").localeCompare(b.label ?? "")).map(([localId, node]) => {
|
|
546
|
+
const qualifiedId = `${systemPath}:${localId}`;
|
|
547
|
+
return {
|
|
548
|
+
// Wave 5 will project content nodes into the graph; until then render as
|
|
549
|
+
// 'item' so the label appears without requiring a graph-node map lookup.
|
|
550
|
+
value: `${ITEM_PREFIX}content:${qualifiedId}`,
|
|
551
|
+
label: node.label ?? localId,
|
|
552
|
+
nodeType: "item",
|
|
553
|
+
domainKey: "content",
|
|
554
|
+
itemId: qualifiedId,
|
|
555
|
+
graphNodeId: `content-node:${qualifiedId}`,
|
|
556
|
+
knowledgeNodeIds: []
|
|
557
|
+
};
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
function buildContentSubgroup(bareId, organizationModel) {
|
|
561
|
+
if (!organizationModel) return [];
|
|
562
|
+
const system = getSystem(organizationModel, bareId);
|
|
563
|
+
const contentMap = system?.content;
|
|
564
|
+
if (!contentMap || Object.keys(contentMap).length === 0) return [];
|
|
565
|
+
const byMetaKind = /* @__PURE__ */ new Map();
|
|
566
|
+
for (const [localId, node] of Object.entries(contentMap)) {
|
|
567
|
+
const bucket = byMetaKind.get(node.kind) ?? [];
|
|
568
|
+
bucket.push([localId, node]);
|
|
569
|
+
byMetaKind.set(node.kind, bucket);
|
|
570
|
+
}
|
|
571
|
+
const kindFolders = [...byMetaKind.entries()].sort(([a], [b]) => contentMetaKindSortKey(a) - contentMetaKindSortKey(b) || a.localeCompare(b)).map(([metaKind, entries]) => {
|
|
572
|
+
const items = buildContentKindItems(bareId, entries);
|
|
573
|
+
return {
|
|
574
|
+
value: `${FOLDER_PREFIX}content:${bareId}:${metaKind}`,
|
|
575
|
+
label: metaKind.charAt(0).toUpperCase() + metaKind.slice(1),
|
|
576
|
+
nodeType: "folder",
|
|
577
|
+
knowledgeNodeIds: [],
|
|
578
|
+
children: items.length > 0 ? items : void 0
|
|
579
|
+
};
|
|
580
|
+
});
|
|
581
|
+
return [
|
|
582
|
+
{
|
|
583
|
+
value: `${FOLDER_PREFIX}content:${bareId}`,
|
|
584
|
+
label: "Content",
|
|
585
|
+
nodeType: "folder",
|
|
586
|
+
knowledgeNodeIds: [],
|
|
587
|
+
children: kindFolders.length > 0 ? kindFolders : void 0
|
|
588
|
+
}
|
|
589
|
+
];
|
|
590
|
+
}
|
|
591
|
+
function buildSpineTreeNode(bareId, allBareIds, spineMetaMap, spine, facetStates, ctx, visibleSpineIds, organizationModel) {
|
|
592
|
+
const graphNodeId = `${spine}:${bareId}`;
|
|
593
|
+
const governing = facetStates.knowledge === "exclude" ? [] : ctx.governsEdgesByTarget.get(graphNodeId) ?? [];
|
|
594
|
+
const childIds = childGraphIds(allBareIds, bareId);
|
|
595
|
+
const contentChildren = spine === "system" ? buildContentSubgroup(bareId, organizationModel) : [];
|
|
596
|
+
const domainConfigChildren = [];
|
|
597
|
+
const childSpineNodes = childIds.filter((childId) => visibleSpineIds.has(childId)).map(
|
|
598
|
+
(childId) => buildSpineTreeNode(childId, allBareIds, spineMetaMap, spine, facetStates, ctx, visibleSpineIds, organizationModel)
|
|
599
|
+
);
|
|
600
|
+
const knowledgeLeaves = createKnowledgeLeaves(graphNodeId, governing);
|
|
601
|
+
const facetLeaves = createFacetGraphLeaves(getIncludedFacetNodes(graphNodeId, spine, facetStates, ctx));
|
|
602
|
+
const children = [...domainConfigChildren, ...contentChildren, ...childSpineNodes, ...knowledgeLeaves, ...facetLeaves];
|
|
603
|
+
const meta = spineMetaMap[bareId];
|
|
604
|
+
return {
|
|
605
|
+
value: `${SPINE_PREFIX}${spine}:${bareId}`,
|
|
606
|
+
label: meta?.label ?? bareId,
|
|
607
|
+
nodeType: "spine",
|
|
608
|
+
icon: meta?.icon,
|
|
609
|
+
graphNodeId,
|
|
610
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
611
|
+
children: children.length > 0 ? children : void 0
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
function getInitialExpandedState(nodes, omRooted) {
|
|
615
|
+
if (!omRooted) return {};
|
|
616
|
+
const systemsValue = `${GROUP_PREFIX}systems`;
|
|
617
|
+
const quickAccessValue = `${GROUP_PREFIX}${QUICK_ACCESS_GROUP_KEY}`;
|
|
618
|
+
const expanded = {};
|
|
619
|
+
for (const node of nodes) {
|
|
620
|
+
if (node.value === systemsValue) expanded[systemsValue] = true;
|
|
621
|
+
if (node.value === quickAccessValue) expanded[quickAccessValue] = true;
|
|
622
|
+
}
|
|
623
|
+
return expanded;
|
|
624
|
+
}
|
|
625
|
+
function buildProfileGroup(organizationModel, knowledgeByTarget, facetStates) {
|
|
626
|
+
return createGroupNode({
|
|
627
|
+
groupKey: "profile",
|
|
628
|
+
label: "Profile",
|
|
629
|
+
children: [
|
|
630
|
+
createDomainNode({
|
|
631
|
+
domainKey: "identity",
|
|
632
|
+
label: "Identity",
|
|
633
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, "identity", facetStates)
|
|
634
|
+
}),
|
|
635
|
+
createDomainNode({
|
|
636
|
+
domainKey: "branding",
|
|
637
|
+
label: "Branding",
|
|
638
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, "branding", facetStates)
|
|
639
|
+
})
|
|
640
|
+
]
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
function buildBusinessModelGroup(organizationModel, knowledgeByTarget, facetStates) {
|
|
644
|
+
return createGroupNode({
|
|
645
|
+
groupKey: "business-model",
|
|
646
|
+
label: "Business Model",
|
|
647
|
+
children: [
|
|
648
|
+
createDomainNode({
|
|
649
|
+
domainKey: "customers",
|
|
650
|
+
label: "Customers",
|
|
651
|
+
children: modelRecordValues(organizationModel?.customers, (segment) => segment.name || segment.id).map(
|
|
652
|
+
(segment) => createItemNode({
|
|
653
|
+
domainKey: "customers",
|
|
654
|
+
itemId: segment.id,
|
|
655
|
+
label: segment.name || segment.id,
|
|
656
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `customers:${segment.id}`, facetStates)
|
|
657
|
+
})
|
|
658
|
+
)
|
|
659
|
+
}),
|
|
660
|
+
createDomainNode({
|
|
661
|
+
domainKey: "offerings",
|
|
662
|
+
label: "Offerings",
|
|
663
|
+
children: modelRecordValues(organizationModel?.offerings, (offering) => offering.name || offering.id).map(
|
|
664
|
+
(offering) => createItemNode({
|
|
665
|
+
domainKey: "offerings",
|
|
666
|
+
itemId: offering.id,
|
|
667
|
+
label: offering.name || offering.id,
|
|
668
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `offerings:${offering.id}`, facetStates)
|
|
669
|
+
})
|
|
670
|
+
)
|
|
671
|
+
}),
|
|
672
|
+
createDomainNode({
|
|
673
|
+
domainKey: "goals",
|
|
674
|
+
label: "Goals",
|
|
675
|
+
children: modelRecordValues(organizationModel?.goals, (goal) => goal.description || goal.id).map(
|
|
676
|
+
(goal) => createItemNode({
|
|
677
|
+
domainKey: "goals",
|
|
678
|
+
itemId: goal.id,
|
|
679
|
+
label: goal.description || goal.id,
|
|
680
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `goals:${goal.id}`, facetStates)
|
|
681
|
+
})
|
|
682
|
+
)
|
|
683
|
+
})
|
|
684
|
+
]
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
function buildRolesDomain(graph, organizationModel, knowledgeByTarget, facetStates) {
|
|
688
|
+
const graphNodesById = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
689
|
+
const roleItems = modelRecordValues(organizationModel?.roles, (role) => role.title || role.id).map(
|
|
690
|
+
(role) => createItemNode({
|
|
691
|
+
domainKey: "roles",
|
|
692
|
+
itemId: role.id,
|
|
693
|
+
label: role.title || role.id,
|
|
694
|
+
graphNodeId: graphNodesById.get(`role:${role.id}`)?.id,
|
|
695
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `role:${role.id}`, facetStates)
|
|
696
|
+
})
|
|
697
|
+
);
|
|
698
|
+
return createDomainNode({ domainKey: "roles", label: "Roles", children: roleItems });
|
|
699
|
+
}
|
|
700
|
+
function buildSystemsGroup(graph, organizationModel, facetStates, ctx, visibleSpineIds) {
|
|
701
|
+
const spineMetaMap = buildSpineMetaMap(graph, "system");
|
|
702
|
+
const allBareIds = Object.keys(spineMetaMap);
|
|
703
|
+
const topIds = topLevelGraphIds(allBareIds);
|
|
704
|
+
const children = topIds.filter((bareId) => visibleSpineIds.has(bareId)).map(
|
|
705
|
+
(bareId) => buildSpineTreeNode(
|
|
706
|
+
bareId,
|
|
707
|
+
allBareIds,
|
|
708
|
+
spineMetaMap,
|
|
709
|
+
"system",
|
|
710
|
+
facetStates,
|
|
711
|
+
ctx,
|
|
712
|
+
visibleSpineIds,
|
|
713
|
+
organizationModel
|
|
714
|
+
)
|
|
715
|
+
);
|
|
716
|
+
return createGroupNode({ groupKey: "systems", label: "Systems", children });
|
|
717
|
+
}
|
|
718
|
+
function graphNodesByKind(graph, kind) {
|
|
719
|
+
return graph.nodes.filter((node) => node.kind === kind).sort((left, right) => left.label.localeCompare(right.label) || left.id.localeCompare(right.id));
|
|
720
|
+
}
|
|
721
|
+
function buildGraphResourcesBranch(graph) {
|
|
722
|
+
const resources = graphNodesByKind(graph, "resource");
|
|
723
|
+
const children = GRAPH_RESOURCE_TYPE_ORDER.map((resourceType) => {
|
|
724
|
+
const resourceNodes = resources.filter((node) => node.resourceType === resourceType);
|
|
725
|
+
if (resourceNodes.length === 0) return void 0;
|
|
726
|
+
return createCollectionNode(
|
|
727
|
+
"graph:resources",
|
|
728
|
+
resourceType,
|
|
729
|
+
GRAPH_RESOURCE_TYPE_LABELS[resourceType],
|
|
730
|
+
resourceNodes.map((node) => createGraphNodeItem(node, "resources"))
|
|
731
|
+
);
|
|
732
|
+
}).filter((node) => node !== void 0);
|
|
733
|
+
const untypedResources = resources.filter((node) => node.resourceType === void 0);
|
|
734
|
+
if (untypedResources.length > 0) {
|
|
735
|
+
children.push(
|
|
736
|
+
createCollectionNode(
|
|
737
|
+
"graph:resources",
|
|
738
|
+
"unknown",
|
|
739
|
+
"Unclassified",
|
|
740
|
+
untypedResources.map((node) => createGraphNodeItem(node, "resources"))
|
|
741
|
+
)
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
return createDomainNode({ domainKey: "resources", label: "Resources", children });
|
|
745
|
+
}
|
|
746
|
+
function buildGraphKnowledgeBranch(graph, knowledgeNodes) {
|
|
747
|
+
const graphNodesBySourceId = new Map(
|
|
748
|
+
graph.nodes.filter((node) => node.kind === "knowledge").map((node) => [node.sourceId ?? node.id, node])
|
|
749
|
+
);
|
|
750
|
+
const knowledgeById = new Map(knowledgeNodes.map((node) => [node.id, node]));
|
|
751
|
+
const startHere = KNOWLEDGE_START_HERE_IDS.map((id) => knowledgeById.get(id)).filter(
|
|
752
|
+
(node) => node !== void 0
|
|
753
|
+
);
|
|
754
|
+
const startHereIds = new Set(startHere.map((node) => node.id));
|
|
755
|
+
const allKnowledge = [...knowledgeNodes].filter((node) => !startHereIds.has(node.id)).sort((left, right) => left.title.localeCompare(right.title));
|
|
756
|
+
const toKnowledgeItem = (node) => createItemNode({
|
|
757
|
+
domainKey: "knowledge",
|
|
758
|
+
itemId: node.id,
|
|
759
|
+
label: node.title,
|
|
760
|
+
graphNodeId: graphNodesBySourceId.get(node.id)?.id
|
|
761
|
+
});
|
|
762
|
+
return createDomainNode({
|
|
763
|
+
domainKey: "knowledge",
|
|
764
|
+
label: "Knowledge",
|
|
765
|
+
children: [
|
|
766
|
+
createCollectionNode("graph:knowledge", "start-here", "Start Here", startHere.map(toKnowledgeItem)),
|
|
767
|
+
createCollectionNode("graph:knowledge", "all", "All", allKnowledge.map(toKnowledgeItem))
|
|
768
|
+
]
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
function buildGraphStagesBranch(graph) {
|
|
772
|
+
return createDomainNode({
|
|
773
|
+
domainKey: "stages",
|
|
774
|
+
label: "Stages",
|
|
775
|
+
children: graphNodesByKind(graph, "stage").map((node) => createGraphNodeItem(node, "stages"))
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
function buildGraphGroup(graph, knowledgeNodes) {
|
|
779
|
+
return createGroupNode({
|
|
780
|
+
groupKey: "graph",
|
|
781
|
+
label: "Graph",
|
|
782
|
+
children: [
|
|
783
|
+
buildGraphResourcesBranch(graph),
|
|
784
|
+
createDomainNode({
|
|
785
|
+
domainKey: "actions",
|
|
786
|
+
label: "Actions",
|
|
787
|
+
children: graphNodesByKind(graph, "action").map((node) => createGraphNodeItem(node, "actions"))
|
|
788
|
+
}),
|
|
789
|
+
createDomainNode({
|
|
790
|
+
domainKey: "entities",
|
|
791
|
+
label: "Entities",
|
|
792
|
+
children: graphNodesByKind(graph, "entity").map((node) => createGraphNodeItem(node, "entities"))
|
|
793
|
+
}),
|
|
794
|
+
createDomainNode({
|
|
795
|
+
domainKey: "events",
|
|
796
|
+
label: "Events",
|
|
797
|
+
children: graphNodesByKind(graph, "event").map((node) => createGraphNodeItem(node, "events"))
|
|
798
|
+
}),
|
|
799
|
+
buildGraphStagesBranch(graph),
|
|
800
|
+
buildGraphKnowledgeBranch(graph, knowledgeNodes)
|
|
801
|
+
]
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
function buildGovernanceGroup(graph, organizationModel, knowledgeByTarget, facetStates) {
|
|
805
|
+
const graphNodesById = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
806
|
+
const policies = modelRecordValues(organizationModel?.policies, (policy) => policy.label || policy.id).map(
|
|
807
|
+
(policy) => createItemNode({
|
|
808
|
+
domainKey: "policies",
|
|
809
|
+
itemId: policy.id,
|
|
810
|
+
label: policy.label || policy.id,
|
|
811
|
+
graphNodeId: graphNodesById.get(`policy:${policy.id}`)?.id,
|
|
812
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `policy:${policy.id}`, facetStates)
|
|
813
|
+
})
|
|
814
|
+
);
|
|
815
|
+
const statusGroups = [];
|
|
816
|
+
const navigationSurfaces = (organizationModel ? projectNavigationSurfaces(organizationModel) : []).sort((left, right) => left.label.localeCompare(right.label)).map(
|
|
817
|
+
(surface) => createItemNode({
|
|
818
|
+
domainKey: "navigation",
|
|
819
|
+
itemId: surface.id,
|
|
820
|
+
label: surface.label
|
|
821
|
+
})
|
|
822
|
+
);
|
|
823
|
+
const rolesDomain = buildRolesDomain(graph, organizationModel, knowledgeByTarget, facetStates);
|
|
824
|
+
return createGroupNode({
|
|
825
|
+
groupKey: "governance-wiring",
|
|
826
|
+
label: "Governance & Wiring",
|
|
827
|
+
children: [
|
|
828
|
+
rolesDomain,
|
|
829
|
+
createDomainNode({ domainKey: "policies", label: "Policies", children: policies }),
|
|
830
|
+
createDomainNode({ domainKey: "statuses", label: "Statuses", children: statusGroups }),
|
|
831
|
+
createDomainNode({ domainKey: "navigation", label: "Navigation", children: navigationSurfaces })
|
|
832
|
+
]
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
function computeVisibleSpineIds(allBareIds, spine, facetStates, ctx, organizationModel) {
|
|
836
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
837
|
+
const visible = /* @__PURE__ */ new Set();
|
|
838
|
+
for (const bareId of allBareIds) {
|
|
839
|
+
if (spineNodeHasVisibleDescendant(bareId, allBareIds, spine, facetStates, ctx, organizationModel, cache2)) {
|
|
840
|
+
visible.add(bareId);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return visible;
|
|
844
|
+
}
|
|
845
|
+
function buildOrgTreeNode(graph, knowledgeNodes, facetStates, organizationModel, favorites = []) {
|
|
846
|
+
const ctx = buildTreeContext(graph, knowledgeNodes);
|
|
847
|
+
const knowledgeByTarget = getKnowledgeByTarget(knowledgeNodes);
|
|
848
|
+
const spineMetaMap = buildSpineMetaMap(graph, "system");
|
|
849
|
+
const allBareIds = Object.keys(spineMetaMap);
|
|
850
|
+
const visibleSpineIds = computeVisibleSpineIds(allBareIds, "system", facetStates, ctx, organizationModel);
|
|
851
|
+
const omGroups = OM_TREE_GROUPS.map((group) => {
|
|
852
|
+
switch (group.key) {
|
|
853
|
+
case "profile":
|
|
854
|
+
return buildProfileGroup(organizationModel, knowledgeByTarget, facetStates);
|
|
855
|
+
case "business-model":
|
|
856
|
+
return buildBusinessModelGroup(organizationModel, knowledgeByTarget, facetStates);
|
|
857
|
+
case "systems":
|
|
858
|
+
return buildSystemsGroup(graph, organizationModel, facetStates, ctx, visibleSpineIds);
|
|
859
|
+
case "graph":
|
|
860
|
+
return buildGraphGroup(graph, knowledgeNodes);
|
|
861
|
+
case "governance-wiring":
|
|
862
|
+
return buildGovernanceGroup(graph, organizationModel, knowledgeByTarget, facetStates);
|
|
863
|
+
default:
|
|
864
|
+
return createGroupNode({ groupKey: group.key, label: group.label, children: [] });
|
|
865
|
+
}
|
|
866
|
+
});
|
|
867
|
+
const quickAccess = buildQuickAccessGroup(favorites, knowledgeNodes, graph);
|
|
868
|
+
return [quickAccess, ...omGroups];
|
|
869
|
+
}
|
|
870
|
+
function buildQuickAccessGroup(favorites, knowledgeNodes, graph) {
|
|
871
|
+
const knowledgeIds = new Set(knowledgeNodes.map((node) => node.id));
|
|
872
|
+
const graphIds = new Set(graph.nodes.map((node) => node.id));
|
|
873
|
+
const children = favorites.filter((favorite) => {
|
|
874
|
+
if (favorite.kind === "knowledge") return knowledgeIds.has(favorite.routeId);
|
|
875
|
+
if (favorite.kind === "graph") return graphIds.has(favorite.routeId);
|
|
876
|
+
return true;
|
|
877
|
+
}).map((favorite) => ({
|
|
878
|
+
value: `${FAVORITE_PREFIX}${favorite.routeId}`,
|
|
879
|
+
label: favorite.label,
|
|
880
|
+
nodeType: "favorite",
|
|
881
|
+
icon: favorite.iconToken,
|
|
882
|
+
favoriteRouteId: favorite.routeId,
|
|
883
|
+
favoriteKind: favorite.kind,
|
|
884
|
+
knowledgeNodeIds: []
|
|
885
|
+
}));
|
|
886
|
+
return {
|
|
887
|
+
value: `${GROUP_PREFIX}${QUICK_ACCESS_GROUP_KEY}`,
|
|
888
|
+
label: "Quick Access",
|
|
889
|
+
nodeType: "group",
|
|
890
|
+
knowledgeNodeIds: [],
|
|
891
|
+
children
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
function KnowledgeTree({
|
|
895
|
+
graph,
|
|
896
|
+
knowledgeNodes,
|
|
897
|
+
organizationModel,
|
|
898
|
+
onSelectNode,
|
|
899
|
+
onSelectGraphNode,
|
|
900
|
+
onSelectDomain,
|
|
901
|
+
onSelectGroup,
|
|
902
|
+
onSelectItem,
|
|
903
|
+
spine = "system",
|
|
904
|
+
omRooted = false,
|
|
905
|
+
facetStates = DEFAULT_KNOWLEDGE_FACET_STATES,
|
|
906
|
+
selectedNodeId
|
|
907
|
+
}) {
|
|
908
|
+
const graphSpine = spine;
|
|
909
|
+
const favoritesMap = useKnowledgeFavoritesStore((state) => state.favorites);
|
|
910
|
+
const favorites = useMemo(
|
|
911
|
+
() => Object.values(favoritesMap).sort((left, right) => right.addedAt - left.addedAt),
|
|
912
|
+
[favoritesMap]
|
|
913
|
+
);
|
|
914
|
+
const treeData = useMemo(() => {
|
|
915
|
+
if (omRooted) {
|
|
916
|
+
return buildOrgTreeNode(graph, knowledgeNodes, facetStates, organizationModel, favorites);
|
|
917
|
+
}
|
|
918
|
+
const ctx = buildTreeContext(graph, knowledgeNodes);
|
|
919
|
+
const spineMetaMap = buildSpineMetaMap(graph, graphSpine);
|
|
920
|
+
const allBareIds = Object.keys(spineMetaMap);
|
|
921
|
+
const topIds = topLevelGraphIds(allBareIds);
|
|
922
|
+
const visibleSpineIds = computeVisibleSpineIds(allBareIds, graphSpine, facetStates, ctx, organizationModel);
|
|
923
|
+
return topIds.filter((bareId) => visibleSpineIds.has(bareId)).map(
|
|
924
|
+
(bareId) => buildSpineTreeNode(
|
|
925
|
+
bareId,
|
|
926
|
+
allBareIds,
|
|
927
|
+
spineMetaMap,
|
|
928
|
+
graphSpine,
|
|
929
|
+
facetStates,
|
|
930
|
+
ctx,
|
|
931
|
+
visibleSpineIds,
|
|
932
|
+
organizationModel
|
|
933
|
+
)
|
|
934
|
+
);
|
|
935
|
+
}, [facetStates, favorites, graph, graphSpine, knowledgeNodes, omRooted, organizationModel]);
|
|
936
|
+
const initialExpandedState = useMemo(() => getInitialExpandedState(treeData, omRooted), [treeData, omRooted]);
|
|
937
|
+
const treeController = useTree({ initialExpandedState });
|
|
938
|
+
const leafNodeMap = useMemo(() => {
|
|
939
|
+
const map = /* @__PURE__ */ new Map();
|
|
940
|
+
for (const node of knowledgeNodes) {
|
|
941
|
+
map.set(node.id, node);
|
|
942
|
+
}
|
|
943
|
+
return map;
|
|
944
|
+
}, [knowledgeNodes]);
|
|
945
|
+
const graphNodeMap = useMemo(() => {
|
|
946
|
+
const map = /* @__PURE__ */ new Map();
|
|
947
|
+
for (const graphNode of graph.nodes) {
|
|
948
|
+
map.set(graphNode.id, graphNode);
|
|
949
|
+
}
|
|
950
|
+
return map;
|
|
951
|
+
}, [graph]);
|
|
952
|
+
if (treeData.length === 0) {
|
|
953
|
+
return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", style: { padding: "var(--mantine-spacing-md)" }, children: omRooted ? "No OM domains in model." : `No ${spine} spine nodes in graph.` });
|
|
954
|
+
}
|
|
955
|
+
return /* @__PURE__ */ jsx(
|
|
956
|
+
Tree,
|
|
957
|
+
{
|
|
958
|
+
data: treeData,
|
|
959
|
+
tree: treeController,
|
|
960
|
+
style: { padding: "var(--mantine-spacing-xs)" },
|
|
961
|
+
renderNode: ({ node, expanded, hasChildren, elementProps }) => {
|
|
962
|
+
const value = node.value;
|
|
963
|
+
const typedNode = node;
|
|
964
|
+
const decoratedElementProps = {
|
|
965
|
+
...elementProps,
|
|
966
|
+
"data-tree-row-value": typeof value === "string" ? value : void 0
|
|
967
|
+
};
|
|
968
|
+
if (typedNode.nodeType === "group") {
|
|
969
|
+
const groupKey = typeof value === "string" ? value.slice(GROUP_PREFIX.length) : "";
|
|
970
|
+
const isActive2 = selectedNodeId === value;
|
|
971
|
+
const isQuickAccess = groupKey === QUICK_ACCESS_GROUP_KEY;
|
|
972
|
+
return /* @__PURE__ */ jsx(
|
|
973
|
+
DirectoryRow,
|
|
974
|
+
{
|
|
975
|
+
elementProps: decoratedElementProps,
|
|
976
|
+
expanded,
|
|
977
|
+
hasChildren,
|
|
978
|
+
label: String(node.label),
|
|
979
|
+
iconToken: GROUP_ICON_TOKENS[groupKey] ?? typedNode.icon,
|
|
980
|
+
command: isQuickAccess ? "" : getKnowledgeDirectoryCommand(
|
|
981
|
+
typedNode.knowledgeNodeIds,
|
|
982
|
+
getKnowledgeReadTreeFolderCommand(`${GROUP_PREFIX}${groupKey}`)
|
|
983
|
+
),
|
|
984
|
+
isActive: isActive2,
|
|
985
|
+
fallbackKind: "organization",
|
|
986
|
+
uppercase: true,
|
|
987
|
+
onSelectGraphNode: isQuickAccess ? void 0 : onSelectGroup ? () => onSelectGroup(groupKey) : void 0,
|
|
988
|
+
favorite: isQuickAccess ? void 0 : {
|
|
989
|
+
routeId: `${GROUP_PREFIX}${groupKey}`,
|
|
990
|
+
label: String(node.label),
|
|
991
|
+
kind: "group",
|
|
992
|
+
iconToken: typedNode.icon
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
if (typedNode.nodeType === "favorite" && typedNode.favoriteRouteId && typedNode.favoriteKind) {
|
|
998
|
+
const routeId = typedNode.favoriteRouteId;
|
|
999
|
+
const favoriteKind = typedNode.favoriteKind;
|
|
1000
|
+
return /* @__PURE__ */ jsx(
|
|
1001
|
+
FavoriteRow,
|
|
1002
|
+
{
|
|
1003
|
+
elementProps: decoratedElementProps,
|
|
1004
|
+
label: String(node.label),
|
|
1005
|
+
routeId,
|
|
1006
|
+
kind: favoriteKind,
|
|
1007
|
+
iconToken: typedNode.icon,
|
|
1008
|
+
onActivate: () => {
|
|
1009
|
+
dispatchFavoriteSelection(routeId, favoriteKind, typedNode, {
|
|
1010
|
+
onSelectNode,
|
|
1011
|
+
onSelectGraphNode,
|
|
1012
|
+
onSelectGroup,
|
|
1013
|
+
onSelectDomain,
|
|
1014
|
+
onSelectItem,
|
|
1015
|
+
leafNodeMap,
|
|
1016
|
+
graphNodeMap
|
|
1017
|
+
});
|
|
1018
|
+
focusFavoriteInTree(treeData, treeController, { routeId, kind: favoriteKind });
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
if (typedNode.nodeType === "domain" && typedNode.domainKey) {
|
|
1024
|
+
const domainKey = typedNode.domainKey;
|
|
1025
|
+
const isActive2 = selectedNodeId === `${DOMAIN_PREFIX}${domainKey}`;
|
|
1026
|
+
return /* @__PURE__ */ jsx(
|
|
1027
|
+
DirectoryRow,
|
|
1028
|
+
{
|
|
1029
|
+
elementProps: decoratedElementProps,
|
|
1030
|
+
expanded,
|
|
1031
|
+
hasChildren,
|
|
1032
|
+
label: String(node.label),
|
|
1033
|
+
iconToken: void 0,
|
|
1034
|
+
command: getKnowledgeDirectoryCommand(
|
|
1035
|
+
typedNode.knowledgeNodeIds,
|
|
1036
|
+
getKnowledgeReadTreeFolderCommand(`${DOMAIN_PREFIX}${domainKey}`)
|
|
1037
|
+
),
|
|
1038
|
+
isActive: isActive2,
|
|
1039
|
+
fallbackKind: "organization",
|
|
1040
|
+
uppercase: true,
|
|
1041
|
+
onSelectGraphNode: onSelectDomain ? () => onSelectDomain(domainKey) : void 0,
|
|
1042
|
+
favorite: {
|
|
1043
|
+
routeId: `${DOMAIN_PREFIX}${domainKey}`,
|
|
1044
|
+
label: String(node.label),
|
|
1045
|
+
kind: "domain"
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
);
|
|
1049
|
+
}
|
|
1050
|
+
if (typedNode.nodeType === "item" && typedNode.domainKey && typedNode.itemId) {
|
|
1051
|
+
const graphNode2 = typedNode.graphNodeId ? graphNodeMap.get(typedNode.graphNodeId) : void 0;
|
|
1052
|
+
const itemRouteId = `${ITEM_PREFIX}${typedNode.domainKey}:${typedNode.itemId}`;
|
|
1053
|
+
const routeToDomainPanel = shouldRouteItemToDomainPanel(typedNode.domainKey);
|
|
1054
|
+
const fallbackCommand = graphNode2?.kind === "knowledge" && graphNode2.sourceId ? getKnowledgeReadCommand(graphNode2.sourceId) : graphNode2 ? getKnowledgeReadTreeFolderCommand(`graph:${graphNode2.id}`) : getKnowledgeReadTreeFolderCommand(itemRouteId);
|
|
1055
|
+
const isActive2 = selectedNodeId !== void 0 && (selectedNodeId === itemRouteId || selectedNodeId === typedNode.itemId || selectedNodeId === typedNode.graphNodeId || graphNode2 !== void 0 && (selectedNodeId === graphNode2.id || selectedNodeId === graphNode2.sourceId));
|
|
1056
|
+
return /* @__PURE__ */ jsx(
|
|
1057
|
+
DirectoryRow,
|
|
1058
|
+
{
|
|
1059
|
+
elementProps: decoratedElementProps,
|
|
1060
|
+
expanded,
|
|
1061
|
+
hasChildren,
|
|
1062
|
+
label: String(node.label),
|
|
1063
|
+
iconToken: typedNode.icon ?? graphNode2?.icon,
|
|
1064
|
+
command: getKnowledgeDirectoryCommand(typedNode.knowledgeNodeIds, fallbackCommand),
|
|
1065
|
+
isActive: isActive2,
|
|
1066
|
+
fallbackKind: graphNode2?.kind ?? "organization",
|
|
1067
|
+
onSelectGraphNode: routeToDomainPanel && onSelectItem ? () => onSelectItem(typedNode.domainKey ?? "", typedNode.itemId ?? "") : graphNode2 ? () => onSelectGraphNode?.(graphNode2) : onSelectItem ? () => onSelectItem(typedNode.domainKey ?? "", typedNode.itemId ?? "") : void 0,
|
|
1068
|
+
favorite: {
|
|
1069
|
+
routeId: itemRouteId,
|
|
1070
|
+
label: String(node.label),
|
|
1071
|
+
kind: "item",
|
|
1072
|
+
iconToken: typedNode.icon ?? graphNode2?.icon
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
if (typeof value === "string" && value.startsWith(LEAF_PREFIX)) {
|
|
1078
|
+
const knowledgeNodeId = value.split("::").at(-1);
|
|
1079
|
+
const knowledgeNode = knowledgeNodeId ? leafNodeMap.get(knowledgeNodeId) : void 0;
|
|
1080
|
+
if (!knowledgeNode) return null;
|
|
1081
|
+
return /* @__PURE__ */ jsx(
|
|
1082
|
+
KnowledgeLeafRow,
|
|
1083
|
+
{
|
|
1084
|
+
elementProps: decoratedElementProps,
|
|
1085
|
+
knowledgeNode,
|
|
1086
|
+
isActive: knowledgeNode.id === selectedNodeId,
|
|
1087
|
+
onSelectNode
|
|
1088
|
+
}
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
if (typeof value === "string" && value.startsWith(FOLDER_PREFIX)) {
|
|
1092
|
+
return /* @__PURE__ */ jsx(
|
|
1093
|
+
DirectoryRow,
|
|
1094
|
+
{
|
|
1095
|
+
elementProps: decoratedElementProps,
|
|
1096
|
+
expanded,
|
|
1097
|
+
hasChildren,
|
|
1098
|
+
label: String(node.label),
|
|
1099
|
+
iconToken: typedNode.icon,
|
|
1100
|
+
command: getKnowledgeDirectoryCommand(
|
|
1101
|
+
typedNode.knowledgeNodeIds,
|
|
1102
|
+
getKnowledgeReadTreeFolderCommand(String(value))
|
|
1103
|
+
),
|
|
1104
|
+
isActive: false
|
|
1105
|
+
}
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
if (typedNode.nodeType === "graph" && typedNode.graphNodeId) {
|
|
1109
|
+
const graphNode2 = graphNodeMap.get(typedNode.graphNodeId);
|
|
1110
|
+
if (!graphNode2) return null;
|
|
1111
|
+
const isActive2 = selectedNodeId !== void 0 && (selectedNodeId === graphNode2.id || selectedNodeId === graphNode2.sourceId);
|
|
1112
|
+
return /* @__PURE__ */ jsx(
|
|
1113
|
+
DirectoryRow,
|
|
1114
|
+
{
|
|
1115
|
+
elementProps: decoratedElementProps,
|
|
1116
|
+
expanded,
|
|
1117
|
+
hasChildren,
|
|
1118
|
+
label: String(node.label),
|
|
1119
|
+
iconToken: typedNode.icon,
|
|
1120
|
+
command: getKnowledgeReadTreeFolderCommand(`graph:${graphNode2.id}`),
|
|
1121
|
+
isActive: isActive2,
|
|
1122
|
+
fallbackKind: graphNode2.kind,
|
|
1123
|
+
onSelectGraphNode: () => onSelectGraphNode?.(graphNode2),
|
|
1124
|
+
favorite: {
|
|
1125
|
+
routeId: graphNode2.id,
|
|
1126
|
+
label: graphNode2.label,
|
|
1127
|
+
kind: "graph",
|
|
1128
|
+
iconToken: typedNode.icon ?? graphNode2.icon
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
const graphNodeId = typedNode.graphNodeId ?? String(value).replace(SPINE_PREFIX, "");
|
|
1134
|
+
const graphNode = graphNodeMap.get(graphNodeId);
|
|
1135
|
+
const isActive = selectedNodeId !== void 0 && graphNode !== void 0 && (selectedNodeId === graphNode.id || selectedNodeId === graphNode.sourceId || selectedNodeId === graphNodeId);
|
|
1136
|
+
return /* @__PURE__ */ jsx(
|
|
1137
|
+
DirectoryRow,
|
|
1138
|
+
{
|
|
1139
|
+
elementProps: decoratedElementProps,
|
|
1140
|
+
expanded,
|
|
1141
|
+
hasChildren,
|
|
1142
|
+
label: String(node.label),
|
|
1143
|
+
iconToken: typedNode.icon,
|
|
1144
|
+
command: graphSpine ? getKnowledgeReadSpineFolderCommand(graphSpine, graphNode?.sourceId ?? graphNodeId) : "",
|
|
1145
|
+
isActive,
|
|
1146
|
+
fallbackKind: graphNode?.kind ?? "system",
|
|
1147
|
+
uppercase: true,
|
|
1148
|
+
onSelectGraphNode: graphNode ? () => onSelectGraphNode?.(graphNode) : void 0,
|
|
1149
|
+
favorite: graphNode ? {
|
|
1150
|
+
routeId: graphNode.id,
|
|
1151
|
+
label: graphNode.label,
|
|
1152
|
+
kind: "graph",
|
|
1153
|
+
iconToken: typedNode.icon ?? graphNode.icon
|
|
1154
|
+
} : void 0
|
|
1155
|
+
}
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
function FavoriteStarControl({ routeId, label, kind, iconToken, hovered }) {
|
|
1162
|
+
const isFavorited = useKnowledgeFavoritesStore((state) => Boolean(state.favorites[routeId]));
|
|
1163
|
+
const toggleFavorite = useKnowledgeFavoritesStore((state) => state.toggleFavorite);
|
|
1164
|
+
const visible = hovered || isFavorited;
|
|
1165
|
+
return /* @__PURE__ */ jsx(
|
|
1166
|
+
"span",
|
|
1167
|
+
{
|
|
1168
|
+
role: "button",
|
|
1169
|
+
tabIndex: visible ? 0 : -1,
|
|
1170
|
+
"aria-hidden": !visible,
|
|
1171
|
+
"aria-pressed": isFavorited,
|
|
1172
|
+
"aria-label": isFavorited ? `Unfavorite ${label}` : `Favorite ${label}`,
|
|
1173
|
+
onClick: (event) => {
|
|
1174
|
+
event.preventDefault();
|
|
1175
|
+
event.stopPropagation();
|
|
1176
|
+
toggleFavorite({ routeId, label, kind, iconToken });
|
|
1177
|
+
},
|
|
1178
|
+
onKeyDown: (event) => {
|
|
1179
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
1180
|
+
event.preventDefault();
|
|
1181
|
+
event.stopPropagation();
|
|
1182
|
+
toggleFavorite({ routeId, label, kind, iconToken });
|
|
1183
|
+
},
|
|
1184
|
+
style: {
|
|
1185
|
+
display: "inline-flex",
|
|
1186
|
+
alignItems: "center",
|
|
1187
|
+
justifyContent: "center",
|
|
1188
|
+
width: 22,
|
|
1189
|
+
height: 22,
|
|
1190
|
+
flexShrink: 0,
|
|
1191
|
+
opacity: visible ? 1 : 0,
|
|
1192
|
+
pointerEvents: visible ? "auto" : "none",
|
|
1193
|
+
color: isFavorited ? "var(--mantine-color-yellow-5)" : "var(--color-text-subtle)",
|
|
1194
|
+
transition: "opacity 120ms ease, color 120ms ease"
|
|
1195
|
+
},
|
|
1196
|
+
children: isFavorited ? /* @__PURE__ */ jsx(IconStarFilled, { size: 14 }) : /* @__PURE__ */ jsx(IconStar, { size: 14 })
|
|
1197
|
+
}
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
function focusFavoriteInTree(treeData, controller, favorite) {
|
|
1201
|
+
const path = findFavoritePathInTree(treeData, favorite);
|
|
1202
|
+
if (!path || path.length === 0) return;
|
|
1203
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
1204
|
+
controller.expand(path[i]);
|
|
1205
|
+
}
|
|
1206
|
+
const targetValue = path[path.length - 1];
|
|
1207
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
1208
|
+
const escape = (raw) => typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(raw) : raw.replace(/"/g, '\\"');
|
|
1209
|
+
window.requestAnimationFrame(() => {
|
|
1210
|
+
window.requestAnimationFrame(() => {
|
|
1211
|
+
const el = document.querySelector(`[data-tree-row-value="${escape(targetValue)}"]`);
|
|
1212
|
+
if (el instanceof HTMLElement) {
|
|
1213
|
+
el.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
1214
|
+
}
|
|
1215
|
+
});
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
function dispatchFavoriteSelection(routeId, kind, typedNode, ctx) {
|
|
1219
|
+
if (kind === "group" && routeId.startsWith(GROUP_PREFIX)) {
|
|
1220
|
+
ctx.onSelectGroup?.(routeId.slice(GROUP_PREFIX.length));
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
if (kind === "domain" && routeId.startsWith(DOMAIN_PREFIX)) {
|
|
1224
|
+
ctx.onSelectDomain?.(routeId.slice(DOMAIN_PREFIX.length));
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
if (kind === "item" && routeId.startsWith(ITEM_PREFIX)) {
|
|
1228
|
+
const rest = routeId.slice(ITEM_PREFIX.length);
|
|
1229
|
+
const sepIndex = rest.indexOf(":");
|
|
1230
|
+
if (sepIndex > 0) {
|
|
1231
|
+
ctx.onSelectItem?.(rest.slice(0, sepIndex), rest.slice(sepIndex + 1));
|
|
1232
|
+
}
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
if (kind === "graph") {
|
|
1236
|
+
const graphNode = ctx.graphNodeMap.get(routeId);
|
|
1237
|
+
if (graphNode) ctx.onSelectGraphNode?.(graphNode);
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (kind === "knowledge") {
|
|
1241
|
+
const knowledgeNode = ctx.leafNodeMap.get(routeId);
|
|
1242
|
+
if (knowledgeNode) ctx.onSelectNode(knowledgeNode);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
function FavoriteRow({ elementProps, label, routeId, kind, iconToken, onActivate }) {
|
|
1246
|
+
const [hovered, setHovered] = useState(false);
|
|
1247
|
+
return /* @__PURE__ */ jsx(
|
|
1248
|
+
UnstyledButton,
|
|
1249
|
+
{
|
|
1250
|
+
...elementProps,
|
|
1251
|
+
onMouseEnter: (event) => {
|
|
1252
|
+
elementProps.onMouseEnter?.(event);
|
|
1253
|
+
setHovered(true);
|
|
1254
|
+
},
|
|
1255
|
+
onMouseLeave: (event) => {
|
|
1256
|
+
elementProps.onMouseLeave?.(event);
|
|
1257
|
+
setHovered(false);
|
|
1258
|
+
},
|
|
1259
|
+
onClick: () => onActivate(),
|
|
1260
|
+
style: {
|
|
1261
|
+
...elementProps.style ?? {},
|
|
1262
|
+
padding: "5px 8px 5px 24px",
|
|
1263
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
1264
|
+
backgroundColor: hovered ? "var(--color-surface-hover)" : "transparent",
|
|
1265
|
+
width: "100%",
|
|
1266
|
+
textAlign: "left",
|
|
1267
|
+
display: "block"
|
|
1268
|
+
},
|
|
1269
|
+
children: /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
|
|
1270
|
+
/* @__PURE__ */ jsx(
|
|
1271
|
+
SemanticIcon,
|
|
1272
|
+
{
|
|
1273
|
+
token: iconToken,
|
|
1274
|
+
fallbackKind: kind === "knowledge" ? "knowledge" : "unknown",
|
|
1275
|
+
size: 15,
|
|
1276
|
+
style: { color: SIDEBAR_TREE_ACCENT_COLOR }
|
|
1277
|
+
}
|
|
1278
|
+
),
|
|
1279
|
+
/* @__PURE__ */ jsx(
|
|
1280
|
+
Text,
|
|
1281
|
+
{
|
|
1282
|
+
size: "sm",
|
|
1283
|
+
c: hovered ? "var(--color-text)" : void 0,
|
|
1284
|
+
style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
1285
|
+
children: label
|
|
1286
|
+
}
|
|
1287
|
+
),
|
|
1288
|
+
/* @__PURE__ */ jsx(
|
|
1289
|
+
TrailingCopySlot,
|
|
1290
|
+
{
|
|
1291
|
+
command: "",
|
|
1292
|
+
label: "",
|
|
1293
|
+
showCopy: false,
|
|
1294
|
+
favorite: { routeId, label, kind, iconToken },
|
|
1295
|
+
hovered
|
|
1296
|
+
}
|
|
1297
|
+
)
|
|
1298
|
+
] })
|
|
1299
|
+
}
|
|
1300
|
+
);
|
|
1301
|
+
}
|
|
1302
|
+
function CopyCommandControl({ command, label, visible }) {
|
|
1303
|
+
const clipboard = useClipboard({ timeout: 1500 });
|
|
1304
|
+
if (!command) return null;
|
|
1305
|
+
return /* @__PURE__ */ jsx(
|
|
1306
|
+
"span",
|
|
1307
|
+
{
|
|
1308
|
+
role: "button",
|
|
1309
|
+
tabIndex: visible ? 0 : -1,
|
|
1310
|
+
"aria-hidden": !visible,
|
|
1311
|
+
"aria-label": label,
|
|
1312
|
+
onClick: (event) => {
|
|
1313
|
+
event.preventDefault();
|
|
1314
|
+
event.stopPropagation();
|
|
1315
|
+
clipboard.copy(command);
|
|
1316
|
+
},
|
|
1317
|
+
onKeyDown: (event) => {
|
|
1318
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
1319
|
+
event.preventDefault();
|
|
1320
|
+
event.stopPropagation();
|
|
1321
|
+
clipboard.copy(command);
|
|
1322
|
+
},
|
|
1323
|
+
style: {
|
|
1324
|
+
display: "inline-flex",
|
|
1325
|
+
alignItems: "center",
|
|
1326
|
+
justifyContent: "center",
|
|
1327
|
+
width: 22,
|
|
1328
|
+
height: 22,
|
|
1329
|
+
flexShrink: 0,
|
|
1330
|
+
opacity: visible ? 1 : 0,
|
|
1331
|
+
pointerEvents: visible ? "auto" : "none",
|
|
1332
|
+
color: clipboard.copied ? "var(--color-primary)" : "var(--color-text-subtle)",
|
|
1333
|
+
transition: "opacity 120ms ease, color 120ms ease"
|
|
1334
|
+
},
|
|
1335
|
+
children: clipboard.copied ? /* @__PURE__ */ jsx(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx(IconCopy, { size: 14 })
|
|
1336
|
+
}
|
|
1337
|
+
);
|
|
1338
|
+
}
|
|
1339
|
+
function KnowledgeLeafRow({ elementProps, knowledgeNode, isActive, onSelectNode }) {
|
|
1340
|
+
const [hovered, setHovered] = useState(false);
|
|
1341
|
+
return /* @__PURE__ */ jsx(
|
|
1342
|
+
UnstyledButton,
|
|
1343
|
+
{
|
|
1344
|
+
...elementProps,
|
|
1345
|
+
onMouseEnter: (event) => {
|
|
1346
|
+
elementProps.onMouseEnter?.(event);
|
|
1347
|
+
setHovered(true);
|
|
1348
|
+
},
|
|
1349
|
+
onMouseLeave: (event) => {
|
|
1350
|
+
elementProps.onMouseLeave?.(event);
|
|
1351
|
+
setHovered(false);
|
|
1352
|
+
},
|
|
1353
|
+
onClick: () => onSelectNode(knowledgeNode),
|
|
1354
|
+
style: {
|
|
1355
|
+
...elementProps.style ?? {},
|
|
1356
|
+
padding: "5px 8px 5px 24px",
|
|
1357
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
1358
|
+
backgroundColor: isActive ? "color-mix(in srgb, var(--color-primary) 10%, transparent)" : hovered ? "var(--color-surface-hover)" : "transparent",
|
|
1359
|
+
width: "100%",
|
|
1360
|
+
textAlign: "left",
|
|
1361
|
+
display: "block"
|
|
1362
|
+
},
|
|
1363
|
+
children: /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
|
|
1364
|
+
/* @__PURE__ */ jsx(
|
|
1365
|
+
SemanticIcon,
|
|
1366
|
+
{
|
|
1367
|
+
token: getKnowledgeIconToken(knowledgeNode),
|
|
1368
|
+
fallbackKind: knowledgeNode.kind,
|
|
1369
|
+
size: 15,
|
|
1370
|
+
style: { color: SIDEBAR_TREE_ACCENT_COLOR }
|
|
1371
|
+
}
|
|
1372
|
+
),
|
|
1373
|
+
/* @__PURE__ */ jsx(
|
|
1374
|
+
Text,
|
|
1375
|
+
{
|
|
1376
|
+
size: "sm",
|
|
1377
|
+
c: isActive ? "var(--color-primary)" : hovered ? "var(--color-text)" : void 0,
|
|
1378
|
+
fw: isActive ? 600 : 400,
|
|
1379
|
+
style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
1380
|
+
children: knowledgeNode.title
|
|
1381
|
+
}
|
|
1382
|
+
),
|
|
1383
|
+
/* @__PURE__ */ jsx(
|
|
1384
|
+
TrailingCopySlot,
|
|
1385
|
+
{
|
|
1386
|
+
command: getKnowledgeReadCommand(knowledgeNode.id),
|
|
1387
|
+
label: "Copy knowledge command",
|
|
1388
|
+
showCopy: hovered,
|
|
1389
|
+
favorite: {
|
|
1390
|
+
routeId: knowledgeNode.id,
|
|
1391
|
+
label: knowledgeNode.title,
|
|
1392
|
+
kind: "knowledge",
|
|
1393
|
+
iconToken: getKnowledgeIconToken(knowledgeNode)
|
|
1394
|
+
},
|
|
1395
|
+
hovered
|
|
1396
|
+
}
|
|
1397
|
+
)
|
|
1398
|
+
] })
|
|
1399
|
+
}
|
|
1400
|
+
);
|
|
1401
|
+
}
|
|
1402
|
+
function DirectoryRow({
|
|
1403
|
+
elementProps,
|
|
1404
|
+
expanded,
|
|
1405
|
+
hasChildren,
|
|
1406
|
+
label,
|
|
1407
|
+
iconToken,
|
|
1408
|
+
command,
|
|
1409
|
+
isActive,
|
|
1410
|
+
fallbackKind = "system",
|
|
1411
|
+
uppercase = false,
|
|
1412
|
+
onSelectGraphNode,
|
|
1413
|
+
favorite
|
|
1414
|
+
}) {
|
|
1415
|
+
const [hovered, setHovered] = useState(false);
|
|
1416
|
+
return /* @__PURE__ */ jsxs(
|
|
1417
|
+
Group,
|
|
1418
|
+
{
|
|
1419
|
+
...elementProps,
|
|
1420
|
+
gap: "xs",
|
|
1421
|
+
onMouseEnter: (event) => {
|
|
1422
|
+
elementProps.onMouseEnter?.(event);
|
|
1423
|
+
setHovered(true);
|
|
1424
|
+
},
|
|
1425
|
+
onMouseLeave: (event) => {
|
|
1426
|
+
elementProps.onMouseLeave?.(event);
|
|
1427
|
+
setHovered(false);
|
|
1428
|
+
},
|
|
1429
|
+
onClick: (event) => {
|
|
1430
|
+
if (onSelectGraphNode) {
|
|
1431
|
+
if (isActive && expanded) {
|
|
1432
|
+
elementProps.onClick?.(event);
|
|
1433
|
+
} else {
|
|
1434
|
+
if (!expanded) elementProps.onClick?.(event);
|
|
1435
|
+
onSelectGraphNode();
|
|
1436
|
+
}
|
|
1437
|
+
} else {
|
|
1438
|
+
elementProps.onClick?.(event);
|
|
1439
|
+
}
|
|
1440
|
+
},
|
|
1441
|
+
style: {
|
|
1442
|
+
...elementProps.style ?? {},
|
|
1443
|
+
padding: "4px 8px",
|
|
1444
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
1445
|
+
backgroundColor: isActive ? "color-mix(in srgb, var(--color-primary) 10%, transparent)" : hovered ? "var(--color-surface-hover)" : "transparent",
|
|
1446
|
+
cursor: onSelectGraphNode || hasChildren ? "pointer" : "default",
|
|
1447
|
+
userSelect: "none"
|
|
1448
|
+
},
|
|
1449
|
+
children: [
|
|
1450
|
+
hasChildren ? /* @__PURE__ */ jsx(
|
|
1451
|
+
"span",
|
|
1452
|
+
{
|
|
1453
|
+
"aria-hidden": "true",
|
|
1454
|
+
style: {
|
|
1455
|
+
display: "inline-flex",
|
|
1456
|
+
alignItems: "center",
|
|
1457
|
+
justifyContent: "center",
|
|
1458
|
+
width: 12,
|
|
1459
|
+
height: 12,
|
|
1460
|
+
color: SIDEBAR_TREE_ACCENT_COLOR,
|
|
1461
|
+
flexShrink: 0
|
|
1462
|
+
},
|
|
1463
|
+
children: expanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: 12, stroke: 2 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 12, stroke: 2 })
|
|
1464
|
+
}
|
|
1465
|
+
) : /* @__PURE__ */ jsx(Text, { size: "xs", style: { width: 12, flexShrink: 0 } }),
|
|
1466
|
+
/* @__PURE__ */ jsx(
|
|
1467
|
+
SemanticIcon,
|
|
1468
|
+
{
|
|
1469
|
+
token: iconToken,
|
|
1470
|
+
fallbackKind: fallbackKind !== void 0 ? toSemanticFallbackKind(fallbackKind) : "unknown",
|
|
1471
|
+
size: 14,
|
|
1472
|
+
style: { color: SIDEBAR_TREE_ACCENT_COLOR }
|
|
1473
|
+
}
|
|
1474
|
+
),
|
|
1475
|
+
/* @__PURE__ */ jsx(
|
|
1476
|
+
Text,
|
|
1477
|
+
{
|
|
1478
|
+
size: "sm",
|
|
1479
|
+
fw: isActive ? 700 : 600,
|
|
1480
|
+
tt: uppercase ? "uppercase" : void 0,
|
|
1481
|
+
c: isActive ? "var(--color-primary)" : hovered ? "var(--color-text)" : void 0,
|
|
1482
|
+
style: {
|
|
1483
|
+
letterSpacing: uppercase ? "0.05em" : 0,
|
|
1484
|
+
flex: 1,
|
|
1485
|
+
minWidth: 0,
|
|
1486
|
+
overflow: "hidden",
|
|
1487
|
+
textOverflow: "ellipsis",
|
|
1488
|
+
whiteSpace: "nowrap"
|
|
1489
|
+
},
|
|
1490
|
+
children: label
|
|
1491
|
+
}
|
|
1492
|
+
),
|
|
1493
|
+
/* @__PURE__ */ jsx(
|
|
1494
|
+
TrailingCopySlot,
|
|
1495
|
+
{
|
|
1496
|
+
command,
|
|
1497
|
+
label: "Copy folder knowledge commands",
|
|
1498
|
+
showCopy: hovered,
|
|
1499
|
+
favorite,
|
|
1500
|
+
hovered
|
|
1501
|
+
}
|
|
1502
|
+
)
|
|
1503
|
+
]
|
|
1504
|
+
}
|
|
1505
|
+
);
|
|
1506
|
+
}
|
|
1507
|
+
function TrailingCopySlot({ command, label, showCopy, favorite, hovered }) {
|
|
1508
|
+
const isFavorited = useKnowledgeFavoritesStore(
|
|
1509
|
+
(state) => favorite ? Boolean(state.favorites[favorite.routeId]) : false
|
|
1510
|
+
);
|
|
1511
|
+
const favoriteVisible = Boolean(favorite) && (hovered || isFavorited);
|
|
1512
|
+
const copyVisible = showCopy && Boolean(command);
|
|
1513
|
+
if (!favoriteVisible && !copyVisible) return null;
|
|
1514
|
+
return /* @__PURE__ */ jsxs(
|
|
1515
|
+
"span",
|
|
1516
|
+
{
|
|
1517
|
+
style: {
|
|
1518
|
+
display: "inline-flex",
|
|
1519
|
+
alignItems: "center",
|
|
1520
|
+
justifyContent: "flex-end",
|
|
1521
|
+
gap: 2,
|
|
1522
|
+
height: 22,
|
|
1523
|
+
flexShrink: 0
|
|
1524
|
+
},
|
|
1525
|
+
children: [
|
|
1526
|
+
copyVisible ? /* @__PURE__ */ jsx(CopyCommandControl, { command, label, visible: true }) : null,
|
|
1527
|
+
favoriteVisible && favorite ? /* @__PURE__ */ jsx(
|
|
1528
|
+
FavoriteStarControl,
|
|
1529
|
+
{
|
|
1530
|
+
routeId: favorite.routeId,
|
|
1531
|
+
label: favorite.label,
|
|
1532
|
+
kind: favorite.kind,
|
|
1533
|
+
iconToken: favorite.iconToken,
|
|
1534
|
+
hovered: true
|
|
1535
|
+
}
|
|
1536
|
+
) : null
|
|
1537
|
+
]
|
|
1538
|
+
}
|
|
1539
|
+
);
|
|
1540
|
+
}
|
|
1541
|
+
var indexPromise = null;
|
|
1542
|
+
function loadSearchIndex() {
|
|
1543
|
+
if (!indexPromise) {
|
|
1544
|
+
indexPromise = import('./knowledge-search-index-5KYPO746.js').then(
|
|
1545
|
+
(mod) => buildSearchIndex(mod.default ?? mod)
|
|
1546
|
+
);
|
|
1547
|
+
}
|
|
1548
|
+
return indexPromise;
|
|
1549
|
+
}
|
|
1550
|
+
function buildSearchIndex(entries) {
|
|
1551
|
+
return {
|
|
1552
|
+
search(query) {
|
|
1553
|
+
if (!query.trim()) return [];
|
|
1554
|
+
const q = query.trim().toLowerCase();
|
|
1555
|
+
const scored = [];
|
|
1556
|
+
for (const entry of entries) {
|
|
1557
|
+
let score = 0;
|
|
1558
|
+
if (entry.title.toLowerCase().includes(q)) score += 3;
|
|
1559
|
+
if (entry.summary.toLowerCase().includes(q)) score += 2;
|
|
1560
|
+
if (entry.bodyText.toLowerCase().includes(q)) score += 1;
|
|
1561
|
+
if (score > 0) scored.push({ id: entry.id, score });
|
|
1562
|
+
}
|
|
1563
|
+
return scored.sort((a, b) => b.score - a.score).map((s) => s.id);
|
|
1564
|
+
}
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
function KnowledgeSearchBar({
|
|
1568
|
+
knowledgeNodes,
|
|
1569
|
+
onResults,
|
|
1570
|
+
placeholder = "Search knowledge\u2026"
|
|
1571
|
+
}) {
|
|
1572
|
+
const [query, setQuery] = useState("");
|
|
1573
|
+
const indexRef = useRef(null);
|
|
1574
|
+
const nodeMapRef = useRef(/* @__PURE__ */ new Map());
|
|
1575
|
+
useEffect(() => {
|
|
1576
|
+
const map = /* @__PURE__ */ new Map();
|
|
1577
|
+
for (const node of knowledgeNodes) map.set(node.id, node);
|
|
1578
|
+
nodeMapRef.current = map;
|
|
1579
|
+
}, [knowledgeNodes]);
|
|
1580
|
+
const handleChange = (value) => {
|
|
1581
|
+
setQuery(value);
|
|
1582
|
+
if (!value.trim()) {
|
|
1583
|
+
onResults(null);
|
|
1584
|
+
return;
|
|
1585
|
+
}
|
|
1586
|
+
if (indexRef.current) {
|
|
1587
|
+
runSearch(value, indexRef.current);
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
void loadSearchIndex().then((index) => {
|
|
1591
|
+
indexRef.current = index;
|
|
1592
|
+
if (query.trim() || value.trim()) runSearch(value, index);
|
|
1593
|
+
});
|
|
1594
|
+
};
|
|
1595
|
+
function runSearch(value, index) {
|
|
1596
|
+
const ids = index.search(value);
|
|
1597
|
+
const hits = ids.flatMap((id) => {
|
|
1598
|
+
const node = nodeMapRef.current.get(id);
|
|
1599
|
+
return node ? [node] : [];
|
|
1600
|
+
});
|
|
1601
|
+
onResults(hits);
|
|
1602
|
+
}
|
|
1603
|
+
const handleClear = () => {
|
|
1604
|
+
setQuery("");
|
|
1605
|
+
onResults(null);
|
|
1606
|
+
};
|
|
1607
|
+
return /* @__PURE__ */ jsx(
|
|
1608
|
+
TextInput,
|
|
1609
|
+
{
|
|
1610
|
+
value: query,
|
|
1611
|
+
onChange: (e) => handleChange(e.currentTarget.value),
|
|
1612
|
+
placeholder,
|
|
1613
|
+
leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
|
|
1614
|
+
rightSection: query ? /* @__PURE__ */ jsx(IconX, { size: 14, style: { cursor: "pointer", color: "var(--color-text-subtle)" }, onClick: handleClear }) : null,
|
|
1615
|
+
styles: {
|
|
1616
|
+
input: {
|
|
1617
|
+
backgroundColor: "var(--color-surface)",
|
|
1618
|
+
borderColor: "var(--color-border)",
|
|
1619
|
+
color: "var(--color-text)"
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
export { KNOWLEDGE_DOMAINS_WITH_PANELS, KNOWLEDGE_ICON_TOKEN_BY_KIND, KnowledgeSearchBar, KnowledgeTree, OM_TREE_GROUPS, getKnowledgeIconToken, getSharedOrganizationGraph, projectNavigationGroups, projectNavigationSurfaces };
|