@bakapiano/ccsm 0.22.6 → 0.22.8

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 (61) hide show
  1. package/CLAUDE.md +521 -540
  2. package/README.md +186 -189
  3. package/bin/ccsm.js +235 -235
  4. package/lib/cliActivity.js +36 -139
  5. package/lib/codexSeed.js +126 -183
  6. package/lib/config.js +277 -274
  7. package/lib/devices.js +229 -229
  8. package/lib/folders.js +124 -124
  9. package/lib/persistedSessions.js +179 -139
  10. package/lib/tunnel.js +621 -621
  11. package/lib/webTerminal.js +225 -225
  12. package/lib/winPath.js +1 -1
  13. package/lib/workspace.js +233 -233
  14. package/package.json +57 -57
  15. package/public/css/base.css +99 -99
  16. package/public/css/cards.css +183 -183
  17. package/public/css/feedback.css +504 -504
  18. package/public/css/forms.css +453 -453
  19. package/public/css/layout.css +154 -154
  20. package/public/css/modal.css +190 -190
  21. package/public/css/responsive.css +176 -176
  22. package/public/css/sidebar.css +707 -707
  23. package/public/css/terminals.css +546 -546
  24. package/public/css/tokens.css +81 -81
  25. package/public/css/wco.css +196 -196
  26. package/public/css/widgets.css +2347 -2725
  27. package/public/index.html +152 -152
  28. package/public/js/api.js +349 -371
  29. package/public/js/backend.js +149 -149
  30. package/public/js/components/App.js +73 -73
  31. package/public/js/components/DirectoryPicker.js +203 -203
  32. package/public/js/components/EntityFormModal.js +153 -153
  33. package/public/js/components/Modal.js +57 -57
  34. package/public/js/components/OfflineBanner.js +67 -67
  35. package/public/js/components/PageTitleBar.js +13 -13
  36. package/public/js/components/PendingApprovalOverlay.js +128 -128
  37. package/public/js/components/Picker.js +179 -179
  38. package/public/js/components/Popover.js +55 -55
  39. package/public/js/components/RestartOverlay.js +36 -36
  40. package/public/js/components/Sidebar.js +380 -380
  41. package/public/js/components/TerminalInstance.js +28 -0
  42. package/public/js/components/useDragSort.js +67 -67
  43. package/public/js/dialog.js +67 -67
  44. package/public/js/icons.js +212 -212
  45. package/public/js/main.js +296 -296
  46. package/public/js/pages/AboutPage.js +90 -90
  47. package/public/js/pages/ConfigurePage.js +730 -713
  48. package/public/js/pages/LaunchPage.js +403 -421
  49. package/public/js/pages/RemotePage.js +743 -743
  50. package/public/js/pages/SessionsPage.js +54 -54
  51. package/public/js/state.js +335 -335
  52. package/public/js/util.js +1 -1
  53. package/scripts/dev.js +149 -149
  54. package/scripts/install.js +153 -153
  55. package/scripts/restart-helper.js +96 -96
  56. package/scripts/upgrade-helper.js +687 -687
  57. package/server.js +1748 -1817
  58. package/lib/localCliSessions.js +0 -519
  59. package/public/js/components/AdoptModal.js +0 -261
  60. package/public/manifest.webmanifest +0 -25
  61. package/public/setup/index.html +0 -567
