flexdesk 0.5.0 → 0.6.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.
Files changed (70) hide show
  1. package/README.md +654 -1
  2. package/css/base.css +2868 -0
  3. package/css/flexdesk.css +2868 -0
  4. package/css/tokens.css +72 -0
  5. package/dist/canvas.js +390 -0
  6. package/dist/canvas.js.map +7 -0
  7. package/dist/charts.js +2 -2
  8. package/dist/{chunk-24MS7W5Y.js → chunk-6NG7YVBG.js} +2 -470
  9. package/dist/chunk-6NG7YVBG.js.map +7 -0
  10. package/dist/chunk-H4LT43RS.js +475 -0
  11. package/dist/chunk-H4LT43RS.js.map +7 -0
  12. package/dist/{chunk-KH2GJTKR.js → chunk-IYV5JVYB.js} +29 -1
  13. package/dist/chunk-IYV5JVYB.js.map +7 -0
  14. package/dist/chunk-SN4LSOAR.js +532 -0
  15. package/dist/chunk-SN4LSOAR.js.map +7 -0
  16. package/dist/{chunk-CNXP3SIN.js → chunk-ZMCRDOCF.js} +2 -2
  17. package/dist/flexdesk.css +2868 -0
  18. package/dist/flow.js +10030 -0
  19. package/dist/flow.js.map +7 -0
  20. package/dist/tiles.js +9 -9
  21. package/dist/tokens.css +72 -0
  22. package/dist/widgets.js +87 -5
  23. package/dist/widgets.js.map +3 -3
  24. package/dist/wm.js +4 -2
  25. package/dist/wm.js.map +1 -1
  26. package/package.json +9 -1
  27. package/src/canvas/canvas_adapter.js +523 -0
  28. package/src/canvas/edge_router.js +392 -0
  29. package/src/canvas/graph/connector_router.js +189 -0
  30. package/src/canvas/graph/history_service.js +170 -0
  31. package/src/canvas/graph/node_platform.js +116 -0
  32. package/src/canvas/index.js +16 -0
  33. package/src/flow/canvas_editor/editor.js +1081 -0
  34. package/src/flow/canvas_editor/index.js +16 -0
  35. package/src/flow/canvas_editor/layout.js +118 -0
  36. package/src/flow/canvas_editor/strings.js +37 -0
  37. package/src/flow/kit/always_before.js +325 -0
  38. package/src/flow/kit/catalogue.js +170 -0
  39. package/src/flow/kit/chip_input.js +461 -0
  40. package/src/flow/kit/dom.js +205 -0
  41. package/src/flow/kit/findings.js +129 -0
  42. package/src/flow/kit/history.js +173 -0
  43. package/src/flow/kit/index.js +38 -0
  44. package/src/flow/kit/keys.js +127 -0
  45. package/src/flow/kit/logic_graph.js +210 -0
  46. package/src/flow/kit/references.js +199 -0
  47. package/src/flow/kit/settings_panel.js +357 -0
  48. package/src/flow/kit/settings_schema.js +175 -0
  49. package/src/flow/kit/step_picker.js +209 -0
  50. package/src/flow/kit/strings.js +102 -0
  51. package/src/flow/kit/value_picker.js +238 -0
  52. package/src/flow/kit/widgets.js +763 -0
  53. package/src/flow/lanes/editor.js +1469 -0
  54. package/src/flow/lanes/index.js +26 -0
  55. package/src/flow/lanes/layout.js +525 -0
  56. package/src/flow/lanes/pipeline.js +327 -0
  57. package/src/flow/lanes/preview.js +109 -0
  58. package/src/flow/lanes/strings.js +98 -0
  59. package/src/flow/outline/editor.js +1511 -0
  60. package/src/flow/outline/index.js +20 -0
  61. package/src/flow/outline/mapping.js +286 -0
  62. package/src/flow/outline/menu.js +154 -0
  63. package/src/flow/outline/operations.js +738 -0
  64. package/src/flow/outline/recognise.js +755 -0
  65. package/src/flow/outline/strings.js +135 -0
  66. package/src/ui/components/data_table.js +40 -0
  67. package/src/ui/utils/scroll_lock.js +111 -0
  68. package/dist/chunk-24MS7W5Y.js.map +0 -7
  69. package/dist/chunk-KH2GJTKR.js.map +0 -7
  70. /package/dist/{chunk-CNXP3SIN.js.map → chunk-ZMCRDOCF.js.map} +0 -0
package/css/tokens.css CHANGED
@@ -193,4 +193,76 @@
193
193
  to its OWN 0.4 values when a token is unset (normal: 6px 8px and an
194
194
  inherited line height; compact: 2px 6px and 1.35), and a default here
195
195
  would replace both densities' values with one. */
