@owdproject/core 3.4.0 → 4.0.0-alpha.3

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 (108) hide show
  1. package/README.md +112 -13
  2. package/dist/dom/index.d.mts +65 -0
  3. package/dist/dom/index.d.ts +65 -0
  4. package/dist/dom/index.mjs +224 -0
  5. package/dist/events/index.d.mts +70 -0
  6. package/dist/events/index.d.ts +70 -0
  7. package/dist/events/index.mjs +3 -0
  8. package/dist/index.d.mts +73 -0
  9. package/dist/index.d.ts +73 -0
  10. package/dist/index.mjs +115 -0
  11. package/dist/layout/index.d.mts +41 -0
  12. package/dist/layout/index.d.ts +41 -0
  13. package/dist/layout/index.mjs +64 -0
  14. package/dist/machines/index.d.mts +31 -0
  15. package/dist/machines/index.d.ts +31 -0
  16. package/dist/machines/index.mjs +2 -0
  17. package/dist/managers/index.d.mts +117 -0
  18. package/dist/managers/index.d.ts +117 -0
  19. package/dist/managers/index.mjs +6 -0
  20. package/dist/session/index.d.mts +57 -0
  21. package/dist/session/index.d.ts +57 -0
  22. package/dist/session/index.mjs +65 -0
  23. package/dist/shared/core.B0B0KfVK.mjs +865 -0
  24. package/dist/shared/core.B1XxB289.mjs +239 -0
  25. package/dist/shared/core.B3mp7ztE.mjs +237 -0
  26. package/dist/shared/core.BOvFdEVQ.d.ts +114 -0
  27. package/dist/shared/core.CsDFgGnX.mjs +40 -0
  28. package/dist/shared/core.Di1eFcr_.d.mts +114 -0
  29. package/dist/shared/core.Pd_Ogt4g.mjs +101 -0
  30. package/dist/shared/core.b3Xldzyu.mjs +29 -0
  31. package/dist/types/index.d.mts +266 -0
  32. package/dist/types/index.d.ts +266 -0
  33. package/dist/types/index.mjs +1 -0
  34. package/package.json +56 -112
  35. package/CHANGELOG.md +0 -98
  36. package/DESKTOP_KERNEL.md +0 -232
  37. package/MIGRATION_3.3.2.md +0 -23
  38. package/MIGRATION_3.4.md +0 -126
  39. package/PLAYGROUND.md +0 -91
  40. package/dist/module.d.mts +0 -13
  41. package/dist/module.json +0 -9
  42. package/dist/module.mjs +0 -254
  43. package/dist/types.d.mts +0 -7
  44. package/index.ts +0 -8
  45. package/kit/authoring.ts +0 -340
  46. package/kit/defineDesktopApp.ts +0 -56
  47. package/module.ts +0 -203
  48. package/runtime/components/Application/DesktopCoreApplicationRender.vue +0 -20
  49. package/runtime/components/Application/DesktopCoreApplicationWindowsRender.vue +0 -38
  50. package/runtime/components/background/DesktopCoreBackground.vue +0 -16
  51. package/runtime/components/core/DesktopCore.vue +0 -43
  52. package/runtime/components/time/DesktopCoreTime.vue +0 -56
  53. package/runtime/components/window/DesktopCoreWindow.vue +0 -215
  54. package/runtime/components/window/DesktopCoreWindowContent.vue +0 -28
  55. package/runtime/components/window/DesktopCoreWindowNav.vue +0 -66
  56. package/runtime/components/window/DesktopCoreWindowSnapHintsBase.vue +0 -74
  57. package/runtime/components/workspace/DesktopCoreWorkspaceEdgeHintsBase.vue +0 -84
  58. package/runtime/composables/useApplicationEntries.ts +0 -51
  59. package/runtime/composables/useApplicationManager.ts +0 -285
  60. package/runtime/composables/useBlockNonInputContextMenu.ts +0 -30
  61. package/runtime/composables/useDesktopConfig.ts +0 -8
  62. package/runtime/composables/useDesktopDialogs.ts +0 -16
  63. package/runtime/composables/useDesktopExtension.ts +0 -8
  64. package/runtime/composables/useDesktopManager.ts +0 -51
  65. package/runtime/composables/useDesktopManifest.ts +0 -17
  66. package/runtime/composables/useDesktopSession.ts +0 -27
  67. package/runtime/composables/useDesktopShellIdentity.ts +0 -99
  68. package/runtime/composables/useDesktopShellOptions.ts +0 -36
  69. package/runtime/composables/useDesktopShellReady.ts +0 -7
  70. package/runtime/composables/useDesktopWorkArea.ts +0 -93
  71. package/runtime/composables/useTerminalManager.ts +0 -159
  72. package/runtime/composables/useToggleWindowMaximize.ts +0 -35
  73. package/runtime/composables/useWindowDragHandlers.ts +0 -47
  74. package/runtime/composables/useWindowSnapDrop.ts +0 -112
  75. package/runtime/composables/useWorkspaceEdgeDrop.ts +0 -176
  76. package/runtime/composables/useWorkspaceManager.ts +0 -67
  77. package/runtime/composables/useWorkspaceOverviewCapture.ts +0 -92
  78. package/runtime/composables/useWorkspaceOverviewLiveScale.ts +0 -151
  79. package/runtime/constants/desktopShellKeys.ts +0 -12
  80. package/runtime/constants/shellLayout.ts +0 -5
  81. package/runtime/dialogs/desktopDialogProvider.ts +0 -73
  82. package/runtime/internal/controllers/ApplicationController.ts +0 -351
  83. package/runtime/internal/controllers/WindowController.ts +0 -547
  84. package/runtime/plugins/01.desktop-shell-init.client.ts +0 -28
  85. package/runtime/plugins/02.desktop-register-desktop-apps.client.ts +0 -13
  86. package/runtime/plugins/resize.client.ts +0 -6
  87. package/runtime/stores/storeApplicationMeta.ts +0 -60
  88. package/runtime/stores/storeApplicationWindows.ts +0 -21
  89. package/runtime/stores/storeDesktop.ts +0 -71
  90. package/runtime/stores/storeDesktopDefaultApps.ts +0 -54
  91. package/runtime/stores/storeDesktopVolume.ts +0 -19
  92. package/runtime/stores/storeDesktopWindow.ts +0 -38
  93. package/runtime/stores/storeDesktopWorkspace.ts +0 -105
  94. package/runtime/stores/storeIds.ts +0 -35
  95. package/runtime/types/desktopMenu.ts +0 -10
  96. package/runtime/utils/initDesktopShell.ts +0 -80
  97. package/runtime/utils/migratePersistedStoreIds.ts +0 -57
  98. package/runtime/utils/utilApp.ts +0 -25
  99. package/runtime/utils/utilCaptureElementToCanvas.ts +0 -21
  100. package/runtime/utils/utilCommon.ts +0 -26
  101. package/runtime/utils/utilDebug.ts +0 -30
  102. package/runtime/utils/utilDetectSnapZone.ts +0 -57
  103. package/runtime/utils/utilTerminal.ts +0 -6
  104. package/runtime/utils/utilWindowControllerAdapter.ts +0 -15
  105. package/runtime/utils/utilWindowLayout.ts +0 -82
  106. package/runtime/utils/utilWindowMaximizeLayout.ts +0 -44
  107. package/runtime/utils/utilWorkspaceWindows.ts +0 -33
  108. package/types/index.d.ts +0 -531
