@tearleads/windowing 0.1.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.
- package/README.md +155 -0
- package/createRequiredContext.d.ts +16 -0
- package/createRequiredContext.js +22 -0
- package/createRequiredContext.js.map +1 -0
- package/index.d.ts +13 -0
- package/index.js +17 -0
- package/index.js.map +1 -0
- package/menu/Menu.css +105 -0
- package/menu/Menu.d.ts +11 -0
- package/menu/Menu.js +175 -0
- package/menu/Menu.js.map +1 -0
- package/menu/MenuItem.d.ts +9 -0
- package/menu/MenuItem.js +5 -0
- package/menu/MenuItem.js.map +1 -0
- package/menu/useContextMenuState.d.ts +20 -0
- package/menu/useContextMenuState.js +45 -0
- package/menu/useContextMenuState.js.map +1 -0
- package/menu/useMenuKeyboard.d.ts +2 -0
- package/menu/useMenuKeyboard.js +90 -0
- package/menu/useMenuKeyboard.js.map +1 -0
- package/package.json +27 -0
- package/sidebar/SidebarResize.css +31 -0
- package/sidebar/SidebarResize.d.ts +18 -0
- package/sidebar/SidebarResize.js +115 -0
- package/sidebar/SidebarResize.js.map +1 -0
- package/tokens.css +63 -0
- package/window/CurrentWindowContext.d.ts +27 -0
- package/window/CurrentWindowContext.js +31 -0
- package/window/CurrentWindowContext.js.map +1 -0
- package/window/Window.css +32 -0
- package/window/Window.d.ts +11 -0
- package/window/Window.js +206 -0
- package/window/Window.js.map +1 -0
- package/window/WindowBody.css +21 -0
- package/window/WindowBody.d.ts +8 -0
- package/window/WindowBody.js +10 -0
- package/window/WindowBody.js.map +1 -0
- package/window/WindowChromeActions.d.ts +55 -0
- package/window/WindowChromeActions.js +61 -0
- package/window/WindowChromeActions.js.map +1 -0
- package/window/WindowCloseButton.d.ts +6 -0
- package/window/WindowCloseButton.js +9 -0
- package/window/WindowCloseButton.js.map +1 -0
- package/window/WindowMaximizeButton.d.ts +3 -0
- package/window/WindowMaximizeButton.js +5 -0
- package/window/WindowMaximizeButton.js.map +1 -0
- package/window/WindowMenuBar.css +63 -0
- package/window/WindowMenuBar.d.ts +14 -0
- package/window/WindowMenuBar.js +37 -0
- package/window/WindowMenuBar.js.map +1 -0
- package/window/WindowMenuContext.d.ts +46 -0
- package/window/WindowMenuContext.js +208 -0
- package/window/WindowMenuContext.js.map +1 -0
- package/window/WindowMinimizeButton.d.ts +3 -0
- package/window/WindowMinimizeButton.js +5 -0
- package/window/WindowMinimizeButton.js.map +1 -0
- package/window/WindowResizeHandle.css +65 -0
- package/window/WindowResizeHandle.d.ts +5 -0
- package/window/WindowResizeHandle.js +6 -0
- package/window/WindowResizeHandle.js.map +1 -0
- package/window/WindowSidebar.css +37 -0
- package/window/WindowSidebar.d.ts +6 -0
- package/window/WindowSidebar.js +9 -0
- package/window/WindowSidebar.js.map +1 -0
- package/window/WindowSidebarContext.d.ts +14 -0
- package/window/WindowSidebarContext.js +43 -0
- package/window/WindowSidebarContext.js.map +1 -0
- package/window/WindowStateProvider/WindowStateProvider.d.ts +2 -0
- package/window/WindowStateProvider/WindowStateProvider.js +16 -0
- package/window/WindowStateProvider/WindowStateProvider.js.map +1 -0
- package/window/WindowStateProvider/context.d.ts +4 -0
- package/window/WindowStateProvider/context.js +7 -0
- package/window/WindowStateProvider/context.js.map +1 -0
- package/window/WindowStateProvider/index.d.ts +5 -0
- package/window/WindowStateProvider/index.js +5 -0
- package/window/WindowStateProvider/index.js.map +1 -0
- package/window/WindowStateProvider/types.d.ts +58 -0
- package/window/WindowStateProvider/types.js +2 -0
- package/window/WindowStateProvider/types.js.map +1 -0
- package/window/WindowStateProvider/useWindowActions.d.ts +1 -0
- package/window/WindowStateProvider/useWindowActions.js +3 -0
- package/window/WindowStateProvider/useWindowActions.js.map +1 -0
- package/window/WindowStateProvider/useWindowStateActions.d.ts +24 -0
- package/window/WindowStateProvider/useWindowStateActions.js +176 -0
- package/window/WindowStateProvider/useWindowStateActions.js.map +1 -0
- package/window/WindowStateProvider/useWindowStateData.d.ts +1 -0
- package/window/WindowStateProvider/useWindowStateData.js +3 -0
- package/window/WindowStateProvider/useWindowStateData.js.map +1 -0
- package/window/WindowStateProvider/util/bringWindowToFront.d.ts +2 -0
- package/window/WindowStateProvider/util/bringWindowToFront.js +21 -0
- package/window/WindowStateProvider/util/bringWindowToFront.js.map +1 -0
- package/window/WindowStateProvider/util/createWindowEntry.d.ts +3 -0
- package/window/WindowStateProvider/util/createWindowEntry.js +20 -0
- package/window/WindowStateProvider/util/createWindowEntry.js.map +1 -0
- package/window/WindowStateProvider/util/findAdjacentWindow.d.ts +2 -0
- package/window/WindowStateProvider/util/findAdjacentWindow.js +22 -0
- package/window/WindowStateProvider/util/findAdjacentWindow.js.map +1 -0
- package/window/WindowStateProvider/util/findTopWindow.d.ts +3 -0
- package/window/WindowStateProvider/util/findTopWindow.js +7 -0
- package/window/WindowStateProvider/util/findTopWindow.js.map +1 -0
- package/window/WindowStateProvider/util/getMaxWindowZIndex.d.ts +2 -0
- package/window/WindowStateProvider/util/getMaxWindowZIndex.js +4 -0
- package/window/WindowStateProvider/util/getMaxWindowZIndex.js.map +1 -0
- package/window/WindowStateProvider/util/index.d.ts +6 -0
- package/window/WindowStateProvider/util/index.js +7 -0
- package/window/WindowStateProvider/util/index.js.map +1 -0
- package/window/WindowStateProvider/util/swapWindowZIndexes.d.ts +2 -0
- package/window/WindowStateProvider/util/swapWindowZIndexes.js +21 -0
- package/window/WindowStateProvider/util/swapWindowZIndexes.js.map +1 -0
- package/window/WindowStateProvider/util/updateWindowFlag.d.ts +2 -0
- package/window/WindowStateProvider/util/updateWindowFlag.js +4 -0
- package/window/WindowStateProvider/util/updateWindowFlag.js.map +1 -0
- package/window/WindowStatusBar.css +40 -0
- package/window/WindowStatusBar.d.ts +4 -0
- package/window/WindowStatusBar.js +20 -0
- package/window/WindowStatusBar.js.map +1 -0
- package/window/WindowTitleBar.css +88 -0
- package/window/WindowTitleBar.d.ts +18 -0
- package/window/WindowTitleBar.js +36 -0
- package/window/WindowTitleBar.js.map +1 -0
- package/window/WindowToolBar.css +75 -0
- package/window/WindowToolBar.d.ts +38 -0
- package/window/WindowToolBar.js +68 -0
- package/window/WindowToolBar.js.map +1 -0
- package/window/useWindowGeometry.d.ts +16 -0
- package/window/useWindowGeometry.js +243 -0
- package/window/useWindowGeometry.js.map +1 -0
- package/window/useWindowItemRegistration.d.ts +10 -0
- package/window/useWindowItemRegistration.js +46 -0
- package/window/useWindowItemRegistration.js.map +1 -0
- package/window/useWindowItemRegistry.d.ts +12 -0
- package/window/useWindowItemRegistry.js +45 -0
- package/window/useWindowItemRegistry.js.map +1 -0
- package/window/useWindowKeyboardGeometry.d.ts +21 -0
- package/window/useWindowKeyboardGeometry.js +139 -0
- package/window/useWindowKeyboardGeometry.js.map +1 -0
- package/window/useWindowLayout.d.ts +18 -0
- package/window/useWindowLayout.js +115 -0
- package/window/useWindowLayout.js.map +1 -0
- package/window/useWindowToolbarReservationRegistry.d.ts +8 -0
- package/window/useWindowToolbarReservationRegistry.js +19 -0
- package/window/useWindowToolbarReservationRegistry.js.map +1 -0
- package/window/windowGeometry.d.ts +36 -0
- package/window/windowGeometry.js +54 -0
- package/window/windowGeometry.js.map +1 -0
- package/window/windowMenuRegistrations.d.ts +18 -0
- package/window/windowMenuRegistrations.js +34 -0
- package/window/windowMenuRegistrations.js.map +1 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
export type WindowMoveDirection = "forward" | "backward";
|
|
3
|
+
export interface WindowPosition {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
}
|
|
7
|
+
export interface WindowSize {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}
|
|
11
|
+
export interface WindowGeometry {
|
|
12
|
+
position: WindowPosition;
|
|
13
|
+
size?: WindowSize | undefined;
|
|
14
|
+
}
|
|
15
|
+
export interface WindowEntry {
|
|
16
|
+
appId?: string;
|
|
17
|
+
id: string;
|
|
18
|
+
initialShowSidebar?: boolean | undefined;
|
|
19
|
+
pathSegments?: ReadonlyArray<string> | undefined;
|
|
20
|
+
routeHistory?: ReadonlyArray<ReadonlyArray<string>> | undefined;
|
|
21
|
+
title: string;
|
|
22
|
+
initialX: number;
|
|
23
|
+
initialY: number;
|
|
24
|
+
position?: WindowPosition | undefined;
|
|
25
|
+
size?: WindowSize | undefined;
|
|
26
|
+
maximized: boolean;
|
|
27
|
+
minimized: boolean;
|
|
28
|
+
zIndex: number;
|
|
29
|
+
component?: ComponentType;
|
|
30
|
+
}
|
|
31
|
+
export interface WindowCreateOptions {
|
|
32
|
+
appId?: string;
|
|
33
|
+
initialShowSidebar?: boolean | undefined;
|
|
34
|
+
pathSegments?: ReadonlyArray<string> | undefined;
|
|
35
|
+
position?: WindowPosition | undefined;
|
|
36
|
+
size?: WindowSize | undefined;
|
|
37
|
+
}
|
|
38
|
+
export interface WindowStateData {
|
|
39
|
+
windows: WindowEntry[];
|
|
40
|
+
windowMap: Map<string, WindowEntry>;
|
|
41
|
+
}
|
|
42
|
+
export interface WindowStateActions {
|
|
43
|
+
create: (title: string, x: number, y: number, component?: ComponentType, options?: WindowCreateOptions) => string;
|
|
44
|
+
close: (id: string) => void;
|
|
45
|
+
maximize: (id: string) => void;
|
|
46
|
+
minimize: (id: string) => void;
|
|
47
|
+
restore: (id: string) => void;
|
|
48
|
+
toggleMaximize: (id: string) => void;
|
|
49
|
+
updateRoute: (id: string, pathSegments: ReadonlyArray<string>, options?: {
|
|
50
|
+
replace?: boolean | undefined;
|
|
51
|
+
}) => void;
|
|
52
|
+
goBackRoute: (id: string) => void;
|
|
53
|
+
updateTitle: (id: string, title: string) => void;
|
|
54
|
+
moveForward: (id: string) => void;
|
|
55
|
+
moveBackward: (id: string) => void;
|
|
56
|
+
bringToFront: (id: string) => void;
|
|
57
|
+
setGeometry: (id: string, geometry: WindowGeometry) => void;
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ComponentType } from \"react\";\n\nexport type WindowMoveDirection = \"forward\" | \"backward\";\n\n// Window geometry is relative to the desktop surface a window is rendered in\n// (the window's offset parent), not to the viewport.\nexport interface WindowPosition {\n x: number;\n y: number;\n}\n\nexport interface WindowSize {\n width: number;\n height: number;\n}\n\nexport interface WindowGeometry {\n position: WindowPosition;\n size?: WindowSize | undefined;\n}\n\nexport interface WindowEntry {\n // An opaque key naming the app that owns this window. The window layer only\n // stores and compares it; the host interprets it (see Window's\n // ContentBoundary).\n appId?: string;\n id: string;\n initialShowSidebar?: boolean | undefined;\n pathSegments?: ReadonlyArray<string> | undefined;\n // The window's own Back stack: routes previously visited in this window, the\n // most recent last. A window is not backed by browser history (only the\n // routed shell is), so this is what gives the windowed toolbar a working Back\n // caret. Forward is deliberately not modelled — the toolbar offers Back only.\n routeHistory?: ReadonlyArray<ReadonlyArray<string>> | undefined;\n title: string;\n // Where the window first appears, in viewport coordinates (for example the\n // point a launcher was clicked). Ignored once position is known.\n initialX: number;\n initialY: number;\n // The window's committed geometry. Set when the window is first laid out and\n // whenever a drag or resize ends, so a host can save and restore a layout.\n // Without size the window takes its stylesheet's default size.\n position?: WindowPosition | undefined;\n size?: WindowSize | undefined;\n // maximized and minimized live here rather than inside Window so the taskbar\n // can drive both without reaching into a window's local state.\n maximized: boolean;\n minimized: boolean;\n zIndex: number;\n component?: ComponentType;\n}\n\nexport interface WindowCreateOptions {\n appId?: string;\n initialShowSidebar?: boolean | undefined;\n pathSegments?: ReadonlyArray<string> | undefined;\n // Surface-relative geometry to open with, such as a restored layout. A\n // position takes precedence over create's viewport x/y.\n position?: WindowPosition | undefined;\n size?: WindowSize | undefined;\n}\n\nexport interface WindowStateData {\n // windows is the raw useState array — stable and cheap to iterate for\n // rendering lists. windowMap is derived via useMemo for O(1) lookups by ID.\n // Both are already memoized so neither adds redundant computation.\n windows: WindowEntry[];\n windowMap: Map<string, WindowEntry>;\n}\n\nexport interface WindowStateActions {\n create: (\n title: string,\n x: number,\n y: number,\n component?: ComponentType,\n options?: WindowCreateOptions,\n ) => string;\n close: (id: string) => void;\n maximize: (id: string) => void;\n minimize: (id: string) => void;\n restore: (id: string) => void;\n toggleMaximize: (id: string) => void;\n updateRoute: (\n id: string,\n pathSegments: ReadonlyArray<string>,\n options?: { replace?: boolean | undefined },\n ) => void;\n goBackRoute: (id: string) => void;\n updateTitle: (id: string, title: string) => void;\n moveForward: (id: string) => void;\n moveBackward: (id: string) => void;\n bringToFront: (id: string) => void;\n setGeometry: (id: string, geometry: WindowGeometry) => void;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useWindowActions: () => import("./types").WindowStateActions;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWindowActions.js","sourceRoot":"","sources":["../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/useWindowActions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,WAAW,CAAC","sourcesContent":["import { windowActionsContext } from \"./context\";\n\nexport const useWindowActions = windowActionsContext.useRequired;\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ComponentType, Dispatch, MutableRefObject, SetStateAction } from "react";
|
|
2
|
+
import type { WindowCreateOptions, WindowEntry, WindowGeometry } from "./types.js";
|
|
3
|
+
interface UseWindowStateActionsParams {
|
|
4
|
+
counter: MutableRefObject<number>;
|
|
5
|
+
setWindows: Dispatch<SetStateAction<WindowEntry[]>>;
|
|
6
|
+
}
|
|
7
|
+
export declare function useWindowStateActions({ counter, setWindows, }: UseWindowStateActionsParams): {
|
|
8
|
+
bringToFront: (id: string) => void;
|
|
9
|
+
close: (id: string) => void;
|
|
10
|
+
create: (title: string, x: number, y: number, component?: ComponentType, options?: WindowCreateOptions) => string;
|
|
11
|
+
goBackRoute: (id: string) => void;
|
|
12
|
+
maximize: (id: string) => void;
|
|
13
|
+
minimize: (id: string) => void;
|
|
14
|
+
moveBackward: (id: string) => void;
|
|
15
|
+
moveForward: (id: string) => void;
|
|
16
|
+
restore: (id: string) => void;
|
|
17
|
+
setGeometry: (id: string, geometry: WindowGeometry) => void;
|
|
18
|
+
toggleMaximize: (id: string) => void;
|
|
19
|
+
updateRoute: (id: string, pathSegments: ReadonlyArray<string>, options?: {
|
|
20
|
+
replace?: boolean | undefined;
|
|
21
|
+
}) => void;
|
|
22
|
+
updateTitle: (id: string, title: string) => void;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react";
|
|
2
|
+
import { bringWindowToFront, createWindowEntry, getMaxWindowZIndex, swapWindowZIndexes, updateWindowFlag, } from "./util/index.js";
|
|
3
|
+
function arePathSegmentsEqual(left, right) {
|
|
4
|
+
return (left.length === right.length &&
|
|
5
|
+
left.every((segment, index) => segment === right[index]));
|
|
6
|
+
}
|
|
7
|
+
function hasGeometry(entry, geometry) {
|
|
8
|
+
return (entry.position?.x === geometry.position.x &&
|
|
9
|
+
entry.position?.y === geometry.position.y &&
|
|
10
|
+
entry.size?.width === geometry.size?.width &&
|
|
11
|
+
entry.size?.height === geometry.size?.height);
|
|
12
|
+
}
|
|
13
|
+
function useSetGeometryAction(setWindows) {
|
|
14
|
+
return useCallback((id, geometry) => {
|
|
15
|
+
setWindows((previousWindows) => {
|
|
16
|
+
const targetWindow = previousWindows.find((windowEntry) => windowEntry.id === id);
|
|
17
|
+
if (!targetWindow || hasGeometry(targetWindow, geometry)) {
|
|
18
|
+
return previousWindows;
|
|
19
|
+
}
|
|
20
|
+
return updateWindowFlag(previousWindows, id, {
|
|
21
|
+
position: { ...geometry.position },
|
|
22
|
+
size: geometry.size ? { ...geometry.size } : undefined,
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}, [setWindows]);
|
|
26
|
+
}
|
|
27
|
+
function useUpdateRouteAction(setWindows) {
|
|
28
|
+
return useCallback((id, pathSegments, options = {}) => {
|
|
29
|
+
setWindows((previousWindows) => {
|
|
30
|
+
const targetWindow = previousWindows.find((windowEntry) => windowEntry.id === id);
|
|
31
|
+
if (!targetWindow) {
|
|
32
|
+
return previousWindows;
|
|
33
|
+
}
|
|
34
|
+
const currentPathSegments = targetWindow.pathSegments ?? [];
|
|
35
|
+
if (arePathSegmentsEqual(currentPathSegments, pathSegments)) {
|
|
36
|
+
return previousWindows;
|
|
37
|
+
}
|
|
38
|
+
// A replacing navigation swaps the current entry rather than stacking on
|
|
39
|
+
// it — the transient step it replaces (a type picker, an unavailable
|
|
40
|
+
// route corrected to the default) must not become a Back destination.
|
|
41
|
+
const nextHistory = options.replace
|
|
42
|
+
? (targetWindow.routeHistory ?? [])
|
|
43
|
+
: [...(targetWindow.routeHistory ?? []), currentPathSegments];
|
|
44
|
+
return previousWindows.map((windowEntry) => windowEntry.id === id
|
|
45
|
+
? {
|
|
46
|
+
...windowEntry,
|
|
47
|
+
pathSegments: [...pathSegments],
|
|
48
|
+
routeHistory: nextHistory,
|
|
49
|
+
}
|
|
50
|
+
: windowEntry);
|
|
51
|
+
});
|
|
52
|
+
}, [setWindows]);
|
|
53
|
+
}
|
|
54
|
+
function useGoBackRouteAction(setWindows) {
|
|
55
|
+
return useCallback((id) => {
|
|
56
|
+
setWindows((previousWindows) => {
|
|
57
|
+
const targetWindow = previousWindows.find((windowEntry) => windowEntry.id === id);
|
|
58
|
+
const history = targetWindow?.routeHistory ?? [];
|
|
59
|
+
const previousPathSegments = history[history.length - 1];
|
|
60
|
+
if (!targetWindow || previousPathSegments === undefined) {
|
|
61
|
+
return previousWindows;
|
|
62
|
+
}
|
|
63
|
+
return previousWindows.map((windowEntry) => windowEntry.id === id
|
|
64
|
+
? {
|
|
65
|
+
...windowEntry,
|
|
66
|
+
pathSegments: [...previousPathSegments],
|
|
67
|
+
routeHistory: history.slice(0, -1),
|
|
68
|
+
}
|
|
69
|
+
: windowEntry);
|
|
70
|
+
});
|
|
71
|
+
}, [setWindows]);
|
|
72
|
+
}
|
|
73
|
+
function useCloseWindowAction(setWindows) {
|
|
74
|
+
return useCallback((id) => {
|
|
75
|
+
setWindows((previousWindows) => previousWindows.filter((windowEntry) => windowEntry.id !== id));
|
|
76
|
+
}, [setWindows]);
|
|
77
|
+
}
|
|
78
|
+
function useWindowMaximizeActions(setWindows) {
|
|
79
|
+
// Maximizing always reveals the window, so it un-minimizes and raises in one
|
|
80
|
+
// step — the taskbar can offer "Maximize" on a minimized window directly.
|
|
81
|
+
const maximize = useCallback((id) => {
|
|
82
|
+
setWindows((previousWindows) => updateWindowFlag(bringWindowToFront(previousWindows, id), id, {
|
|
83
|
+
maximized: true,
|
|
84
|
+
minimized: false,
|
|
85
|
+
}));
|
|
86
|
+
}, [setWindows]);
|
|
87
|
+
const toggleMaximize = useCallback((id) => {
|
|
88
|
+
setWindows((previousWindows) => {
|
|
89
|
+
const target = previousWindows.find((windowEntry) => windowEntry.id === id);
|
|
90
|
+
if (!target) {
|
|
91
|
+
return previousWindows;
|
|
92
|
+
}
|
|
93
|
+
const maximized = !target.maximized;
|
|
94
|
+
return updateWindowFlag(maximized ? bringWindowToFront(previousWindows, id) : previousWindows, id, { maximized });
|
|
95
|
+
});
|
|
96
|
+
}, [setWindows]);
|
|
97
|
+
return { maximize, toggleMaximize };
|
|
98
|
+
}
|
|
99
|
+
function useWindowZOrderActions(setWindows) {
|
|
100
|
+
const moveForward = useCallback((id) => {
|
|
101
|
+
setWindows((previousWindows) => swapWindowZIndexes(previousWindows, id, "forward"));
|
|
102
|
+
}, [setWindows]);
|
|
103
|
+
const moveBackward = useCallback((id) => {
|
|
104
|
+
setWindows((previousWindows) => swapWindowZIndexes(previousWindows, id, "backward"));
|
|
105
|
+
}, [setWindows]);
|
|
106
|
+
const bringToFront = useCallback((id) => {
|
|
107
|
+
setWindows((previousWindows) => bringWindowToFront(previousWindows, id));
|
|
108
|
+
}, [setWindows]);
|
|
109
|
+
return { bringToFront, moveBackward, moveForward };
|
|
110
|
+
}
|
|
111
|
+
// Updates to a single window's own fields: its title and its geometry.
|
|
112
|
+
function useWindowFieldActions(setWindows) {
|
|
113
|
+
const updateTitle = useCallback((id, title) => {
|
|
114
|
+
setWindows((previousWindows) => updateWindowFlag(previousWindows, id, { title }));
|
|
115
|
+
}, [setWindows]);
|
|
116
|
+
const setGeometry = useSetGeometryAction(setWindows);
|
|
117
|
+
return { setGeometry, updateTitle };
|
|
118
|
+
}
|
|
119
|
+
export function useWindowStateActions({ counter, setWindows, }) {
|
|
120
|
+
const create = useCallback((title, x, y, component, options = {}) => {
|
|
121
|
+
const id = String(++counter.current);
|
|
122
|
+
setWindows((previousWindows) => {
|
|
123
|
+
const maxZIndex = getMaxWindowZIndex(previousWindows);
|
|
124
|
+
return [
|
|
125
|
+
...previousWindows,
|
|
126
|
+
createWindowEntry(id, title, x, y, maxZIndex + 1, component, options),
|
|
127
|
+
];
|
|
128
|
+
});
|
|
129
|
+
return id;
|
|
130
|
+
}, [counter, setWindows]);
|
|
131
|
+
const close = useCloseWindowAction(setWindows);
|
|
132
|
+
const minimize = useCallback((id) => {
|
|
133
|
+
setWindows((previousWindows) => updateWindowFlag(previousWindows, id, { minimized: true }));
|
|
134
|
+
}, [setWindows]);
|
|
135
|
+
const restore = useCallback((id) => {
|
|
136
|
+
setWindows((previousWindows) => {
|
|
137
|
+
const frontWindows = bringWindowToFront(previousWindows, id);
|
|
138
|
+
return updateWindowFlag(frontWindows, id, { minimized: false });
|
|
139
|
+
});
|
|
140
|
+
}, [setWindows]);
|
|
141
|
+
const { maximize, toggleMaximize } = useWindowMaximizeActions(setWindows);
|
|
142
|
+
const updateRoute = useUpdateRouteAction(setWindows);
|
|
143
|
+
const goBackRoute = useGoBackRouteAction(setWindows);
|
|
144
|
+
const { setGeometry, updateTitle } = useWindowFieldActions(setWindows);
|
|
145
|
+
const { bringToFront, moveBackward, moveForward } = useWindowZOrderActions(setWindows);
|
|
146
|
+
return useMemo(() => ({
|
|
147
|
+
bringToFront,
|
|
148
|
+
close,
|
|
149
|
+
create,
|
|
150
|
+
goBackRoute,
|
|
151
|
+
maximize,
|
|
152
|
+
minimize,
|
|
153
|
+
moveBackward,
|
|
154
|
+
moveForward,
|
|
155
|
+
restore,
|
|
156
|
+
setGeometry,
|
|
157
|
+
toggleMaximize,
|
|
158
|
+
updateRoute,
|
|
159
|
+
updateTitle,
|
|
160
|
+
}), [
|
|
161
|
+
bringToFront,
|
|
162
|
+
close,
|
|
163
|
+
create,
|
|
164
|
+
goBackRoute,
|
|
165
|
+
maximize,
|
|
166
|
+
minimize,
|
|
167
|
+
moveBackward,
|
|
168
|
+
moveForward,
|
|
169
|
+
restore,
|
|
170
|
+
setGeometry,
|
|
171
|
+
toggleMaximize,
|
|
172
|
+
updateRoute,
|
|
173
|
+
updateTitle,
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=useWindowStateActions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWindowStateActions.js","sourceRoot":"","sources":["../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/useWindowStateActions.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ComponentType,\n Dispatch,\n MutableRefObject,\n SetStateAction,\n} from \"react\";\nimport { useCallback, useMemo } from \"react\";\nimport type { WindowCreateOptions, WindowEntry, WindowGeometry } from \"./types\";\nimport {\n bringWindowToFront,\n createWindowEntry,\n getMaxWindowZIndex,\n swapWindowZIndexes,\n updateWindowFlag,\n} from \"./util\";\n\ninterface UseWindowStateActionsParams {\n counter: MutableRefObject<number>;\n setWindows: Dispatch<SetStateAction<WindowEntry[]>>;\n}\n\nfunction arePathSegmentsEqual(\n left: ReadonlyArray<string>,\n right: ReadonlyArray<string>,\n) {\n return (\n left.length === right.length &&\n left.every((segment, index) => segment === right[index])\n );\n}\n\nfunction hasGeometry(entry: WindowEntry, geometry: WindowGeometry) {\n return (\n entry.position?.x === geometry.position.x &&\n entry.position?.y === geometry.position.y &&\n entry.size?.width === geometry.size?.width &&\n entry.size?.height === geometry.size?.height\n );\n}\n\nfunction useSetGeometryAction(\n setWindows: Dispatch<SetStateAction<WindowEntry[]>>,\n) {\n return useCallback(\n (id: string, geometry: WindowGeometry) => {\n setWindows((previousWindows) => {\n const targetWindow = previousWindows.find(\n (windowEntry) => windowEntry.id === id,\n );\n if (!targetWindow || hasGeometry(targetWindow, geometry)) {\n return previousWindows;\n }\n\n return updateWindowFlag(previousWindows, id, {\n position: { ...geometry.position },\n size: geometry.size ? { ...geometry.size } : undefined,\n });\n });\n },\n [setWindows],\n );\n}\n\nfunction useUpdateRouteAction(\n setWindows: Dispatch<SetStateAction<WindowEntry[]>>,\n) {\n return useCallback(\n (\n id: string,\n pathSegments: ReadonlyArray<string>,\n options: { replace?: boolean | undefined } = {},\n ) => {\n setWindows((previousWindows) => {\n const targetWindow = previousWindows.find(\n (windowEntry) => windowEntry.id === id,\n );\n if (!targetWindow) {\n return previousWindows;\n }\n\n const currentPathSegments = targetWindow.pathSegments ?? [];\n if (arePathSegmentsEqual(currentPathSegments, pathSegments)) {\n return previousWindows;\n }\n\n // A replacing navigation swaps the current entry rather than stacking on\n // it — the transient step it replaces (a type picker, an unavailable\n // route corrected to the default) must not become a Back destination.\n const nextHistory = options.replace\n ? (targetWindow.routeHistory ?? [])\n : [...(targetWindow.routeHistory ?? []), currentPathSegments];\n\n return previousWindows.map((windowEntry) =>\n windowEntry.id === id\n ? {\n ...windowEntry,\n pathSegments: [...pathSegments],\n routeHistory: nextHistory,\n }\n : windowEntry,\n );\n });\n },\n [setWindows],\n );\n}\n\nfunction useGoBackRouteAction(\n setWindows: Dispatch<SetStateAction<WindowEntry[]>>,\n) {\n return useCallback(\n (id: string) => {\n setWindows((previousWindows) => {\n const targetWindow = previousWindows.find(\n (windowEntry) => windowEntry.id === id,\n );\n const history = targetWindow?.routeHistory ?? [];\n const previousPathSegments = history[history.length - 1];\n if (!targetWindow || previousPathSegments === undefined) {\n return previousWindows;\n }\n\n return previousWindows.map((windowEntry) =>\n windowEntry.id === id\n ? {\n ...windowEntry,\n pathSegments: [...previousPathSegments],\n routeHistory: history.slice(0, -1),\n }\n : windowEntry,\n );\n });\n },\n [setWindows],\n );\n}\n\nfunction useCloseWindowAction(\n setWindows: Dispatch<SetStateAction<WindowEntry[]>>,\n) {\n return useCallback(\n (id: string) => {\n setWindows((previousWindows) =>\n previousWindows.filter((windowEntry) => windowEntry.id !== id),\n );\n },\n [setWindows],\n );\n}\n\nfunction useWindowMaximizeActions(\n setWindows: Dispatch<SetStateAction<WindowEntry[]>>,\n) {\n // Maximizing always reveals the window, so it un-minimizes and raises in one\n // step — the taskbar can offer \"Maximize\" on a minimized window directly.\n const maximize = useCallback(\n (id: string) => {\n setWindows((previousWindows) =>\n updateWindowFlag(bringWindowToFront(previousWindows, id), id, {\n maximized: true,\n minimized: false,\n }),\n );\n },\n [setWindows],\n );\n\n const toggleMaximize = useCallback(\n (id: string) => {\n setWindows((previousWindows) => {\n const target = previousWindows.find(\n (windowEntry) => windowEntry.id === id,\n );\n if (!target) {\n return previousWindows;\n }\n\n const maximized = !target.maximized;\n return updateWindowFlag(\n maximized ? bringWindowToFront(previousWindows, id) : previousWindows,\n id,\n { maximized },\n );\n });\n },\n [setWindows],\n );\n\n return { maximize, toggleMaximize };\n}\n\nfunction useWindowZOrderActions(\n setWindows: Dispatch<SetStateAction<WindowEntry[]>>,\n) {\n const moveForward = useCallback(\n (id: string) => {\n setWindows((previousWindows) =>\n swapWindowZIndexes(previousWindows, id, \"forward\"),\n );\n },\n [setWindows],\n );\n\n const moveBackward = useCallback(\n (id: string) => {\n setWindows((previousWindows) =>\n swapWindowZIndexes(previousWindows, id, \"backward\"),\n );\n },\n [setWindows],\n );\n\n const bringToFront = useCallback(\n (id: string) => {\n setWindows((previousWindows) => bringWindowToFront(previousWindows, id));\n },\n [setWindows],\n );\n\n return { bringToFront, moveBackward, moveForward };\n}\n\n// Updates to a single window's own fields: its title and its geometry.\nfunction useWindowFieldActions(\n setWindows: Dispatch<SetStateAction<WindowEntry[]>>,\n) {\n const updateTitle = useCallback(\n (id: string, title: string) => {\n setWindows((previousWindows) =>\n updateWindowFlag(previousWindows, id, { title }),\n );\n },\n [setWindows],\n );\n const setGeometry = useSetGeometryAction(setWindows);\n\n return { setGeometry, updateTitle };\n}\n\nexport function useWindowStateActions({\n counter,\n setWindows,\n}: UseWindowStateActionsParams) {\n const create = useCallback(\n (\n title: string,\n x: number,\n y: number,\n component?: ComponentType,\n options: WindowCreateOptions = {},\n ) => {\n const id = String(++counter.current);\n setWindows((previousWindows) => {\n const maxZIndex = getMaxWindowZIndex(previousWindows);\n return [\n ...previousWindows,\n createWindowEntry(id, title, x, y, maxZIndex + 1, component, options),\n ];\n });\n return id;\n },\n [counter, setWindows],\n );\n\n const close = useCloseWindowAction(setWindows);\n\n const minimize = useCallback(\n (id: string) => {\n setWindows((previousWindows) =>\n updateWindowFlag(previousWindows, id, { minimized: true }),\n );\n },\n [setWindows],\n );\n\n const restore = useCallback(\n (id: string) => {\n setWindows((previousWindows) => {\n const frontWindows = bringWindowToFront(previousWindows, id);\n return updateWindowFlag(frontWindows, id, { minimized: false });\n });\n },\n [setWindows],\n );\n\n const { maximize, toggleMaximize } = useWindowMaximizeActions(setWindows);\n\n const updateRoute = useUpdateRouteAction(setWindows);\n const goBackRoute = useGoBackRouteAction(setWindows);\n\n const { setGeometry, updateTitle } = useWindowFieldActions(setWindows);\n\n const { bringToFront, moveBackward, moveForward } =\n useWindowZOrderActions(setWindows);\n\n return useMemo(\n () => ({\n bringToFront,\n close,\n create,\n goBackRoute,\n maximize,\n minimize,\n moveBackward,\n moveForward,\n restore,\n setGeometry,\n toggleMaximize,\n updateRoute,\n updateTitle,\n }),\n [\n bringToFront,\n close,\n create,\n goBackRoute,\n maximize,\n minimize,\n moveBackward,\n moveForward,\n restore,\n setGeometry,\n toggleMaximize,\n updateRoute,\n updateTitle,\n ],\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useWindowStateData: () => import("./types").WindowStateData;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWindowStateData.js","sourceRoot":"","sources":["../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/useWindowStateData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,WAAW,CAAC","sourcesContent":["import { windowStateContext } from \"./context\";\n\nexport const useWindowStateData = windowStateContext.useRequired;\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getMaxWindowZIndex } from "./getMaxWindowZIndex.js";
|
|
2
|
+
export function bringWindowToFront(windows, id) {
|
|
3
|
+
const target = windows.find((windowEntry) => windowEntry.id === id);
|
|
4
|
+
if (!target) {
|
|
5
|
+
return windows;
|
|
6
|
+
}
|
|
7
|
+
const topZIndex = getMaxWindowZIndex(windows);
|
|
8
|
+
if (target.zIndex === topZIndex) {
|
|
9
|
+
return windows;
|
|
10
|
+
}
|
|
11
|
+
return windows.map((windowEntry) => {
|
|
12
|
+
if (windowEntry.id === target.id) {
|
|
13
|
+
return { ...windowEntry, zIndex: topZIndex };
|
|
14
|
+
}
|
|
15
|
+
if (windowEntry.zIndex > target.zIndex) {
|
|
16
|
+
return { ...windowEntry, zIndex: windowEntry.zIndex - 1 };
|
|
17
|
+
}
|
|
18
|
+
return windowEntry;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=bringWindowToFront.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bringWindowToFront.js","sourceRoot":"","sources":["../../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/util/bringWindowToFront.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,UAAU,kBAAkB,CAAC,OAAsB,EAAE,EAAU;IACnE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE;QACjC,IAAI,WAAW,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC;YACjC,OAAO,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/C,CAAC;QACD,IAAI,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YACvC,OAAO,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { WindowEntry } from \"../types\";\nimport { getMaxWindowZIndex } from \"./getMaxWindowZIndex\";\n\nexport function bringWindowToFront(windows: WindowEntry[], id: string) {\n const target = windows.find((windowEntry) => windowEntry.id === id);\n if (!target) {\n return windows;\n }\n\n const topZIndex = getMaxWindowZIndex(windows);\n if (target.zIndex === topZIndex) {\n return windows;\n }\n\n return windows.map((windowEntry) => {\n if (windowEntry.id === target.id) {\n return { ...windowEntry, zIndex: topZIndex };\n }\n if (windowEntry.zIndex > target.zIndex) {\n return { ...windowEntry, zIndex: windowEntry.zIndex - 1 };\n }\n return windowEntry;\n });\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
import type { WindowCreateOptions, WindowEntry } from "../types.js";
|
|
3
|
+
export declare function createWindowEntry(id: string, title: string, x: number, y: number, zIndex: number, component?: ComponentType, options?: WindowCreateOptions): WindowEntry;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function createWindowEntry(id, title, x, y, zIndex, component, options = {}) {
|
|
2
|
+
return {
|
|
3
|
+
id,
|
|
4
|
+
...(options.appId ? { appId: options.appId } : {}),
|
|
5
|
+
initialShowSidebar: options.initialShowSidebar,
|
|
6
|
+
...(options.pathSegments
|
|
7
|
+
? { pathSegments: [...options.pathSegments] }
|
|
8
|
+
: {}),
|
|
9
|
+
title,
|
|
10
|
+
initialX: x,
|
|
11
|
+
initialY: y,
|
|
12
|
+
...(options.position ? { position: { ...options.position } } : {}),
|
|
13
|
+
...(options.size ? { size: { ...options.size } } : {}),
|
|
14
|
+
maximized: false,
|
|
15
|
+
minimized: false,
|
|
16
|
+
zIndex,
|
|
17
|
+
...(component ? { component } : {}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=createWindowEntry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createWindowEntry.js","sourceRoot":"","sources":["../../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/util/createWindowEntry.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,iBAAiB,CAC/B,EAAU,EACV,KAAa,EACb,CAAS,EACT,CAAS,EACT,MAAc,EACd,SAAyB,EACzB,UAA+B,EAAE;IAEjC,OAAO;QACL,EAAE;QACF,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,GAAG,CAAC,OAAO,CAAC,YAAY;YACtB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,EAAE;YAC7C,CAAC,CAAC,EAAE,CAAC;QACP,KAAK;QACL,QAAQ,EAAE,CAAC;QACX,QAAQ,EAAE,CAAC;QACX,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,KAAK;QAChB,MAAM;QACN,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpC,CAAC;AACJ,CAAC","sourcesContent":["import type { ComponentType } from \"react\";\nimport type { WindowCreateOptions, WindowEntry } from \"../types\";\n\nexport function createWindowEntry(\n id: string,\n title: string,\n x: number,\n y: number,\n zIndex: number,\n component?: ComponentType,\n options: WindowCreateOptions = {},\n): WindowEntry {\n return {\n id,\n ...(options.appId ? { appId: options.appId } : {}),\n initialShowSidebar: options.initialShowSidebar,\n ...(options.pathSegments\n ? { pathSegments: [...options.pathSegments] }\n : {}),\n title,\n initialX: x,\n initialY: y,\n ...(options.position ? { position: { ...options.position } } : {}),\n ...(options.size ? { size: { ...options.size } } : {}),\n maximized: false,\n minimized: false,\n zIndex,\n ...(component ? { component } : {}),\n };\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function findAdjacentWindow(windows, target, direction) {
|
|
2
|
+
let candidate = null;
|
|
3
|
+
for (const windowEntry of windows) {
|
|
4
|
+
if (direction === "forward") {
|
|
5
|
+
if (windowEntry.zIndex <= target.zIndex) {
|
|
6
|
+
continue;
|
|
7
|
+
}
|
|
8
|
+
if (!candidate || windowEntry.zIndex < candidate.zIndex) {
|
|
9
|
+
candidate = windowEntry;
|
|
10
|
+
}
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (windowEntry.zIndex >= target.zIndex) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (!candidate || windowEntry.zIndex > candidate.zIndex) {
|
|
17
|
+
candidate = windowEntry;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return candidate;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=findAdjacentWindow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findAdjacentWindow.js","sourceRoot":"","sources":["../../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/util/findAdjacentWindow.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAChC,OAAsB,EACtB,MAAmB,EACnB,SAA8B;IAE9B,IAAI,SAAS,GAAuB,IAAI,CAAC;IAEzC,KAAK,MAAM,WAAW,IAAI,OAAO,EAAE,CAAC;QAClC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,WAAW,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBACxC,SAAS;YACX,CAAC;YACD,IAAI,CAAC,SAAS,IAAI,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;gBACxD,SAAS,GAAG,WAAW,CAAC;YAC1B,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,WAAW,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACxC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,SAAS,IAAI,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;YACxD,SAAS,GAAG,WAAW,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import type { WindowEntry, WindowMoveDirection } from \"../types\";\n\nexport function findAdjacentWindow(\n windows: WindowEntry[],\n target: WindowEntry,\n direction: WindowMoveDirection,\n) {\n let candidate: WindowEntry | null = null;\n\n for (const windowEntry of windows) {\n if (direction === \"forward\") {\n if (windowEntry.zIndex <= target.zIndex) {\n continue;\n }\n if (!candidate || windowEntry.zIndex < candidate.zIndex) {\n candidate = windowEntry;\n }\n continue;\n }\n\n if (windowEntry.zIndex >= target.zIndex) {\n continue;\n }\n if (!candidate || windowEntry.zIndex > candidate.zIndex) {\n candidate = windowEntry;\n }\n }\n\n return candidate;\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** The highest-zIndex window matching `matches`, or null when none do. */
|
|
2
|
+
export function findTopWindow(windows, matches) {
|
|
3
|
+
return windows.reduce((top, candidate) => matches(candidate) && (!top || candidate.zIndex > top.zIndex)
|
|
4
|
+
? candidate
|
|
5
|
+
: top, null);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=findTopWindow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findTopWindow.js","sourceRoot":"","sources":["../../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/util/findTopWindow.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,MAAM,UAAU,aAAa,CAC3B,OAAmC,EACnC,OAA8C;IAE9C,OAAO,OAAO,CAAC,MAAM,CACnB,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CACjB,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QAC3D,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,EACT,IAAI,CACL,CAAC;AACJ,CAAC","sourcesContent":["import type { WindowEntry } from \"../types\";\n\n/** The highest-zIndex window matching `matches`, or null when none do. */\nexport function findTopWindow(\n windows: ReadonlyArray<WindowEntry>,\n matches: (windowEntry: WindowEntry) => boolean,\n): WindowEntry | null {\n return windows.reduce<WindowEntry | null>(\n (top, candidate) =>\n matches(candidate) && (!top || candidate.zIndex > top.zIndex)\n ? candidate\n : top,\n null,\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getMaxWindowZIndex.js","sourceRoot":"","sources":["../../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/util/getMaxWindowZIndex.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,OAAmC;IACpE,OAAO,OAAO,CAAC,MAAM,CACnB,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,EACnE,CAAC,CACF,CAAC;AACJ,CAAC","sourcesContent":["import type { WindowEntry } from \"../types\";\n\nexport function getMaxWindowZIndex(windows: ReadonlyArray<WindowEntry>) {\n return windows.reduce(\n (maxZIndex, windowEntry) => Math.max(maxZIndex, windowEntry.zIndex),\n 0,\n );\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { bringWindowToFront } from "./bringWindowToFront.js";
|
|
2
|
+
export { createWindowEntry } from "./createWindowEntry.js";
|
|
3
|
+
export { findTopWindow } from "./findTopWindow.js";
|
|
4
|
+
export { getMaxWindowZIndex } from "./getMaxWindowZIndex.js";
|
|
5
|
+
export { swapWindowZIndexes } from "./swapWindowZIndexes.js";
|
|
6
|
+
export { updateWindowFlag } from "./updateWindowFlag.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { bringWindowToFront } from "./bringWindowToFront.js";
|
|
2
|
+
export { createWindowEntry } from "./createWindowEntry.js";
|
|
3
|
+
export { findTopWindow } from "./findTopWindow.js";
|
|
4
|
+
export { getMaxWindowZIndex } from "./getMaxWindowZIndex.js";
|
|
5
|
+
export { swapWindowZIndexes } from "./swapWindowZIndexes.js";
|
|
6
|
+
export { updateWindowFlag } from "./updateWindowFlag.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/util/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC","sourcesContent":["export { bringWindowToFront } from \"./bringWindowToFront\";\nexport { createWindowEntry } from \"./createWindowEntry\";\nexport { findTopWindow } from \"./findTopWindow\";\nexport { getMaxWindowZIndex } from \"./getMaxWindowZIndex\";\nexport { swapWindowZIndexes } from \"./swapWindowZIndexes\";\nexport { updateWindowFlag } from \"./updateWindowFlag\";\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { findAdjacentWindow } from "./findAdjacentWindow.js";
|
|
2
|
+
export function swapWindowZIndexes(windows, id, direction) {
|
|
3
|
+
const target = windows.find((windowEntry) => windowEntry.id === id);
|
|
4
|
+
if (!target) {
|
|
5
|
+
return windows;
|
|
6
|
+
}
|
|
7
|
+
const swapWith = findAdjacentWindow(windows, target, direction);
|
|
8
|
+
if (!swapWith) {
|
|
9
|
+
return windows;
|
|
10
|
+
}
|
|
11
|
+
return windows.map((windowEntry) => {
|
|
12
|
+
if (windowEntry.id === target.id) {
|
|
13
|
+
return { ...windowEntry, zIndex: swapWith.zIndex };
|
|
14
|
+
}
|
|
15
|
+
if (windowEntry.id === swapWith.id) {
|
|
16
|
+
return { ...windowEntry, zIndex: target.zIndex };
|
|
17
|
+
}
|
|
18
|
+
return windowEntry;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=swapWindowZIndexes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swapWindowZIndexes.js","sourceRoot":"","sources":["../../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/util/swapWindowZIndexes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,UAAU,kBAAkB,CAChC,OAAsB,EACtB,EAAU,EACV,SAA8B;IAE9B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IAChE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE;QACjC,IAAI,WAAW,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC;YACjC,OAAO,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrD,CAAC;QACD,IAAI,WAAW,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,EAAE,CAAC;YACnC,OAAO,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACnD,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { WindowEntry, WindowMoveDirection } from \"../types\";\nimport { findAdjacentWindow } from \"./findAdjacentWindow\";\n\nexport function swapWindowZIndexes(\n windows: WindowEntry[],\n id: string,\n direction: WindowMoveDirection,\n) {\n const target = windows.find((windowEntry) => windowEntry.id === id);\n if (!target) {\n return windows;\n }\n\n const swapWith = findAdjacentWindow(windows, target, direction);\n if (!swapWith) {\n return windows;\n }\n\n return windows.map((windowEntry) => {\n if (windowEntry.id === target.id) {\n return { ...windowEntry, zIndex: swapWith.zIndex };\n }\n if (windowEntry.id === swapWith.id) {\n return { ...windowEntry, zIndex: target.zIndex };\n }\n return windowEntry;\n });\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateWindowFlag.js","sourceRoot":"","sources":["../../../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStateProvider/util/updateWindowFlag.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAC9B,OAAsB,EACtB,EAAU,EACV,KAEC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CACjC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,WAAW,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,WAAW,CACnE,CAAC;AACJ,CAAC","sourcesContent":["import type { WindowEntry } from \"../types\";\n\nexport function updateWindowFlag(\n windows: WindowEntry[],\n id: string,\n patch: Partial<\n Pick<WindowEntry, \"maximized\" | \"minimized\" | \"position\" | \"size\" | \"title\">\n >,\n) {\n return windows.map((windowEntry) =>\n windowEntry.id === id ? { ...windowEntry, ...patch } : windowEntry,\n );\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The live-region wrapper is always mounted (see WindowStatusBar.tsx) so it must
|
|
3
|
+
* add no height of its own, leaving the window flush when there is no message.
|
|
4
|
+
* Avoid `display: contents` here: it drops the element from the box tree, which
|
|
5
|
+
* some screen readers extend to the accessibility tree, silencing the very
|
|
6
|
+
* announcements the always-mounted region exists to preserve.
|
|
7
|
+
*/
|
|
8
|
+
.window-statusbar-live {
|
|
9
|
+
display: block;
|
|
10
|
+
line-height: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.window-statusbar {
|
|
14
|
+
border-radius: 0 0 var(--app-radius-surface) var(--app-radius-surface);
|
|
15
|
+
display: block;
|
|
16
|
+
min-height: var(--window-bar-height);
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
padding: var(--window-bar-padding);
|
|
19
|
+
background: var(--color-muted);
|
|
20
|
+
line-height: var(--window-bar-line-height);
|
|
21
|
+
text-overflow: ellipsis;
|
|
22
|
+
user-select: none;
|
|
23
|
+
white-space: nowrap;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.window--maximized .window-statusbar {
|
|
27
|
+
border-radius: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* A hidden status bar keeps its message for assistive technology only. */
|
|
31
|
+
.window-statusbar--hidden {
|
|
32
|
+
position: absolute;
|
|
33
|
+
width: 1px;
|
|
34
|
+
height: 1px;
|
|
35
|
+
min-height: 0;
|
|
36
|
+
padding: 0;
|
|
37
|
+
overflow: hidden;
|
|
38
|
+
clip-path: inset(50%);
|
|
39
|
+
white-space: nowrap;
|
|
40
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import "./WindowStatusBar.css";
|
|
3
|
+
export function WindowStatusBar({ text, visible = true, }) {
|
|
4
|
+
/*
|
|
5
|
+
* The live region stays mounted while the visible bar collapses. A `role="status"`
|
|
6
|
+
* region only announces when text changes on an element already in the DOM, so
|
|
7
|
+
* mounting the region together with its first message loses the announcement.
|
|
8
|
+
* The visible bar is skipped when empty because an empty one would hold
|
|
9
|
+
* `--window-bar-height` of `--color-muted` directly above the equally-muted
|
|
10
|
+
* taskbar, reading as a dead grey band rather than window chrome.
|
|
11
|
+
*
|
|
12
|
+
* Hiding the status bar hides only the visible band: the region stays mounted
|
|
13
|
+
* and the message stays in it, visually hidden, so announcements such as the
|
|
14
|
+
* keyboard move and resize instructions still reach assistive technology.
|
|
15
|
+
*/
|
|
16
|
+
return (_jsx("div", { className: "window-statusbar-live", "aria-live": "polite", role: "status", children: text ? (_jsx("div", { className: visible
|
|
17
|
+
? "window-statusbar"
|
|
18
|
+
: "window-statusbar window-statusbar--hidden", children: text })) : null }));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=WindowStatusBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WindowStatusBar.js","sourceRoot":"","sources":["../../../../../../../Users/a2f0/github/tearleads5/packages/windowing/src/window/WindowStatusBar.tsx"],"names":[],"mappings":";AAAA,OAAO,uBAAuB,CAAC;AAE/B,MAAM,UAAU,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,GAAG,IAAI,GAIf;IACC;;;;;;;;;;;OAWG;IACH,OAAO,CACL,cAAK,SAAS,EAAC,uBAAuB,eAAW,QAAQ,EAAC,IAAI,EAAC,QAAQ,YACpE,IAAI,CAAC,CAAC,CAAC,CACN,cACE,SAAS,EACP,OAAO;gBACL,CAAC,CAAC,kBAAkB;gBACpB,CAAC,CAAC,2CAA2C,YAGhD,IAAI,GACD,CACP,CAAC,CAAC,CAAC,IAAI,GACJ,CACP,CAAC;AACJ,CAAC","sourcesContent":["import \"./WindowStatusBar.css\";\n\nexport function WindowStatusBar({\n text,\n visible = true,\n}: {\n text?: string;\n visible?: boolean;\n}) {\n /*\n * The live region stays mounted while the visible bar collapses. A `role=\"status\"`\n * region only announces when text changes on an element already in the DOM, so\n * mounting the region together with its first message loses the announcement.\n * The visible bar is skipped when empty because an empty one would hold\n * `--window-bar-height` of `--color-muted` directly above the equally-muted\n * taskbar, reading as a dead grey band rather than window chrome.\n *\n * Hiding the status bar hides only the visible band: the region stays mounted\n * and the message stays in it, visually hidden, so announcements such as the\n * keyboard move and resize instructions still reach assistive technology.\n */\n return (\n <div className=\"window-statusbar-live\" aria-live=\"polite\" role=\"status\">\n {text ? (\n <div\n className={\n visible\n ? \"window-statusbar\"\n : \"window-statusbar window-statusbar--hidden\"\n }\n >\n {text}\n </div>\n ) : null}\n </div>\n );\n}\n"]}
|