@statelyai/flow-dom 0.1.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.
@@ -0,0 +1,20 @@
1
+ import { FlowStore } from "@statelyai/flow";
2
+
3
+ //#region src/index.d.ts
4
+ type MeasurementTarget = {
5
+ nodeId: string;
6
+ } | {
7
+ nodeId: string;
8
+ portName: string;
9
+ } | {
10
+ edgeId: string;
11
+ };
12
+ type MeasurementObserver = {
13
+ observe(element: Element, target: MeasurementTarget): void;
14
+ unobserve(element: Element): void;
15
+ disconnect(): void;
16
+ };
17
+ declare function createMeasurementObserver(store: FlowStore): MeasurementObserver;
18
+ declare function attachContainer(store: FlowStore, element: Element): () => void;
19
+ //#endregion
20
+ export { MeasurementObserver, MeasurementTarget, attachContainer, createMeasurementObserver };
@@ -0,0 +1,82 @@
1
+ //#region src/index.ts
2
+ function createMeasurementObserver(store) {
3
+ const elementMap = /* @__PURE__ */ new Map();
4
+ let pendingMeasurements = /* @__PURE__ */ new Map();
5
+ let pendingPorts = [];
6
+ let rafId = null;
7
+ function flush() {
8
+ rafId = null;
9
+ if (pendingMeasurements.size > 0) {
10
+ store.trigger.reportMeasurements({ measurements: pendingMeasurements });
11
+ pendingMeasurements = /* @__PURE__ */ new Map();
12
+ }
13
+ if (pendingPorts.length > 0) {
14
+ store.trigger.reportPortMeasurements({ measurements: pendingPorts });
15
+ pendingPorts = [];
16
+ }
17
+ }
18
+ function scheduleFlush() {
19
+ if (rafId === null) rafId = requestAnimationFrame(flush);
20
+ }
21
+ const observer = new ResizeObserver((entries) => {
22
+ for (const entry of entries) {
23
+ const target = elementMap.get(entry.target);
24
+ if (!target) continue;
25
+ const rect = entry.target.getBoundingClientRect();
26
+ if ("portName" in target) {
27
+ const nodeRect = entry.target.closest(`[data-entity-id="${target.nodeId}"]`)?.getBoundingClientRect();
28
+ if (nodeRect) pendingPorts.push({
29
+ nodeId: target.nodeId,
30
+ portName: target.portName,
31
+ x: rect.left - nodeRect.left,
32
+ y: rect.top - nodeRect.top,
33
+ width: rect.width,
34
+ height: rect.height
35
+ });
36
+ } else if ("nodeId" in target) pendingMeasurements.set(target.nodeId, {
37
+ width: rect.width,
38
+ height: rect.height
39
+ });
40
+ else pendingMeasurements.set(target.edgeId, {
41
+ width: rect.width,
42
+ height: rect.height
43
+ });
44
+ }
45
+ scheduleFlush();
46
+ });
47
+ return {
48
+ observe(element, target) {
49
+ elementMap.set(element, target);
50
+ observer.observe(element);
51
+ },
52
+ unobserve(element) {
53
+ elementMap.delete(element);
54
+ observer.unobserve(element);
55
+ },
56
+ disconnect() {
57
+ elementMap.clear();
58
+ observer.disconnect();
59
+ if (rafId !== null) {
60
+ cancelAnimationFrame(rafId);
61
+ rafId = null;
62
+ }
63
+ pendingMeasurements = /* @__PURE__ */ new Map();
64
+ pendingPorts = [];
65
+ }
66
+ };
67
+ }
68
+ function attachContainer(store, element) {
69
+ const update = () => {
70
+ const rect = element.getBoundingClientRect();
71
+ if (rect.width > 0 && rect.height > 0) store.trigger.updateViewportSize({
72
+ width: rect.width,
73
+ height: rect.height
74
+ });
75
+ };
76
+ update();
77
+ const observer = new ResizeObserver(update);
78
+ observer.observe(element);
79
+ return () => observer.disconnect();
80
+ }
81
+ //#endregion
82
+ export { attachContainer, createMeasurementObserver };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@statelyai/flow-dom",
3
+ "version": "0.1.0",
4
+ "description": "DOM-specific helpers for @statelyai/flow.",
5
+ "keywords": [
6
+ "flow",
7
+ "diagram",
8
+ "dom",
9
+ "resizeobserver"
10
+ ],
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "source": "src/index.ts",
15
+ "main": "dist/esm/index.js",
16
+ "module": "dist/esm/index.js",
17
+ "types": "dist/esm/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/esm/index.d.ts",
21
+ "import": "./dist/esm/index.js",
22
+ "default": "./dist/esm/index.js"
23
+ },
24
+ "./src/index.ts": {
25
+ "types": "./src/index.ts",
26
+ "import": "./src/index.ts",
27
+ "default": "./src/index.ts"
28
+ }
29
+ },
30
+ "license": "MIT",
31
+ "scripts": {
32
+ "dev": "tsdown --watch",
33
+ "build": "tsdown",
34
+ "typecheck": "tsc --noEmit"
35
+ },
36
+ "peerDependencies": {
37
+ "@statelyai/flow": ">=0.1.0"
38
+ },
39
+ "devDependencies": {
40
+ "tsdown": "^0.12.0",
41
+ "typescript": "^5.8.0"
42
+ }
43
+ }