package/README.md CHANGED
@@ -1,22 +1,121 @@
1
- # 📦 OWD Core
1
+ <div align="center">
2
2
 
3
- > The kernel and runtime engine for Open Web Desktop
3
+ <h1>@owdproject/core</h1>
4
4
 
5
- This package provides the core logic, Vue components, and Nuxt module required to run an Open Web Desktop experience.
5
+ <p>
6
+ <strong>A TypeScript runtime for web desktop interfaces.</strong><br /><br />
7
+ A deterministic, framework-independent runtime for multi-window workspaces,<br />
8
+ XState v5 process orchestration, magnetic snap geometry, and W3C Pointer math.
9
+ </p>
6
10
 
7
- ## Features
11
+ <br />
8
12
 
9
- - **Window Management**: Z-index handling, focusing, and lifecycle.
10
- - **Runtime Components**: \`DesktopCore\`, \`DesktopWindow\`, and more.
11
- - **State Management**: Pinia stores for workspaces, applications, and settings.
12
- - **Nuxt Integration**: Seamless module for Nuxt 3/4.
13
+ <p>
14
+ <a href="https://npmjs.com/package/@owdproject/core"><img src="https://img.shields.io/npm/v/@owdproject/core/alpha.svg?style=flat&colorA=020420&colorB=00DC82" alt="npm version" /></a>
15
+ <a href="https://npm.chart.dev/@owdproject/core"><img src="https://img.shields.io/npm/dm/@owdproject/core.svg?style=flat&colorA=020420&colorB=00DC82" alt="npm downloads" /></a>
16
+ <a href="https://github.com/owdproject/core/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-00DC82.svg?style=flat&colorA=020420&colorB=00DC82" alt="License" /></a>
17
+ </p>
13
18
 
14
- ## Installation
19
+ <p>
20
+ <a href="#overview">Overview</a> ·
21
+ <a href="#architecture--capabilities">Architecture</a> ·
22
+ <a href="#quick-start">Quick Start</a> ·
23
+ <a href="#desktop-subsystems-createdesktop">Subsystems API</a> ·
24
+ <a href="#official-framework-adapters">Adapters</a>
25
+ </p>
15
26
 
16
- \`\`\`bash
17
- pnpm add @owdproject/core
18
- \`\`\`
27
+ </div>
19
28
 
20
29
  ---
21
30
 
22
- Licensed under [MIT](./LICENSE)
31
+ ## Overview
32
+
33
+ `@owdproject/core` (`4.0.0-alpha.0`) is the pure TypeScript & XState v5 engine behind [Open Web Desktop](https://github.com/owdproject/nuxt-desktop).
34
+
35
+ Completely decoupled from any UI framework, it exposes `createDesktop()`—an isolated desktop kernel encapsulating window management, application lifecycle states (`PID`, `SIGSTOP`, `SIGCONT`, `SIGTERM`, `SIGKILL`), virtual workspaces, CLI command parsing, a 19-event `hookable` lifecycle bus, a pub/sub IPC bus, and a Pointer Events drag/resize engine.
36
+
37
+ ---
38
+
39
+ ## Architecture & Capabilities
40
+
41
+ * **Zero UI Framework Dependencies** — Pure TypeScript, `xstate` v5, `hookable`, `nanoid`, `getopts`, and `shellwords`. Runs identically in browsers, SSR, and Node.js test suites.
42
+ * **Frozen Immutable Snapshots (`Object.freeze`)** — Every window, process, and workspace transition emits a frozen snapshot compatible with React `useSyncExternalStore`, Vue `shallowRef`, Svelte stores, and Angular signals.
43
+ * **Deterministic XState v5 Machines** — `windowMachine` and `applicationMachine` prevent invalid state combinations across maximization, snapping, minimization, and process suspension.
44
+ * **W3C Pointer Engine & `IframeGuard`** — Native `setPointerCapture` drag and 8-directional resize math with magnetic snap-zone detection (`left-half`, `right-half`, `maximize`, corners) and automatic `<iframe>` pointer-event protection.
45
+ * **Cancellable Runtime Hooks** — Intercept and cancel `app:before-launch`, `window:before-open`, `command:before-exec`, or `workspace:before-switch` via `desktop.hooks`.
46
+
47
+ ---
48
+
49
+ ## Quick Start
50
+
51
+ Install `@owdproject/core`:
52
+
53
+ ```bash
54
+ pnpm add @owdproject/core@4.0.0-alpha.0
55
+ ```
56
+
57
+ Create an isolated desktop instance with `createDesktop()`:
58
+
59
+ ```ts
60
+ import { createDesktop } from '@owdproject/core'
61
+
62
+ const desktop = createDesktop({
63
+ workspaces: ['ws-main', 'ws-dev'],
64
+ activeWorkspace: 'ws-main',
65
+ workarea: { x: 0, y: 32, width: 1920, height: 1048 },
66
+ })
67
+
68
+ // Spawn a window
69
+ const win = desktop.windows.createWindow({
70
+ id: 'terminal-1',
71
+ model: 'terminal',
72
+ config: {
73
+ title: 'Terminal',
74
+ size: { width: 680, height: 440, minWidth: 320, minHeight: 220 },
75
+ position: { x: 120, y: 80 },
76
+ resizable: true,
77
+ maximizable: true,
78
+ minimizable: true,
79
+ },
80
+ })
81
+
82
+ // Snap to left half of workarea
83
+ win.setLayout('left-half', desktop.workspaces.workarea)
84
+
85
+ // Subscribe to immutable desktop snapshots
86
+ desktop.subscribe((snapshot) => {
87
+ console.log('Active windows:', snapshot.windows.length)
88
+ })
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Desktop Subsystems (`createDesktop()`)
94
+
95
+ | Subsystem | Type | Responsibility |
96
+ | :--- | :--- | :--- |
97
+ | **`desktop.windows`** | `WindowManager` | Window lookup, focus stacking, snap zones, and `tileWindows('horizontal' \| 'vertical' \| 'grid')`. |
98
+ | **`desktop.applications`** | `ApplicationManager` | Application manifest registry, `PID` allocation, and Unix signals (`suspend`, `resume`, `terminate`). |
99
+ | **`desktop.workspaces`** | `WorkspaceManager` | Virtual workspace switching, overview state, and workarea rectangle geometry. |
100
+ | **`desktop.commands`** | `DesktopCommands` | CLI command registry, tokenizer, and `exec()` dispatcher. |
101
+ | **`desktop.hooks`** | `Hookable<DesktopRuntimeHooks>` | 19 synchronous/asynchronous lifecycle hooks with `before-*` cancellation support. |
102
+ | **`desktop.ipc`** | `CoreIPCBus` | Cross-application pub/sub bus with wildcard (`*`) listener and event history ring buffer. |
103
+ | **`desktop.session`** | `{ serialize, restore }` | JSON session serialization and hydration for active windows and workspaces. |
104
+
105
+ ---
106
+
107
+ ## Official Framework Adapters
108
+
109
+ * **[@owdproject/nuxt](https://npmjs.com/package/@owdproject/nuxt)** — Official Nuxt & Vue 3 reactive composables and `WindowController`.
110
+ * **[@owdproject/react](https://npmjs.com/package/@owdproject/react)** — Official React 18/19 concurrent-safe hooks (`useSyncExternalStore`).
111
+ * **[@owdproject/svelte](https://npmjs.com/package/@owdproject/svelte)** — Official Svelte 4/5 `Readable` stores and pointer actions.
112
+ * **[@owdproject/angular](https://npmjs.com/package/@owdproject/angular)** — Official Angular 17+ `DesktopAdapterService` and reactive streams.
113
+ * **[@owdproject/astro](https://npmjs.com/package/@owdproject/astro)** — Official Astro multi-framework Islands and `<owd-desktop-window>` Custom Element.
114
+
115
+ ---
116
+
117
+ ## License
118
+
119
+ [MIT](https://opensource.org/licenses/MIT)
120
+
121
+ Copyright (c) 2024-present, [Diego Villa (@dxlliv)](https://github.com/dxlliv) and Open Web Desktop contributors.
@@ -0,0 +1,65 @@
1
+ import { WindowBounds, DesktopWorkareaRect, SnapZoneHint } from '../types/index.mjs';
2
+
3
+ /**
4
+ * IframeGuard: prevents embedded <iframe> apps from stealing pointer events
5
+ * during window dragging and resizing across all frameworks.
6
+ */
7
+ declare class IframeGuard {
8
+ /**
9
+ * Disables pointer events on all iframes in the document.
10
+ * Safe to call repeatedly; uses reference counting.
11
+ */
12
+ static enable(selector?: string): void;
13
+ /**
14
+ * Restores pointer events on all iframes once all active operations end.
15
+ */
16
+ static disable(selector?: string): void;
17
+ /**
18
+ * Guard an asynchronous or synchronous action with automatic enable/disable.
19
+ */
20
+ static wrap<T>(action: () => Promise<T> | T, selector?: string): Promise<T>;
21
+ }
22
+
23
+ /**
24
+ * @owdproject/core - Framework-Agnostic W3C Pointer Events Engine
25
+ * High-performance, zero-framework Drag & Resize controller with Pointer Capture,
26
+ * Boundary Clamping, 8-directional Resizing, and IframeGuard integration.
27
+ */
28
+
29
+ type ResizeDirection = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
30
+ interface DragSessionOptions {
31
+ initialBounds: WindowBounds;
32
+ workarea?: DesktopWorkareaRect;
33
+ minDistanceToDrag?: number;
34
+ onStart?: () => void;
35
+ onMove?: (bounds: WindowBounds, snapZone: SnapZoneHint | null) => void;
36
+ onEnd?: (finalBounds: WindowBounds, snapZone: SnapZoneHint | null) => void;
37
+ onCancel?: () => void;
38
+ }
39
+ interface ResizeSessionOptions {
40
+ direction: ResizeDirection;
41
+ initialBounds: WindowBounds;
42
+ minWidth?: number;
43
+ minHeight?: number;
44
+ maxWidth?: number;
45
+ maxHeight?: number;
46
+ workarea?: DesktopWorkareaRect;
47
+ onStart?: () => void;
48
+ onMove?: (bounds: WindowBounds) => void;
49
+ onEnd?: (finalBounds: WindowBounds) => void;
50
+ onCancel?: () => void;
51
+ }
52
+ declare class DesktopPointerSession {
53
+ /**
54
+ * Starts an agnostic pointer drag operation on any DOM element.
55
+ * Uses setPointerCapture to guarantee smooth tracking even if the cursor leaves the window.
56
+ */
57
+ static startDrag(event: PointerEvent, options: DragSessionOptions): () => void;
58
+ /**
59
+ * Starts an agnostic 8-directional pointer resize operation on any DOM element.
60
+ */
61
+ static startResize(event: PointerEvent, options: ResizeSessionOptions): () => void;
62
+ }
63
+
64
+ export { DesktopPointerSession, IframeGuard };
65
+ export type { DragSessionOptions, ResizeDirection, ResizeSessionOptions };
@@ -0,0 +1,65 @@
1
+ import { WindowBounds, DesktopWorkareaRect, SnapZoneHint } from '../types/index.js';
2
+
3
+ /**
4
+ * IframeGuard: prevents embedded <iframe> apps from stealing pointer events
5
+ * during window dragging and resizing across all frameworks.
6
+ */
7
+ declare class IframeGuard {
8
+ /**
9
+ * Disables pointer events on all iframes in the document.
10
+ * Safe to call repeatedly; uses reference counting.
11
+ */
12
+ static enable(selector?: string): void;
13
+ /**
14
+ * Restores pointer events on all iframes once all active operations end.
15
+ */
16
+ static disable(selector?: string): void;
17
+ /**
18
+ * Guard an asynchronous or synchronous action with automatic enable/disable.
19
+ */
20
+ static wrap<T>(action: () => Promise<T> | T, selector?: string): Promise<T>;
21
+ }
22
+
23
+ /**
24
+ * @owdproject/core - Framework-Agnostic W3C Pointer Events Engine
25
+ * High-performance, zero-framework Drag & Resize controller with Pointer Capture,
26
+ * Boundary Clamping, 8-directional Resizing, and IframeGuard integration.
27
+ */
28
+
29
+ type ResizeDirection = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
30
+ interface DragSessionOptions {
31
+ initialBounds: WindowBounds;
32
+ workarea?: DesktopWorkareaRect;
33
+ minDistanceToDrag?: number;
34
+ onStart?: () => void;
35
+ onMove?: (bounds: WindowBounds, snapZone: SnapZoneHint | null) => void;
36
+ onEnd?: (finalBounds: WindowBounds, snapZone: SnapZoneHint | null) => void;
37
+ onCancel?: () => void;
38
+ }
39
+ interface ResizeSessionOptions {
40
+ direction: ResizeDirection;
41
+ initialBounds: WindowBounds;
42
+ minWidth?: number;
43
+ minHeight?: number;
44
+ maxWidth?: number;
45
+ maxHeight?: number;
46
+ workarea?: DesktopWorkareaRect;
47
+ onStart?: () => void;
48
+ onMove?: (bounds: WindowBounds) => void;
49
+ onEnd?: (finalBounds: WindowBounds) => void;
50
+ onCancel?: () => void;
51
+ }
52
+ declare class DesktopPointerSession {
53
+ /**
54
+ * Starts an agnostic pointer drag operation on any DOM element.
55
+ * Uses setPointerCapture to guarantee smooth tracking even if the cursor leaves the window.
56
+ */
57
+ static startDrag(event: PointerEvent, options: DragSessionOptions): () => void;
58
+ /**
59
+ * Starts an agnostic 8-directional pointer resize operation on any DOM element.
60
+ */
61
+ static startResize(event: PointerEvent, options: ResizeSessionOptions): () => void;
62
+ }
63
+
64
+ export { DesktopPointerSession, IframeGuard };
65
+ export type { DragSessionOptions, ResizeDirection, ResizeSessionOptions };
@@ -0,0 +1,224 @@
1
+ import { d as detectSnapZone } from '../shared/core.b3Xldzyu.mjs';
2
+ import '../shared/core.CsDFgGnX.mjs';
3
+
4
+ let activeGuardCount = 0;
5
+ const originalPointerEventsMap = /* @__PURE__ */ new WeakMap();
6
+ class IframeGuard {
7
+ /**
8
+ * Disables pointer events on all iframes in the document.
9
+ * Safe to call repeatedly; uses reference counting.
10
+ */
11
+ static enable(selector = "iframe") {
12
+ if (typeof document === "undefined") return;
13
+ activeGuardCount++;
14
+ if (activeGuardCount === 1) {
15
+ const iframes = document.querySelectorAll(selector);
16
+ iframes.forEach((iframe) => {
17
+ originalPointerEventsMap.set(iframe, iframe.style.pointerEvents);
18
+ iframe.style.pointerEvents = "none";
19
+ });
20
+ }
21
+ }
22
+ /**
23
+ * Restores pointer events on all iframes once all active operations end.
24
+ */
25
+ static disable(selector = "iframe") {
26
+ if (typeof document === "undefined") return;
27
+ activeGuardCount = Math.max(0, activeGuardCount - 1);
28
+ if (activeGuardCount === 0) {
29
+ const iframes = document.querySelectorAll(selector);
30
+ iframes.forEach((iframe) => {
31
+ const orig = originalPointerEventsMap.get(iframe) ?? "";
32
+ iframe.style.pointerEvents = orig;
33
+ originalPointerEventsMap.delete(iframe);
34
+ });
35
+ }
36
+ }
37
+ /**
38
+ * Guard an asynchronous or synchronous action with automatic enable/disable.
39
+ */
40
+ static async wrap(action, selector = "iframe") {
41
+ IframeGuard.enable(selector);
42
+ try {
43
+ return await action();
44
+ } finally {
45
+ IframeGuard.disable(selector);
46
+ }
47
+ }
48
+ }
49
+
50
+ class DesktopPointerSession {
51
+ /**
52
+ * Starts an agnostic pointer drag operation on any DOM element.
53
+ * Uses setPointerCapture to guarantee smooth tracking even if the cursor leaves the window.
54
+ */
55
+ static startDrag(event, options) {
56
+ if (typeof window === "undefined") return () => {
57
+ };
58
+ const target = event.currentTarget;
59
+ const pointerId = event.pointerId;
60
+ const startX = event.clientX;
61
+ const startY = event.clientY;
62
+ const { initialBounds, workarea, minDistanceToDrag = 3 } = options;
63
+ let hasStarted = false;
64
+ let currentBounds = { ...initialBounds };
65
+ let currentSnapZone = null;
66
+ try {
67
+ target?.setPointerCapture(pointerId);
68
+ } catch {
69
+ }
70
+ const onPointerMove = (e) => {
71
+ if (e.pointerId !== pointerId) return;
72
+ const deltaX = e.clientX - startX;
73
+ const deltaY = e.clientY - startY;
74
+ if (!hasStarted) {
75
+ const distance = Math.hypot(deltaX, deltaY);
76
+ if (distance >= minDistanceToDrag) {
77
+ hasStarted = true;
78
+ IframeGuard.enable();
79
+ options.onStart?.();
80
+ } else {
81
+ return;
82
+ }
83
+ }
84
+ let newX = initialBounds.x + deltaX;
85
+ let newY = initialBounds.y + deltaY;
86
+ if (workarea) {
87
+ const minVisiblePx = 40;
88
+ newX = Math.max(workarea.x - initialBounds.width + minVisiblePx, Math.min(newX, workarea.x + workarea.width - minVisiblePx));
89
+ newY = Math.max(workarea.y, Math.min(newY, workarea.y + workarea.height - 30));
90
+ }
91
+ currentBounds = {
92
+ x: Math.round(newX),
93
+ y: Math.round(newY),
94
+ width: initialBounds.width,
95
+ height: initialBounds.height
96
+ };
97
+ if (workarea) {
98
+ currentSnapZone = detectSnapZone(e.clientX, e.clientY, workarea);
99
+ }
100
+ options.onMove?.(currentBounds, currentSnapZone);
101
+ };
102
+ const cleanup = () => {
103
+ window.removeEventListener("pointermove", onPointerMove);
104
+ window.removeEventListener("pointerup", onPointerUp);
105
+ window.removeEventListener("pointercancel", onPointerCancel);
106
+ try {
107
+ if (target?.hasPointerCapture(pointerId)) {
108
+ target.releasePointerCapture(pointerId);
109
+ }
110
+ } catch {
111
+ }
112
+ IframeGuard.disable();
113
+ };
114
+ const onPointerUp = (e) => {
115
+ if (e.pointerId !== pointerId) return;
116
+ cleanup();
117
+ if (hasStarted) {
118
+ options.onEnd?.(currentBounds, currentSnapZone);
119
+ }
120
+ };
121
+ const onPointerCancel = (e) => {
122
+ if (e.pointerId !== pointerId) return;
123
+ cleanup();
124
+ if (hasStarted) {
125
+ options.onCancel?.();
126
+ }
127
+ };
128
+ window.addEventListener("pointermove", onPointerMove, { passive: false });
129
+ window.addEventListener("pointerup", onPointerUp, { passive: true });
130
+ window.addEventListener("pointercancel", onPointerCancel, { passive: true });
131
+ return cleanup;
132
+ }
133
+ /**
134
+ * Starts an agnostic 8-directional pointer resize operation on any DOM element.
135
+ */
136
+ static startResize(event, options) {
137
+ if (typeof window === "undefined") return () => {
138
+ };
139
+ const target = event.currentTarget;
140
+ const pointerId = event.pointerId;
141
+ const startX = event.clientX;
142
+ const startY = event.clientY;
143
+ const {
144
+ direction,
145
+ initialBounds,
146
+ minWidth = 240,
147
+ minHeight = 160,
148
+ maxWidth = 3840,
149
+ maxHeight = 2160
150
+ } = options;
151
+ let currentBounds = { ...initialBounds };
152
+ try {
153
+ target?.setPointerCapture(pointerId);
154
+ } catch {
155
+ }
156
+ IframeGuard.enable();
157
+ options.onStart?.();
158
+ const onPointerMove = (e) => {
159
+ if (e.pointerId !== pointerId) return;
160
+ const deltaX = e.clientX - startX;
161
+ const deltaY = e.clientY - startY;
162
+ let { x, y, width, height } = initialBounds;
163
+ if (direction.includes("e")) {
164
+ width = Math.min(maxWidth, Math.max(minWidth, initialBounds.width + deltaX));
165
+ } else if (direction.includes("w")) {
166
+ const potentialWidth = initialBounds.width - deltaX;
167
+ if (potentialWidth >= minWidth && potentialWidth <= maxWidth) {
168
+ width = potentialWidth;
169
+ x = initialBounds.x + deltaX;
170
+ } else if (potentialWidth < minWidth) {
171
+ width = minWidth;
172
+ x = initialBounds.x + (initialBounds.width - minWidth);
173
+ }
174
+ }
175
+ if (direction.includes("s")) {
176
+ height = Math.min(maxHeight, Math.max(minHeight, initialBounds.height + deltaY));
177
+ } else if (direction.includes("n")) {
178
+ const potentialHeight = initialBounds.height - deltaY;
179
+ if (potentialHeight >= minHeight && potentialHeight <= maxHeight) {
180
+ height = potentialHeight;
181
+ y = initialBounds.y + deltaY;
182
+ } else if (potentialHeight < minHeight) {
183
+ height = minHeight;
184
+ y = initialBounds.y + (initialBounds.height - minHeight);
185
+ }
186
+ }
187
+ currentBounds = {
188
+ x: Math.round(x),
189
+ y: Math.round(y),
190
+ width: Math.round(width),
191
+ height: Math.round(height)
192
+ };
193
+ options.onMove?.(currentBounds);
194
+ };
195
+ const cleanup = () => {
196
+ window.removeEventListener("pointermove", onPointerMove);
197
+ window.removeEventListener("pointerup", onPointerUp);
198
+ window.removeEventListener("pointercancel", onPointerCancel);
199
+ try {
200
+ if (target?.hasPointerCapture(pointerId)) {
201
+ target.releasePointerCapture(pointerId);
202
+ }
203
+ } catch {
204
+ }
205
+ IframeGuard.disable();
206
+ };
207
+ const onPointerUp = (e) => {
208
+ if (e.pointerId !== pointerId) return;
209
+ cleanup();
210
+ options.onEnd?.(currentBounds);
211
+ };
212
+ const onPointerCancel = (e) => {
213
+ if (e.pointerId !== pointerId) return;
214
+ cleanup();
215
+ options.onCancel?.();
216
+ };
217
+ window.addEventListener("pointermove", onPointerMove, { passive: false });
218
+ window.addEventListener("pointerup", onPointerUp, { passive: true });
219
+ window.addEventListener("pointercancel", onPointerCancel, { passive: true });
220
+ return cleanup;
221
+ }
222
+ }
223
+
224
+ export { DesktopPointerSession, IframeGuard };
@@ -0,0 +1,70 @@
1
+ import { C as CoreIPCBus } from '../shared/core.Di1eFcr_.mjs';
2
+ import { WindowManager } from '../index.mjs';
3
+ export { E as EventHandler, g as globalIPCBus } from '../shared/core.Di1eFcr_.mjs';
4
+ import { Hookable } from 'hookable';
5
+ import { DesktopRuntimeHooks, DesktopWorkareaRect, CommandOutput, DesktopCommand } from '../types/index.mjs';
6
+
7
+ declare function createDesktopHooks(): Hookable<DesktopRuntimeHooks>;
8
+ declare const globalDesktopHooks: Hookable<DesktopRuntimeHooks>;
9
+
10
+ declare function shellEscape(str: string): string;
11
+ declare function padEnd(str: string, len: number): string;
12
+ declare function formatDuration(ms: number): string;
13
+ declare function parseCommandLine(input: string): {
14
+ name: string;
15
+ args: string[];
16
+ };
17
+
18
+ /**
19
+ * @owdproject/core - Framework-Agnostic Desktop Keybindings Engine
20
+ * Listens to OS-level shortcuts (Alt+Tab, Super+Arrows, Close, Minimize) and triggers actions.
21
+ */
22
+
23
+ interface KeybindingActionContext {
24
+ event: KeyboardEvent;
25
+ windowManager: WindowManager;
26
+ workarea?: DesktopWorkareaRect;
27
+ }
28
+ type KeybindingHandler = (ctx: KeybindingActionContext) => void | boolean;
29
+ declare class DesktopKeybindings {
30
+ private windowManager;
31
+ private workareaProvider?;
32
+ private customHandlers;
33
+ private isListening;
34
+ private listenerRef?;
35
+ constructor(windowManager: WindowManager, options?: {
36
+ workareaProvider?: () => DesktopWorkareaRect | undefined;
37
+ });
38
+ register(shortcut: string, handler: KeybindingHandler): this;
39
+ listen(): () => void;
40
+ stop(): void;
41
+ private handleKeyDown;
42
+ private cycleWindowFocus;
43
+ }
44
+
45
+ type DesktopCommandHandler = (args: string[], rawInput: string) => Promise<CommandOutput | string | void> | CommandOutput | string | void;
46
+ interface RegisteredDesktopCommand extends DesktopCommand {
47
+ handler: DesktopCommandHandler;
48
+ }
49
+ declare class DesktopCommands {
50
+ private commands;
51
+ private snapshotCache;
52
+ private subscribers;
53
+ private hooks;
54
+ private ipc;
55
+ constructor(options?: {
56
+ hooks?: Hookable<DesktopRuntimeHooks>;
57
+ ipc?: CoreIPCBus;
58
+ });
59
+ getSnapshot(): DesktopCommand[];
60
+ subscribe(callback: (commands: DesktopCommand[]) => void): () => void;
61
+ private notify;
62
+ register(command: DesktopCommand, handler: DesktopCommandHandler): () => void;
63
+ unregister(name: string): boolean;
64
+ has(name: string): boolean;
65
+ getCommands(): DesktopCommand[];
66
+ exec(input: string): Promise<CommandOutput | void>;
67
+ }
68
+
69
+ export { CoreIPCBus, DesktopCommands, DesktopKeybindings, DesktopRuntimeHooks, createDesktopHooks, formatDuration, globalDesktopHooks, padEnd, parseCommandLine, shellEscape };
70
+ export type { DesktopCommandHandler, KeybindingActionContext, KeybindingHandler, RegisteredDesktopCommand };
@@ -0,0 +1,70 @@
1
+ import { C as CoreIPCBus } from '../shared/core.BOvFdEVQ.js';
2
+ import { WindowManager } from '../index.js';
3
+ export { E as EventHandler, g as globalIPCBus } from '../shared/core.BOvFdEVQ.js';
4
+ import { Hookable } from 'hookable';
5
+ import { DesktopRuntimeHooks, DesktopWorkareaRect, CommandOutput, DesktopCommand } from '../types/index.js';
6
+
7
+ declare function createDesktopHooks(): Hookable<DesktopRuntimeHooks>;
8
+ declare const globalDesktopHooks: Hookable<DesktopRuntimeHooks>;
9
+
10
+ declare function shellEscape(str: string): string;
11
+ declare function padEnd(str: string, len: number): string;
12
+ declare function formatDuration(ms: number): string;
13
+ declare function parseCommandLine(input: string): {
14
+ name: string;
15
+ args: string[];
16
+ };
17
+
18
+ /**
19
+ * @owdproject/core - Framework-Agnostic Desktop Keybindings Engine
20
+ * Listens to OS-level shortcuts (Alt+Tab, Super+Arrows, Close, Minimize) and triggers actions.
21
+ */
22
+
23
+ interface KeybindingActionContext {
24
+ event: KeyboardEvent;
25
+ windowManager: WindowManager;
26
+ workarea?: DesktopWorkareaRect;
27
+ }
28
+ type KeybindingHandler = (ctx: KeybindingActionContext) => void | boolean;
29
+ declare class DesktopKeybindings {
30
+ private windowManager;
31
+ private workareaProvider?;
32
+ private customHandlers;
33
+ private isListening;
34
+ private listenerRef?;
35
+ constructor(windowManager: WindowManager, options?: {
36
+ workareaProvider?: () => DesktopWorkareaRect | undefined;
37
+ });
38
+ register(shortcut: string, handler: KeybindingHandler): this;
39
+ listen(): () => void;
40
+ stop(): void;
41
+ private handleKeyDown;
42
+ private cycleWindowFocus;
43
+ }
44
+
45
+ type DesktopCommandHandler = (args: string[], rawInput: string) => Promise<CommandOutput | string | void> | CommandOutput | string | void;
46
+ interface RegisteredDesktopCommand extends DesktopCommand {
47
+ handler: DesktopCommandHandler;
48
+ }
49
+ declare class DesktopCommands {
50
+ private commands;
51
+ private snapshotCache;
52
+ private subscribers;
53
+ private hooks;
54
+ private ipc;
55
+ constructor(options?: {
56
+ hooks?: Hookable<DesktopRuntimeHooks>;
57
+ ipc?: CoreIPCBus;
58
+ });
59
+ getSnapshot(): DesktopCommand[];
60
+ subscribe(callback: (commands: DesktopCommand[]) => void): () => void;
61
+ private notify;
62
+ register(command: DesktopCommand, handler: DesktopCommandHandler): () => void;
63
+ unregister(name: string): boolean;
64
+ has(name: string): boolean;
65
+ getCommands(): DesktopCommand[];
66
+ exec(input: string): Promise<CommandOutput | void>;
67
+ }
68
+
69
+ export { CoreIPCBus, DesktopCommands, DesktopKeybindings, DesktopRuntimeHooks, createDesktopHooks, formatDuration, globalDesktopHooks, padEnd, parseCommandLine, shellEscape };
70
+ export type { DesktopCommandHandler, KeybindingActionContext, KeybindingHandler, RegisteredDesktopCommand };
@@ -0,0 +1,3 @@
1
+ export { C as CoreIPCBus, c as createDesktopHooks, g as globalDesktopHooks, a as globalIPCBus } from '../shared/core.Pd_Ogt4g.mjs';
2
+ export { D as DesktopCommands, a as DesktopKeybindings, f as formatDuration, p as padEnd, b as parseCommandLine, s as shellEscape } from '../shared/core.B1XxB289.mjs';
3
+ import 'hookable';