196
+
197
+ /* ── Flow editors (@flexdesk/flow) — TONES, not colours ───────────
198
+ A step-type category names a TONE (`violet`, `teal`, `amber`, `grey`,
199
+ `blue`, `indigo`) and these map the tone to its colours, so a consumer
200
+ restyles every editor's categories here and nowhere else. Each tone is:
201
+
202
+ -bg / -fg a step's icon chip, a picker row's chip, a chip's fill
203
+ -line a reference chip's border
204
+ -icon-bg a lane card's icon zone
205
+ -text-bg a lane card's text zone
206
+ -dot a step tab's dot
207
+
208
+ New in the flow work and read by nothing older, so defining them
209
+ changes no existing screen. The values are the approved mocks'. */
210
+ --twm-flow-violet-bg: rgba(167, 139, 250, 0.16);
211
+ --twm-flow-violet-fg: #c6b4fb;
212
+ --twm-flow-violet-line: rgba(167, 139, 250, 0.45);
213
+ --twm-flow-violet-icon-bg: #351a40;
214
+ --twm-flow-violet-text-bg: #261e30;
215
+ --twm-flow-violet-dot: #a785e8;
216
+
217
+ --twm-flow-teal-bg: rgba(45, 180, 165, 0.17);
218
+ --twm-flow-teal-fg: #72d8c8;
219
+ --twm-flow-teal-line: rgba(45, 180, 165, 0.45);
220
+ --twm-flow-teal-icon-bg: #1a403a;
221
+ --twm-flow-teal-text-bg: #1a2b2a;
222
+ --twm-flow-teal-dot: #3fb8a6;
223
+
224
+ --twm-flow-amber-bg: rgba(222, 150, 70, 0.17);
225
+ --twm-flow-amber-fg: #ecb27a;
226
+ --twm-flow-amber-line: rgba(215, 163, 74, 0.45);
227
+ --twm-flow-amber-icon-bg: #3a3018;
228
+ --twm-flow-amber-text-bg: #2b2518;
229
+ --twm-flow-amber-dot: #d79a52;
230
+
231
+ --twm-flow-grey-bg: rgba(255, 255, 255, 0.08);
232
+ --twm-flow-grey-fg: #c4c4c4;
233
+ --twm-flow-grey-line: rgba(255, 255, 255, 0.28);
234
+ --twm-flow-grey-icon-bg: #333334;
235
+ --twm-flow-grey-text-bg: #262627;
236
+ --twm-flow-grey-dot: #9a9a9a;
237
+
238
+ --twm-flow-blue-bg: rgba(22, 131, 196, 0.22);
239
+ --twm-flow-blue-fg: #a8d4f2;
240
+ --twm-flow-blue-line: rgba(80, 160, 220, 0.45);
241
+ --twm-flow-blue-icon-bg: #173447;
242
+ --twm-flow-blue-text-bg: #1a2630;
243
+ --twm-flow-blue-dot: #4aa3dc;
244
+
245
+ --twm-flow-indigo-bg: rgba(127, 140, 240, 0.17);
246
+ --twm-flow-indigo-fg: #aab6fb;
247
+ --twm-flow-indigo-line: rgba(127, 140, 240, 0.45);
248
+ --twm-flow-indigo-icon-bg: #252850;
249
+ --twm-flow-indigo-text-bg: #1e1f30;
250
+ --twm-flow-indigo-dot: #7f8cf0;
251
+
252
+ /* The kit's own surfaces and signal colours (the mocks' values). The
253
+ focus ring is the canonical bright accent, so a consumer that restyles
254
+ the accent restyles it. */
255
+ --twm-flow-control-bg: #2b2b2c;
256
+ --twm-flow-control-border: #454545;
257
+ --twm-flow-muted: #a6a6a6;
258
+ --twm-flow-focus: var(--accent-bright);
259
+ --twm-flow-error: #f48771;
260
+ --twm-flow-error-bg: rgba(244, 135, 113, 0.09);
261
+ --twm-flow-error-line: rgba(244, 135, 113, 0.35);
262
+ --twm-flow-error-text: #f2cfc6;
263
+ --twm-flow-warning: #e2b366;
264
+ --twm-flow-warning-bg: rgba(226, 179, 102, 0.09);
265
+ --twm-flow-warning-line: rgba(226, 179, 102, 0.35);
266
+ --twm-flow-warning-text: #f0dcb8;
267
+ --twm-flow-ok: #89d185;
196
268
  }
