@grifhinz/logics-manager 2.2.0 → 2.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.
Files changed (43) hide show
  1. package/README.md +95 -1
  2. package/VERSION +1 -1
  3. package/clients/README.md +9 -0
  4. package/clients/shared-web/media/css/board.css +658 -0
  5. package/clients/shared-web/media/css/details.css +457 -0
  6. package/clients/shared-web/media/css/layout.css +123 -0
  7. package/clients/shared-web/media/css/toolbar.css +576 -0
  8. package/clients/shared-web/media/harnessApi.js +324 -0
  9. package/clients/shared-web/media/hostApi.js +213 -0
  10. package/clients/shared-web/media/hostApiContract.js +55 -0
  11. package/clients/shared-web/media/icon.png +0 -0
  12. package/clients/shared-web/media/layoutController.js +246 -0
  13. package/clients/shared-web/media/logics.svg +7 -0
  14. package/clients/shared-web/media/logicsModel.js +910 -0
  15. package/clients/shared-web/media/main.css +112 -0
  16. package/clients/shared-web/media/main.js +3 -0
  17. package/clients/shared-web/media/mainApp.js +1005 -0
  18. package/clients/shared-web/media/mainCore.js +604 -0
  19. package/clients/shared-web/media/mainInteractionHandlers.js +324 -0
  20. package/clients/shared-web/media/mainInteractions.js +378 -0
  21. package/clients/shared-web/media/renderBoard.js +3 -0
  22. package/clients/shared-web/media/renderBoardApp.js +1339 -0
  23. package/clients/shared-web/media/renderDetails.js +685 -0
  24. package/clients/shared-web/media/renderMarkdown.js +449 -0
  25. package/clients/shared-web/media/toolsPanelLayout.js +172 -0
  26. package/clients/shared-web/media/uiStatus.js +54 -0
  27. package/clients/shared-web/media/webviewChrome.js +405 -0
  28. package/clients/shared-web/media/webviewPersistence.js +116 -0
  29. package/clients/shared-web/media/webviewSelectors.js +491 -0
  30. package/clients/viewer/README.md +5 -0
  31. package/clients/viewer/browser-host.js +847 -0
  32. package/clients/viewer/index.html +237 -0
  33. package/clients/viewer/viewer.css +433 -0
  34. package/logics_manager/assist.py +9 -142
  35. package/logics_manager/assist_handoff.py +132 -0
  36. package/logics_manager/assist_surface.py +38 -0
  37. package/logics_manager/cli.py +78 -5
  38. package/logics_manager/flow.py +126 -24
  39. package/logics_manager/flow_evidence.py +63 -0
  40. package/logics_manager/update_check.py +138 -0
  41. package/logics_manager/viewer.py +533 -0
  42. package/package.json +12 -6
  43. package/pyproject.toml +1 -1
