@booboo-brain/panel 0.5.4 → 0.5.6
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/index.d.ts +2 -1
- package/dist/index.js +104 -36
- package/dist-app/assets/index-CMTXU3r8.js +1130 -0
- package/dist-app/index.html +22 -22
- package/package.json +1 -1
- package/dist-app/assets/index-CgJZeTDV.js +0 -1079
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
|
|
3
3
|
type ApiFn = (path: string, init?: RequestInit) => Promise<any>;
|
|
4
|
-
declare function Panel({ api }?: {
|
|
4
|
+
declare function Panel({ api, theme }?: {
|
|
5
5
|
api?: ApiFn;
|
|
6
|
+
theme?: "dark" | "light";
|
|
6
7
|
}): react.JSX.Element;
|
|
7
8
|
|
|
8
9
|
declare const PANEL_VERSION: string;
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { orgBootSlice, relTime } from "@booboo-brain/spec";
|
|
|
5
5
|
// src/panel-css.ts
|
|
6
6
|
var PANEL_CSS = String.raw`
|
|
7
7
|
/* GENERATED from design/tokens.json by scripts/gen-tokens.mjs — DO NOT EDIT */
|
|
8
|
-
|
|
8
|
+
.pnl, .pnl-fatal {
|
|
9
9
|
--bg: #06080e;
|
|
10
10
|
--bg-lift: #0a0d15;
|
|
11
11
|
--card: #0f131c;
|
|
@@ -59,7 +59,12 @@ var PANEL_CSS = String.raw`
|
|
|
59
59
|
the dachshund's collar), a slow aurora breathing behind everything, cards
|
|
60
60
|
that lift and settle, numbers that count up. Dark by default. */
|
|
61
61
|
|
|
62
|
-
:root
|
|
62
|
+
/* Scoped to the panel's own roots, NEVER :root — see scripts/gen-tokens.mjs.
|
|
63
|
+
A custom property on :root is shadowed by any ancestor declaring the same
|
|
64
|
+
name, so a host whose shell declares --bg-1/--line/--gold silently repaints
|
|
65
|
+
the board. Declaring them here means nothing can sit between these names and
|
|
66
|
+
the elements that read them. */
|
|
67
|
+
.pnl, .pnl-fatal {
|
|
63
68
|
/* THE STAFF BOARD — a master-key rack, not a dashboard.
|
|
64
69
|
Structure comes from two real artefacts: a master-key hierarchy (passe
|
|
65
70
|
général → passe partiel → cylinder, which is literally how a hotel is
|
|
@@ -118,8 +123,10 @@ var PANEL_CSS = String.raw`
|
|
|
118
123
|
}
|
|
119
124
|
|
|
120
125
|
/* DARK — the wine-and-brass board, now one toggle away instead of the default.
|
|
121
|
-
Same structure, same shadows-as-depth logic, inverted ground.
|
|
122
|
-
:root
|
|
126
|
+
Same structure, same shadows-as-depth logic, inverted ground.
|
|
127
|
+
Scoped to the panel's own root (not :root) for two reasons: the panel must
|
|
128
|
+
not read a HOST's data-theme as its own, and it must not write one either. */
|
|
129
|
+
.pnl[data-theme="dark"], .pnl-fatal[data-theme="dark"] {
|
|
123
130
|
--bg: var(--wine);
|
|
124
131
|
--bg-1: var(--plate);
|
|
125
132
|
--bg-2: var(--wine2);
|
|
@@ -146,15 +153,19 @@ var PANEL_CSS = String.raw`
|
|
|
146
153
|
--sh-2: 0 2px 4px rgba(0, 0, 0, .5), 0 16px 34px -18px rgba(0, 0, 0, .85);
|
|
147
154
|
--sh-3: 0 4px 8px rgba(0, 0, 0, .5), 0 22px 48px -18px rgba(0, 0, 0, .9);
|
|
148
155
|
}
|
|
149
|
-
[data-theme="dark"] body
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
156
|
+
/* The [data-theme="dark"] body rule that used to live here is GONE. A mounted
|
|
157
|
+
component has no business repainting its host's <body> — in Dionisos OS it
|
|
158
|
+
turned the cockpit's body white while the cards stayed dark, which is half of
|
|
159
|
+
what "split-brain" looked like. The standalone app paints its own body in
|
|
160
|
+
app/index.html, which is the page that actually owns it. */
|
|
161
|
+
.pnl[data-theme="dark"] .ag { background: linear-gradient(168deg, var(--plate-lift), #180e16); }
|
|
162
|
+
.pnl[data-theme="dark"] .bar, .pnl[data-theme="dark"] .tabs { background: rgba(11, 5, 9, 0.72); }
|
|
163
|
+
.pnl[data-theme="dark"] .rack .wt { background: #fff; border-color: transparent; }
|
|
164
|
+
.pnl[data-theme="dark"] .pnl-stars { opacity: .45; }
|
|
154
165
|
|
|
155
|
-
* { box-sizing: border-box; }
|
|
156
|
-
body { font-family: var(--font); color: var(--ink); background: var(--bg); overflow-x: hidden; }
|
|
166
|
+
.pnl, .pnl-fatal, .pnl *, .pnl-fatal * { box-sizing: border-box; }
|
|
157
167
|
|
|
168
|
+
.pnl, .pnl-fatal { font-family: var(--font); color: var(--ink); background: var(--bg); }
|
|
158
169
|
.pnl { display: flex; flex-direction: column; position: relative; overflow: hidden; }
|
|
159
170
|
|
|
160
171
|
/* the ground — warm wine light pooling from the top-left, exactly as the hero
|
|
@@ -422,7 +433,8 @@ body { font-family: var(--font); color: var(--ink); background: var(--bg); overf
|
|
|
422
433
|
.pending-item:hover i { background: var(--warn); color: var(--bg-1); }
|
|
423
434
|
|
|
424
435
|
/* the lane lights up as a drop target, so a near-miss is impossible */
|
|
425
|
-
.oc-row.lanes > .oc-child.lane-over
|
|
436
|
+
.oc-row.lanes > .oc-child.lane-over,
|
|
437
|
+
.oc-row.solo-pack > .oc-child.lane-over {
|
|
426
438
|
border-color: var(--accent); background: var(--accent-dim);
|
|
427
439
|
box-shadow: 0 0 0 3px var(--accent-dim), var(--sh-2);
|
|
428
440
|
}
|
|
@@ -585,12 +597,21 @@ body { font-family: var(--font); color: var(--ink); background: var(--bg); overf
|
|
|
585
597
|
row — 2,400px natural width, which fit-to-width then scaled to 52% and made
|
|
586
598
|
every plate unreadable. Rank IV wraps; the board stays legible. */
|
|
587
599
|
grid-template-columns: max-content var(--rail-w, 56px) minmax(420px, 940px);
|
|
588
|
-
|
|
600
|
+
/* Row 2 carries the PACK (childless rank-III units). It is a second row and
|
|
601
|
+
not a second area on row 1 because two items cannot share one named area
|
|
602
|
+
without overlapping — and the gm/rail cells are deliberately left EMPTY on
|
|
603
|
+
row 2 so the GM stays in row 1 rather than stretching down the whole board
|
|
604
|
+
(the C18 defect, in reverse: there the lanes spanned two rows and pinned
|
|
605
|
+
the GM to the top of the first). */
|
|
606
|
+
grid-template-areas:
|
|
607
|
+
"gm rail lanes"
|
|
608
|
+
". . pack";
|
|
589
609
|
align-items: start;
|
|
590
610
|
}
|
|
591
611
|
.cascade > .ocn > .casc-head { grid-area: gm; display: flex; flex-direction: column; align-items: stretch; }
|
|
592
612
|
.cascade > .ocn > .oc-down { grid-area: rail; }
|
|
593
613
|
.cascade > .ocn > .oc-row.lanes { grid-area: lanes; }
|
|
614
|
+
.cascade > .ocn > .oc-row.solo-pack { grid-area: pack; }
|
|
594
615
|
|
|
595
616
|
/* the SVG rail plane — sits under the plates, never intercepts a click */
|
|
596
617
|
.rails { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: visible; width: 100%; height: 100%; }
|
|
@@ -631,6 +652,36 @@ body { font-family: var(--font); color: var(--ink); background: var(--bg); overf
|
|
|
631
652
|
transition: border-color .25s ease, box-shadow .35s var(--ease);
|
|
632
653
|
}
|
|
633
654
|
.oc-row.lanes > .oc-child:hover { border-color: var(--line-2, #d9d3c9); box-shadow: var(--sh-2); }
|
|
655
|
+
|
|
656
|
+
/* ── THE PACK: rank-III units that have no staff ───────────────────────────
|
|
657
|
+
A lane is a shelf for a department AND ITS PEOPLE. A unit with nobody under
|
|
658
|
+
it has no shelf to fill — it is a card, and 43 cards each claiming a
|
|
659
|
+
940px-wide tray is what turned the live fleet into a 12,000px queue
|
|
660
|
+
(GAPS C34). They pack instead: same tray material, sized to the card, wrapped
|
|
661
|
+
into rows. Still drop targets, still railed. */
|
|
662
|
+
.oc-row.solo-pack {
|
|
663
|
+
display: grid;
|
|
664
|
+
grid-template-columns: repeat(auto-fill, minmax(278px, 1fr));
|
|
665
|
+
gap: 14px;
|
|
666
|
+
width: 100%;
|
|
667
|
+
margin-top: 14px;
|
|
668
|
+
align-items: stretch;
|
|
669
|
+
}
|
|
670
|
+
.oc-row.solo-pack > .oc-child {
|
|
671
|
+
position: relative;
|
|
672
|
+
border: 1px solid var(--line);
|
|
673
|
+
border-radius: 18px;
|
|
674
|
+
background: var(--surface-tray);
|
|
675
|
+
padding: 14px;
|
|
676
|
+
transition: border-color .25s ease, box-shadow .35s var(--ease);
|
|
677
|
+
}
|
|
678
|
+
.oc-row.solo-pack > .oc-child:hover { border-color: var(--line-2, #d9d3c9); box-shadow: var(--sh-2); }
|
|
679
|
+
/* the pack owns its connectors, exactly as the lanes do */
|
|
680
|
+
.oc-row.solo-pack > .oc-child::before,
|
|
681
|
+
.oc-row.solo-pack > .oc-child::after { display: none; }
|
|
682
|
+
.oc-row.solo-pack > .oc-child > .ocn > .oc-down { display: none; }
|
|
683
|
+
.oc-row.solo-pack > .oc-child > .ocn { display: block; }
|
|
684
|
+
.oc-row.solo-pack > .oc-child > .ocn > .ag { width: 100%; }
|
|
634
685
|
@media (prefers-reduced-motion: reduce) {
|
|
635
686
|
.oc-row.lanes > .oc-child:hover { transform: none; }
|
|
636
687
|
}
|
|
@@ -1161,17 +1212,18 @@ function readTheme() {
|
|
|
1161
1212
|
return "light";
|
|
1162
1213
|
}
|
|
1163
1214
|
}
|
|
1164
|
-
function useTheme() {
|
|
1215
|
+
function useTheme(pinned) {
|
|
1165
1216
|
const [theme, setTheme] = useState(readTheme);
|
|
1166
1217
|
const chosen = useRef(false);
|
|
1167
1218
|
useEffect(() => {
|
|
1168
|
-
|
|
1219
|
+
if (pinned) return;
|
|
1169
1220
|
if (!chosen.current) return;
|
|
1170
1221
|
try {
|
|
1171
1222
|
localStorage.setItem(THEME_KEY, theme);
|
|
1172
1223
|
} catch {
|
|
1173
1224
|
}
|
|
1174
|
-
}, [theme]);
|
|
1225
|
+
}, [theme, pinned]);
|
|
1226
|
+
if (pinned) return [pinned, null];
|
|
1175
1227
|
return [theme, () => {
|
|
1176
1228
|
chosen.current = true;
|
|
1177
1229
|
setTheme((t) => t === "dark" ? "light" : "dark");
|
|
@@ -1527,6 +1579,9 @@ function ChartNode({
|
|
|
1527
1579
|
}) {
|
|
1528
1580
|
const kidsRaw = org.agents.filter((c) => c.parent === a.id && c.kind !== "automation");
|
|
1529
1581
|
const kids = depth === 0 ? [...kidsRaw].sort((x, y) => x.id.localeCompare(y.id)) : kidsRaw;
|
|
1582
|
+
const hasStaff = (k) => org.agents.some((x) => x.parent === k.id && x.kind !== "automation");
|
|
1583
|
+
const laneKids = depth === 0 ? kids.filter(hasStaff) : kids;
|
|
1584
|
+
const soloKids = depth === 0 ? kids.filter((k) => !hasStaff(k)) : [];
|
|
1530
1585
|
const machines = (() => {
|
|
1531
1586
|
const out = [];
|
|
1532
1587
|
const walk = (pid) => {
|
|
@@ -1652,17 +1707,30 @@ function ChartNode({
|
|
|
1652
1707
|
" staff \xB7 folded to department level \u2014 click to expand"
|
|
1653
1708
|
]
|
|
1654
1709
|
}
|
|
1655
|
-
) : /* @__PURE__ */
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1710
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1711
|
+
/* @__PURE__ */ jsx("div", { className: `oc-row${depth > 0 && kids.length > 3 ? " wrap" : ""}${depth === 0 ? " lanes" : ""}`, children: laneKids.map((k, i) => /* @__PURE__ */ jsx(
|
|
1712
|
+
Lane,
|
|
1713
|
+
{
|
|
1714
|
+
laneId: k.id,
|
|
1715
|
+
isLane: depth === 0,
|
|
1716
|
+
dragId: cardProps.dragId,
|
|
1717
|
+
onDropOn: cardProps.onDropOn,
|
|
1718
|
+
children: /* @__PURE__ */ jsx(ChartNode, { org, a: k, depth: depth + 1, order: i, ...cardProps })
|
|
1719
|
+
},
|
|
1720
|
+
k.id
|
|
1721
|
+
)) }),
|
|
1722
|
+
soloKids.length > 0 && /* @__PURE__ */ jsx("div", { className: "oc-row solo-pack", children: soloKids.map((k, i) => /* @__PURE__ */ jsx(
|
|
1723
|
+
Lane,
|
|
1724
|
+
{
|
|
1725
|
+
laneId: k.id,
|
|
1726
|
+
isLane: true,
|
|
1727
|
+
dragId: cardProps.dragId,
|
|
1728
|
+
onDropOn: cardProps.onDropOn,
|
|
1729
|
+
children: /* @__PURE__ */ jsx(ChartNode, { org, a: k, depth: depth + 1, order: laneKids.length + i, ...cardProps })
|
|
1730
|
+
},
|
|
1731
|
+
k.id
|
|
1732
|
+
)) })
|
|
1733
|
+
] })
|
|
1666
1734
|
] })
|
|
1667
1735
|
] });
|
|
1668
1736
|
}
|
|
@@ -2422,7 +2490,7 @@ function GraphScreen({ hasSnapshot }) {
|
|
|
2422
2490
|
] });
|
|
2423
2491
|
return /* @__PURE__ */ jsx("div", { className: "graph-wrap", children: /* @__PURE__ */ jsx("iframe", { className: "graph-frame", src: "/view/?file=/snapshot.json", title: "Booboo 3D brain" }) });
|
|
2424
2492
|
}
|
|
2425
|
-
function App() {
|
|
2493
|
+
function App({ theme: pinnedTheme }) {
|
|
2426
2494
|
const api = useApi();
|
|
2427
2495
|
const [tab, param] = useRoute();
|
|
2428
2496
|
const [saved, setSaved] = useState(null);
|
|
@@ -2553,11 +2621,11 @@ function App() {
|
|
|
2553
2621
|
const nodeCount = useCountUp(stats?.nodes ?? 0, 1200);
|
|
2554
2622
|
const memTotal = useCountUp(totals?.mem ?? 0, 1100);
|
|
2555
2623
|
const repTotal = useCountUp(totals?.rep ?? 0, 1300);
|
|
2556
|
-
const [theme, toggleTheme] = useTheme();
|
|
2624
|
+
const [theme, toggleTheme] = useTheme(pinnedTheme);
|
|
2557
2625
|
const [showLaw, setShowLaw] = useState(false);
|
|
2558
|
-
if (err && !draft) return /* @__PURE__ */ jsx("div", { className: "pnl-fatal", children: err });
|
|
2559
|
-
if (!draft) return /* @__PURE__ */ jsx("div", { className: "pnl-fatal calm", children: "waking the organigram\u2026" });
|
|
2560
|
-
return /* @__PURE__ */ jsxs("div", { className: "pnl", children: [
|
|
2626
|
+
if (err && !draft) return /* @__PURE__ */ jsx("div", { className: "pnl-fatal", "data-theme": theme, children: err });
|
|
2627
|
+
if (!draft) return /* @__PURE__ */ jsx("div", { className: "pnl-fatal calm", "data-theme": theme, children: "waking the organigram\u2026" });
|
|
2628
|
+
return /* @__PURE__ */ jsxs("div", { className: "pnl", "data-theme": theme, children: [
|
|
2561
2629
|
/* @__PURE__ */ jsx("div", { className: "pnl-aurora", "aria-hidden": true }),
|
|
2562
2630
|
/* @__PURE__ */ jsx(Constellation, {}),
|
|
2563
2631
|
/* @__PURE__ */ jsxs("header", { className: "bar", children: [
|
|
@@ -2594,7 +2662,7 @@ function App() {
|
|
|
2594
2662
|
children: "\u2696 show the law"
|
|
2595
2663
|
}
|
|
2596
2664
|
),
|
|
2597
|
-
/* @__PURE__ */ jsx("button", { className: "btn ghost theme-toggle", title: "light / dark", "aria-label": "toggle light or dark theme", onClick: toggleTheme, children: theme === "dark" ? "\u2600" : "\u263E" }),
|
|
2665
|
+
toggleTheme && /* @__PURE__ */ jsx("button", { className: "btn ghost theme-toggle", title: "light / dark", "aria-label": "toggle light or dark theme", onClick: toggleTheme, children: theme === "dark" ? "\u2600" : "\u263E" }),
|
|
2598
2666
|
changes.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2599
2667
|
/* @__PURE__ */ jsxs("span", { className: "bar-draft", children: [
|
|
2600
2668
|
changes.length,
|
|
@@ -2653,17 +2721,17 @@ function App() {
|
|
|
2653
2721
|
] }, tab + (param ?? ""))
|
|
2654
2722
|
] });
|
|
2655
2723
|
}
|
|
2656
|
-
function Panel({ api = defaultApi } = {}) {
|
|
2724
|
+
function Panel({ api = defaultApi, theme } = {}) {
|
|
2657
2725
|
return /* @__PURE__ */ jsxs(ApiCtx.Provider, { value: api, children: [
|
|
2658
2726
|
/* @__PURE__ */ jsx("style", { children: PANEL_CSS }),
|
|
2659
|
-
/* @__PURE__ */ jsx(App, {})
|
|
2727
|
+
/* @__PURE__ */ jsx(App, { theme })
|
|
2660
2728
|
] });
|
|
2661
2729
|
}
|
|
2662
2730
|
|
|
2663
2731
|
// package.json
|
|
2664
2732
|
var package_default = {
|
|
2665
2733
|
name: "@booboo-brain/panel",
|
|
2666
|
-
version: "0.5.
|
|
2734
|
+
version: "0.5.6",
|
|
2667
2735
|
description: "Booboo panel \u2014 the organigram. Run your agents like a company: a drag-drop hierarchy your agents boot from, with buckets, reports, rules and the 3D graph, over one org file + snapshot.",
|
|
2668
2736
|
license: "MIT",
|
|
2669
2737
|
repository: {
|