@@ -1,55 +1,55 @@
1
- // Tiny popover primitive — positions a floating panel relative to an
2
- // anchor element, closes on outside click + Escape. Used by the unified
3
- // pickers (CLI / Folder / Repo) so they all share interaction behavior.
4
- //
5
- // Usage:
6
- // const [open, setOpen] = useState(false);
7
- // const anchor = useRef(null);
8
- // <button ref=${anchor} onClick=${() => setOpen(true)}>Trigger</button>
9
- // ${open ? html`<${Popover} anchor=${anchor} onClose=${() => setOpen(false)}>
10
- // ...panel contents...
11
- // </${Popover}>` : null}
12
-
13
- import { html } from '../html.js';
14
- import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks';
15
- import { createPortal } from 'preact/compat';
16
-
17
- export function Popover({ anchor, onClose, align = 'left', width, children }) {
18
- const panelRef = useRef(null);
19
- const [pos, setPos] = useState({ top: 0, left: 0, width: width || 320 });
20
-
21
- useLayoutEffect(() => {
22
- const a = anchor && anchor.current;
23
- if (!a) return;
24
- const rect = a.getBoundingClientRect();
25
- const w = width || Math.max(rect.width, 320);
26
- let left = align === 'right' ? rect.right - w : rect.left;
27
- // Clamp to viewport with 8px margin.
28
- left = Math.max(8, Math.min(window.innerWidth - w - 8, left));
29
- const top = rect.bottom + 6;
30
- setPos({ top, left, width: w });
31
- }, [anchor, align, width]);
32
-
33
- useEffect(() => {
34
- const onDown = (ev) => {
35
- if (panelRef.current?.contains(ev.target)) return;
36
- if (anchor.current?.contains(ev.target)) return;
37
- onClose?.();
38
- };
39
- const onKey = (ev) => { if (ev.key === 'Escape') onClose?.(); };
40
- document.addEventListener('mousedown', onDown, true);
41
- document.addEventListener('keydown', onKey, true);
42
- return () => {
43
- document.removeEventListener('mousedown', onDown, true);
44
- document.removeEventListener('keydown', onKey, true);
45
- };
46
- }, [anchor, onClose]);
47
-
48
- return createPortal(
49
- html`<div ref=${panelRef} class="popover-panel"
50
- style=${`top:${pos.top}px;left:${pos.left}px;width:${pos.width}px;`}>
51
- ${children}
52
- </div>`,
53
- document.body
54
- );
55
- }
1
+ // Tiny popover primitive — positions a floating panel relative to an
2
+ // anchor element, closes on outside click + Escape. Used by the unified
3
+ // pickers (CLI / Folder / Repo) so they all share interaction behavior.
4
+ //
5
+ // Usage:
6
+ // const [open, setOpen] = useState(false);
7
+ // const anchor = useRef(null);
8
+ // <button ref=${anchor} onClick=${() => setOpen(true)}>Trigger</button>
9
+ // ${open ? html`<${Popover} anchor=${anchor} onClose=${() => setOpen(false)}>
10
+ // ...panel contents...
11
+ // </${Popover}>` : null}
12
+
13
+ import { html } from '../html.js';
14
+ import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks';
15
+ import { createPortal } from 'preact/compat';
16
+
17
+ export function Popover({ anchor, onClose, align = 'left', width, children }) {
18
+ const panelRef = useRef(null);
19
+ const [pos, setPos] = useState({ top: 0, left: 0, width: width || 320 });
20
+
21
+ useLayoutEffect(() => {
22
+ const a = anchor && anchor.current;
23
+ if (!a) return;
24
+ const rect = a.getBoundingClientRect();
25
+ const w = width || Math.max(rect.width, 320);
26
+ let left = align === 'right' ? rect.right - w : rect.left;
27
+ // Clamp to viewport with 8px margin.
28
+ left = Math.max(8, Math.min(window.innerWidth - w - 8, left));
29
+ const top = rect.bottom + 6;
30
+ setPos({ top, left, width: w });
31
+ }, [anchor, align, width]);
32
+
33
+ useEffect(() => {
34
+ const onDown = (ev) => {
35
+ if (panelRef.current?.contains(ev.target)) return;
36
+ if (anchor.current?.contains(ev.target)) return;
37
+ onClose?.();
38
+ };
39
+ const onKey = (ev) => { if (ev.key === 'Escape') onClose?.(); };
40
+ document.addEventListener('mousedown', onDown, true);
41
+ document.addEventListener('keydown', onKey, true);
42
+ return () => {
43
+ document.removeEventListener('mousedown', onDown, true);
44
+ document.removeEventListener('keydown', onKey, true);
45
+ };
46
+ }, [anchor, onClose]);
47
+
48
+ return createPortal(
49
+ html`<div ref=${panelRef} class="popover-panel"
50
+ style=${`top:${pos.top}px;left:${pos.left}px;width:${pos.width}px;`}>
51
+ ${children}
52
+ </div>`,
53
+ document.body
54
+ );
55
+ }
@@ -1,36 +1,36 @@
1
- // Small top-of-viewport banner shown while a user-initiated backend
2
- // restart is in flight. Used to be a full-screen blocking modal;
3
- // turned out the user just wanted visible "we're working" feedback,
4
- // not a giant card-and-button covering the page. Self-dismisses when
5
- // /api/health reports a fresh PID (different from the one we captured
6
- // at click time), or after 30s as a safety net.
7
-
8
- import { html } from '../html.js';
9
- import { useEffect } from 'preact/hooks';
10
- import { restartInFlight, serverHealth } from '../state.js';
11
- import { refreshAll } from '../api.js';
12
-
13
- export function RestartOverlay() {
14
- const info = restartInFlight.value;
15
- const h = serverHealth.value;
16
-
17
- useEffect(() => {
18
- if (!info) return;
19
- if (h.state === 'online' && h.pid && h.pid !== info.prevPid) {
20
- restartInFlight.value = null;
21
- refreshAll().catch(() => {});
22
- }
23
- const id = setTimeout(() => {
24
- if (restartInFlight.value === info) restartInFlight.value = null;
25
- }, 30_000);
26
- return () => clearTimeout(id);
27
- }, [info, h.state, h.pid]);
28
-
29
- if (!info) return null;
30
-
31
- return html`
32
- <div class="restart-banner" role="status" aria-live="polite">
33
- <span class="restart-banner-spinner" aria-hidden="true"></span>
34
- <span class="restart-banner-text">Restarting backend…</span>
35
- </div>`;
36
- }
1
+ // Small top-of-viewport banner shown while a user-initiated backend
2
+ // restart is in flight. Used to be a full-screen blocking modal;
3
+ // turned out the user just wanted visible "we're working" feedback,
4
+ // not a giant card-and-button covering the page. Self-dismisses when
5
+ // /api/health reports a fresh PID (different from the one we captured
6
+ // at click time), or after 30s as a safety net.
7
+
8
+ import { html } from '../html.js';
9
+ import { useEffect } from 'preact/hooks';
10
+ import { restartInFlight, serverHealth } from '../state.js';
11
+ import { refreshAll } from '../api.js';
12
+
13
+ export function RestartOverlay() {
14
+ const info = restartInFlight.value;
15
+ const h = serverHealth.value;
16
+
17
+ useEffect(() => {
18
+ if (!info) return;
19
+ if (h.state === 'online' && h.pid && h.pid !== info.prevPid) {
20
+ restartInFlight.value = null;
21
+ refreshAll().catch(() => {});
22
+ }
23
+ const id = setTimeout(() => {
24
+ if (restartInFlight.value === info) restartInFlight.value = null;
25
+ }, 30_000);
26
+ return () => clearTimeout(id);
27
+ }, [info, h.state, h.pid]);
28
+
29
+ if (!info) return null;
30
+
31
+ return html`
32
+ <div class="restart-banner" role="status" aria-live="polite">
33
+ <span class="restart-banner-spinner" aria-hidden="true"></span>
34
+ <span class="restart-banner-text">Restarting backend…</span>
35
+ </div>`;
36
+ }