@laitszkin/apollo-toolkit 3.10.0 → 3.11.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 (47) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/analyse-app-logs/scripts/__pycache__/filter_logs_by_time.cpython-312.pyc +0 -0
  3. package/analyse-app-logs/scripts/__pycache__/log_cli_utils.cpython-312.pyc +0 -0
  4. package/analyse-app-logs/scripts/__pycache__/search_logs.cpython-312.pyc +0 -0
  5. package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
  6. package/generate-spec/SKILL.md +17 -15
  7. package/generate-spec/agents/openai.yaml +1 -1
  8. package/generate-spec/references/TEMPLATE_SPEC.md +103 -84
  9. package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
  10. package/init-project-html/SKILL.md +117 -125
  11. package/init-project-html/agents/openai.yaml +18 -9
  12. package/init-project-html/lib/atlas/assets/architecture.css +161 -0
  13. package/init-project-html/lib/atlas/assets/viewer.client.js +136 -0
  14. package/init-project-html/lib/atlas/cli.js +1023 -0
  15. package/init-project-html/lib/atlas/layout.js +330 -0
  16. package/init-project-html/lib/atlas/render.js +583 -0
  17. package/init-project-html/lib/atlas/schema.js +347 -0
  18. package/init-project-html/lib/atlas/state.js +402 -0
  19. package/init-project-html/references/TEMPLATE_SPEC.md +140 -83
  20. package/init-project-html/sample-demo/resources/project-architecture/assets/architecture.css +160 -1058
  21. package/init-project-html/sample-demo/resources/project-architecture/assets/viewer.client.js +136 -0
  22. package/init-project-html/sample-demo/resources/project-architecture/atlas/atlas.index.yaml +34 -0
  23. package/init-project-html/sample-demo/resources/project-architecture/atlas/features/get-invite-codes.yaml +172 -0
  24. package/init-project-html/sample-demo/resources/project-architecture/atlas/features/invite-code-registration.yaml +160 -0
  25. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/index.html +67 -52
  26. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-code-generator.html +64 -163
  27. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-issuance-service.html +102 -196
  28. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/postgresql.html +82 -163
  29. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/public-api.html +88 -150
  30. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/web-get-invite-ui.html +83 -138
  31. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/index.html +61 -51
  32. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/postgresql.html +84 -159
  33. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/public-api.html +81 -143
  34. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/registration-service.html +98 -188
  35. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/web-register-ui.html +83 -138
  36. package/init-project-html/sample-demo/resources/project-architecture/index.html +256 -335
  37. package/init-project-html/scripts/architecture.js +65 -247
  38. package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
  39. package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
  40. package/package.json +6 -2
  41. package/read-github-issue/scripts/__pycache__/find_issues.cpython-312.pyc +0 -0
  42. package/read-github-issue/scripts/__pycache__/read_issue.cpython-312.pyc +0 -0
  43. package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
  44. package/spec-to-project-html/SKILL.md +74 -67
  45. package/spec-to-project-html/agents/openai.yaml +14 -8
  46. package/spec-to-project-html/references/TEMPLATE_SPEC.md +98 -83
  47. package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
