diff --git a/VERSION b/VERSION index ac454c6..54d1a4f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.12.0 +0.13.0 diff --git a/web/package-lock.json b/web/package-lock.json index a08cd35..4bb29d3 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -18,7 +18,8 @@ "uplot": "^1.6.32" }, "devDependencies": { - "@lucide/svelte": "^1.23.0", + "@internationalized/date": "^3.12.2", + "@lucide/svelte": "^1.25.0", "@sveltejs/vite-plugin-svelte": "^5.0.0", "@tailwindcss/vite": "^4.3.2", "@tsconfig/svelte": "^5.0.0", @@ -870,7 +871,6 @@ "integrity": "sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@swc/helpers": "^0.5.0" } @@ -921,9 +921,9 @@ } }, "node_modules/@lucide/svelte": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-1.23.0.tgz", - "integrity": "sha512-3LQbKXx9vId6Nx4E2Nu2qwgJfdmr5+CVeVJbxe5cy+HcnCRd9QVVtZXqvgBYAV1OJrPmQAf9/3gJWLCpASC/Ng==", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-1.25.0.tgz", + "integrity": "sha512-v9m+dD68jxVnqkU3K59mG/RSRFlPGzmKCGSyMfnXcaGv9jODDQMyQkcp1CGvk3Y/cUj9v7f8rw1n//K0B53xGQ==", "dev": true, "license": "ISC", "peerDependencies": { @@ -1378,7 +1378,6 @@ "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.8.0" } diff --git a/web/package.json b/web/package.json index 58573f6..ebaf7fa 100644 --- a/web/package.json +++ b/web/package.json @@ -17,7 +17,8 @@ "test:watch": "vitest" }, "devDependencies": { - "@lucide/svelte": "^1.23.0", + "@internationalized/date": "^3.12.2", + "@lucide/svelte": "^1.25.0", "@sveltejs/vite-plugin-svelte": "^5.0.0", "@tailwindcss/vite": "^4.3.2", "@tsconfig/svelte": "^5.0.0", diff --git a/web/src/lib/components/desktop-shell/Desktop.svelte b/web/src/lib/components/desktop-shell/Desktop.svelte index 2226bd6..e4da1cd 100644 --- a/web/src/lib/components/desktop-shell/Desktop.svelte +++ b/web/src/lib/components/desktop-shell/Desktop.svelte @@ -15,6 +15,7 @@ import WindowLayer from './WindowLayer.svelte' import DockedLayer from './DockedLayer.svelte' import Taskbar from './Taskbar.svelte' + import * as ContextMenu from '$lib/components/ui/context-menu' import LayersIcon from '@lucide/svelte/icons/layers' import Rows3Icon from '@lucide/svelte/icons/rows-3' import MonitorIcon from '@lucide/svelte/icons/monitor' @@ -22,37 +23,18 @@ import Undo2Icon from '@lucide/svelte/icons/undo-2' import Redo2Icon from '@lucide/svelte/icons/redo-2' - // Clicking the bare desktop (not an icon, not a window) blurs the focused - // window — the familiar "click empty desktop to deselect" affordance. - function onSurfaceClick(e: MouseEvent) { - if (e.currentTarget === e.target) wm.blur() - } - - // Right-click menu, bare desktop only (same currentTarget===target gate as - // onSurfaceClick above — icons and windows sit on pointer-events-auto - // layers above the otherwise pointer-events-none surface, so a right-click - // that lands on either of them never reaches here). canUndo/canRedo are - // plain wmkit method calls (not stores), so they're snapshotted once at - // open time rather than read reactively in the template. - let menuPos = $state<{ x: number; y: number } | null>(null) + // canUndo/canRedo are plain wmkit method calls (not stores), so they're + // snapshotted once when the menu opens (onOpenChange) rather than read + // reactively in the template. bits-ui auto-dismisses on item select and + // on Escape / click-away, so the old manual menuPos/closeMenu/runMenuAction + // machinery is gone. let menuCanUndo = $state(false) let menuCanRedo = $state(false) - function onSurfaceContextMenu(e: MouseEvent) { - if (e.currentTarget !== e.target) return - e.preventDefault() + function onOpenChange(open: boolean) { + if (!open) return menuCanUndo = wm.canUndo() menuCanRedo = wm.canRedo() - menuPos = { x: e.clientX, y: e.clientY } - } - - function closeMenu() { - menuPos = null - } - - function runMenuAction(fn: () => void) { - fn() - closeMenu() } // Cmd/Ctrl+Z / Shift+Z for window-arrangement undo/redo (move, resize, @@ -61,10 +43,6 @@ // fights the browser's own text-undo inside the task input or a form // field. function onWindowKeydown(e: KeyboardEvent) { - if (e.key === 'Escape' && menuPos) { - closeMenu() - return - } const target = e.target as HTMLElement | null const editable = !!target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) if (editable) return @@ -75,17 +53,48 @@ } - +
-