bireactive 0.2.4 → 0.3.1
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/animation/anim.js +4 -0
- package/dist/automerge/doc-cell.d.ts +20 -0
- package/dist/automerge/doc-cell.js +80 -0
- package/dist/automerge/index.d.ts +3 -0
- package/dist/automerge/index.js +12 -0
- package/dist/automerge/reconcile.d.ts +5 -0
- package/dist/automerge/reconcile.js +63 -0
- package/dist/coll.d.ts +7 -7
- package/dist/core/_counts.d.ts +48 -0
- package/dist/core/_counts.js +58 -0
- package/dist/core/cell.d.ts +182 -123
- package/dist/core/cell.js +1140 -721
- package/dist/core/debug.d.ts +25 -0
- package/dist/core/debug.js +121 -0
- package/dist/core/index.d.ts +9 -14
- package/dist/core/index.js +9 -14
- package/dist/core/lenses/aggregates.d.ts +1 -1
- package/dist/core/lenses/aggregates.js +4 -3
- package/dist/core/lenses/closed-form-policies.js +14 -9
- package/dist/core/lenses/decompositions.js +3 -3
- package/dist/core/lenses/domain-aggregates.js +5 -5
- package/dist/core/lenses/geometry.d.ts +1 -1
- package/dist/core/lenses/geometry.js +6 -7
- package/dist/core/lenses/index.d.ts +1 -0
- package/dist/core/lenses/index.js +1 -0
- package/dist/core/lenses/memory.d.ts +2 -2
- package/dist/core/lenses/memory.js +3 -3
- package/dist/core/lenses/snap.d.ts +18 -0
- package/dist/core/lenses/snap.js +145 -0
- package/dist/core/lenses/typed-factor.js +4 -3
- package/dist/core/optic.d.ts +13 -0
- package/dist/core/optic.js +44 -0
- package/dist/core/optics.d.ts +10 -0
- package/dist/core/optics.js +30 -0
- package/dist/core/store.d.ts +10 -0
- package/dist/core/store.js +85 -0
- package/dist/core/traits.d.ts +1 -0
- package/dist/core/values/audio.js +4 -5
- package/dist/core/values/box.js +7 -7
- package/dist/core/values/canvas.js +15 -18
- package/dist/core/values/color.js +5 -5
- package/dist/core/values/field.d.ts +70 -0
- package/dist/core/values/field.js +230 -0
- package/dist/core/values/gpu.d.ts +4 -2
- package/dist/core/values/gpu.js +11 -4
- package/dist/core/values/matrix.js +7 -7
- package/dist/core/values/num.d.ts +1 -1
- package/dist/core/values/num.js +1 -1
- package/dist/core/values/pose.js +4 -4
- package/dist/core/values/range.js +6 -6
- package/dist/core/values/str.js +8 -8
- package/dist/core/values/template.d.ts +1 -1
- package/dist/core/values/template.js +2 -1
- package/dist/core/values/transform.js +7 -7
- package/dist/core/values/tri.js +3 -3
- package/dist/core/values/vec.js +8 -12
- package/dist/ext/timeline.js +2 -2
- package/dist/formats/cst.d.ts +127 -0
- package/dist/formats/cst.js +280 -0
- package/dist/formats/edn.d.ts +2 -0
- package/dist/formats/edn.js +301 -0
- package/dist/formats/index.d.ts +6 -0
- package/dist/formats/index.js +8 -0
- package/dist/formats/json.d.ts +2 -0
- package/dist/formats/json.js +332 -0
- package/dist/formats/lens.d.ts +8 -0
- package/dist/formats/lens.js +51 -0
- package/dist/formats/toml.d.ts +2 -0
- package/dist/formats/toml.js +526 -0
- package/dist/formats/yaml.d.ts +2 -0
- package/dist/formats/yaml.js +661 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx-dev-runtime.js +5 -0
- package/dist/jsx-runtime.d.ts +54 -0
- package/dist/jsx-runtime.js +219 -0
- package/dist/learn/data.d.ts +49 -0
- package/dist/learn/data.js +181 -0
- package/dist/learn/index.d.ts +3 -0
- package/dist/learn/index.js +6 -0
- package/dist/learn/lens-net.d.ts +63 -0
- package/dist/learn/lens-net.js +219 -0
- package/dist/learn/mlp.d.ts +77 -0
- package/dist/learn/mlp.js +292 -0
- package/dist/propagators/csp.d.ts +13 -0
- package/dist/propagators/csp.js +52 -0
- package/dist/propagators/flex.d.ts +31 -0
- package/dist/propagators/flex.js +189 -0
- package/dist/propagators/graph.d.ts +73 -0
- package/dist/propagators/graph.js +543 -0
- package/dist/propagators/index.d.ts +8 -6
- package/dist/propagators/index.js +15 -6
- package/dist/propagators/lattice.d.ts +45 -0
- package/dist/propagators/lattice.js +113 -0
- package/dist/propagators/layout.d.ts +1 -27
- package/dist/propagators/layout.js +6 -175
- package/dist/propagators/numeric.d.ts +17 -0
- package/dist/propagators/numeric.js +93 -0
- package/dist/propagators/solver.d.ts +51 -0
- package/dist/propagators/solver.js +175 -0
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.js +3 -0
- package/dist/schema/lens.d.ts +121 -0
- package/dist/schema/lens.js +429 -0
- package/dist/shapes/annular-sector.js +4 -4
- package/dist/shapes/button.js +1 -1
- package/dist/shapes/circle.js +1 -1
- package/dist/shapes/drag-behaviors.d.ts +56 -0
- package/dist/shapes/drag-behaviors.js +102 -0
- package/dist/shapes/drag-spec.d.ts +52 -0
- package/dist/shapes/drag-spec.js +112 -0
- package/dist/shapes/handle.js +2 -2
- package/dist/shapes/index.d.ts +3 -1
- package/dist/shapes/index.js +3 -1
- package/dist/shapes/interaction.d.ts +2 -3
- package/dist/shapes/interaction.js +77 -56
- package/dist/shapes/label.js +7 -1
- package/dist/shapes/layout.d.ts +47 -1
- package/dist/shapes/layout.js +60 -2
- package/dist/shapes/rect.js +7 -7
- package/dist/shapes/shape.js +8 -8
- package/dist/web/diagram.js +2 -2
- package/package.json +24 -2
- package/dist/propagators/network.d.ts +0 -52
- package/dist/propagators/network.js +0 -185
- package/dist/propagators/propagator.d.ts +0 -12
- package/dist/propagators/propagator.js +0 -16
- package/dist/propagators/range.d.ts +0 -45
- package/dist/propagators/range.js +0 -147
- package/dist/propagators/relations.d.ts +0 -60
- package/dist/propagators/relations.js +0 -343
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// flex.ts — flexbox as interval propagation.
|
|
2
|
+
//
|
|
3
|
+
// A flex line is two phases, both grounded in the interval lattice:
|
|
4
|
+
//
|
|
5
|
+
// 1. FEASIBILITY (narrowing). Given the container's content size and
|
|
6
|
+
// each item's [min, max], the `total` relation narrows every item
|
|
7
|
+
// to the band it could occupy: `wᵢ ∈ content − Σ(others)`. If any
|
|
8
|
+
// band comes back empty the line can't fit — that's a real lattice
|
|
9
|
+
// contradiction, reported, not a silent overflow.
|
|
10
|
+
//
|
|
11
|
+
// 2. RESOLUTION (point pick). Within the feasible bands, grow/shrink
|
|
12
|
+
// weights distribute the slack to a single size per item. This is
|
|
13
|
+
// the one place a *preference* (not a constraint) enters, so it's
|
|
14
|
+
// kept out of the narrowing.
|
|
15
|
+
//
|
|
16
|
+
// The line operates on plain `Box` cells — zero ceremony, nothing is
|
|
17
|
+
// coloured. Nesting composes through the ordinary reactive graph: a
|
|
18
|
+
// child container is just an item of its parent, so resizing the root
|
|
19
|
+
// re-runs each line top-down. `row`/`col` are the only public surface;
|
|
20
|
+
// everything else is the two phases above.
|
|
21
|
+
import { isCell, readNow, } from "../core/index.js";
|
|
22
|
+
import { interval } from "./lattice.js";
|
|
23
|
+
import { propagator } from "./solver.js";
|
|
24
|
+
const asW = (n) => n;
|
|
25
|
+
function readDeps(...vs) {
|
|
26
|
+
return vs.filter(isCell);
|
|
27
|
+
}
|
|
28
|
+
const clamp = (v, lo, hi) => Math.min(Math.max(v, lo), hi);
|
|
29
|
+
function specs(items) {
|
|
30
|
+
return items.map(it => "box" in it
|
|
31
|
+
? {
|
|
32
|
+
box: it.box,
|
|
33
|
+
grow: it.grow ?? 1,
|
|
34
|
+
shrink: it.shrink ?? 1,
|
|
35
|
+
min: it.min ?? 0,
|
|
36
|
+
max: it.max ?? Number.POSITIVE_INFINITY,
|
|
37
|
+
basis: it.basis,
|
|
38
|
+
}
|
|
39
|
+
: { box: it, grow: 1, shrink: 1, min: 0, max: Number.POSITIVE_INFINITY });
|
|
40
|
+
}
|
|
41
|
+
/** Horizontal flex line over plain `Box` cells. */
|
|
42
|
+
export function row(c, items, opts = {}) {
|
|
43
|
+
return line(c, items, opts, "x");
|
|
44
|
+
}
|
|
45
|
+
/** Vertical flex line over plain `Box` cells. */
|
|
46
|
+
export function col(c, items, opts = {}) {
|
|
47
|
+
return line(c, items, opts, "y");
|
|
48
|
+
}
|
|
49
|
+
function line(c, rawItems, opts, main) {
|
|
50
|
+
const items = specs(rawItems);
|
|
51
|
+
const horizontal = main === "x";
|
|
52
|
+
const mainPos = (b) => asW(horizontal ? b.x : b.y);
|
|
53
|
+
const mainSize = (b) => asW(horizontal ? b.w : b.h);
|
|
54
|
+
const crossPos = (b) => asW(horizontal ? b.y : b.x);
|
|
55
|
+
const crossSize = (b) => asW(horizontal ? b.h : b.w);
|
|
56
|
+
const align = opts.align ?? "stretch";
|
|
57
|
+
const reads = [
|
|
58
|
+
mainPos(c),
|
|
59
|
+
mainSize(c),
|
|
60
|
+
crossPos(c),
|
|
61
|
+
crossSize(c),
|
|
62
|
+
...items.map(it => crossSize(it.box)),
|
|
63
|
+
...readDeps(opts.gap ?? 0, opts.padding ?? 0),
|
|
64
|
+
];
|
|
65
|
+
const writes = [];
|
|
66
|
+
for (const it of items) {
|
|
67
|
+
writes.push(mainPos(it.box), mainSize(it.box), crossPos(it.box));
|
|
68
|
+
if (align === "stretch")
|
|
69
|
+
writes.push(crossSize(it.box));
|
|
70
|
+
}
|
|
71
|
+
if (typeof opts.report !== "function" && opts.report)
|
|
72
|
+
writes.push(opts.report);
|
|
73
|
+
return propagator(reads, writes, () => {
|
|
74
|
+
const gap = readNow(opts.gap ?? 0);
|
|
75
|
+
const pad = readNow(opts.padding ?? 0);
|
|
76
|
+
const n = items.length;
|
|
77
|
+
if (n === 0)
|
|
78
|
+
return;
|
|
79
|
+
const content = mainSize(c).value - 2 * pad - (n - 1) * gap;
|
|
80
|
+
const mins = items.map(it => it.min);
|
|
81
|
+
const maxs = items.map(it => it.max);
|
|
82
|
+
const sumMin = mins.reduce((a, b) => a + b, 0);
|
|
83
|
+
const sumMax = maxs.reduce((a, b) => a + b, 0);
|
|
84
|
+
// Phase 1 — feasibility. Per-item band from the `total` relation:
|
|
85
|
+
// wᵢ ∈ [content − Σmax(others), content − Σmin(others)] ∩ [minᵢ, maxᵢ].
|
|
86
|
+
const bands = items.map((_, i) => {
|
|
87
|
+
const lo = content - (sumMax - maxs[i]);
|
|
88
|
+
const hi = content - (sumMin - mins[i]);
|
|
89
|
+
return interval.meet([Math.max(lo, mins[i]), Math.min(hi, maxs[i])], [mins[i], maxs[i]]);
|
|
90
|
+
});
|
|
91
|
+
const infeasible = content < sumMin - 1e-9 || bands.some(interval.isBottom);
|
|
92
|
+
report(opts, infeasible);
|
|
93
|
+
// Phase 2 — resolution. Distribute slack from the basis sizes,
|
|
94
|
+
// weighted by grow (free > 0) / shrink (free < 0), clamped into the
|
|
95
|
+
// feasible band each pass and redistributed.
|
|
96
|
+
const base = items.map((it, i) => clamp(it.basis ?? mainSize(it.box).value, mins[i], maxs[i]));
|
|
97
|
+
const sizes = distribute(base, items, mins, maxs, content);
|
|
98
|
+
let cursor = mainPos(c).value + pad;
|
|
99
|
+
for (let i = 0; i < n; i++) {
|
|
100
|
+
mainPos(items[i].box).value = cursor;
|
|
101
|
+
mainSize(items[i].box).value = sizes[i];
|
|
102
|
+
cursor += sizes[i] + gap;
|
|
103
|
+
}
|
|
104
|
+
const cBase = crossPos(c).value + pad;
|
|
105
|
+
const cAvail = crossSize(c).value - 2 * pad;
|
|
106
|
+
for (const it of items) {
|
|
107
|
+
const itSize = crossSize(it.box).value;
|
|
108
|
+
switch (align) {
|
|
109
|
+
case "start":
|
|
110
|
+
crossPos(it.box).value = cBase;
|
|
111
|
+
break;
|
|
112
|
+
case "center":
|
|
113
|
+
crossPos(it.box).value = cBase + (cAvail - itSize) / 2;
|
|
114
|
+
break;
|
|
115
|
+
case "end":
|
|
116
|
+
crossPos(it.box).value = cBase + cAvail - itSize;
|
|
117
|
+
break;
|
|
118
|
+
case "stretch":
|
|
119
|
+
crossPos(it.box).value = cBase;
|
|
120
|
+
crossSize(it.box).value = cAvail;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/** CSS-flex slack distribution, clamped into [min, max] with overflow
|
|
127
|
+
* redistributed across still-eligible items. */
|
|
128
|
+
function distribute(base, items, mins, maxs, content) {
|
|
129
|
+
const n = base.length;
|
|
130
|
+
const sizes = base.slice();
|
|
131
|
+
const free = content - base.reduce((a, b) => a + b, 0);
|
|
132
|
+
if (free > 1e-9) {
|
|
133
|
+
let remaining = free;
|
|
134
|
+
const eligible = new Set();
|
|
135
|
+
for (let i = 0; i < n; i++)
|
|
136
|
+
if (items[i].grow > 0 && sizes[i] < maxs[i])
|
|
137
|
+
eligible.add(i);
|
|
138
|
+
while (remaining > 1e-9 && eligible.size > 0) {
|
|
139
|
+
let weight = 0;
|
|
140
|
+
for (const i of eligible)
|
|
141
|
+
weight += items[i].grow;
|
|
142
|
+
if (weight === 0)
|
|
143
|
+
break;
|
|
144
|
+
let absorbed = 0;
|
|
145
|
+
for (const i of [...eligible]) {
|
|
146
|
+
const next = Math.min(sizes[i] + (remaining * items[i].grow) / weight, maxs[i]);
|
|
147
|
+
absorbed += next - sizes[i];
|
|
148
|
+
sizes[i] = next;
|
|
149
|
+
if (next >= maxs[i])
|
|
150
|
+
eligible.delete(i);
|
|
151
|
+
}
|
|
152
|
+
if (absorbed < 1e-9)
|
|
153
|
+
break;
|
|
154
|
+
remaining -= absorbed;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else if (free < -1e-9) {
|
|
158
|
+
let remaining = -free;
|
|
159
|
+
const eligible = new Set();
|
|
160
|
+
for (let i = 0; i < n; i++)
|
|
161
|
+
if (items[i].shrink > 0 && sizes[i] > mins[i])
|
|
162
|
+
eligible.add(i);
|
|
163
|
+
while (remaining > 1e-9 && eligible.size > 0) {
|
|
164
|
+
let weight = 0;
|
|
165
|
+
for (const i of eligible)
|
|
166
|
+
weight += items[i].shrink;
|
|
167
|
+
if (weight === 0)
|
|
168
|
+
break;
|
|
169
|
+
let absorbed = 0;
|
|
170
|
+
for (const i of [...eligible]) {
|
|
171
|
+
const next = Math.max(sizes[i] - (remaining * items[i].shrink) / weight, mins[i]);
|
|
172
|
+
absorbed += sizes[i] - next;
|
|
173
|
+
sizes[i] = next;
|
|
174
|
+
if (next <= mins[i])
|
|
175
|
+
eligible.delete(i);
|
|
176
|
+
}
|
|
177
|
+
if (absorbed < 1e-9)
|
|
178
|
+
break;
|
|
179
|
+
remaining -= absorbed;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return sizes;
|
|
183
|
+
}
|
|
184
|
+
function report(opts, infeasible) {
|
|
185
|
+
if (typeof opts.report === "function")
|
|
186
|
+
opts.report(infeasible);
|
|
187
|
+
else if (opts.report)
|
|
188
|
+
asW(opts.report).value = infeasible ? 1 : 0;
|
|
189
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** A directed graph. Edges are `[from, to]`; nodes carry any identity. */
|
|
2
|
+
export interface Graph<N> {
|
|
3
|
+
readonly nodes: readonly N[];
|
|
4
|
+
readonly edges: readonly (readonly [N, N])[];
|
|
5
|
+
}
|
|
6
|
+
export type Direction = "TB" | "BT" | "LR" | "RL";
|
|
7
|
+
/** Intrinsic size of a node's box. */
|
|
8
|
+
export interface Size {
|
|
9
|
+
w: number;
|
|
10
|
+
h: number;
|
|
11
|
+
}
|
|
12
|
+
/** Top-left placement of a node's box. */
|
|
13
|
+
export interface Placement {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
w: number;
|
|
17
|
+
h: number;
|
|
18
|
+
}
|
|
19
|
+
export interface LayeredOpts<N> {
|
|
20
|
+
direction?: Direction;
|
|
21
|
+
/** Centre-to-centre distance between adjacent layers. Default 90. */
|
|
22
|
+
layerGap?: number;
|
|
23
|
+
/** Minimum edge-to-edge distance within a layer. Default 28. */
|
|
24
|
+
nodeGap?: number;
|
|
25
|
+
/** Intrinsic node size. Default 46×34. */
|
|
26
|
+
sizeOf?: (n: N) => Size;
|
|
27
|
+
/** Crossing-reduction sweeps. Default 6. */
|
|
28
|
+
sweeps?: number;
|
|
29
|
+
/** Barycenter source: "both" (DAG), "down" (parents over children,
|
|
30
|
+
* the tree look), "up". Default "both". */
|
|
31
|
+
align?: "both" | "down" | "up";
|
|
32
|
+
}
|
|
33
|
+
/** Assign each node an integer layer so every edge increases layer by
|
|
34
|
+
* ≥1. Cycles are broken (back edges reversed for ranking only). The
|
|
35
|
+
* value is the longest path from a source — computed as the lower
|
|
36
|
+
* bound the `order` atoms narrow each layer cell to. */
|
|
37
|
+
export declare function rank<N>(g: Graph<N>): Map<N, number>;
|
|
38
|
+
/** Strongly-connected components (Tarjan), each a list of mutually
|
|
39
|
+
* reachable nodes, in reverse-topological order of the condensation.
|
|
40
|
+
* Singletons are size-1 components; a self-loop still reports size 1.
|
|
41
|
+
* The cyclic cores of a graph are exactly the components of size > 1. */
|
|
42
|
+
export declare function scc<N>(g: Graph<N>): N[][];
|
|
43
|
+
/** Count edge crossings given per-layer orderings (for tests / quality). */
|
|
44
|
+
export declare function crossings<N>(g: Graph<N>, layer: Map<N, number>, layers: N[][]): number;
|
|
45
|
+
/** Full layered layout → top-left placement per node. */
|
|
46
|
+
export declare function layered<N>(g: Graph<N>, opts?: LayeredOpts<N>): Map<N, Placement>;
|
|
47
|
+
/** Tree layout: parents centred over their children. A `layered` with
|
|
48
|
+
* downward barycenter and tighter defaults. */
|
|
49
|
+
export declare function tree<N>(g: Graph<N>, opts?: LayeredOpts<N>): Map<N, Placement>;
|
|
50
|
+
/** Radial layout: layers become concentric rings, cross-axis position
|
|
51
|
+
* becomes angle. Reads a `layered` (TB) result and re-maps to polar. */
|
|
52
|
+
export declare function radial<N>(g: Graph<N>, opts?: LayeredOpts<N>): Map<N, Placement>;
|
|
53
|
+
/** Recurrent-hierarchy layout: decompose into strongly-connected
|
|
54
|
+
* components, lay the condensation (a DAG of SCCs) out hierarchically,
|
|
55
|
+
* and draw every cyclic component as a ring centred on its condensation
|
|
56
|
+
* slot. The cycle closes by going around the circle — no backward edge.
|
|
57
|
+
* Singleton components are placed as ordinary nodes. */
|
|
58
|
+
export declare function recurrent<N>(g: Graph<N>, opts?: LayeredOpts<N>): Map<N, Placement>;
|
|
59
|
+
export interface LanesOpts<N> {
|
|
60
|
+
/** Row height (topological order axis). Default 56. */
|
|
61
|
+
rowGap?: number;
|
|
62
|
+
/** Lane width (column axis). Default 46. */
|
|
63
|
+
laneGap?: number;
|
|
64
|
+
sizeOf?: (n: N) => Size;
|
|
65
|
+
}
|
|
66
|
+
/** Git-style lane packing: nodes flow top-to-bottom in topological
|
|
67
|
+
* order (one row each), each assigned the first free column ("lane")
|
|
68
|
+
* that no live edge occupies. Branch points open lanes, merges free
|
|
69
|
+
* them. Expects a DAG whose `nodes` are in commit order (parents
|
|
70
|
+
* before children). */
|
|
71
|
+
export declare function lanes<N>(g: Graph<N>, opts?: LanesOpts<N>): Map<N, Placement>;
|
|
72
|
+
/** Bounding size of a placement map. */
|
|
73
|
+
export declare function extent<N>(p: Map<N, Placement>): Size;
|