package/dist/canvas.js ADDED
@@ -0,0 +1,390 @@
1
+ import {
2
+ CanvasAdapter,
3
+ OBSTACLE_ROUTING_NODE_LIMIT,
4
+ arrange,
5
+ cardinality,
6
+ crowsFoot,
7
+ footAnchor,
8
+ returnEdge,
9
+ routeEdge,
10
+ selfLoop
11
+ } from "./chunk-SN4LSOAR.js";
12
+ import "./chunk-JYWURG5T.js";
13
+
14
+ // src/canvas/graph/node_platform.js
15
+ var NodePlatform = class {
16
+ /**
17
+ * @param {object} [options]
18
+ * @param {(node: object) => object[]} [options.collapsedPorts] the ports a COLLAPSED node
19
+ * still offers; by default none
20
+ */
21
+ constructor({ collapsedPorts = null } = {}) {
22
+ this.nodes = /* @__PURE__ */ new Map();
23
+ this.listeners = /* @__PURE__ */ new Map();
24
+ this.collapsedPorts = typeof collapsedPorts === "function" ? collapsedPorts : null;
25
+ }
26
+ on(event, handler) {
27
+ if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
28
+ this.listeners.get(event).add(handler);
29
+ return () => this.listeners.get(event).delete(handler);
30
+ }
31
+ emit(event, payload) {
32
+ for (const handler of this.listeners.get(event) || []) handler(payload);
33
+ }
34
+ /**
35
+ * Replace the whole graph. Hydration, not an edit — see `HistoryService`.
36
+ *
37
+ * Each node is `{id, position?, size?, collapsed?, ports?, …}`: the position
38
+ * is copied (a missing one is (0, 0)), `size` is `{w, h}` or null, `ports`
39
+ * an array (none when absent), and every other key is kept as it is.
40
+ */
41
+ hydrate(nodes) {
42
+ this.nodes.clear();
43
+ for (const raw of Array.isArray(nodes) ? nodes : []) {
44
+ if (!raw || raw.id === void 0 || raw.id === null) continue;
45
+ const id = raw.id;
46
+ this.nodes.set(id, {
47
+ ...raw,
48
+ id,
49
+ // `size` and `collapsed` are in the snapshot, not derived: at
50
+ // hundreds of nodes a node showing forty ports is unreadable, and
51
+ // a collapsed node's ports fold away.
52
+ position: raw.position ? { x: raw.position.x, y: raw.position.y } : { x: 0, y: 0 },
53
+ size: raw.size ? { w: raw.size.w, h: raw.size.h } : null,
54
+ collapsed: Boolean(raw.collapsed),
55
+ ports: Array.isArray(raw.ports) ? raw.ports : []
56
+ });
57
+ }
58
+ this.emit("hydrated", { count: this.nodes.size });
59
+ }
60
+ get(id) {
61
+ return this.nodes.get(id);
62
+ }
63
+ all() {
64
+ return [...this.nodes.values()];
65
+ }
66
+ port(nodeId, portId) {
67
+ return this.nodes.get(nodeId)?.ports.find((p) => p.id === portId) || null;
68
+ }
69
+ setPosition(id, position, { silent = false } = {}) {
70
+ const node = this.nodes.get(id);
71
+ if (!node) return null;
72
+ const before = { ...node.position };
73
+ node.position = { ...position };
74
+ if (!silent) this.emit("moved", { id, before, after: { ...position } });
75
+ return before;
76
+ }
77
+ setCollapsed(id, collapsed, { silent = false } = {}) {
78
+ const node = this.nodes.get(id);
79
+ if (!node) return null;
80
+ const before = node.collapsed;
81
+ node.collapsed = Boolean(collapsed);
82
+ if (!silent) this.emit("collapsed", { id, before, after: node.collapsed });
83
+ return before;
84
+ }
85
+ /**
86
+ * Ports that are visible right now.
87
+ *
88
+ * A collapsed node offers only what `collapsedPorts` says it keeps (by
89
+ * default nothing). Answering from one place is what stops a renderer and
90
+ * the legality guard disagreeing about what can be dropped on.
91
+ */
92
+ visiblePorts(id) {
93
+ const node = this.nodes.get(id);
94
+ if (!node) return [];
95
+ if (node.collapsed) return this.collapsedPorts ? this.collapsedPorts(node) : [];
96
+ return node.ports;
97
+ }
98
+ };
99
+
100
+ // src/canvas/graph/connector_router.js
101
+ var CONNECTOR_STRINGS = Object.freeze({
102
+ nodeGone: "That node is no longer on the canvas.",
103
+ portGone: "That port is no longer on the canvas.",
104
+ portDisabled: "That port cannot be connected.",
105
+ selfReference: "A node cannot connect to itself on this canvas.",
106
+ portFull: (max) => max === 1 ? "That port already carries its one connection." : `That port already carries its ${max} connections.`
107
+ });
108
+ var say = (strings, key, ...args) => {
109
+ const s = strings[key];
110
+ return typeof s === "function" ? s(...args) : String(s);
111
+ };
112
+ var defaultEndsOf = (edge) => ({ from: edge?.fromPort ?? null, to: edge?.toPort ?? null });
113
+ function capacityOf(port) {
114
+ if (Number.isFinite(port?.maxConnections)) return port.maxConnections;
115
+ if (port?.allowMultiple === false) return 1;
116
+ return Infinity;
117
+ }
118
+ var ConnectorRouter = class {
119
+ /**
120
+ * @param {object} o
121
+ * @param {object} o.platform a `NodePlatform`
122
+ * @param {boolean} [o.selfReference] may a node connect to itself
123
+ * @param {(ctx: object) => object|null|undefined} [o.policy] the embedder's rules, asked last
124
+ * @param {(edge: object) => {from, to}} [o.endsOf] the port ids an edge uses at each end
125
+ * @param {('source'|'target')[]} [o.disabledEnds] which ends a disabled port refuses
126
+ * @param {object} [o.strings] the generic refusals' words
127
+ */
128
+ constructor({
129
+ platform,
130
+ selfReference = false,
131
+ policy = null,
132
+ endsOf = null,
133
+ disabledEnds = ["source", "target"],
134
+ strings = null
135
+ } = {}) {
136
+ this.platform = platform;
137
+ this.selfReference = selfReference;
138
+ this.policy = typeof policy === "function" ? policy : null;
139
+ this.endsOf = typeof endsOf === "function" ? endsOf : defaultEndsOf;
140
+ this.disabledEnds = new Set(disabledEnds);
141
+ this.strings = Object.freeze({ ...CONNECTOR_STRINGS, ...strings || {} });
142
+ this.edges = /* @__PURE__ */ new Map();
143
+ }
144
+ hydrate(edges) {
145
+ this.edges.clear();
146
+ for (const edge of edges) this.edges.set(edge.id, edge);
147
+ }
148
+ /** Every edge already touching this node, in either direction. */
149
+ edgesFor(nodeId) {
150
+ return [...this.edges.values()].filter((e) => e.from === nodeId || e.to === nodeId);
151
+ }
152
+ /** How many edges (applied and `pending`) already use this port at this node. */
153
+ connectionsAt(nodeId, portId, { pendingEdges = [] } = {}) {
154
+ let n = 0;
155
+ for (const edge of [...this.edges.values(), ...pendingEdges]) {
156
+ const ends = this.endsOf(edge) || {};
157
+ if (edge.from === nodeId && ends.from === portId) n += 1;
158
+ if (edge.to === nodeId && ends.to === portId) n += 1;
159
+ }
160
+ return n;
161
+ }
162
+ /**
163
+ * Can this drop become an edge?
164
+ *
165
+ * `source` and `target` are `{nodeId, portId}`. The answer is a verdict the
166
+ * caller can render directly — the reason strings ARE the notice text, so a
167
+ * policy should name the objects rather than describe the rule.
168
+ */
169
+ canConnect(source, target, { pendingEdges = [] } = {}) {
170
+ const S = this.strings;
171
+ const fromNode = this.platform.get(source.nodeId);
172
+ const toNode = this.platform.get(target.nodeId);
173
+ if (!fromNode || !toNode) return { ok: false, reason: say(S, "nodeGone") };
174
+ const fromPort = this.platform.port(source.nodeId, source.portId);
175
+ const toPort = this.platform.port(target.nodeId, target.portId);
176
+ if (!fromPort || !toPort) return { ok: false, reason: say(S, "portGone") };
177
+ if (fromPort.disabled && this.disabledEnds.has("source")) {
178
+ return { ok: false, reason: fromPort.disabledReason || say(S, "portDisabled") };
179
+ }
180
+ if (toPort.disabled && this.disabledEnds.has("target")) {
181
+ return { ok: false, reason: toPort.disabledReason || say(S, "portDisabled") };
182
+ }
183
+ const selfReference = fromNode.id === toNode.id;
184
+ if (selfReference && !this.selfReference) return { ok: false, reason: say(S, "selfReference") };
185
+ for (const [node, port] of [[fromNode, fromPort], [toNode, toPort]]) {
186
+ const max = capacityOf(port);
187
+ if (max !== Infinity && this.connectionsAt(node.id, port.id, { pendingEdges }) >= max) {
188
+ return { ok: false, reason: say(S, "portFull", max) };
189
+ }
190
+ }
191
+ if (this.policy) {
192
+ const verdict = this.policy({
193
+ source,
194
+ target,
195
+ fromNode,
196
+ toNode,
197
+ fromPort,
198
+ toPort,
199
+ pendingEdges,
200
+ selfReference,
201
+ edges: [...this.edges.values()],
202
+ router: this
203
+ });
204
+ if (verdict && typeof verdict === "object") return verdict;
205
+ }
206
+ return { ok: true, selfReference };
207
+ }
208
+ /**
209
+ * Record a STAGED edge. Nothing here talks to a server — the embedder turns
210
+ * a staged edge into whatever its own write is, and only that makes it real.
211
+ */
212
+ stage(edge) {
213
+ this.edges.set(edge.id, edge);
214
+ return edge;
215
+ }
216
+ unstage(id) {
217
+ const edge = this.edges.get(id);
218
+ this.edges.delete(id);
219
+ return edge || null;
220
+ }
221
+ /**
222
+ * Re-map edges when a node's port set is rebuilt.
223
+ *
224
+ * A node gains or loses a port constantly in a live diagram. Matches by port
225
+ * id, drops what cannot be mapped, and reports both — a silently dropped
226
+ * edge is a line that vanished from the drawing while what it stands for
227
+ * still exists. `endsOf` (else the router's own) names the ports an edge
228
+ * uses; an end that names none is not checked.
229
+ */
230
+ remapNodeConnections(nodeId, portIds, { endsOf = null } = {}) {
231
+ const ends = typeof endsOf === "function" ? endsOf : this.endsOf;
232
+ const available = new Set(portIds);
233
+ let remapped = 0;
234
+ const removed = [];
235
+ for (const [id, edge] of [...this.edges]) {
236
+ const at = ends(edge) || {};
237
+ const touches = [];
238
+ if (edge.from === nodeId && at.from !== null && at.from !== void 0) touches.push(at.from);
239
+ if (edge.to === nodeId && at.to !== null && at.to !== void 0) touches.push(at.to);
240
+ if (edge.from !== nodeId && edge.to !== nodeId) continue;
241
+ if (touches.every((portId) => available.has(portId))) {
242
+ remapped += 1;
243
+ continue;
244
+ }
245
+ this.edges.delete(id);
246
+ removed.push(edge);
247
+ }
248
+ return { remapped, removed };
249
+ }
250
+ };
251
+
252
+ // src/canvas/graph/history_service.js
253
+ var DEFAULT_LIMIT = 200;
254
+ var missing = (name) => new Error(
255
+ `HistoryService needs ${name}. Constructing it without the full dependency set is how an undo engine ends up silently doing nothing.`
256
+ );
257
+ var HistoryService = class {
258
+ /**
259
+ * @param {object} o
260
+ * @param {readonly string[]} o.actions the only actions `record` accepts
261
+ * @param {(entry: object, direction: 'undo'|'redo') => void} o.apply puts one entry back (or forward)
262
+ * @param {(state: {canUndo, canRedo, depth}) => void} [o.onState]
263
+ * @param {number} [o.limit] entries kept; the oldest goes first
264
+ * @param {object} [o.requires] `{name: value}` a subclass cannot work without; each is checked
265
+ * @param {(action: string) => string} [o.refusal] the sentence a refused `record` throws
266
+ */
267
+ constructor({ actions, apply, onState, limit = DEFAULT_LIMIT, requires = null, refusal = null } = {}) {
268
+ for (const [name, value] of Object.entries(requires || {})) {
269
+ if (!value) throw missing(name);
270
+ }
271
+ if (!Array.isArray(actions) || !actions.length) throw missing("actions (its closed list)");
272
+ if (typeof apply !== "function") throw missing("apply(entry, direction)");
273
+ this.actions = Object.freeze([...actions]);
274
+ this._applyEntry = apply;
275
+ this.onState = onState;
276
+ this.limit = limit;
277
+ this.refusal = typeof refusal === "function" ? refusal : null;
278
+ this.undoStack = [];
279
+ this.redoStack = [];
280
+ this.recording = false;
281
+ this.batch = null;
282
+ }
283
+ /** The drawing has been loaded: the stacks start empty, and recording starts. */
284
+ hydrated() {
285
+ this.undoStack = [];
286
+ this.redoStack = [];
287
+ this.recording = true;
288
+ this._publish();
289
+ }
290
+ /** Group what is recorded until `endBatch` into one entry. */
291
+ startBatch(label) {
292
+ if (!this.recording) return;
293
+ this.batch = { action: "batch", label, entries: [] };
294
+ }
295
+ endBatch() {
296
+ if (!this.batch) return;
297
+ const batch = this.batch;
298
+ this.batch = null;
299
+ if (batch.entries.length) this._push(batch);
300
+ }
301
+ record(action, payload) {
302
+ if (!this.recording) return;
303
+ if (!this.actions.includes(action)) {
304
+ throw new Error(this.refusal ? this.refusal(action) : `${action} is not an undoable action here; the ones that are: ${this.actions.join(", ")}.`);
305
+ }
306
+ const entry = { action, ...payload };
307
+ if (this.batch) {
308
+ this.batch.entries.push(entry);
309
+ return;
310
+ }
311
+ this._push(entry);
312
+ }
313
+ undo() {
314
+ const entry = this.undoStack.pop();
315
+ if (!entry) return false;
316
+ this._apply(entry, "undo");
317
+ this.redoStack.push(entry);
318
+ this._publish();
319
+ return true;
320
+ }
321
+ redo() {
322
+ const entry = this.redoStack.pop();
323
+ if (!entry) return false;
324
+ this._apply(entry, "redo");
325
+ this.undoStack.push(entry);
326
+ this._publish();
327
+ return true;
328
+ }
329
+ reset() {
330
+ this.undoStack = [];
331
+ this.redoStack = [];
332
+ this._publish();
333
+ }
334
+ /**
335
+ * Take over the undo and redo stacks of a torn-down view whose state this
336
+ * one has just taken on, entry for entry and in the same order. Nothing new
337
+ * becomes undoable: every entry was recorded through a `record` whose action
338
+ * list is closed, so a stack can only carry what that list allows. Call it
339
+ * after `hydrated()`.
340
+ */
341
+ adopt({ undo = [], redo = [] } = {}) {
342
+ if (!this.recording) return;
343
+ this.undoStack = [...undo].slice(-this.limit);
344
+ this.redoStack = [...redo];
345
+ this._publish();
346
+ }
347
+ get canUndo() {
348
+ return this.undoStack.length > 0;
349
+ }
350
+ get canRedo() {
351
+ return this.redoStack.length > 0;
352
+ }
353
+ _push(entry) {
354
+ this.undoStack.push(entry);
355
+ this.redoStack = [];
356
+ if (this.undoStack.length > this.limit) this.undoStack.shift();
357
+ this._publish();
358
+ }
359
+ _publish() {
360
+ this.onState?.({
361
+ canUndo: this.canUndo,
362
+ canRedo: this.canRedo,
363
+ depth: this.undoStack.length
364
+ });
365
+ }
366
+ _apply(entry, direction) {
367
+ if (entry.action === "batch") {
368
+ const entries = direction === "undo" ? [...entry.entries].reverse() : entry.entries;
369
+ for (const child of entries) this._apply(child, direction);
370
+ return;
371
+ }
372
+ this._applyEntry(entry, direction);
373
+ }
374
+ };
375
+ export {
376
+ CONNECTOR_STRINGS,
377
+ CanvasAdapter,
378
+ ConnectorRouter,
379
+ HistoryService,
380
+ NodePlatform,
381
+ OBSTACLE_ROUTING_NODE_LIMIT,
382
+ arrange,
383
+ cardinality,
384
+ crowsFoot,
385
+ footAnchor,
386
+ returnEdge,
387
+ routeEdge,
388
+ selfLoop
389
+ };
390
+ //# sourceMappingURL=canvas.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/canvas/graph/node_platform.js", "../src/canvas/graph/connector_router.js", "../src/canvas/graph/history_service.js"],
4
+ "sourcesContent": ["/**\n * The canvas kernel \u2014 GRAPH LAYER: the node and port model (36 \u00A74.3).\n *\n * GENERIC. It holds nodes \u2014 each `{id, position, size, collapsed, ports}` plus\n * whatever else the embedder hangs on it \u2014 and answers which ports a node\n * offers. What a node IS (a table, a step, a form field) and which ports a\n * collapsed one keeps are the embedder's: a subclass builds the nodes and\n * calls `hydrate`, and the `collapsedPorts(node)` option decides what a folded\n * node shows.\n *\n * The genuinely reusable idea is the shape of a port descriptor \u2014 `{id, role,\n * direction, type, accepts, provides, allowMultiple, maxConnections, disabled,\n * disabledReason, meta}` \u2014 which is what lets one legality guard\n * (`ConnectorRouter`) serve a schema diagram, a flow graph and a form\n * designer. Nothing here requires any of those keys but `id`; the router reads\n * the ones it knows.\n *\n * DOM-free on purpose. It holds the graph; the embedder renders it. That split\n * is what makes the legality guard and the history service testable under\n * plain node.\n *\n * Events (`on(name, handler)` \u2192 an unsubscribe):\n * `hydrated` `{count}` after `hydrate`\n * `moved` `{id, before, after}` after a `setPosition` that is not `silent`\n * `collapsed` `{id, before, after}` after a `setCollapsed` that is not `silent`\n */\n\nexport class NodePlatform {\n /**\n * @param {object} [options]\n * @param {(node: object) => object[]} [options.collapsedPorts] the ports a COLLAPSED node\n * still offers; by default none\n */\n constructor({ collapsedPorts = null } = {}) {\n /** @type {Map<string, object>} node id -> snapshot */\n this.nodes = new Map();\n this.listeners = new Map();\n this.collapsedPorts = typeof collapsedPorts === 'function' ? collapsedPorts : null;\n }\n\n on(event, handler) {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n this.listeners.get(event).add(handler);\n return () => this.listeners.get(event).delete(handler);\n }\n\n emit(event, payload) {\n for (const handler of this.listeners.get(event) || []) handler(payload);\n }\n\n /**\n * Replace the whole graph. Hydration, not an edit \u2014 see `HistoryService`.\n *\n * Each node is `{id, position?, size?, collapsed?, ports?, \u2026}`: the position\n * is copied (a missing one is (0, 0)), `size` is `{w, h}` or null, `ports`\n * an array (none when absent), and every other key is kept as it is.\n */\n hydrate(nodes) {\n this.nodes.clear();\n for (const raw of Array.isArray(nodes) ? nodes : []) {\n if (!raw || raw.id === undefined || raw.id === null) continue;\n const id = raw.id;\n this.nodes.set(id, {\n ...raw,\n id,\n // `size` and `collapsed` are in the snapshot, not derived: at\n // hundreds of nodes a node showing forty ports is unreadable, and\n // a collapsed node's ports fold away.\n position: raw.position ? { x: raw.position.x, y: raw.position.y } : { x: 0, y: 0 },\n size: raw.size ? { w: raw.size.w, h: raw.size.h } : null,\n collapsed: Boolean(raw.collapsed),\n ports: Array.isArray(raw.ports) ? raw.ports : [],\n });\n }\n this.emit('hydrated', { count: this.nodes.size });\n }\n\n get(id) { return this.nodes.get(id); }\n all() { return [...this.nodes.values()]; }\n\n port(nodeId, portId) {\n return this.nodes.get(nodeId)?.ports.find((p) => p.id === portId) || null;\n }\n\n setPosition(id, position, { silent = false } = {}) {\n const node = this.nodes.get(id);\n if (!node) return null;\n const before = { ...node.position };\n node.position = { ...position };\n if (!silent) this.emit('moved', { id, before, after: { ...position } });\n return before;\n }\n\n setCollapsed(id, collapsed, { silent = false } = {}) {\n const node = this.nodes.get(id);\n if (!node) return null;\n const before = node.collapsed;\n node.collapsed = Boolean(collapsed);\n if (!silent) this.emit('collapsed', { id, before, after: node.collapsed });\n return before;\n }\n\n /**\n * Ports that are visible right now.\n *\n * A collapsed node offers only what `collapsedPorts` says it keeps (by\n * default nothing). Answering from one place is what stops a renderer and\n * the legality guard disagreeing about what can be dropped on.\n */\n visiblePorts(id) {\n const node = this.nodes.get(id);\n if (!node) return [];\n if (node.collapsed) return this.collapsedPorts ? this.collapsedPorts(node) : [];\n return node.ports;\n }\n}\n", "/**\n * The canvas kernel \u2014 GRAPH LAYER: the edge model and its legality guard\n * (36 \u00A74.3).\n *\n * THE POINT OF THIS FILE IS THAT A DROP IS REFUSED \u2014 OR BETTER, NEGOTIATED \u2014\n * BEFORE ANY NETWORK CALL. A gesture that produces a round trip and then a\n * server error reads as a broken editor; the same gesture producing an\n * immediate reason reads as an editor that knows the rules.\n *\n * GENERIC. `canConnect` makes the refusals every graph shares, in this order:\n *\n * 1. an end is gone \u2014 a node the platform no longer has\n * 2. a port is gone \u2014 a port its node no longer has\n * 3. a disabled port \u2014 `port.disabled`, refused with `port.disabledReason`\n * when it carries one (by default at either end;\n * `disabledEnds: ['source']` asks only of the source)\n * 4. a self-reference \u2014 unless `selfReference: true`\n * 5. capacity \u2014 a port with `maxConnections` (or `allowMultiple:\n * false`, which is one) that already carries that many\n *\n * and THEN asks the embedder's `policy(ctx)`, which is where a domain's own rules\n * live \u2014 and its sentences. A policy returns a verdict, or nothing for \"allowed\".\n *\n * SELF-REFERENCES ARE OPT-IN PER ROUTER rather than blanket-refused:\n * `employee.manager_id \u2192 employee` is the most common recursive relationship\n * in business schemas, and a diagram of them needs it on; a graph that must be\n * a DAG leaves it off. There is no cycle detection here at all \u2014 mutual\n * references are legal and common, and a graph that needs a DAG says so in\n * its policy.\n *\n * A verdict is `{ok: true, selfReference, \u2026}` or `{ok: false, reason}`. A policy\n * may answer `{ok: true, offer: {\u2026}}`: a drop that is legal once something\n * else changes too is an OFFER, not a failure.\n *\n * An edge is the embedder's object with at least `{id, from, to}`; which PORT\n * each end uses is read through `endsOf(edge) \u2192 {from, to}` (port ids, or null\n * for an end that names none), by default `edge.fromPort` and `edge.toPort`.\n */\n\nexport const CONNECTOR_STRINGS = Object.freeze({\n nodeGone: 'That node is no longer on the canvas.',\n portGone: 'That port is no longer on the canvas.',\n portDisabled: 'That port cannot be connected.',\n selfReference: 'A node cannot connect to itself on this canvas.',\n portFull: (max) => (max === 1 ? 'That port already carries its one connection.'\n : `That port already carries its ${max} connections.`),\n});\n\nconst say = (strings, key, ...args) => {\n const s = strings[key];\n return typeof s === 'function' ? s(...args) : String(s);\n};\n\nconst defaultEndsOf = (edge) => ({ from: edge?.fromPort ?? null, to: edge?.toPort ?? null });\n\n/** The most connections a port may carry: `maxConnections`, else one when it allows no more. */\nfunction capacityOf(port) {\n if (Number.isFinite(port?.maxConnections)) return port.maxConnections;\n if (port?.allowMultiple === false) return 1;\n return Infinity;\n}\n\nexport class ConnectorRouter {\n /**\n * @param {object} o\n * @param {object} o.platform a `NodePlatform`\n * @param {boolean} [o.selfReference] may a node connect to itself\n * @param {(ctx: object) => object|null|undefined} [o.policy] the embedder's rules, asked last\n * @param {(edge: object) => {from, to}} [o.endsOf] the port ids an edge uses at each end\n * @param {('source'|'target')[]} [o.disabledEnds] which ends a disabled port refuses\n * @param {object} [o.strings] the generic refusals' words\n */\n constructor({ platform, selfReference = false, policy = null, endsOf = null,\n disabledEnds = ['source', 'target'], strings = null } = {}) {\n this.platform = platform;\n this.selfReference = selfReference;\n this.policy = typeof policy === 'function' ? policy : null;\n this.endsOf = typeof endsOf === 'function' ? endsOf : defaultEndsOf;\n this.disabledEnds = new Set(disabledEnds);\n this.strings = Object.freeze({ ...CONNECTOR_STRINGS, ...(strings || {}) });\n /** @type {Map<string, object>} edge id -> edge */\n this.edges = new Map();\n }\n\n hydrate(edges) {\n this.edges.clear();\n for (const edge of edges) this.edges.set(edge.id, edge);\n }\n\n /** Every edge already touching this node, in either direction. */\n edgesFor(nodeId) {\n return [...this.edges.values()].filter((e) => e.from === nodeId || e.to === nodeId);\n }\n\n /** How many edges (applied and `pending`) already use this port at this node. */\n connectionsAt(nodeId, portId, { pendingEdges = [] } = {}) {\n let n = 0;\n for (const edge of [...this.edges.values(), ...pendingEdges]) {\n const ends = this.endsOf(edge) || {};\n if (edge.from === nodeId && ends.from === portId) n += 1;\n if (edge.to === nodeId && ends.to === portId) n += 1;\n }\n return n;\n }\n\n /**\n * Can this drop become an edge?\n *\n * `source` and `target` are `{nodeId, portId}`. The answer is a verdict the\n * caller can render directly \u2014 the reason strings ARE the notice text, so a\n * policy should name the objects rather than describe the rule.\n */\n canConnect(source, target, { pendingEdges = [] } = {}) {\n const S = this.strings;\n const fromNode = this.platform.get(source.nodeId);\n const toNode = this.platform.get(target.nodeId);\n if (!fromNode || !toNode) return { ok: false, reason: say(S, 'nodeGone') };\n const fromPort = this.platform.port(source.nodeId, source.portId);\n const toPort = this.platform.port(target.nodeId, target.portId);\n if (!fromPort || !toPort) return { ok: false, reason: say(S, 'portGone') };\n if (fromPort.disabled && this.disabledEnds.has('source')) {\n return { ok: false, reason: fromPort.disabledReason || say(S, 'portDisabled') };\n }\n if (toPort.disabled && this.disabledEnds.has('target')) {\n return { ok: false, reason: toPort.disabledReason || say(S, 'portDisabled') };\n }\n const selfReference = fromNode.id === toNode.id;\n if (selfReference && !this.selfReference) return { ok: false, reason: say(S, 'selfReference') };\n for (const [node, port] of [[fromNode, fromPort], [toNode, toPort]]) {\n const max = capacityOf(port);\n if (max !== Infinity && this.connectionsAt(node.id, port.id, { pendingEdges }) >= max) {\n return { ok: false, reason: say(S, 'portFull', max) };\n }\n }\n if (this.policy) {\n const verdict = this.policy({\n source, target, fromNode, toNode, fromPort, toPort, pendingEdges, selfReference,\n edges: [...this.edges.values()], router: this,\n });\n if (verdict && typeof verdict === 'object') return verdict;\n }\n return { ok: true, selfReference };\n }\n\n /**\n * Record a STAGED edge. Nothing here talks to a server \u2014 the embedder turns\n * a staged edge into whatever its own write is, and only that makes it real.\n */\n stage(edge) {\n this.edges.set(edge.id, edge);\n return edge;\n }\n\n unstage(id) {\n const edge = this.edges.get(id);\n this.edges.delete(id);\n return edge || null;\n }\n\n /**\n * Re-map edges when a node's port set is rebuilt.\n *\n * A node gains or loses a port constantly in a live diagram. Matches by port\n * id, drops what cannot be mapped, and reports both \u2014 a silently dropped\n * edge is a line that vanished from the drawing while what it stands for\n * still exists. `endsOf` (else the router's own) names the ports an edge\n * uses; an end that names none is not checked.\n */\n remapNodeConnections(nodeId, portIds, { endsOf = null } = {}) {\n const ends = typeof endsOf === 'function' ? endsOf : this.endsOf;\n const available = new Set(portIds);\n let remapped = 0;\n const removed = [];\n for (const [id, edge] of [...this.edges]) {\n const at = ends(edge) || {};\n const touches = [];\n if (edge.from === nodeId && at.from !== null && at.from !== undefined) touches.push(at.from);\n if (edge.to === nodeId && at.to !== null && at.to !== undefined) touches.push(at.to);\n if (edge.from !== nodeId && edge.to !== nodeId) continue;\n if (touches.every((portId) => available.has(portId))) {\n remapped += 1;\n continue;\n }\n this.edges.delete(id);\n removed.push(edge);\n }\n return { remapped, removed };\n }\n}\n", "/**\n * The canvas kernel \u2014 GRAPH LAYER: undo and redo over recorded edits, behind a\n * CLOSED action list (36 \u00A74.3).\n *\n * GENERIC. An entry is `{action, \u2026payload}` \u2014 typically `before` and `after` \u2014\n * and putting one back is the embedder's `apply(entry, direction)`: the\n * service knows the stack, the batch, the hydration gate and the closed list,\n * never what an entry means. (A whole-snapshot history, for a graph small\n * enough to copy, is `@flexdesk/flow`'s `FlowHistory`; this one records\n * DELTAS, for a diagram too large to snapshot on every move.)\n *\n * \u2550\u2550 THE CLOSED LIST \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n *\n * The only actions that exist are the ones the embedder declares, and\n * `record()` REJECTS anything else \u2014 loudly, with `refusal(action)`'s\n * sentence. An embedder whose Ctrl+Z must never reach something (a change\n * already applied to a server, say) enforces that structurally: the action\n * that would touch it cannot be recorded by accident; it has to be added on\n * purpose, to a list the embedder's own comment says not to add it to.\n *\n * \u2550\u2550 TWO TRAPS THIS IS BUILT AGAINST \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n *\n * 1. A MISSING DEPENDENCY FAILS LOUDLY, AT CONSTRUCTION. An undo engine\n * constructed with the wrong dependency set does nothing and reports\n * nothing \u2014 every restore path quietly returns \u2014 and the symptom, \"undo\n * does nothing\", says nothing about the cause. So `actions` and `apply`\n * are required, and `requires` lets a subclass name its own\n * (`{platform, router, plan}`): each must be present, or the constructor\n * throws naming it.\n * 2. THE HYDRATION GATE. Loading a drawing must not itself be undoable \u2014\n * otherwise the first Ctrl+Z after opening \"undoes\" the opening. Nothing is\n * recorded until `hydrated()`.\n */\n\nconst DEFAULT_LIMIT = 200;\n\nconst missing = (name) => new Error(\n `HistoryService needs ${name}. Constructing it without the full dependency set is how an undo `\n + 'engine ends up silently doing nothing.');\n\nexport class HistoryService {\n /**\n * @param {object} o\n * @param {readonly string[]} o.actions the only actions `record` accepts\n * @param {(entry: object, direction: 'undo'|'redo') => void} o.apply puts one entry back (or forward)\n * @param {(state: {canUndo, canRedo, depth}) => void} [o.onState]\n * @param {number} [o.limit] entries kept; the oldest goes first\n * @param {object} [o.requires] `{name: value}` a subclass cannot work without; each is checked\n * @param {(action: string) => string} [o.refusal] the sentence a refused `record` throws\n */\n constructor({ actions, apply, onState, limit = DEFAULT_LIMIT, requires = null, refusal = null } = {}) {\n // Loudly, at construction \u2014 see the header.\n for (const [name, value] of Object.entries(requires || {})) {\n if (!value) throw missing(name);\n }\n if (!Array.isArray(actions) || !actions.length) throw missing('actions (its closed list)');\n if (typeof apply !== 'function') throw missing('apply(entry, direction)');\n this.actions = Object.freeze([...actions]);\n this._applyEntry = apply;\n this.onState = onState;\n this.limit = limit;\n this.refusal = typeof refusal === 'function' ? refusal : null;\n this.undoStack = [];\n this.redoStack = [];\n // The hydration gate. Recording starts only once a drawing is loaded.\n this.recording = false;\n this.batch = null;\n }\n\n /** The drawing has been loaded: the stacks start empty, and recording starts. */\n hydrated() {\n this.undoStack = [];\n this.redoStack = [];\n this.recording = true;\n this._publish();\n }\n\n /** Group what is recorded until `endBatch` into one entry. */\n startBatch(label) {\n if (!this.recording) return;\n this.batch = { action: 'batch', label, entries: [] };\n }\n\n endBatch() {\n if (!this.batch) return;\n const batch = this.batch;\n this.batch = null;\n if (batch.entries.length) this._push(batch);\n }\n\n record(action, payload) {\n if (!this.recording) return;\n if (!this.actions.includes(action)) {\n throw new Error(this.refusal\n ? this.refusal(action)\n : `${action} is not an undoable action here; the ones that are: ${this.actions.join(', ')}.`);\n }\n const entry = { action, ...payload };\n if (this.batch) { this.batch.entries.push(entry); return; }\n this._push(entry);\n }\n\n undo() {\n const entry = this.undoStack.pop();\n if (!entry) return false;\n this._apply(entry, 'undo');\n this.redoStack.push(entry);\n this._publish();\n return true;\n }\n\n redo() {\n const entry = this.redoStack.pop();\n if (!entry) return false;\n this._apply(entry, 'redo');\n this.undoStack.push(entry);\n this._publish();\n return true;\n }\n\n reset() {\n this.undoStack = [];\n this.redoStack = [];\n this._publish();\n }\n\n /**\n * Take over the undo and redo stacks of a torn-down view whose state this\n * one has just taken on, entry for entry and in the same order. Nothing new\n * becomes undoable: every entry was recorded through a `record` whose action\n * list is closed, so a stack can only carry what that list allows. Call it\n * after `hydrated()`.\n */\n adopt({ undo = [], redo = [] } = {}) {\n if (!this.recording) return;\n this.undoStack = [...undo].slice(-this.limit);\n this.redoStack = [...redo];\n this._publish();\n }\n\n get canUndo() { return this.undoStack.length > 0; }\n get canRedo() { return this.redoStack.length > 0; }\n\n _push(entry) {\n this.undoStack.push(entry);\n // A new action invalidates the redo branch. Keeping it would let a user\n // redo their way into a state that never existed.\n this.redoStack = [];\n if (this.undoStack.length > this.limit) this.undoStack.shift();\n this._publish();\n }\n\n _publish() {\n this.onState?.({\n canUndo: this.canUndo,\n canRedo: this.canRedo,\n depth: this.undoStack.length,\n });\n }\n\n _apply(entry, direction) {\n if (entry.action === 'batch') {\n const entries = direction === 'undo'\n ? [...entry.entries].reverse() : entry.entries;\n for (const child of entries) this._apply(child, direction);\n return;\n }\n this._applyEntry(entry, direction);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/charts.js CHANGED
@@ -39,10 +39,10 @@ import {
39
39
  setPlotlySource,
40
40
  uid,
41
41
  updateChart
42
- } from "./chunk-CNXP3SIN.js";
42
+ } from "./chunk-ZMCRDOCF.js";
43
43
  import {
44
44
  createRafResizeObserver
45
- } from "./chunk-KH2GJTKR.js";
45
+ } from "./chunk-IYV5JVYB.js";
46
46
  import {
47
47
  ManagedWindow
48
48
  } from "./chunk-6JSOVNID.js";