@@ -0,0 +1,246 @@
1
+ (() => {
2
+ window.createCdxLogicsLayoutController = function createCdxLogicsLayoutController(options) {
3
+ const {
4
+ layout,
5
+ mainPane,
6
+ board,
7
+ activityPanel,
8
+ details,
9
+ splitter,
10
+ stackedQuery,
11
+ uiState,
12
+ persistState,
13
+ debugLog,
14
+ isDetailsCollapsed,
15
+ getPrimaryPaneScrollHeight
16
+ } = options;
17
+
18
+ const minBoardHeight = 120;
19
+ const minDetailsHeight = 220;
20
+ let isDraggingSplit = false;
21
+
22
+ function detectLayoutMode() {
23
+ return Boolean(stackedQuery && stackedQuery.matches) ? "stacked" : "horizontal";
24
+ }
25
+
26
+ function isStackedLayout() {
27
+ return uiState.layoutMode === "stacked";
28
+ }
29
+
30
+ function isSplitInteractionDisabled() {
31
+ return isStackedLayout() && isDetailsCollapsed();
32
+ }
33
+
34
+ function clearSplitSizing() {
35
+ if (!mainPane || !details) {
36
+ return;
37
+ }
38
+ mainPane.style.flex = "";
39
+ mainPane.style.height = "";
40
+ mainPane.style.paddingBottom = "";
41
+ details.style.flex = "";
42
+ details.style.height = "";
43
+ details.style.maxHeight = "";
44
+ if (splitter) {
45
+ splitter.style.bottom = "";
46
+ }
47
+ }
48
+
49
+ function syncStackedAnchoredLayout() {
50
+ if (!layout || !mainPane || !details || !isStackedLayout()) {
51
+ return;
52
+ }
53
+ const splitterHeight = splitter ? splitter.getBoundingClientRect().height : 0;
54
+ const detailsHeight = Math.ceil(details.getBoundingClientRect().height || details.offsetHeight || 0);
55
+ const reservedBottom = detailsHeight + (isSplitInteractionDisabled() ? 0 : splitterHeight);
56
+ mainPane.style.paddingBottom = `${reservedBottom}px`;
57
+ if (splitter) {
58
+ splitter.style.bottom = isSplitInteractionDisabled() ? "" : `${detailsHeight}px`;
59
+ }
60
+ }
61
+
62
+ function updateSplitterA11y() {
63
+ if (!splitter) {
64
+ return;
65
+ }
66
+ const splitDisabled = isSplitInteractionDisabled();
67
+ splitter.setAttribute("aria-disabled", String(splitDisabled));
68
+ splitter.tabIndex = splitDisabled ? -1 : 0;
69
+ if (isStackedLayout() && !splitDisabled) {
70
+ splitter.setAttribute("aria-valuemin", "0");
71
+ splitter.setAttribute("aria-valuemax", "100");
72
+ splitter.setAttribute("aria-valuenow", String(Math.round(uiState.splitRatio * 100)));
73
+ } else {
74
+ splitter.removeAttribute("aria-valuemin");
75
+ splitter.removeAttribute("aria-valuemax");
76
+ splitter.removeAttribute("aria-valuenow");
77
+ }
78
+ }
79
+
80
+ function applySplitRatio(nextRatio, shouldPersist = false) {
81
+ if (!layout || !mainPane || !details || !isStackedLayout()) {
82
+ return;
83
+ }
84
+ if (isSplitInteractionDisabled()) {
85
+ mainPane.style.flex = "1 1 auto";
86
+ mainPane.style.height = "";
87
+ mainPane.style.paddingBottom = "";
88
+ details.style.flex = "0 0 auto";
89
+ details.style.height = "";
90
+ details.style.maxHeight = "";
91
+ syncStackedAnchoredLayout();
92
+ updateSplitterA11y();
93
+ if (shouldPersist) {
94
+ persistState();
95
+ }
96
+ return;
97
+ }
98
+ const splitterHeight = splitter ? splitter.getBoundingClientRect().height : 0;
99
+ const available = layout.clientHeight - splitterHeight;
100
+ if (!Number.isFinite(available) || available <= 0) {
101
+ return;
102
+ }
103
+ const minBoard = Math.min(minBoardHeight, available);
104
+ const minDetails = Math.min(minDetailsHeight, Math.max(0, available - minBoard));
105
+ const minRatio = minBoard / available;
106
+ const maxRatio = (available - minDetails) / available;
107
+ const clampedRatio = Math.min(Math.max(nextRatio, minRatio), maxRatio);
108
+ const targetBoardHeight = Math.round(available * clampedRatio);
109
+ const boardContentHeight = Math.max(
110
+ typeof getPrimaryPaneScrollHeight === "function" ? getPrimaryPaneScrollHeight() || 0 : board?.scrollHeight || 0,
111
+ 0
112
+ );
113
+ const compactBoardFloor = boardContentHeight > 0 ? Math.min(minBoardHeight, boardContentHeight) : minBoardHeight;
114
+ const boardHeight =
115
+ boardContentHeight > 0
116
+ ? Math.max(compactBoardFloor, Math.min(targetBoardHeight, boardContentHeight))
117
+ : targetBoardHeight;
118
+ const detailsHeight = Math.max(minDetails, available - boardHeight);
119
+ mainPane.style.flex = "1 1 auto";
120
+ mainPane.style.height = "";
121
+ details.style.flex = "0 0 auto";
122
+ details.style.height = `${detailsHeight}px`;
123
+ details.style.maxHeight = `${available}px`;
124
+ uiState.splitRatio = clampedRatio;
125
+ debugLog("split-ratio:update", { splitRatio: uiState.splitRatio });
126
+ syncStackedAnchoredLayout();
127
+ updateSplitterA11y();
128
+ if (shouldPersist) {
129
+ persistState();
130
+ }
131
+ }
132
+
133
+ function updateLayoutMode() {
134
+ if (!layout) {
135
+ return;
136
+ }
137
+ const previousLayoutMode = uiState.layoutMode;
138
+ uiState.layoutMode = detectLayoutMode();
139
+ const stacked = isStackedLayout();
140
+ layout.classList.toggle("layout--stacked", stacked);
141
+ layout.classList.toggle("layout--horizontal", !stacked);
142
+ layout.classList.toggle("layout--split-disabled", stacked && isDetailsCollapsed());
143
+ if (previousLayoutMode !== uiState.layoutMode) {
144
+ debugLog("layout-mode:change", { from: previousLayoutMode, to: uiState.layoutMode });
145
+ }
146
+ if (!stacked && isDraggingSplit) {
147
+ isDraggingSplit = false;
148
+ if (splitter) {
149
+ splitter.classList.remove("splitter--dragging");
150
+ }
151
+ document.body.classList.remove("is-resizing");
152
+ debugLog("splitter:drag-reset", { reason: "layout-not-stacked" });
153
+ }
154
+ if (stacked) {
155
+ if (splitter) {
156
+ splitter.style.display = "";
157
+ }
158
+ applySplitRatio(uiState.splitRatio, false);
159
+ } else {
160
+ if (splitter) {
161
+ splitter.style.display = "none";
162
+ }
163
+ clearSplitSizing();
164
+ }
165
+ }
166
+
167
+ function startSplitDrag(event) {
168
+ if (!splitter || !layout || !isStackedLayout() || isSplitInteractionDisabled()) {
169
+ return;
170
+ }
171
+ event.preventDefault();
172
+ isDraggingSplit = true;
173
+ splitter.classList.add("splitter--dragging");
174
+ document.body.classList.add("is-resizing");
175
+ if (typeof splitter.setPointerCapture === "function" && typeof event.pointerId === "number") {
176
+ splitter.setPointerCapture(event.pointerId);
177
+ }
178
+ }
179
+
180
+ function updateSplitDrag(event) {
181
+ if (!isDraggingSplit || !layout || !isStackedLayout() || isSplitInteractionDisabled()) {
182
+ return;
183
+ }
184
+ const rect = layout.getBoundingClientRect();
185
+ const splitterHeight = splitter ? splitter.getBoundingClientRect().height : 0;
186
+ const available = rect.height - splitterHeight;
187
+ if (available <= 0) {
188
+ return;
189
+ }
190
+ const offsetY = event.clientY - rect.top - splitterHeight / 2;
191
+ const minBoard = Math.min(minBoardHeight, available);
192
+ const minDetails = Math.min(minDetailsHeight, Math.max(0, available - minBoard));
193
+ const boardHeight = Math.min(Math.max(offsetY, minBoard), available - minDetails);
194
+ const ratio = boardHeight / available;
195
+ applySplitRatio(ratio, false);
196
+ }
197
+
198
+ function endSplitDrag(event) {
199
+ if (!isDraggingSplit) {
200
+ return;
201
+ }
202
+ isDraggingSplit = false;
203
+ if (splitter) {
204
+ splitter.classList.remove("splitter--dragging");
205
+ if (typeof splitter.releasePointerCapture === "function" && typeof event.pointerId === "number") {
206
+ splitter.releasePointerCapture(event.pointerId);
207
+ }
208
+ }
209
+ document.body.classList.remove("is-resizing");
210
+ persistState();
211
+ }
212
+
213
+ function nudgeSplitFromKeyboard(delta) {
214
+ if (!isStackedLayout() || isSplitInteractionDisabled()) {
215
+ return;
216
+ }
217
+ applySplitRatio(uiState.splitRatio + delta, true);
218
+ }
219
+
220
+ return {
221
+ updateSplitterA11y,
222
+ nudgeSplitFromKeyboard,
223
+ persistAndApplySplitRatio(nextRatio) {
224
+ applySplitRatio(nextRatio, true);
225
+ },
226
+ applySplitRatio,
227
+ syncStackedAnchoredLayout,
228
+ updateLayoutMode,
229
+ startSplitDrag,
230
+ updateSplitDrag,
231
+ endSplitDrag,
232
+ isStackedLayout,
233
+ isSplitInteractionDisabled,
234
+ isDraggingSplit() {
235
+ return isDraggingSplit;
236
+ },
237
+ resetDraggingState() {
238
+ isDraggingSplit = false;
239
+ if (splitter) {
240
+ splitter.classList.remove("splitter--dragging");
241
+ }
242
+ document.body.classList.remove("is-resizing");
243
+ }
244
+ };
245
+ };
246
+ })();
@@ -0,0 +1,7 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <circle cx="6" cy="6" r="2.5" stroke="currentColor" stroke-width="1.8"/>
3
+ <circle cx="18" cy="6" r="2.5" stroke="currentColor" stroke-width="1.8"/>
4
+ <circle cx="12" cy="18" r="2.5" stroke="currentColor" stroke-width="1.8"/>
5
+ <path d="M8 7.5L10.5 15.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
6
+ <path d="M16 7.5L13.5 15.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
7
+ </svg>