@flyingrobots/bijou 0.3.0 → 0.5.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/README.md +5 -4
- package/dist/core/components/dag-source.d.ts +64 -0
- package/dist/core/components/dag-source.d.ts.map +1 -0
- package/dist/core/components/dag-source.js +227 -0
- package/dist/core/components/dag-source.js.map +1 -0
- package/dist/core/components/dag.d.ts +20 -4
- package/dist/core/components/dag.d.ts.map +1 -1
- package/dist/core/components/dag.js +32 -125
- package/dist/core/components/dag.js.map +1 -1
- package/dist/core/components/index.d.ts +4 -2
- package/dist/core/components/index.d.ts.map +1 -1
- package/dist/core/components/index.js +2 -1
- package/dist/core/components/index.js.map +1 -1
- package/dist/core/forms/filter.d.ts +16 -0
- package/dist/core/forms/filter.d.ts.map +1 -0
- package/dist/core/forms/filter.js +199 -0
- package/dist/core/forms/filter.js.map +1 -0
- package/dist/core/forms/index.d.ts +4 -0
- package/dist/core/forms/index.d.ts.map +1 -1
- package/dist/core/forms/index.js +2 -0
- package/dist/core/forms/index.js.map +1 -1
- package/dist/core/forms/textarea.d.ts +12 -0
- package/dist/core/forms/textarea.d.ts.map +1 -0
- package/dist/core/forms/textarea.js +232 -0
- package/dist/core/forms/textarea.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,10 +4,11 @@ Themed terminal components for CLIs, loggers, and scripts — graceful degradati
|
|
|
4
4
|
|
|
5
5
|
**Zero dependencies. Hexagonal architecture. Works everywhere.**
|
|
6
6
|
|
|
7
|
-
## What's New in 0.
|
|
7
|
+
## What's New in 0.5.0?
|
|
8
8
|
|
|
9
|
-
- **`
|
|
10
|
-
-
|
|
9
|
+
- **`DagSource` adapter** — bring your own graph representation (database, API, adjacency matrix). DAG rendering no longer requires `DagNode[]`
|
|
10
|
+
- **Traversal-based slicing** — `dagSlice()` BFS-walks via `has()`/`children()`/`parents()`, never enumerates the full graph
|
|
11
|
+
- **Composable slices** — `dagSlice()` returns a `SlicedDagSource` when given `DagSource`, enabling slice-of-slice chains
|
|
11
12
|
|
|
12
13
|
See the [CHANGELOG](https://github.com/flyingrobots/bijou/blob/main/docs/CHANGELOG.md) for the full release history.
|
|
13
14
|
|
|
@@ -40,7 +41,7 @@ console.log(box('Hello, world!'));
|
|
|
40
41
|
`badge()`, `alert()`, `kbd()`, `skeleton()` — status indicators and UI primitives.
|
|
41
42
|
|
|
42
43
|
### Data
|
|
43
|
-
`table()`, `tree()`, `accordion()`, `timeline()` — structured data display.
|
|
44
|
+
`table()`, `tree()`, `accordion()`, `timeline()`, `dag()`, `dagSlice()`, `dagLayout()` — structured data display and DAG rendering with `DagSource` adapter for external graphs.
|
|
44
45
|
|
|
45
46
|
### Navigation
|
|
46
47
|
`tabs()`, `breadcrumb()`, `stepper()`, `paginator()` — wayfinding components.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { TokenValue } from '../theme/tokens.js';
|
|
2
|
+
import type { DagNode } from './dag.js';
|
|
3
|
+
/**
|
|
4
|
+
* Adapter interface for accessing graph data. Decouples DAG rendering
|
|
5
|
+
* from any specific in-memory representation. Implementations can wrap
|
|
6
|
+
* arrays, databases, APIs, or any other graph store.
|
|
7
|
+
*
|
|
8
|
+
* A DagSource may represent an unbounded graph — it has no enumeration
|
|
9
|
+
* method. Use `dagSlice()` to BFS-walk from a focus node and produce
|
|
10
|
+
* a bounded `SlicedDagSource` that the renderer can consume.
|
|
11
|
+
*/
|
|
12
|
+
export interface DagSource {
|
|
13
|
+
/** Returns true if a node with this ID exists in the graph. */
|
|
14
|
+
has(id: string): boolean;
|
|
15
|
+
/** Human-readable label for a node. */
|
|
16
|
+
label(id: string): string;
|
|
17
|
+
/** Child node IDs (outgoing edges). */
|
|
18
|
+
children(id: string): readonly string[];
|
|
19
|
+
/**
|
|
20
|
+
* Parent node IDs (incoming edges). Required for ancestor traversal
|
|
21
|
+
* in `dagSlice()`. Without this, only `direction: 'descendants'` is
|
|
22
|
+
* supported.
|
|
23
|
+
*/
|
|
24
|
+
parents?(id: string): readonly string[];
|
|
25
|
+
/** Optional badge text for a node. */
|
|
26
|
+
badge?(id: string): string | undefined;
|
|
27
|
+
/** Optional per-node color/style token. */
|
|
28
|
+
token?(id: string): TokenValue | undefined;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A bounded DagSource produced by `sliceSource()`. Extends DagSource
|
|
32
|
+
* with `ids()` so the renderer can enumerate the finite node set.
|
|
33
|
+
*/
|
|
34
|
+
export interface SlicedDagSource extends DagSource {
|
|
35
|
+
/** All node IDs in this bounded slice. */
|
|
36
|
+
ids(): readonly string[];
|
|
37
|
+
/** Whether this node is a ghost (boundary placeholder). */
|
|
38
|
+
ghost(id: string): boolean;
|
|
39
|
+
/** Ghost label override (e.g., "... 3 ancestors"). */
|
|
40
|
+
ghostLabel(id: string): string | undefined;
|
|
41
|
+
}
|
|
42
|
+
/** Options for `dagSlice()`. */
|
|
43
|
+
export interface DagSliceOptions {
|
|
44
|
+
direction?: 'ancestors' | 'descendants' | 'both';
|
|
45
|
+
depth?: number;
|
|
46
|
+
}
|
|
47
|
+
/** Returns true if the value implements the `DagSource` interface. */
|
|
48
|
+
export declare function isDagSource(value: unknown): value is DagSource;
|
|
49
|
+
/** Returns true if the value is a `SlicedDagSource` (bounded, with `ids()`). */
|
|
50
|
+
export declare function isSlicedDagSource(value: unknown): value is SlicedDagSource;
|
|
51
|
+
/** Wraps a `DagNode[]` as a `SlicedDagSource`. Already bounded. */
|
|
52
|
+
export declare function arraySource(nodes: DagNode[]): SlicedDagSource;
|
|
53
|
+
/** @internal Converts a `SlicedDagSource` to `DagNode[]` for internal renderers. */
|
|
54
|
+
export declare function materialize(source: SlicedDagSource): DagNode[];
|
|
55
|
+
/**
|
|
56
|
+
* BFS-walks a `DagSource` from a focus node and returns a bounded
|
|
57
|
+
* `SlicedDagSource` containing only the neighborhood. Ghost nodes are
|
|
58
|
+
* injected at depth boundaries.
|
|
59
|
+
*
|
|
60
|
+
* Never calls `ids()` on the source — works purely via traversal.
|
|
61
|
+
* For ancestor/both directions, `source.parents()` must be provided.
|
|
62
|
+
*/
|
|
63
|
+
export declare function sliceSource(source: DagSource, focus: string, opts?: DagSliceOptions): SlicedDagSource;
|
|
64
|
+
//# sourceMappingURL=dag-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-source.d.ts","sourceRoot":"","sources":["../../../src/core/components/dag-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAIxC;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAEzB,uCAAuC;IACvC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IAE1B,uCAAuC;IACvC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAExC;;;;OAIG;IACH,OAAO,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAExC,sCAAsC;IACtC,KAAK,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAEvC,2CAA2C;IAC3C,KAAK,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;CAC5C;AAED;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,0CAA0C;IAC1C,GAAG,IAAI,SAAS,MAAM,EAAE,CAAC;IAEzB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAE3B,sDAAsD;IACtD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC5C;AAED,gCAAgC;AAChC,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,MAAM,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,sEAAsE;AACtE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAS9D;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAO1E;AAID,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,eAAe,CA2B7D;AAID,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,EAAE,CAqB9D;AAuBD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,eAAe,GACrB,eAAe,CAsIjB"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// ── Type Guard ──────────────────────────────────────────────────────
|
|
2
|
+
/** Returns true if the value implements the `DagSource` interface. */
|
|
3
|
+
export function isDagSource(value) {
|
|
4
|
+
return (typeof value === 'object' &&
|
|
5
|
+
value !== null &&
|
|
6
|
+
!Array.isArray(value) &&
|
|
7
|
+
typeof value.has === 'function' &&
|
|
8
|
+
typeof value.label === 'function' &&
|
|
9
|
+
typeof value.children === 'function');
|
|
10
|
+
}
|
|
11
|
+
/** Returns true if the value is a `SlicedDagSource` (bounded, with `ids()`). */
|
|
12
|
+
export function isSlicedDagSource(value) {
|
|
13
|
+
return (isDagSource(value) &&
|
|
14
|
+
typeof value.ids === 'function' &&
|
|
15
|
+
typeof value.ghost === 'function' &&
|
|
16
|
+
typeof value.ghostLabel === 'function');
|
|
17
|
+
}
|
|
18
|
+
// ── arraySource ─────────────────────────────────────────────────────
|
|
19
|
+
/** Wraps a `DagNode[]` as a `SlicedDagSource`. Already bounded. */
|
|
20
|
+
export function arraySource(nodes) {
|
|
21
|
+
const map = new Map();
|
|
22
|
+
for (const n of nodes)
|
|
23
|
+
map.set(n.id, n);
|
|
24
|
+
// Pre-compute parent map
|
|
25
|
+
const parentMap = new Map();
|
|
26
|
+
for (const n of nodes) {
|
|
27
|
+
if (!parentMap.has(n.id))
|
|
28
|
+
parentMap.set(n.id, []);
|
|
29
|
+
for (const c of n.edges ?? []) {
|
|
30
|
+
if (!parentMap.has(c))
|
|
31
|
+
parentMap.set(c, []);
|
|
32
|
+
parentMap.get(c).push(n.id);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const idList = Object.freeze(nodes.map(n => n.id));
|
|
36
|
+
return {
|
|
37
|
+
ids: () => idList,
|
|
38
|
+
has: (id) => map.has(id),
|
|
39
|
+
label: (id) => map.get(id)?.label ?? id,
|
|
40
|
+
children: (id) => [...(map.get(id)?.edges ?? [])],
|
|
41
|
+
parents: (id) => [...(parentMap.get(id) ?? [])],
|
|
42
|
+
badge: (id) => map.get(id)?.badge,
|
|
43
|
+
token: (id) => map.get(id)?.token,
|
|
44
|
+
ghost: (id) => map.get(id)?._ghost ?? false,
|
|
45
|
+
ghostLabel: (id) => map.get(id)?._ghostLabel,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// ── materialize ─────────────────────────────────────────────────────
|
|
49
|
+
/** @internal Converts a `SlicedDagSource` to `DagNode[]` for internal renderers. */
|
|
50
|
+
export function materialize(source) {
|
|
51
|
+
const ids = source.ids();
|
|
52
|
+
const nodes = [];
|
|
53
|
+
for (const id of ids) {
|
|
54
|
+
const children = source.children(id);
|
|
55
|
+
const node = {
|
|
56
|
+
id,
|
|
57
|
+
label: source.label(id),
|
|
58
|
+
edges: children.length > 0 ? [...children] : undefined,
|
|
59
|
+
};
|
|
60
|
+
const badge = source.badge?.(id);
|
|
61
|
+
if (badge !== undefined)
|
|
62
|
+
node.badge = badge;
|
|
63
|
+
const token = source.token?.(id);
|
|
64
|
+
if (token !== undefined)
|
|
65
|
+
node.token = token;
|
|
66
|
+
if (source.ghost(id)) {
|
|
67
|
+
node._ghost = true;
|
|
68
|
+
node._ghostLabel = source.ghostLabel(id);
|
|
69
|
+
}
|
|
70
|
+
nodes.push(node);
|
|
71
|
+
}
|
|
72
|
+
return nodes;
|
|
73
|
+
}
|
|
74
|
+
// ── emptySource ─────────────────────────────────────────────────────
|
|
75
|
+
const EMPTY_IDS = Object.freeze([]);
|
|
76
|
+
/** @internal Singleton empty source for missing focus nodes. */
|
|
77
|
+
const EMPTY_SOURCE = Object.freeze({
|
|
78
|
+
ids: () => EMPTY_IDS,
|
|
79
|
+
has: () => false,
|
|
80
|
+
label: () => '',
|
|
81
|
+
children: () => EMPTY_IDS,
|
|
82
|
+
ghost: () => false,
|
|
83
|
+
ghostLabel: () => undefined,
|
|
84
|
+
});
|
|
85
|
+
// ── Ghost ID Prefixes ───────────────────────────────────────────────
|
|
86
|
+
const GHOST_ANCESTORS_PREFIX = '__ghost_ancestors_';
|
|
87
|
+
const GHOST_DESCENDANTS_PREFIX = '__ghost_descendants_';
|
|
88
|
+
// ── sliceSource ─────────────────────────────────────────────────────
|
|
89
|
+
/**
|
|
90
|
+
* BFS-walks a `DagSource` from a focus node and returns a bounded
|
|
91
|
+
* `SlicedDagSource` containing only the neighborhood. Ghost nodes are
|
|
92
|
+
* injected at depth boundaries.
|
|
93
|
+
*
|
|
94
|
+
* Never calls `ids()` on the source — works purely via traversal.
|
|
95
|
+
* For ancestor/both directions, `source.parents()` must be provided.
|
|
96
|
+
*/
|
|
97
|
+
export function sliceSource(source, focus, opts) {
|
|
98
|
+
const explicitDirection = opts?.direction;
|
|
99
|
+
const direction = explicitDirection ?? 'both';
|
|
100
|
+
const maxDepth = opts?.depth ?? Infinity;
|
|
101
|
+
if (!source.has(focus))
|
|
102
|
+
return EMPTY_SOURCE;
|
|
103
|
+
const included = new Set();
|
|
104
|
+
const ghostNodes = new Map();
|
|
105
|
+
// Precomputed reverse map for when source.parents is absent
|
|
106
|
+
const derivedParents = new Map();
|
|
107
|
+
// BFS ancestors
|
|
108
|
+
if (direction === 'ancestors' || direction === 'both') {
|
|
109
|
+
if (!source.parents) {
|
|
110
|
+
if (explicitDirection === 'ancestors') {
|
|
111
|
+
throw new Error('[bijou] dagSlice(): source.parents() is required for ancestor traversal');
|
|
112
|
+
}
|
|
113
|
+
// direction defaulted to 'both' — silently downgrade to descendants-only
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const getParents = source.parents.bind(source);
|
|
117
|
+
const queue = [[focus, 0]];
|
|
118
|
+
const visited = new Set();
|
|
119
|
+
while (queue.length > 0) {
|
|
120
|
+
const [id, depth] = queue.shift();
|
|
121
|
+
if (visited.has(id))
|
|
122
|
+
continue;
|
|
123
|
+
visited.add(id);
|
|
124
|
+
included.add(id);
|
|
125
|
+
if (depth < maxDepth) {
|
|
126
|
+
for (const p of getParents(id)) {
|
|
127
|
+
if (!visited.has(p) && source.has(p))
|
|
128
|
+
queue.push([p, depth + 1]);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const boundaryParents = [...getParents(id)].filter(p => !visited.has(p) && source.has(p));
|
|
133
|
+
if (boundaryParents.length > 0) {
|
|
134
|
+
const ghostId = `${GHOST_ANCESTORS_PREFIX}${id}`;
|
|
135
|
+
included.add(ghostId);
|
|
136
|
+
const count = boundaryParents.length;
|
|
137
|
+
ghostNodes.set(ghostId, {
|
|
138
|
+
label: `... ${count} ancestor${count !== 1 ? 's' : ''}`,
|
|
139
|
+
edges: [id],
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// BFS descendants
|
|
147
|
+
if (direction === 'descendants' || direction === 'both') {
|
|
148
|
+
const queue = [[focus, 0]];
|
|
149
|
+
const visited = new Set();
|
|
150
|
+
while (queue.length > 0) {
|
|
151
|
+
const [id, depth] = queue.shift();
|
|
152
|
+
if (visited.has(id))
|
|
153
|
+
continue;
|
|
154
|
+
visited.add(id);
|
|
155
|
+
included.add(id);
|
|
156
|
+
const ch = [...source.children(id)].filter(c => source.has(c));
|
|
157
|
+
// Track reverse edges for derived parent map
|
|
158
|
+
if (!source.parents) {
|
|
159
|
+
for (const c of ch) {
|
|
160
|
+
if (!derivedParents.has(c))
|
|
161
|
+
derivedParents.set(c, []);
|
|
162
|
+
derivedParents.get(c).push(id);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (depth < maxDepth) {
|
|
166
|
+
for (const c of ch) {
|
|
167
|
+
if (!visited.has(c))
|
|
168
|
+
queue.push([c, depth + 1]);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const boundaryChildren = ch.filter(c => !visited.has(c));
|
|
173
|
+
if (boundaryChildren.length > 0) {
|
|
174
|
+
const ghostId = `${GHOST_DESCENDANTS_PREFIX}${id}`;
|
|
175
|
+
included.add(ghostId);
|
|
176
|
+
const count = boundaryChildren.length;
|
|
177
|
+
ghostNodes.set(ghostId, {
|
|
178
|
+
label: `... ${count} descendant${count !== 1 ? 's' : ''}`,
|
|
179
|
+
edges: [],
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Build the sliced DagSource
|
|
186
|
+
const slicedIds = Object.freeze([...included]);
|
|
187
|
+
// Inherit ghost status from input when slicing a SlicedDagSource
|
|
188
|
+
const inheritGhost = isSlicedDagSource(source) ? source : null;
|
|
189
|
+
return {
|
|
190
|
+
ids: () => slicedIds,
|
|
191
|
+
has: (id) => included.has(id),
|
|
192
|
+
label: (id) => {
|
|
193
|
+
const ghost = ghostNodes.get(id);
|
|
194
|
+
if (ghost)
|
|
195
|
+
return ghost.label;
|
|
196
|
+
return source.label(id);
|
|
197
|
+
},
|
|
198
|
+
children: (id) => {
|
|
199
|
+
const ghost = ghostNodes.get(id);
|
|
200
|
+
if (ghost)
|
|
201
|
+
return [...ghost.edges];
|
|
202
|
+
// Filter to included IDs, plus any descendant ghost for this node
|
|
203
|
+
const ch = [...source.children(id)].filter(c => included.has(c));
|
|
204
|
+
const descGhostId = `${GHOST_DESCENDANTS_PREFIX}${id}`;
|
|
205
|
+
if (ghostNodes.has(descGhostId))
|
|
206
|
+
ch.push(descGhostId);
|
|
207
|
+
return ch;
|
|
208
|
+
},
|
|
209
|
+
parents: (id) => {
|
|
210
|
+
if (ghostNodes.has(id)) {
|
|
211
|
+
if (id.startsWith(GHOST_ANCESTORS_PREFIX))
|
|
212
|
+
return [];
|
|
213
|
+
const boundaryId = id.replace(GHOST_DESCENDANTS_PREFIX, '');
|
|
214
|
+
return included.has(boundaryId) ? [boundaryId] : [];
|
|
215
|
+
}
|
|
216
|
+
if (source.parents) {
|
|
217
|
+
return [...source.parents(id)].filter(p => included.has(p));
|
|
218
|
+
}
|
|
219
|
+
return (derivedParents.get(id) ?? []).filter(p => included.has(p));
|
|
220
|
+
},
|
|
221
|
+
badge: (id) => ghostNodes.has(id) ? undefined : source.badge?.(id),
|
|
222
|
+
token: (id) => ghostNodes.has(id) ? undefined : source.token?.(id),
|
|
223
|
+
ghost: (id) => ghostNodes.has(id) || (inheritGhost !== null && inheritGhost.ghost(id)),
|
|
224
|
+
ghostLabel: (id) => ghostNodes.get(id)?.label ?? inheritGhost?.ghostLabel(id),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=dag-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-source.js","sourceRoot":"","sources":["../../../src/core/components/dag-source.ts"],"names":[],"mappings":"AA2DA,uEAAuE;AAEvE,sEAAsE;AACtE,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,OAAQ,KAAmB,CAAC,GAAG,KAAK,UAAU;QAC9C,OAAQ,KAAmB,CAAC,KAAK,KAAK,UAAU;QAChD,OAAQ,KAAmB,CAAC,QAAQ,KAAK,UAAU,CACpD,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,CACL,WAAW,CAAC,KAAK,CAAC;QAClB,OAAQ,KAAyB,CAAC,GAAG,KAAK,UAAU;QACpD,OAAQ,KAAyB,CAAC,KAAK,KAAK,UAAU;QACtD,OAAQ,KAAyB,CAAC,UAAU,KAAK,UAAU,CAC5D,CAAC;AACJ,CAAC;AAED,uEAAuE;AAEvE,mEAAmE;AACnE,MAAM,UAAU,WAAW,CAAC,KAAgB;IAC1C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmB,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAExC,yBAAyB;IACzB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAClD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5C,SAAS,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnD,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM;QACjB,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE;QACvC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QACjD,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/C,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK;QACjC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK;QACjC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,IAAI,KAAK;QAC3C,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW;KAC7C,CAAC;AACJ,CAAC;AAED,uEAAuE;AAEvE,oFAAoF;AACpF,MAAM,UAAU,WAAW,CAAC,MAAuB;IACjD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,KAAK,GAAc,EAAE,CAAC;IAC5B,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,IAAI,GAAY;YACpB,EAAE;YACF,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;SACvD,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAC5C,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,uEAAuE;AAEvE,MAAM,SAAS,GAAsB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAEvD,gEAAgE;AAChE,MAAM,YAAY,GAAoB,MAAM,CAAC,MAAM,CAAC;IAClD,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS;IACpB,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK;IAChB,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE;IACf,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;IACzB,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK;IAClB,UAAU,EAAE,GAAG,EAAE,CAAC,SAAS;CAC5B,CAAC,CAAC;AAEH,uEAAuE;AAEvE,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AACpD,MAAM,wBAAwB,GAAG,sBAAsB,CAAC;AAExD,uEAAuE;AAEvE;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CACzB,MAAiB,EACjB,KAAa,EACb,IAAsB;IAEtB,MAAM,iBAAiB,GAAG,IAAI,EAAE,SAAS,CAAC;IAC1C,MAAM,SAAS,GAAG,iBAAiB,IAAI,MAAM,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,EAAE,KAAK,IAAI,QAAQ,CAAC;IAEzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,YAAY,CAAC;IAE5C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,GAAG,EAA8C,CAAC;IACzE,4DAA4D;IAC5D,MAAM,cAAc,GAAG,IAAI,GAAG,EAAoB,CAAC;IAEnD,gBAAgB;IAChB,IAAI,SAAS,KAAK,WAAW,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,iBAAiB,KAAK,WAAW,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAC;YACJ,CAAC;YACD,yEAAyE;QAC3E,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAuB,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;YAClC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;gBACnC,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;oBAAE,SAAS;gBAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAChB,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACjB,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;oBACrB,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;wBAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;4BAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;oBACnE,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,MAAM,eAAe,GAAG,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAChD,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CACtC,CAAC;oBACF,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC/B,MAAM,OAAO,GAAG,GAAG,sBAAsB,GAAG,EAAE,EAAE,CAAC;wBACjD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;wBACtB,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC;wBACrC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE;4BACtB,KAAK,EAAE,OAAO,KAAK,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;4BACvD,KAAK,EAAE,CAAC,EAAE,CAAC;yBACZ,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,IAAI,SAAS,KAAK,aAAa,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACxD,MAAM,KAAK,GAAuB,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;YACnC,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,SAAS;YAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjB,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/D,6CAA6C;YAC7C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;oBACnB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;wBAAE,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACtD,cAAc,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;YACD,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;gBACrB,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;oBACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;wBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,gBAAgB,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzD,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAChC,MAAM,OAAO,GAAG,GAAG,wBAAwB,GAAG,EAAE,EAAE,CAAC;oBACnD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACtB,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC;oBACtC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE;wBACtB,KAAK,EAAE,OAAO,KAAK,cAAc,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;wBACzD,KAAK,EAAE,EAAE;qBACV,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC/C,iEAAiE;IACjE,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAE/D,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS;QAEpB,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAE7B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;YACZ,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC,KAAK,CAAC;YAC9B,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;QAED,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE;YACf,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,KAAK;gBAAE,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,kEAAkE;YAClE,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,WAAW,GAAG,GAAG,wBAAwB,GAAG,EAAE,EAAE,CAAC;YACvD,IAAI,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;gBAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACtD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;YACd,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACvB,IAAI,EAAE,CAAC,UAAU,CAAC,sBAAsB,CAAC;oBAAE,OAAO,EAAE,CAAC;gBACrD,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;gBAC5D,OAAO,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtD,CAAC;YACD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9D,CAAC;YACD,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrE,CAAC;QAED,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;QAElE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;QAElE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,KAAK,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEtF,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,YAAY,EAAE,UAAU,CAAC,EAAE,CAAC;KAC9E,CAAC;AACJ,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BijouContext } from '../../ports/context.js';
|
|
2
2
|
import type { TokenValue } from '../theme/tokens.js';
|
|
3
|
+
import type { DagSource, SlicedDagSource, DagSliceOptions } from './dag-source.js';
|
|
3
4
|
export interface DagNode {
|
|
4
5
|
id: string;
|
|
5
6
|
label: string;
|
|
@@ -15,14 +16,29 @@ export interface DagOptions {
|
|
|
15
16
|
edgeToken?: TokenValue;
|
|
16
17
|
highlightPath?: string[];
|
|
17
18
|
highlightToken?: TokenValue;
|
|
19
|
+
selectedId?: string;
|
|
20
|
+
selectedToken?: TokenValue;
|
|
18
21
|
nodeWidth?: number;
|
|
19
22
|
maxWidth?: number;
|
|
20
23
|
direction?: 'down' | 'right';
|
|
21
24
|
ctx?: BijouContext;
|
|
22
25
|
}
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
export interface DagNodePosition {
|
|
27
|
+
readonly row: number;
|
|
28
|
+
readonly col: number;
|
|
29
|
+
readonly width: number;
|
|
30
|
+
readonly height: number;
|
|
31
|
+
}
|
|
32
|
+
export interface DagLayout {
|
|
33
|
+
readonly output: string;
|
|
34
|
+
readonly nodes: ReadonlyMap<string, DagNodePosition>;
|
|
35
|
+
readonly width: number;
|
|
36
|
+
readonly height: number;
|
|
37
|
+
}
|
|
38
|
+
export declare function dagSlice(source: DagSource, focus: string, opts?: DagSliceOptions): SlicedDagSource;
|
|
39
|
+
export declare function dagSlice(nodes: DagNode[], focus: string, opts?: DagSliceOptions): DagNode[];
|
|
40
|
+
export declare function dagLayout(source: SlicedDagSource, options?: DagOptions): DagLayout;
|
|
41
|
+
export declare function dagLayout(nodes: DagNode[], options?: DagOptions): DagLayout;
|
|
42
|
+
export declare function dag(source: SlicedDagSource, options?: DagOptions): string;
|
|
27
43
|
export declare function dag(nodes: DagNode[], options?: DagOptions): string;
|
|
28
44
|
//# sourceMappingURL=dag.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../../../src/core/components/dag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../../../src/core/components/dag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAInF,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAiiBD,wBAAgB,QAAQ,CACtB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,eAAe,GACrB,eAAe,CAAC;AACnB,wBAAgB,QAAQ,CACtB,KAAK,EAAE,OAAO,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,EAAE,CAAC;AAgBb,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;AACpF,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;AAmB7E,wBAAgB,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;AAC3E,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getDefaultContext } from '../../context.js';
|
|
2
|
+
import { isDagSource, isSlicedDagSource, arraySource, materialize, sliceSource } from './dag-source.js';
|
|
2
3
|
// ── Helpers ────────────────────────────────────────────────────────
|
|
3
4
|
function resolveCtx(ctx) {
|
|
4
5
|
if (ctx)
|
|
@@ -226,9 +227,9 @@ function renderNodeBox(label, badgeText, width, ghost) {
|
|
|
226
227
|
return [top, mid, bot];
|
|
227
228
|
}
|
|
228
229
|
// ── Interactive Renderer ───────────────────────────────────────────
|
|
229
|
-
function
|
|
230
|
+
function renderInteractiveLayout(nodes, options, ctx) {
|
|
230
231
|
if (nodes.length === 0)
|
|
231
|
-
return '';
|
|
232
|
+
return { output: '', nodes: new Map(), width: 0, height: 0 };
|
|
232
233
|
const nodeMap = new Map();
|
|
233
234
|
for (const n of nodes)
|
|
234
235
|
nodeMap.set(n.id, n);
|
|
@@ -356,6 +357,7 @@ function renderInteractive(nodes, options, ctx) {
|
|
|
356
357
|
}
|
|
357
358
|
}
|
|
358
359
|
// Write node boxes
|
|
360
|
+
const positions = new Map();
|
|
359
361
|
for (const n of nodes) {
|
|
360
362
|
const layer = layerMap.get(n.id);
|
|
361
363
|
const col = colIndex.get(n.id);
|
|
@@ -363,9 +365,13 @@ function renderInteractive(nodes, options, ctx) {
|
|
|
363
365
|
continue;
|
|
364
366
|
const startCol = col * colStride;
|
|
365
367
|
const startRow = layer * RS;
|
|
368
|
+
positions.set(n.id, { row: startRow, col: startCol, width: nodeWidth, height: 3 });
|
|
366
369
|
const boxLines = renderNodeBox(n.label, n.badge, nodeWidth, n._ghost === true);
|
|
367
370
|
let nToken;
|
|
368
|
-
if (
|
|
371
|
+
if (options.selectedId === n.id) {
|
|
372
|
+
nToken = options.selectedToken ?? ctx.theme.theme.ui.cursor;
|
|
373
|
+
}
|
|
374
|
+
else if (highlightSet.has(n.id) && options.highlightToken) {
|
|
369
375
|
nToken = options.highlightToken;
|
|
370
376
|
}
|
|
371
377
|
else if (n.token) {
|
|
@@ -417,7 +423,7 @@ function renderInteractive(nodes, options, ctx) {
|
|
|
417
423
|
while (lines.length > 0 && lines[lines.length - 1].trim() === '') {
|
|
418
424
|
lines.pop();
|
|
419
425
|
}
|
|
420
|
-
return lines.join('\n');
|
|
426
|
+
return { output: lines.join('\n'), nodes: positions, width: gridCols, height: gridRows };
|
|
421
427
|
}
|
|
422
428
|
// ── Pipe Renderer ──────────────────────────────────────────────────
|
|
423
429
|
function renderPipe(nodes) {
|
|
@@ -474,131 +480,32 @@ function renderAccessible(nodes, layerMap) {
|
|
|
474
480
|
lines.pop();
|
|
475
481
|
return lines.join('\n');
|
|
476
482
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const maxDepth = opts?.depth ?? Infinity;
|
|
481
|
-
const nodeMap = new Map();
|
|
482
|
-
for (const n of nodes)
|
|
483
|
-
nodeMap.set(n.id, n);
|
|
484
|
-
if (!nodeMap.has(focus))
|
|
485
|
-
return [];
|
|
486
|
-
const included = new Set();
|
|
487
|
-
const ghostIds = new Set();
|
|
488
|
-
// Build parent map
|
|
489
|
-
const parentsMap = new Map();
|
|
490
|
-
for (const n of nodes) {
|
|
491
|
-
if (!parentsMap.has(n.id))
|
|
492
|
-
parentsMap.set(n.id, []);
|
|
493
|
-
for (const c of n.edges ?? []) {
|
|
494
|
-
if (!parentsMap.has(c))
|
|
495
|
-
parentsMap.set(c, []);
|
|
496
|
-
parentsMap.get(c).push(n.id);
|
|
497
|
-
}
|
|
483
|
+
export function dagSlice(input, focus, opts) {
|
|
484
|
+
if (isDagSource(input)) {
|
|
485
|
+
return sliceSource(input, focus, opts);
|
|
498
486
|
}
|
|
499
|
-
//
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
const depth = entry[1];
|
|
507
|
-
if (visited.has(id))
|
|
508
|
-
continue;
|
|
509
|
-
visited.add(id);
|
|
510
|
-
included.add(id);
|
|
511
|
-
if (depth < maxDepth) {
|
|
512
|
-
for (const p of parentsMap.get(id) ?? []) {
|
|
513
|
-
if (!visited.has(p))
|
|
514
|
-
queue.push([p, depth + 1]);
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
else {
|
|
518
|
-
const boundaryParents = (parentsMap.get(id) ?? []).filter(p => !visited.has(p));
|
|
519
|
-
if (boundaryParents.length > 0) {
|
|
520
|
-
const ghostId = `__ghost_ancestors_${id}`;
|
|
521
|
-
ghostIds.add(ghostId);
|
|
522
|
-
included.add(ghostId);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
// BFS descendants
|
|
528
|
-
if (direction === 'descendants' || direction === 'both') {
|
|
529
|
-
const queue = [[focus, 0]];
|
|
530
|
-
const visited = new Set();
|
|
531
|
-
while (queue.length > 0) {
|
|
532
|
-
const entry = queue.shift();
|
|
533
|
-
const id = entry[0];
|
|
534
|
-
const depth = entry[1];
|
|
535
|
-
if (visited.has(id))
|
|
536
|
-
continue;
|
|
537
|
-
visited.add(id);
|
|
538
|
-
included.add(id);
|
|
539
|
-
const ch = nodeMap.get(id)?.edges ?? [];
|
|
540
|
-
if (depth < maxDepth) {
|
|
541
|
-
for (const c of ch) {
|
|
542
|
-
if (!visited.has(c) && nodeMap.has(c))
|
|
543
|
-
queue.push([c, depth + 1]);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
else {
|
|
547
|
-
const boundaryChildren = ch.filter(c => !visited.has(c) && nodeMap.has(c));
|
|
548
|
-
if (boundaryChildren.length > 0) {
|
|
549
|
-
const ghostId = `__ghost_descendants_${id}`;
|
|
550
|
-
ghostIds.add(ghostId);
|
|
551
|
-
included.add(ghostId);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
// Build result
|
|
557
|
-
const result = [];
|
|
558
|
-
for (const gid of ghostIds) {
|
|
559
|
-
if (gid.startsWith('__ghost_ancestors_')) {
|
|
560
|
-
const boundaryId = gid.replace('__ghost_ancestors_', '');
|
|
561
|
-
const allParents = (parentsMap.get(boundaryId) ?? []).filter(p => !included.has(p));
|
|
562
|
-
const count = allParents.length;
|
|
563
|
-
result.push({
|
|
564
|
-
id: gid,
|
|
565
|
-
label: `... ${count} ancestor${count !== 1 ? 's' : ''}`,
|
|
566
|
-
edges: [boundaryId],
|
|
567
|
-
_ghost: true,
|
|
568
|
-
_ghostLabel: `... ${count} ancestor${count !== 1 ? 's' : ''}`,
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
for (const n of nodes) {
|
|
573
|
-
if (!included.has(n.id))
|
|
574
|
-
continue;
|
|
575
|
-
const filteredEdges = (n.edges ?? []).filter(e => included.has(e));
|
|
576
|
-
const descGhostId = `__ghost_descendants_${n.id}`;
|
|
577
|
-
if (ghostIds.has(descGhostId)) {
|
|
578
|
-
filteredEdges.push(descGhostId);
|
|
579
|
-
}
|
|
580
|
-
result.push({ ...n, edges: filteredEdges.length > 0 ? filteredEdges : undefined });
|
|
581
|
-
}
|
|
582
|
-
for (const gid of ghostIds) {
|
|
583
|
-
if (gid.startsWith('__ghost_descendants_')) {
|
|
584
|
-
const boundaryId = gid.replace('__ghost_descendants_', '');
|
|
585
|
-
const boundaryNode = nodeMap.get(boundaryId);
|
|
586
|
-
const allChildren = (boundaryNode?.edges ?? []).filter(c => !included.has(c) && nodeMap.has(c));
|
|
587
|
-
const count = allChildren.length;
|
|
588
|
-
result.push({
|
|
589
|
-
id: gid,
|
|
590
|
-
label: `... ${count} descendant${count !== 1 ? 's' : ''}`,
|
|
591
|
-
_ghost: true,
|
|
592
|
-
_ghostLabel: `... ${count} descendant${count !== 1 ? 's' : ''}`,
|
|
593
|
-
});
|
|
594
|
-
}
|
|
487
|
+
// Array path: wrap, slice, materialize back for backward compat
|
|
488
|
+
const source = arraySource(input);
|
|
489
|
+
return materialize(sliceSource(source, focus, opts));
|
|
490
|
+
}
|
|
491
|
+
export function dagLayout(input, options = {}) {
|
|
492
|
+
if (isDagSource(input) && !isSlicedDagSource(input)) {
|
|
493
|
+
throw new Error('[bijou] dagLayout(): received an unbounded DagSource. Use dagSlice() to produce a SlicedDagSource first.');
|
|
595
494
|
}
|
|
596
|
-
|
|
495
|
+
const ctx = resolveCtx(options.ctx);
|
|
496
|
+
const nodes = isSlicedDagSource(input) ? materialize(input) : input;
|
|
497
|
+
if (nodes.length === 0)
|
|
498
|
+
return { output: '', nodes: new Map(), width: 0, height: 0 };
|
|
499
|
+
const result = renderInteractiveLayout(nodes, options, ctx);
|
|
500
|
+
return { output: result.output, nodes: result.nodes, width: result.width, height: result.height };
|
|
597
501
|
}
|
|
598
|
-
|
|
599
|
-
|
|
502
|
+
export function dag(input, options = {}) {
|
|
503
|
+
if (isDagSource(input) && !isSlicedDagSource(input)) {
|
|
504
|
+
throw new Error('[bijou] dag(): received an unbounded DagSource. Use dagSlice() to produce a SlicedDagSource first.');
|
|
505
|
+
}
|
|
600
506
|
const ctx = resolveCtx(options.ctx);
|
|
601
507
|
const mode = ctx.mode;
|
|
508
|
+
const nodes = isSlicedDagSource(input) ? materialize(input) : input;
|
|
602
509
|
if (nodes.length === 0)
|
|
603
510
|
return '';
|
|
604
511
|
if (mode === 'pipe') {
|
|
@@ -608,6 +515,6 @@ export function dag(nodes, options = {}) {
|
|
|
608
515
|
const layerMap = assignLayers(nodes);
|
|
609
516
|
return renderAccessible(nodes, layerMap);
|
|
610
517
|
}
|
|
611
|
-
return
|
|
518
|
+
return renderInteractiveLayout(nodes, options, ctx).output;
|
|
612
519
|
}
|
|
613
520
|
//# sourceMappingURL=dag.js.map
|