@unson/brainbase-mcp 0.6.0 → 0.8.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/contracts/foundation/graph-history.sql +634 -0
- package/contracts/judgment-value-proof/schema.json +43 -1
- package/dist/canonical-task-contract.d.ts +9 -0
- package/dist/canonical-task-contract.js +39 -0
- package/dist/canonical-task-principal.d.ts +16 -0
- package/dist/canonical-task-principal.js +36 -0
- package/dist/canonical-task-service.d.ts +251 -0
- package/dist/canonical-task-service.js +820 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +107 -0
- package/dist/company-os-evaluation.d.ts +193 -0
- package/dist/company-os-evaluation.js +1150 -0
- package/dist/company-os-impact-review.d.ts +248 -0
- package/dist/company-os-impact-review.js +663 -0
- package/dist/company-os-learning-adoption.d.ts +288 -0
- package/dist/company-os-learning-adoption.js +944 -0
- package/dist/company-os-objectives.d.ts +63 -0
- package/dist/company-os-objectives.js +234 -0
- package/dist/company-os-receipt-adapter.d.ts +109 -0
- package/dist/company-os-receipt-adapter.js +636 -0
- package/dist/constraint-exception-store.d.ts +23 -0
- package/dist/constraint-exception-store.js +108 -0
- package/dist/constraint-resolution.d.ts +175 -0
- package/dist/constraint-resolution.js +922 -0
- package/dist/decision-adapter.d.ts +145 -0
- package/dist/decision-adapter.js +586 -0
- package/dist/durable-wait-http.d.ts +51 -0
- package/dist/durable-wait-http.js +497 -0
- package/dist/durable-waits.d.ts +234 -0
- package/dist/durable-waits.js +944 -0
- package/dist/execution-authority-http.d.ts +28 -0
- package/dist/execution-authority-http.js +359 -0
- package/dist/execution-authority.d.ts +201 -0
- package/dist/execution-authority.js +634 -0
- package/dist/foundation-authenticated-tools.d.ts +56 -0
- package/dist/foundation-authenticated-tools.js +347 -0
- package/dist/foundation-catalog.d.ts +26 -0
- package/dist/foundation-catalog.js +206 -0
- package/dist/foundation-constraint-store.d.ts +50 -0
- package/dist/foundation-constraint-store.js +215 -0
- package/dist/foundation-graph-http.d.ts +43 -0
- package/dist/foundation-graph-http.js +243 -0
- package/dist/foundation-graph-write.d.ts +90 -0
- package/dist/foundation-graph-write.js +447 -0
- package/dist/foundation-http.d.ts +90 -0
- package/dist/foundation-http.js +439 -0
- package/dist/foundation-public-provider.d.ts +140 -0
- package/dist/foundation-public-provider.js +192 -0
- package/dist/foundation-store.d.ts +132 -0
- package/dist/foundation-store.js +654 -0
- package/dist/graph-corrections.d.ts +157 -0
- package/dist/graph-corrections.js +620 -0
- package/dist/graph-foundation-reader.d.ts +60 -0
- package/dist/graph-foundation-reader.js +494 -0
- package/dist/graph-retrieval.d.ts +6 -1
- package/dist/graph-revision-reader.d.ts +80 -0
- package/dist/graph-revision-reader.js +246 -0
- package/dist/graph-web-http.d.ts +26 -0
- package/dist/graph-web-http.js +215 -0
- package/dist/graph-web.d.ts +364 -0
- package/dist/graph-web.js +639 -0
- package/dist/judgment-dag-composition.d.ts +224 -0
- package/dist/judgment-dag-composition.js +731 -0
- package/dist/judgment-dag.d.ts +2 -0
- package/dist/judgment-dag.js +1 -0
- package/dist/judgment-problem-snapshot.d.ts +213 -0
- package/dist/judgment-problem-snapshot.js +1073 -0
- package/dist/judgment-value-proof-review.d.ts +166 -0
- package/dist/judgment-value-proof-review.js +437 -0
- package/dist/judgment-value-proof.d.ts +28 -1
- package/dist/judgment-value-proof.js +53 -8
- package/dist/judgment-view-http.d.ts +22 -0
- package/dist/judgment-view-http.js +128 -0
- package/dist/judgment-view.d.ts +222 -0
- package/dist/judgment-view.js +627 -0
- package/dist/knowledge-adapter.d.ts +112 -0
- package/dist/knowledge-adapter.js +691 -0
- package/dist/knowledge-continuation.d.ts +127 -0
- package/dist/knowledge-continuation.js +446 -0
- package/dist/knowledge-lookup.d.ts +178 -0
- package/dist/knowledge-lookup.js +758 -0
- package/dist/local-web-fetch-bridge.d.ts +5 -0
- package/dist/local-web-fetch-bridge.js +37 -0
- package/dist/local-web-host.d.ts +109 -0
- package/dist/local-web-host.js +688 -0
- package/dist/local-web-security.d.ts +25 -0
- package/dist/local-web-security.js +95 -0
- package/dist/ontology-foundation.d.ts +209 -0
- package/dist/ontology-foundation.js +1000 -0
- package/dist/ontology.d.ts +13 -0
- package/dist/ontology.js +14 -0
- package/dist/organization-connection.d.ts +164 -0
- package/dist/organization-connection.js +428 -0
- package/dist/organization-graph.d.ts +15 -0
- package/dist/organization-graph.js +24 -4
- package/dist/personal-knowledge.d.ts +132 -0
- package/dist/personal-knowledge.js +779 -0
- package/dist/personal-memory-handover.d.ts +108 -0
- package/dist/personal-memory-handover.js +369 -0
- package/dist/philosophy-revision-reader.d.ts +85 -0
- package/dist/philosophy-revision-reader.js +241 -0
- package/dist/portable-graph.d.ts +24 -0
- package/dist/portable-graph.js +77 -0
- package/dist/problem-candidates.d.ts +149 -0
- package/dist/problem-candidates.js +898 -0
- package/dist/problem-selection.d.ts +238 -0
- package/dist/problem-selection.js +995 -0
- package/dist/resource-reservation-http.d.ts +31 -0
- package/dist/resource-reservation-http.js +371 -0
- package/dist/resource-reservations.d.ts +221 -0
- package/dist/resource-reservations.js +577 -0
- package/dist/server.d.ts +104 -2
- package/dist/server.js +186 -4
- package/dist/ssot.d.ts +6 -1
- package/dist/ssot.js +63 -5
- package/dist/streamable-http.d.ts +42 -0
- package/dist/streamable-http.js +288 -0
- package/dist/types.d.ts +20 -0
- package/dist/value-proof-review-http.d.ts +25 -0
- package/dist/value-proof-review-http.js +185 -0
- package/dist/world-model.d.ts +199 -0
- package/dist/world-model.js +955 -0
- package/package.json +230 -3
- package/ui/brainbase-tokens.css +56 -0
- package/ui/graph-own-share.js +367 -0
- package/ui/graph-projects-view.css +23 -0
- package/ui/graph-projects-view.js +730 -0
- package/ui/graph-registry-view.css +101 -0
- package/ui/graph-registry-view.js +804 -0
- package/ui/graph-view-shared.css +522 -0
- package/ui/graph-view-shared.js +1227 -0
- package/ui/judgment-view.css +312 -0
- package/ui/judgment-view.js +508 -0
- package/ui/local-web-shell.css +396 -0
- package/ui/local-web-shell.js +378 -0
- package/ui/objective-editor-http-port.js +154 -0
- package/ui/objective-editor.css +286 -0
- package/ui/objective-editor.js +1586 -0
- package/ui/outcome-knowledge.css +50 -14
- package/ui/outcome-knowledge.js +15 -1
- package/ui/outcome-mana.css +91 -14
- package/ui/outcome-mana.js +958 -61
- package/ui/value-proof-review.css +504 -0
- package/ui/value-proof-review.js +1104 -0
- package/ui/workspace-kit.css +485 -0
- package/ui/workspace-kit.js +229 -0
- package/ui/world-model-view.css +188 -0
- package/ui/world-model-view.js +486 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Workspace kit: the organization edition's screen pattern (page head, notice,
|
|
3
|
+
* metrics, ledger, right rail). Values follow brainbase-organization
|
|
4
|
+
* apps/web/public/styles.css (final layer) through the shared tokens only.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* Page head */
|
|
8
|
+
.bb-ws-page {
|
|
9
|
+
display: grid;
|
|
10
|
+
gap: 0;
|
|
11
|
+
min-width: 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.bb-ws-breadcrumb {
|
|
15
|
+
margin-bottom: 24px;
|
|
16
|
+
color: var(--bb-color-quiet);
|
|
17
|
+
font-size: 11px;
|
|
18
|
+
letter-spacing: .02em;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.bb-ws-breadcrumb-separator {
|
|
22
|
+
margin-inline: 8px;
|
|
23
|
+
color: var(--bb-color-border-strong);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.bb-ws-page-head {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-wrap: wrap;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: space-between;
|
|
31
|
+
gap: 16px 30px;
|
|
32
|
+
min-width: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* The title is never broken inside a word: when it and the actions do not fit
|
|
36
|
+
on one line, the actions move below it. */
|
|
37
|
+
.bb-ws-page-copy {
|
|
38
|
+
flex: 1 1 0;
|
|
39
|
+
min-width: min-content;
|
|
40
|
+
max-width: 100%;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.bb-ws-page-head h1 {
|
|
44
|
+
margin: 0;
|
|
45
|
+
color: var(--bb-color-ink);
|
|
46
|
+
font-size: clamp(32px, 3.5vw, 44px);
|
|
47
|
+
font-weight: 760;
|
|
48
|
+
line-height: 1.1;
|
|
49
|
+
letter-spacing: -.055em;
|
|
50
|
+
word-break: keep-all;
|
|
51
|
+
overflow-wrap: break-word;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.bb-ws-lead {
|
|
55
|
+
max-width: 720px;
|
|
56
|
+
margin: 12px 0 0;
|
|
57
|
+
color: var(--bb-color-muted);
|
|
58
|
+
line-height: 1.65;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.bb-ws-page-side {
|
|
62
|
+
display: flex;
|
|
63
|
+
flex: none;
|
|
64
|
+
align-items: center;
|
|
65
|
+
gap: var(--bb-space-2);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.bb-ws-source {
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
gap: 7px;
|
|
72
|
+
min-height: 30px;
|
|
73
|
+
border-radius: var(--bb-radius-sm);
|
|
74
|
+
padding: 7px 10px;
|
|
75
|
+
background: var(--bb-color-accent-soft);
|
|
76
|
+
color: var(--bb-color-accent-strong);
|
|
77
|
+
font-size: 11px;
|
|
78
|
+
font-weight: 720;
|
|
79
|
+
white-space: nowrap;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.bb-ws-source::before {
|
|
83
|
+
width: 7px;
|
|
84
|
+
height: 7px;
|
|
85
|
+
border-radius: 50%;
|
|
86
|
+
background: currentColor;
|
|
87
|
+
content: "";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Notice */
|
|
91
|
+
.bb-ws-notice {
|
|
92
|
+
display: grid;
|
|
93
|
+
grid-template-columns: 92px minmax(0, 1fr);
|
|
94
|
+
gap: 12px;
|
|
95
|
+
margin: 30px 0;
|
|
96
|
+
border: 1px solid var(--bb-color-border);
|
|
97
|
+
border-left: 3px solid var(--bb-color-accent);
|
|
98
|
+
padding: 14px 16px;
|
|
99
|
+
background: var(--bb-color-surface);
|
|
100
|
+
color: var(--bb-color-muted);
|
|
101
|
+
font-size: 12px;
|
|
102
|
+
line-height: 1.65;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.bb-ws-notice > :only-child {
|
|
106
|
+
grid-column: 1 / -1;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.bb-ws-notice strong {
|
|
110
|
+
color: var(--bb-color-accent-strong);
|
|
111
|
+
font-size: 12px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.bb-ws-notice.is-warning {
|
|
115
|
+
border-left-color: var(--bb-color-warning);
|
|
116
|
+
background: var(--bb-color-warning-soft);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.bb-ws-notice.is-warning strong {
|
|
120
|
+
color: var(--bb-color-warning);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.bb-ws-notice.is-danger {
|
|
124
|
+
border-left-color: var(--bb-color-danger);
|
|
125
|
+
background: var(--bb-color-danger-soft);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.bb-ws-notice.is-danger strong {
|
|
129
|
+
color: var(--bb-color-danger);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Buttons */
|
|
133
|
+
.bb-ws-actions {
|
|
134
|
+
display: flex;
|
|
135
|
+
flex-wrap: wrap;
|
|
136
|
+
align-items: center;
|
|
137
|
+
gap: var(--bb-space-2);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.bb-ws-button {
|
|
141
|
+
min-height: 38px;
|
|
142
|
+
display: inline-flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
gap: var(--bb-space-2);
|
|
145
|
+
border: 1px solid var(--bb-color-border-strong);
|
|
146
|
+
border-radius: var(--bb-radius-sm);
|
|
147
|
+
padding: 8px 13px;
|
|
148
|
+
background: var(--bb-color-panel);
|
|
149
|
+
color: var(--bb-color-ink);
|
|
150
|
+
font: inherit;
|
|
151
|
+
font-size: 13px;
|
|
152
|
+
font-weight: 680;
|
|
153
|
+
cursor: pointer;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.bb-ws-button:hover {
|
|
157
|
+
border-color: var(--bb-color-muted);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.bb-ws-button.is-primary {
|
|
161
|
+
border-color: var(--bb-color-rail);
|
|
162
|
+
background: var(--bb-color-rail);
|
|
163
|
+
color: var(--bb-color-rail-strong);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.bb-ws-button.is-primary:hover {
|
|
167
|
+
border-color: var(--bb-color-accent);
|
|
168
|
+
background: var(--bb-color-accent);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.bb-ws-button.is-danger {
|
|
172
|
+
color: var(--bb-color-danger);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.bb-ws-button.is-quiet {
|
|
176
|
+
min-height: 30px;
|
|
177
|
+
padding: 4px 10px;
|
|
178
|
+
font-size: 12px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.bb-ws-button:disabled {
|
|
182
|
+
cursor: not-allowed;
|
|
183
|
+
opacity: .58;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* Summary metrics */
|
|
187
|
+
.bb-ws-summary {
|
|
188
|
+
display: grid;
|
|
189
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
190
|
+
margin: 0 0 34px;
|
|
191
|
+
border-block: 1px solid var(--bb-color-border);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.bb-ws-summary.is-1 { grid-template-columns: minmax(0, 1fr); }
|
|
195
|
+
.bb-ws-summary.is-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
196
|
+
.bb-ws-summary.is-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
|
197
|
+
.bb-ws-summary.is-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
|
198
|
+
.bb-ws-summary.is-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
|
199
|
+
|
|
200
|
+
.bb-ws-metric {
|
|
201
|
+
min-width: 0;
|
|
202
|
+
border-right: 1px solid var(--bb-color-border);
|
|
203
|
+
padding: 20px 24px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.bb-ws-metric:first-child {
|
|
207
|
+
padding-left: 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.bb-ws-metric:last-child {
|
|
211
|
+
border-right: 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.bb-ws-metric small,
|
|
215
|
+
.bb-ws-metric span {
|
|
216
|
+
display: block;
|
|
217
|
+
color: var(--bb-color-muted);
|
|
218
|
+
font-size: 11px;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.bb-ws-metric strong {
|
|
222
|
+
display: block;
|
|
223
|
+
margin-block: 8px 3px;
|
|
224
|
+
color: var(--bb-color-ink);
|
|
225
|
+
font-size: 30px;
|
|
226
|
+
letter-spacing: -.03em;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* Ledger */
|
|
230
|
+
.bb-ws-ledger {
|
|
231
|
+
width: 100%;
|
|
232
|
+
min-width: 0;
|
|
233
|
+
border-top: 1px solid var(--bb-color-border-strong);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.bb-ws-ledger-row {
|
|
237
|
+
width: 100%;
|
|
238
|
+
min-height: 60px;
|
|
239
|
+
display: grid;
|
|
240
|
+
grid-template-columns: minmax(0, 1fr);
|
|
241
|
+
align-items: center;
|
|
242
|
+
border: 0;
|
|
243
|
+
border-bottom: 1px solid var(--bb-color-border);
|
|
244
|
+
padding: 0;
|
|
245
|
+
background: transparent;
|
|
246
|
+
color: var(--bb-color-muted);
|
|
247
|
+
font: inherit;
|
|
248
|
+
font-size: 12px;
|
|
249
|
+
text-align: left;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.bb-ws-ledger-row > span {
|
|
253
|
+
min-width: 0;
|
|
254
|
+
overflow: hidden;
|
|
255
|
+
padding: 9px 12px;
|
|
256
|
+
text-overflow: ellipsis;
|
|
257
|
+
white-space: nowrap;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.bb-ws-ledger-row > span:first-child {
|
|
261
|
+
padding-left: 8px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.bb-ws-ledger-head {
|
|
265
|
+
min-height: 38px;
|
|
266
|
+
color: var(--bb-color-quiet);
|
|
267
|
+
font-size: 10px;
|
|
268
|
+
font-weight: 700;
|
|
269
|
+
letter-spacing: .08em;
|
|
270
|
+
text-transform: uppercase;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.bb-ws-ledger-row.is-selectable {
|
|
274
|
+
cursor: pointer;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.bb-ws-ledger-row.is-selectable:hover {
|
|
278
|
+
background: var(--bb-color-surface);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.bb-ws-ledger-row.is-selected,
|
|
282
|
+
.bb-ws-ledger-row.is-selectable.is-selected:hover {
|
|
283
|
+
background: var(--bb-color-accent-soft);
|
|
284
|
+
box-shadow: inset 3px 0 var(--bb-color-accent);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.bb-ws-ledger-object {
|
|
288
|
+
display: grid;
|
|
289
|
+
gap: 4px;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.bb-ws-ledger-object strong {
|
|
293
|
+
overflow: hidden;
|
|
294
|
+
color: var(--bb-color-ink);
|
|
295
|
+
text-overflow: ellipsis;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.bb-ws-ledger-object code {
|
|
299
|
+
overflow: hidden;
|
|
300
|
+
color: var(--bb-color-quiet);
|
|
301
|
+
font-family: var(--bb-font-mono);
|
|
302
|
+
font-size: 10px;
|
|
303
|
+
text-overflow: ellipsis;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.bb-ws-ledger .is-unresolved,
|
|
307
|
+
.bb-ws-definition .is-unrecorded {
|
|
308
|
+
color: var(--bb-color-quiet);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.bb-ws-ledger-empty {
|
|
312
|
+
margin: 0;
|
|
313
|
+
border-bottom: 1px solid var(--bb-color-border);
|
|
314
|
+
padding: 18px 8px;
|
|
315
|
+
color: var(--bb-color-muted);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/* Right rail */
|
|
319
|
+
.bb-ws-rail-head {
|
|
320
|
+
display: block;
|
|
321
|
+
border-bottom: 1px solid var(--bb-color-border);
|
|
322
|
+
padding-bottom: 22px;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.bb-ws-rail-head small {
|
|
326
|
+
display: block;
|
|
327
|
+
margin-bottom: 8px;
|
|
328
|
+
color: var(--bb-color-eyebrow);
|
|
329
|
+
font-size: 11px;
|
|
330
|
+
font-weight: 720;
|
|
331
|
+
letter-spacing: .08em;
|
|
332
|
+
text-transform: uppercase;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.bb-ws-rail-head h2 {
|
|
336
|
+
margin: 0;
|
|
337
|
+
color: var(--bb-color-ink);
|
|
338
|
+
font-size: 24px;
|
|
339
|
+
line-height: 1.32;
|
|
340
|
+
letter-spacing: -.035em;
|
|
341
|
+
overflow-wrap: anywhere;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.bb-ws-rail-head span {
|
|
345
|
+
display: block;
|
|
346
|
+
margin-top: 8px;
|
|
347
|
+
color: var(--bb-color-muted);
|
|
348
|
+
font-size: 12px;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.bb-ws-rail-head p {
|
|
352
|
+
margin: 12px 0 0;
|
|
353
|
+
color: var(--bb-color-muted);
|
|
354
|
+
font-size: 14px;
|
|
355
|
+
line-height: 1.6;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.bb-ws-rail-block {
|
|
359
|
+
border-bottom: 1px solid var(--bb-color-border);
|
|
360
|
+
padding-block: 22px;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.bb-ws-rail-block h3 {
|
|
364
|
+
margin: 0 0 10px;
|
|
365
|
+
color: var(--bb-color-ink);
|
|
366
|
+
font-size: 15px;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.bb-ws-rail-block p {
|
|
370
|
+
margin: 0;
|
|
371
|
+
color: var(--bb-color-muted);
|
|
372
|
+
font-size: 14px;
|
|
373
|
+
line-height: 1.6;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.bb-ws-definition {
|
|
377
|
+
display: grid;
|
|
378
|
+
grid-template-columns: 105px minmax(0, 1fr);
|
|
379
|
+
gap: 10px 12px;
|
|
380
|
+
margin: 0;
|
|
381
|
+
font-size: 13px;
|
|
382
|
+
line-height: 1.5;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.bb-ws-definition dt {
|
|
386
|
+
color: var(--bb-color-muted);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.bb-ws-definition dd {
|
|
390
|
+
margin: 0;
|
|
391
|
+
color: var(--bb-color-ink);
|
|
392
|
+
overflow-wrap: anywhere;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.bb-ws-detail-empty {
|
|
396
|
+
min-height: 60vh;
|
|
397
|
+
display: grid;
|
|
398
|
+
align-content: center;
|
|
399
|
+
justify-items: center;
|
|
400
|
+
color: var(--bb-color-muted);
|
|
401
|
+
text-align: center;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.bb-ws-detail-empty h2 {
|
|
405
|
+
margin: 14px 0 6px;
|
|
406
|
+
color: var(--bb-color-ink);
|
|
407
|
+
font-size: 20px;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.bb-ws-detail-empty p {
|
|
411
|
+
max-width: 270px;
|
|
412
|
+
margin: 0;
|
|
413
|
+
line-height: 1.65;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.bb-ws-empty-mark {
|
|
417
|
+
width: 44px;
|
|
418
|
+
height: 44px;
|
|
419
|
+
display: grid;
|
|
420
|
+
place-items: center;
|
|
421
|
+
border: 1px solid var(--bb-color-border);
|
|
422
|
+
border-radius: 50%;
|
|
423
|
+
color: var(--bb-color-muted);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/* Section title below a ledger */
|
|
427
|
+
.bb-ws-section-title {
|
|
428
|
+
display: grid;
|
|
429
|
+
gap: 6px;
|
|
430
|
+
margin: 48px 0 16px;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.bb-ws-section-title h2 {
|
|
434
|
+
margin: 0;
|
|
435
|
+
color: var(--bb-color-ink);
|
|
436
|
+
font-size: 22px;
|
|
437
|
+
letter-spacing: -.035em;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.bb-ws-section-title p {
|
|
441
|
+
margin: 0;
|
|
442
|
+
color: var(--bb-color-muted);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
@media (max-width: 760px) {
|
|
446
|
+
.bb-ws-page-head {
|
|
447
|
+
align-items: flex-start;
|
|
448
|
+
flex-direction: column;
|
|
449
|
+
gap: 16px;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.bb-ws-page-head h1 {
|
|
453
|
+
font-size: 34px;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.bb-ws-notice {
|
|
457
|
+
grid-template-columns: minmax(0, 1fr);
|
|
458
|
+
gap: 4px;
|
|
459
|
+
margin-block: 24px;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.bb-ws-source {
|
|
463
|
+
display: none;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
.bb-ws-summary,
|
|
467
|
+
.bb-ws-summary.is-2,
|
|
468
|
+
.bb-ws-summary.is-4,
|
|
469
|
+
.bb-ws-summary.is-5,
|
|
470
|
+
.bb-ws-summary.is-6 {
|
|
471
|
+
grid-template-columns: minmax(0, 1fr);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.bb-ws-metric,
|
|
475
|
+
.bb-ws-metric:first-child {
|
|
476
|
+
border-right: 0;
|
|
477
|
+
border-bottom: 1px solid var(--bb-color-border);
|
|
478
|
+
padding: 14px 0;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.bb-ws-metric:last-child {
|
|
482
|
+
border-bottom: 0;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Workspace kit: the organization edition's screen pattern as shared parts.
|
|
3
|
+
*
|
|
4
|
+
* Every Brainbase screen is built the same way — breadcrumb and page head,
|
|
5
|
+
* a notice about the source, actions, summary metrics, a ledger of rows the
|
|
6
|
+
* owner selects, and a right rail with the selected item's detail. The look
|
|
7
|
+
* comes from workspace-kit.css (organization design values through the
|
|
8
|
+
* `--bb-*` tokens). Builders take the host's document and return elements;
|
|
9
|
+
* they keep no state. Column widths are set by the caller's CSS class on the
|
|
10
|
+
* ledger, because the hosts' CSP forbids inline styles.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const WORKSPACE_KIT_CONTRACT_VERSION = 'brainbase.workspace-kit.v1';
|
|
14
|
+
|
|
15
|
+
export function makeWorkspaceElement(doc, tag, { className, text, attrs = {} } = {}) {
|
|
16
|
+
const element = doc.createElement(tag);
|
|
17
|
+
if (className) element.className = className;
|
|
18
|
+
if (text !== undefined && text !== null) element.textContent = String(text);
|
|
19
|
+
for (const [name, value] of Object.entries(attrs)) {
|
|
20
|
+
if (value === undefined || value === null || value === false) continue;
|
|
21
|
+
element.setAttribute(name, value === true ? '' : String(value));
|
|
22
|
+
}
|
|
23
|
+
return element;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const el = makeWorkspaceElement;
|
|
27
|
+
|
|
28
|
+
function appendContent(parent, doc, content) {
|
|
29
|
+
if (content === undefined || content === null || content === false) return;
|
|
30
|
+
if (Array.isArray(content)) {
|
|
31
|
+
for (const item of content) appendContent(parent, doc, item);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (typeof content === 'object' && typeof content.tagName === 'string') {
|
|
35
|
+
parent.append(content);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (typeof content === 'object' && 'text' in content) {
|
|
39
|
+
parent.append(el(doc, 'span', { className: content.className, text: content.text }));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
parent.append(el(doc, 'span', { text: String(content) }));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Breadcrumb, h1, lead, source label and actions, as on the organization screens. */
|
|
46
|
+
export function workspacePageHeader(doc, { crumbs = [], title, lead, source, actions = [] } = {}) {
|
|
47
|
+
const wrap = el(doc, 'div', { className: 'bb-ws-page' });
|
|
48
|
+
if (crumbs.length > 0) {
|
|
49
|
+
const breadcrumb = el(doc, 'nav', { className: 'bb-ws-breadcrumb', attrs: { 'aria-label': 'パンくず' } });
|
|
50
|
+
crumbs.forEach((crumb, index) => {
|
|
51
|
+
if (index > 0) breadcrumb.append(el(doc, 'span', { className: 'bb-ws-breadcrumb-separator', text: '/', attrs: { 'aria-hidden': 'true' } }));
|
|
52
|
+
breadcrumb.append(el(doc, 'span', { text: crumb }));
|
|
53
|
+
});
|
|
54
|
+
wrap.append(breadcrumb);
|
|
55
|
+
}
|
|
56
|
+
const head = el(doc, 'header', { className: 'bb-ws-page-head' });
|
|
57
|
+
const copy = el(doc, 'div', { className: 'bb-ws-page-copy' });
|
|
58
|
+
copy.append(el(doc, 'h1', { text: title }));
|
|
59
|
+
if (lead) copy.append(el(doc, 'p', { className: 'bb-ws-lead', text: lead }));
|
|
60
|
+
head.append(copy);
|
|
61
|
+
const side = el(doc, 'div', { className: 'bb-ws-page-side' });
|
|
62
|
+
if (source) side.append(el(doc, 'span', { className: 'bb-ws-source', text: source }));
|
|
63
|
+
if (actions.length > 0) side.append(workspaceActions(doc, actions));
|
|
64
|
+
if (source || actions.length > 0) head.append(side);
|
|
65
|
+
wrap.append(head);
|
|
66
|
+
return wrap;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A notice with a short label, like 接続範囲 on the organization screens. */
|
|
70
|
+
export function workspaceNotice(doc, { label, text, tone = 'info', role } = {}) {
|
|
71
|
+
const notice = el(doc, 'div', { className: `bb-ws-notice is-${tone}`, attrs: { role: role ?? (tone === 'info' ? undefined : 'alert') } });
|
|
72
|
+
if (label) notice.append(el(doc, 'strong', { text: label }));
|
|
73
|
+
appendContent(notice, doc, text);
|
|
74
|
+
return notice;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The notice a host passes to a part in place of (or in addition to) the
|
|
79
|
+
* part's own: `{ label, text }`, where `text` is a string or an element. Null
|
|
80
|
+
* when the host passed none.
|
|
81
|
+
*/
|
|
82
|
+
export function workspaceHostNotice(doc, notice) {
|
|
83
|
+
if (!notice || typeof notice !== 'object' || Array.isArray(notice)) return null;
|
|
84
|
+
const label = typeof notice.label === 'string' && notice.label.trim() ? notice.label.trim() : undefined;
|
|
85
|
+
return workspaceNotice(doc, { label, text: notice.text });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** A host's extra page-head buttons, `[{ text, variant, onClick, disabled }]`, as `workspaceActions` items. */
|
|
89
|
+
export function workspaceHostActions(actions) {
|
|
90
|
+
if (!Array.isArray(actions)) return [];
|
|
91
|
+
return actions
|
|
92
|
+
.filter((action) => action && typeof action === 'object' && typeof action.text === 'string' && action.text.trim())
|
|
93
|
+
.map(({ text, variant, onClick, disabled }) => ({ text, variant, onClick, disabled: disabled === true }));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function workspaceButton(doc, { text, variant = 'default', onClick, disabled = false, attrs = {} } = {}) {
|
|
97
|
+
const button = el(doc, 'button', {
|
|
98
|
+
className: `bb-ws-button${variant === 'primary' ? ' is-primary' : variant === 'danger' ? ' is-danger' : variant === 'quiet' ? ' is-quiet' : ''}`,
|
|
99
|
+
text,
|
|
100
|
+
attrs: { type: 'button', disabled, ...attrs },
|
|
101
|
+
});
|
|
102
|
+
if (typeof onClick === 'function') button.addEventListener('click', onClick);
|
|
103
|
+
return button;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function workspaceActions(doc, buttons = []) {
|
|
107
|
+
const actions = el(doc, 'div', { className: 'bb-ws-actions' });
|
|
108
|
+
for (const button of buttons) {
|
|
109
|
+
if (button) actions.append(typeof button.tagName === 'string' ? button : workspaceButton(doc, button));
|
|
110
|
+
}
|
|
111
|
+
return actions;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Summary metrics in one ruled row. `value` null means 未確認, never zero. */
|
|
115
|
+
export function workspaceMetrics(doc, items = [], { ariaLabel = '集計' } = {}) {
|
|
116
|
+
const summary = el(doc, 'section', { className: `bb-ws-summary is-${Math.min(Math.max(items.length, 1), 6)}`, attrs: { 'aria-label': ariaLabel } });
|
|
117
|
+
for (const item of items) {
|
|
118
|
+
const card = el(doc, 'div', { className: 'bb-ws-metric' });
|
|
119
|
+
card.append(
|
|
120
|
+
el(doc, 'small', { text: item.label }),
|
|
121
|
+
el(doc, 'strong', { text: item.value === null || item.value === undefined ? '未確認' : item.value }),
|
|
122
|
+
);
|
|
123
|
+
if (item.note) card.append(el(doc, 'span', { text: item.note }));
|
|
124
|
+
summary.append(card);
|
|
125
|
+
}
|
|
126
|
+
return summary;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// A readable name for a row: its first cell's text (a button with role=row has no name of its own).
|
|
130
|
+
function ledgerRowLabel(cells = []) {
|
|
131
|
+
const first = cells[0];
|
|
132
|
+
if (first === null || first === undefined) return undefined;
|
|
133
|
+
if (typeof first === 'object' && 'primary' in first) return String(first.primary);
|
|
134
|
+
if (typeof first === 'object' && 'text' in first) return String(first.text);
|
|
135
|
+
if (typeof first === 'object' && typeof first.tagName === 'string') return first.textContent || undefined;
|
|
136
|
+
return String(first);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A ledger: a header row and selectable rows. `className` sets the column
|
|
141
|
+
* template in the caller's CSS. A cell is text, an element, `{ text, className }`,
|
|
142
|
+
* or `{ primary, secondary }` for a name with its id underneath.
|
|
143
|
+
*/
|
|
144
|
+
export function workspaceLedger(doc, { columns = [], rows = [], className = '', ariaLabel, empty } = {}) {
|
|
145
|
+
const ledger = el(doc, 'div', { className: `bb-ws-ledger${className ? ` ${className}` : ''}`, attrs: { role: 'table', 'aria-label': ariaLabel } });
|
|
146
|
+
const head = el(doc, 'div', { className: 'bb-ws-ledger-row bb-ws-ledger-head', attrs: { role: 'row' } });
|
|
147
|
+
for (const column of columns) head.append(el(doc, 'span', { text: column, attrs: { role: 'columnheader' } }));
|
|
148
|
+
ledger.append(head);
|
|
149
|
+
if (rows.length === 0 && empty) {
|
|
150
|
+
ledger.append(el(doc, 'p', { className: 'bb-ws-ledger-empty', text: empty }));
|
|
151
|
+
return ledger;
|
|
152
|
+
}
|
|
153
|
+
for (const row of rows) {
|
|
154
|
+
const selectable = typeof row.onSelect === 'function';
|
|
155
|
+
const item = el(doc, selectable ? 'button' : 'div', {
|
|
156
|
+
className: `bb-ws-ledger-row${selectable ? ' is-selectable' : ''}${row.selected ? ' is-selected' : ''}${row.className ? ` ${row.className}` : ''}`,
|
|
157
|
+
attrs: {
|
|
158
|
+
type: selectable ? 'button' : undefined,
|
|
159
|
+
role: 'row',
|
|
160
|
+
'aria-pressed': selectable ? (row.selected ? 'true' : 'false') : undefined,
|
|
161
|
+
'aria-label': row.label ?? ledgerRowLabel(row.cells),
|
|
162
|
+
'data-key': row.key,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
for (const cell of row.cells ?? []) {
|
|
166
|
+
if (cell && typeof cell === 'object' && 'primary' in cell) {
|
|
167
|
+
const object = el(doc, 'span', { className: 'bb-ws-ledger-object', attrs: { role: 'cell' } });
|
|
168
|
+
object.append(el(doc, 'strong', { text: cell.primary }));
|
|
169
|
+
if (cell.secondary) object.append(el(doc, 'code', { text: cell.secondary }));
|
|
170
|
+
item.append(object);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const span = el(doc, 'span', { attrs: { role: 'cell' } });
|
|
174
|
+
if (cell && typeof cell === 'object' && typeof cell.tagName === 'string') span.append(cell);
|
|
175
|
+
else if (cell && typeof cell === 'object' && 'text' in cell) {
|
|
176
|
+
span.className = cell.className ?? '';
|
|
177
|
+
span.textContent = String(cell.text);
|
|
178
|
+
} else span.textContent = cell === null || cell === undefined ? '' : String(cell);
|
|
179
|
+
item.append(span);
|
|
180
|
+
}
|
|
181
|
+
if (selectable) item.addEventListener('click', () => row.onSelect(row.key));
|
|
182
|
+
ledger.append(item);
|
|
183
|
+
}
|
|
184
|
+
return ledger;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** The selected item's head in the right rail. */
|
|
188
|
+
export function workspaceRailHead(doc, { kicker, title, sub, lead } = {}) {
|
|
189
|
+
const head = el(doc, 'div', { className: 'bb-ws-rail-head' });
|
|
190
|
+
if (kicker) head.append(el(doc, 'small', { text: kicker }));
|
|
191
|
+
head.append(el(doc, 'h2', { text: title }));
|
|
192
|
+
if (sub) head.append(el(doc, 'span', { text: sub }));
|
|
193
|
+
if (lead) head.append(el(doc, 'p', { text: lead }));
|
|
194
|
+
return head;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function workspaceRailBlock(doc, { title, content, className } = {}) {
|
|
198
|
+
const block = el(doc, 'section', { className: `bb-ws-rail-block${className ? ` ${className}` : ''}`, attrs: { 'aria-label': title } });
|
|
199
|
+
if (title) block.append(el(doc, 'h3', { text: title }));
|
|
200
|
+
appendContent(block, doc, content);
|
|
201
|
+
return block;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Term and value pairs; a null value is shown as 未記録. */
|
|
205
|
+
export function workspaceDefinition(doc, pairs = []) {
|
|
206
|
+
const list = el(doc, 'dl', { className: 'bb-ws-definition' });
|
|
207
|
+
for (const [term, value] of pairs) {
|
|
208
|
+
list.append(el(doc, 'dt', { text: term }));
|
|
209
|
+
const dd = el(doc, 'dd');
|
|
210
|
+
appendContent(dd, doc, value === null || value === undefined || value === '' ? { text: '未記録', className: 'is-unrecorded' } : value);
|
|
211
|
+
list.append(dd);
|
|
212
|
+
}
|
|
213
|
+
return list;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function workspaceDetailEmpty(doc, { mark = '?', title, text } = {}) {
|
|
217
|
+
const empty = el(doc, 'div', { className: 'bb-ws-detail-empty' });
|
|
218
|
+
empty.append(el(doc, 'div', { className: 'bb-ws-empty-mark', text: mark, attrs: { 'aria-hidden': 'true' } }), el(doc, 'h2', { text: title }));
|
|
219
|
+
if (text) empty.append(el(doc, 'p', { text }));
|
|
220
|
+
return empty;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** A plain section title inside the workspace, below the ledger. */
|
|
224
|
+
export function workspaceSectionTitle(doc, { title, lead } = {}) {
|
|
225
|
+
const wrap = el(doc, 'div', { className: 'bb-ws-section-title' });
|
|
226
|
+
wrap.append(el(doc, 'h2', { text: title }));
|
|
227
|
+
if (lead) wrap.append(el(doc, 'p', { text: lead }));
|
|
228
|
+
return wrap;
|
|
229
|
+
}
|