@@ -0,0 +1,136 @@
1
+ /* viewer.client.js — pan/zoom for every atlas SVG on the page.
2
+ *
3
+ * Each `[data-pan-zoom-viewport]` element gets its own state and
4
+ * handlers, so a single page can host the macro atlas SVG AND
5
+ * sub-module-internal dataflow SVGs simultaneously. Toolbar buttons
6
+ * (`[data-pan-zoom="zoom-in|zoom-out|fit"]`) are scoped to the
7
+ * containing `[data-pan-zoom-container]` (falls back to the viewport's
8
+ * direct parent), so multiple toolbars on one page do not collide.
9
+ * Keyboard shortcuts (`←` / `→` / `↑` / `↓` / `+` / `−` / `0`) drive
10
+ * the page's first viewport — the "primary" diagram of that page
11
+ * (macro SVG on `index.html`; sub-dataflow SVG on a sub-module page).
12
+ */
13
+
14
+ (function () {
15
+ 'use strict';
16
+
17
+ const viewports = Array.from(document.querySelectorAll('[data-pan-zoom-viewport]'));
18
+ const controllers = viewports.map(setupViewport).filter(Boolean);
19
+ if (controllers.length === 0) return;
20
+
21
+ const primary = controllers[0];
22
+ document.addEventListener('keydown', function (evt) {
23
+ if (evt.target && (evt.target.tagName === 'INPUT' || evt.target.tagName === 'TEXTAREA')) return;
24
+ if (evt.key === 'ArrowLeft') { primary.pan(-1, 0); }
25
+ else if (evt.key === 'ArrowRight') { primary.pan(1, 0); }
26
+ else if (evt.key === 'ArrowUp') { primary.pan(0, -1); }
27
+ else if (evt.key === 'ArrowDown') { primary.pan(0, 1); }
28
+ else if (evt.key === '+' || evt.key === '=') { primary.zoom(1 / 1.2); }
29
+ else if (evt.key === '-' || evt.key === '_') { primary.zoom(1.2); }
30
+ else if (evt.key === '0') { primary.fit(); }
31
+ });
32
+
33
+ function setupViewport(viewport) {
34
+ const svg = viewport.querySelector('[data-atlas-svg]');
35
+ if (!svg) return null;
36
+ const initial = svg.getAttribute('viewBox');
37
+ if (!initial) return null;
38
+ const [ix, iy, iw, ih] = initial.split(/\s+/).map(Number);
39
+ const state = { x: ix, y: iy, w: iw, h: ih };
40
+
41
+ function apply() {
42
+ svg.setAttribute('viewBox', `${state.x} ${state.y} ${state.w} ${state.h}`);
43
+ }
44
+ function fit() {
45
+ state.x = ix; state.y = iy; state.w = iw; state.h = ih;
46
+ apply();
47
+ }
48
+ function zoom(factor, cx, cy) {
49
+ const newW = Math.max(40, Math.min(state.w * factor, iw * 8));
50
+ const newH = newW * (state.h / state.w);
51
+ if (cx == null) { cx = state.x + state.w / 2; cy = state.y + state.h / 2; }
52
+ state.x = cx - (cx - state.x) * (newW / state.w);
53
+ state.y = cy - (cy - state.y) * (newH / state.h);
54
+ state.w = newW;
55
+ state.h = newH;
56
+ apply();
57
+ }
58
+ function pan(dirX, dirY) {
59
+ const stepX = state.w * 0.08;
60
+ const stepY = state.h * 0.08;
61
+ state.x += dirX * stepX;
62
+ state.y += dirY * stepY;
63
+ apply();
64
+ }
65
+ function clientToSvg(evt) {
66
+ const rect = svg.getBoundingClientRect();
67
+ const xRatio = (evt.clientX - rect.left) / rect.width;
68
+ const yRatio = (evt.clientY - rect.top) / rect.height;
69
+ return { x: state.x + xRatio * state.w, y: state.y + yRatio * state.h };
70
+ }
71
+
72
+ viewport.addEventListener('wheel', function (evt) {
73
+ if (!evt.ctrlKey && !evt.metaKey && Math.abs(evt.deltaY) < 4 && Math.abs(evt.deltaX) < 4) return;
74
+ evt.preventDefault();
75
+ const factor = evt.deltaY > 0 ? 1.1 : 1 / 1.1;
76
+ const pt = clientToSvg(evt);
77
+ zoom(factor, pt.x, pt.y);
78
+ }, { passive: false });
79
+
80
+ // Drag-pan: defer the pointer capture (and the "is-grabbing" class)
81
+ // until the pointer actually moves past a small threshold. Without
82
+ // this, a single click on an SVG <a> (sub-module link) would be
83
+ // captured by the viewport and never reach the link.
84
+ const DRAG_THRESHOLD_PX = 4;
85
+ let pending = null;
86
+ let dragging = null;
87
+ viewport.addEventListener('pointerdown', function (evt) {
88
+ if (evt.button !== 0) return;
89
+ pending = { x: evt.clientX, y: evt.clientY, pointerId: evt.pointerId };
90
+ });
91
+ viewport.addEventListener('pointermove', function (evt) {
92
+ if (!dragging && pending && pending.pointerId === evt.pointerId) {
93
+ const dx = evt.clientX - pending.x;
94
+ const dy = evt.clientY - pending.y;
95
+ if (Math.hypot(dx, dy) < DRAG_THRESHOLD_PX) return;
96
+ dragging = { x: pending.x, y: pending.y, pointerId: pending.pointerId };
97
+ pending = null;
98
+ viewport.classList.add('is-grabbing');
99
+ try { viewport.setPointerCapture(dragging.pointerId); } catch (e) { /* ignore */ }
100
+ }
101
+ if (!dragging || dragging.pointerId !== evt.pointerId) return;
102
+ evt.preventDefault();
103
+ const rect = svg.getBoundingClientRect();
104
+ const dx = ((evt.clientX - dragging.x) / rect.width) * state.w;
105
+ const dy = ((evt.clientY - dragging.y) / rect.height) * state.h;
106
+ state.x -= dx;
107
+ state.y -= dy;
108
+ dragging.x = evt.clientX;
109
+ dragging.y = evt.clientY;
110
+ apply();
111
+ });
112
+ function endDrag(evt) {
113
+ pending = null;
114
+ if (!dragging) return;
115
+ const draggedId = dragging.pointerId;
116
+ dragging = null;
117
+ viewport.classList.remove('is-grabbing');
118
+ try { viewport.releasePointerCapture(draggedId); } catch (e) { /* ignore */ }
119
+ // Suppress the synthetic click that would follow a drag-release
120
+ // on top of a sub-module <a>; only the no-movement case should
121
+ // navigate.
122
+ const swallow = (e) => { e.preventDefault(); e.stopPropagation(); };
123
+ viewport.addEventListener('click', swallow, { capture: true, once: true });
124
+ }
125
+ viewport.addEventListener('pointerup', endDrag);
126
+ viewport.addEventListener('pointercancel', endDrag);
127
+ viewport.addEventListener('pointerleave', endDrag);
128
+
129
+ const container = viewport.closest('[data-pan-zoom-container]') || viewport.parentElement || document;
130
+ container.querySelectorAll('[data-pan-zoom="zoom-in"]').forEach((btn) => btn.addEventListener('click', () => zoom(1 / 1.2)));
131
+ container.querySelectorAll('[data-pan-zoom="zoom-out"]').forEach((btn) => btn.addEventListener('click', () => zoom(1.2)));
132
+ container.querySelectorAll('[data-pan-zoom="fit"]').forEach((btn) => btn.addEventListener('click', fit));
133
+
134
+ return { zoom, fit, pan };
135
+ }
136
+ })();