sh3-core 0.15.0 → 0.15.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/dist/app/store/verbs.js +4 -0
- package/dist/overlays/FloatFrame.svelte +132 -8
- package/dist/overlays/FloatFrame.svelte.d.ts +1 -1
- package/dist/overlays/FloatLayer.svelte +2 -2
- package/dist/overlays/float.d.ts +21 -0
- package/dist/overlays/float.js +66 -0
- package/dist/overlays/float.test.js +359 -0
- package/dist/overlays/floatMaximized.svelte.d.ts +4 -0
- package/dist/overlays/floatMaximized.svelte.js +30 -0
- package/dist/runtime/runVerb-shell.test.d.ts +1 -0
- package/dist/runtime/runVerb-shell.test.js +231 -0
- package/dist/sh3core-shard/sh3coreShard.svelte.d.ts +7 -0
- package/dist/sh3core-shard/sh3coreShard.svelte.js +23 -0
- package/dist/shards/activate-runtime.test.js +24 -2
- package/dist/shards/activate.svelte.js +7 -2
- package/dist/shards/types.d.ts +11 -3
- package/dist/shell-shard/Terminal.svelte +1 -0
- package/dist/shell-shard/shellApi.js +1 -0
- package/dist/shell-shard/verbs/apps.js +2 -0
- package/dist/shell-shard/verbs/cat.js +1 -0
- package/dist/shell-shard/verbs/help.js +5 -1
- package/dist/shell-shard/verbs/help.svelte.test.d.ts +1 -0
- package/dist/shell-shard/verbs/help.svelte.test.js +53 -0
- package/dist/shell-shard/verbs/ls.js +1 -0
- package/dist/shell-shard/verbs/session.js +2 -0
- package/dist/shell-shard/verbs/shards.js +1 -0
- package/dist/shell-shard/verbs/views.js +5 -0
- package/dist/shell-shard/verbs/zones.js +2 -0
- package/dist/verbs/types.d.ts +9 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/app/store/verbs.js
CHANGED
|
@@ -17,6 +17,7 @@ function findInstalled(id) {
|
|
|
17
17
|
export const installVerb = {
|
|
18
18
|
name: 'install',
|
|
19
19
|
summary: 'Install a package by id from the catalog.',
|
|
20
|
+
programmatic: true,
|
|
20
21
|
async run(ctx, args) {
|
|
21
22
|
var _a, _b, _c;
|
|
22
23
|
const id = args[0];
|
|
@@ -117,6 +118,7 @@ export const installVerb = {
|
|
|
117
118
|
export const uninstallVerb = {
|
|
118
119
|
name: 'uninstall',
|
|
119
120
|
summary: 'Uninstall an installed package by id.',
|
|
121
|
+
programmatic: true,
|
|
120
122
|
async run(ctx, args) {
|
|
121
123
|
const id = args[0];
|
|
122
124
|
if (!id) {
|
|
@@ -168,6 +170,7 @@ export const updateVerb = {
|
|
|
168
170
|
summary: 'Update an installed package (sh3-store:update <id> [version]). When ' +
|
|
169
171
|
'version is omitted, bumps to latest; with a version, installs that ' +
|
|
170
172
|
'exact version (downgrade or same-version reinstall allowed).',
|
|
173
|
+
programmatic: true,
|
|
171
174
|
async run(ctx, args) {
|
|
172
175
|
var _a, _b;
|
|
173
176
|
const id = args[0];
|
|
@@ -243,6 +246,7 @@ export const updateVerb = {
|
|
|
243
246
|
export const appinfoVerb = {
|
|
244
247
|
name: 'appinfo',
|
|
245
248
|
summary: 'Show info about a package (installed status, version, catalog details).',
|
|
249
|
+
programmatic: true,
|
|
246
250
|
async run(ctx, args) {
|
|
247
251
|
const id = args[0];
|
|
248
252
|
if (!id) {
|
|
@@ -2,34 +2,55 @@
|
|
|
2
2
|
Single floating panel frame.
|
|
3
3
|
|
|
4
4
|
Renders:
|
|
5
|
-
- Header bar (title + close
|
|
5
|
+
- Header bar (title + maximize/close buttons, receives pointerdown for drag).
|
|
6
6
|
- Body that mounts the float's content subtree via LayoutRenderer
|
|
7
7
|
using rootRef={{ kind: 'float', floatId: entry.id }} so the
|
|
8
8
|
renderer reads from layoutStore.tree.floats[...].content instead
|
|
9
9
|
of layoutStore.root.
|
|
10
|
+
- Bottom-right resize grip (always rendered, including on dismissable
|
|
11
|
+
pickers — its pointerdown is inside the frame so the dismiss listener
|
|
12
|
+
doesn't fire).
|
|
10
13
|
|
|
11
14
|
Behavior:
|
|
12
15
|
- Pointer drag on header mutates entry.position in place. The entry
|
|
13
16
|
is a live reference from layoutStore.tree.floats, so mutation
|
|
14
17
|
reactivity flows through the workspace-zone proxy.
|
|
18
|
+
- Pointer drag on the resize grip mutates entry.size, clamped at
|
|
19
|
+
computeMinSize(entry.content).
|
|
15
20
|
- Click anywhere on the frame raises it (calls floatManager.focus).
|
|
16
|
-
- Close button calls floatManager.close.
|
|
21
|
+
- Close button calls floatManager.close. Maximize button toggles.
|
|
22
|
+
- Header double-click toggles maximize (excluding clicks on the close /
|
|
23
|
+
maximize buttons).
|
|
24
|
+
- Drag or resize while maximized implicitly un-maximizes (forgets the
|
|
25
|
+
saved prev rect; keeps the current rect and proceeds). See spec
|
|
26
|
+
docs/superpowers/specs/2026-05-07-float-resize-maximize-design.md.
|
|
17
27
|
-->
|
|
18
28
|
<script lang="ts">
|
|
19
29
|
import LayoutRenderer from '../layout/LayoutRenderer.svelte';
|
|
20
30
|
import { floatManager, getFloatParentHost } from './float';
|
|
21
31
|
import { registerDismissableFrame, unregisterDismissableFrame } from './floatDismiss';
|
|
32
|
+
import { computeMinSize } from '../layout/floats';
|
|
22
33
|
import type { FloatEntry } from '../layout/types';
|
|
23
34
|
|
|
24
35
|
interface Props {
|
|
25
36
|
entry: FloatEntry;
|
|
26
37
|
}
|
|
27
|
-
|
|
38
|
+
// `entry` is the live workspace-zone proxy from `layoutStore.floats`; the
|
|
39
|
+
// drag/resize/dismiss-listener paths mutate `entry.position` and
|
|
40
|
+
// `entry.size` in place, which is the canonical reactive flow. Marking
|
|
41
|
+
// it `$bindable()` opts into that mutation so Svelte 5 doesn't emit the
|
|
42
|
+
// ownership_invalid_mutation warning. The parent (FloatLayer) uses
|
|
43
|
+
// `bind:entry` to acknowledge the contract.
|
|
44
|
+
let { entry = $bindable() }: Props = $props();
|
|
28
45
|
|
|
29
46
|
let dragging = $state(false);
|
|
30
47
|
let dragOffset = { x: 0, y: 0 };
|
|
48
|
+
let resizing = $state(false);
|
|
49
|
+
let resizeStart = { pointer: { x: 0, y: 0 }, size: { w: 0, h: 0 }, min: { w: 0, h: 0 } };
|
|
31
50
|
let frameEl: HTMLDivElement | undefined = $state();
|
|
32
51
|
|
|
52
|
+
const isMaximized = $derived(floatManager.isMaximized(entry.id));
|
|
53
|
+
|
|
33
54
|
$effect(() => {
|
|
34
55
|
if (!entry.dismissable) return;
|
|
35
56
|
if (!frameEl) return;
|
|
@@ -62,8 +83,9 @@
|
|
|
62
83
|
function onHeaderPointerDown(e: PointerEvent): void {
|
|
63
84
|
if (e.button !== 0) return;
|
|
64
85
|
if ((e.target as HTMLElement).closest('.sh3-float-close')) return;
|
|
86
|
+
if ((e.target as HTMLElement).closest('.sh3-float-maximize')) return;
|
|
65
87
|
const target = e.currentTarget as HTMLElement;
|
|
66
|
-
target.setPointerCapture(e.pointerId);
|
|
88
|
+
target.setPointerCapture?.(e.pointerId);
|
|
67
89
|
dragging = true;
|
|
68
90
|
dragOffset = { x: e.clientX - entry.position.x, y: e.clientY - entry.position.y };
|
|
69
91
|
floatManager.focus(entry.id);
|
|
@@ -71,6 +93,11 @@
|
|
|
71
93
|
|
|
72
94
|
function onHeaderPointerMove(e: PointerEvent): void {
|
|
73
95
|
if (!dragging) return;
|
|
96
|
+
// Implicit un-maximize on first drag movement (no-op if not maximized).
|
|
97
|
+
// We unmaximize on move rather than pointerdown so a casual click —
|
|
98
|
+
// which precedes a dblclick — does not destroy the saved prev rect
|
|
99
|
+
// and break the dblclick toggle.
|
|
100
|
+
floatManager.unmaximize(entry.id);
|
|
74
101
|
entry.position.x = e.clientX - dragOffset.x;
|
|
75
102
|
entry.position.y = e.clientY - dragOffset.y;
|
|
76
103
|
}
|
|
@@ -79,7 +106,45 @@
|
|
|
79
106
|
if (!dragging) return;
|
|
80
107
|
dragging = false;
|
|
81
108
|
const target = e.currentTarget as HTMLElement;
|
|
82
|
-
if (target.hasPointerCapture(e.pointerId)) {
|
|
109
|
+
if (target.hasPointerCapture?.(e.pointerId)) {
|
|
110
|
+
target.releasePointerCapture(e.pointerId);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function onHeaderDblClick(e: MouseEvent): void {
|
|
115
|
+
if ((e.target as HTMLElement).closest('.sh3-float-close')) return;
|
|
116
|
+
if ((e.target as HTMLElement).closest('.sh3-float-maximize')) return;
|
|
117
|
+
floatManager.toggleMaximize(entry.id);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function onGripPointerDown(e: PointerEvent): void {
|
|
121
|
+
if (e.button !== 0) return;
|
|
122
|
+
e.stopPropagation();
|
|
123
|
+
const target = e.currentTarget as HTMLElement;
|
|
124
|
+
target.setPointerCapture?.(e.pointerId);
|
|
125
|
+
resizing = true;
|
|
126
|
+
resizeStart = {
|
|
127
|
+
pointer: { x: e.clientX, y: e.clientY },
|
|
128
|
+
size: { w: entry.size.w, h: entry.size.h },
|
|
129
|
+
min: computeMinSize(entry.content),
|
|
130
|
+
};
|
|
131
|
+
floatManager.focus(entry.id);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function onGripPointerMove(e: PointerEvent): void {
|
|
135
|
+
if (!resizing) return;
|
|
136
|
+
floatManager.unmaximize(entry.id);
|
|
137
|
+
const dx = e.clientX - resizeStart.pointer.x;
|
|
138
|
+
const dy = e.clientY - resizeStart.pointer.y;
|
|
139
|
+
entry.size.w = Math.max(resizeStart.min.w, resizeStart.size.w + dx);
|
|
140
|
+
entry.size.h = Math.max(resizeStart.min.h, resizeStart.size.h + dy);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function onGripPointerUp(e: PointerEvent): void {
|
|
144
|
+
if (!resizing) return;
|
|
145
|
+
resizing = false;
|
|
146
|
+
const target = e.currentTarget as HTMLElement;
|
|
147
|
+
if (target.hasPointerCapture?.(e.pointerId)) {
|
|
83
148
|
target.releasePointerCapture(e.pointerId);
|
|
84
149
|
}
|
|
85
150
|
}
|
|
@@ -88,6 +153,11 @@
|
|
|
88
153
|
floatManager.focus(entry.id);
|
|
89
154
|
}
|
|
90
155
|
|
|
156
|
+
function onMaximize(e: MouseEvent): void {
|
|
157
|
+
e.stopPropagation();
|
|
158
|
+
floatManager.toggleMaximize(entry.id);
|
|
159
|
+
}
|
|
160
|
+
|
|
91
161
|
function onClose(e: MouseEvent): void {
|
|
92
162
|
e.stopPropagation();
|
|
93
163
|
floatManager.close(entry.id);
|
|
@@ -117,14 +187,33 @@
|
|
|
117
187
|
onpointermove={onHeaderPointerMove}
|
|
118
188
|
onpointerup={onHeaderPointerUp}
|
|
119
189
|
onpointercancel={onHeaderPointerUp}
|
|
190
|
+
ondblclick={onHeaderDblClick}
|
|
120
191
|
>
|
|
121
192
|
<span class="sh3-float-title">{entry.title}</span>
|
|
122
|
-
<
|
|
193
|
+
<span class="sh3-float-header-actions">
|
|
194
|
+
<button
|
|
195
|
+
class="sh3-float-maximize"
|
|
196
|
+
onclick={onMaximize}
|
|
197
|
+
aria-label={isMaximized ? 'Restore float' : 'Maximize float'}
|
|
198
|
+
aria-pressed={isMaximized}
|
|
199
|
+
>{isMaximized ? '\u{1F5D7}' : '\u{1F5D6}'}</button>
|
|
200
|
+
<button class="sh3-float-close" onclick={onClose} aria-label="Close float">×</button>
|
|
201
|
+
</span>
|
|
123
202
|
</header>
|
|
124
203
|
{/if}
|
|
125
204
|
<div class="sh3-float-body">
|
|
126
205
|
<LayoutRenderer rootRef={{ kind: 'float', floatId: entry.id }} path={[]} />
|
|
127
206
|
</div>
|
|
207
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
208
|
+
<div
|
|
209
|
+
class="sh3-float-resize-grip"
|
|
210
|
+
role="presentation"
|
|
211
|
+
aria-hidden="true"
|
|
212
|
+
onpointerdown={onGripPointerDown}
|
|
213
|
+
onpointermove={onGripPointerMove}
|
|
214
|
+
onpointerup={onGripPointerUp}
|
|
215
|
+
onpointercancel={onGripPointerUp}
|
|
216
|
+
></div>
|
|
128
217
|
</div>
|
|
129
218
|
|
|
130
219
|
<style>
|
|
@@ -159,15 +248,26 @@
|
|
|
159
248
|
text-overflow: ellipsis;
|
|
160
249
|
white-space: nowrap;
|
|
161
250
|
}
|
|
251
|
+
.sh3-float-header-actions {
|
|
252
|
+
display: inline-flex;
|
|
253
|
+
align-items: center;
|
|
254
|
+
gap: 2px;
|
|
255
|
+
flex-shrink: 0;
|
|
256
|
+
}
|
|
257
|
+
.sh3-float-maximize,
|
|
162
258
|
.sh3-float-close {
|
|
163
259
|
background: transparent;
|
|
164
260
|
border: none;
|
|
165
261
|
color: var(--shell-fg);
|
|
166
|
-
font-size: 16px;
|
|
167
262
|
line-height: 1;
|
|
168
263
|
cursor: pointer;
|
|
169
264
|
padding: 0 4px;
|
|
170
|
-
|
|
265
|
+
}
|
|
266
|
+
.sh3-float-maximize {
|
|
267
|
+
font-size: 12px;
|
|
268
|
+
}
|
|
269
|
+
.sh3-float-close {
|
|
270
|
+
font-size: 16px;
|
|
171
271
|
}
|
|
172
272
|
.sh3-float-body {
|
|
173
273
|
flex: 1;
|
|
@@ -175,4 +275,28 @@
|
|
|
175
275
|
overflow: hidden;
|
|
176
276
|
min-height: 0;
|
|
177
277
|
}
|
|
278
|
+
.sh3-float-resize-grip {
|
|
279
|
+
position: absolute;
|
|
280
|
+
right: 0;
|
|
281
|
+
bottom: 0;
|
|
282
|
+
width: 16px;
|
|
283
|
+
height: 16px;
|
|
284
|
+
cursor: nwse-resize;
|
|
285
|
+
/* Subtle visual hint without being obtrusive — two diagonal lines made
|
|
286
|
+
from a CSS gradient stripe. */
|
|
287
|
+
background:
|
|
288
|
+
linear-gradient(
|
|
289
|
+
135deg,
|
|
290
|
+
transparent 0,
|
|
291
|
+
transparent 6px,
|
|
292
|
+
var(--shell-border-strong) 6px,
|
|
293
|
+
var(--shell-border-strong) 7px,
|
|
294
|
+
transparent 7px,
|
|
295
|
+
transparent 10px,
|
|
296
|
+
var(--shell-border-strong) 10px,
|
|
297
|
+
var(--shell-border-strong) 11px,
|
|
298
|
+
transparent 11px
|
|
299
|
+
);
|
|
300
|
+
border-bottom-right-radius: var(--shell-radius);
|
|
301
|
+
}
|
|
178
302
|
</style>
|
|
@@ -2,6 +2,6 @@ import type { FloatEntry } from '../layout/types';
|
|
|
2
2
|
interface Props {
|
|
3
3
|
entry: FloatEntry;
|
|
4
4
|
}
|
|
5
|
-
declare const FloatFrame: import("svelte").Component<Props, {}, "">;
|
|
5
|
+
declare const FloatFrame: import("svelte").Component<Props, {}, "entry">;
|
|
6
6
|
type FloatFrame = ReturnType<typeof FloatFrame>;
|
|
7
7
|
export default FloatFrame;
|
package/dist/overlays/float.d.ts
CHANGED
|
@@ -32,6 +32,27 @@ export interface FloatManager {
|
|
|
32
32
|
close(floatId: string): void;
|
|
33
33
|
list(): FloatEntry[];
|
|
34
34
|
focus(floatId: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Snapshot the current rect, override with the float layer bounds, and
|
|
37
|
+
* raise. No-op if the float is already maximized or unknown. Bounds are
|
|
38
|
+
* frozen at maximize time — shell resize while maximized does not refit.
|
|
39
|
+
*/
|
|
40
|
+
maximize(floatId: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Roll the rect back to the snapshot taken at maximize time. No-op if
|
|
43
|
+
* the float was not maximized.
|
|
44
|
+
*/
|
|
45
|
+
restore(floatId: string): void;
|
|
46
|
+
/** `isMaximized(id) ? restore(id) : maximize(id)`. */
|
|
47
|
+
toggleMaximize(floatId: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Forget the saved rect snapshot without rolling back. Used by drag /
|
|
50
|
+
* resize handlers to "exit maximize but keep the current rect" — distinct
|
|
51
|
+
* from `restore`, which would snap back. Safe no-op when the float was
|
|
52
|
+
* not maximized.
|
|
53
|
+
*/
|
|
54
|
+
unmaximize(floatId: string): void;
|
|
55
|
+
isMaximized(floatId: string): boolean;
|
|
35
56
|
}
|
|
36
57
|
/**
|
|
37
58
|
* Bind the manager to the active LayoutTree's `floats` array. Called
|
package/dist/overlays/float.js
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
*/
|
|
29
29
|
import { computeMinSize, cascadePosition, generateFloatId } from '../layout/floats';
|
|
30
30
|
import { findEnclosingOverlayHost } from './parentHost';
|
|
31
|
+
import { setMaximizedReactive, readMaximizedReactive, __resetMaximizedReactiveForTest, } from './floatMaximized.svelte';
|
|
31
32
|
// ----- storage binding ---------------------------------------------------
|
|
32
33
|
let fallbackFloats = [];
|
|
33
34
|
let boundFloats = null;
|
|
@@ -51,6 +52,8 @@ export function __resetFloatManagerForTest() {
|
|
|
51
52
|
boundFloats = null;
|
|
52
53
|
getTreeBounds = () => ({ w: 1600, h: 900 });
|
|
53
54
|
parentHosts.clear();
|
|
55
|
+
maximizedRects.clear();
|
|
56
|
+
__resetMaximizedReactiveForTest();
|
|
54
57
|
}
|
|
55
58
|
function activeStore() {
|
|
56
59
|
return boundFloats !== null && boundFloats !== void 0 ? boundFloats : fallbackFloats;
|
|
@@ -63,6 +66,12 @@ const parentHosts = new Map();
|
|
|
63
66
|
export function getFloatParentHost(id) {
|
|
64
67
|
return parentHosts.get(id);
|
|
65
68
|
}
|
|
69
|
+
// ----- maximize sidecar --------------------------------------------------
|
|
70
|
+
// Presence in this map ⇒ the float is currently maximized; the value is the
|
|
71
|
+
// rect to restore to. Lives outside FloatEntry so the layout schema doesn't
|
|
72
|
+
// need to bump for an in-memory, non-persisted concern. Reactivity is mirrored
|
|
73
|
+
// into floatMaximized.svelte.ts so Svelte components observe state changes.
|
|
74
|
+
const maximizedRects = new Map();
|
|
66
75
|
// ----- slot id minting ---------------------------------------------------
|
|
67
76
|
let floatSlotCounter = 0;
|
|
68
77
|
function mintFloatSlotId(viewId) {
|
|
@@ -135,6 +144,8 @@ function closeFloat(floatId) {
|
|
|
135
144
|
return;
|
|
136
145
|
store.splice(idx, 1);
|
|
137
146
|
parentHosts.delete(floatId);
|
|
147
|
+
maximizedRects.delete(floatId);
|
|
148
|
+
setMaximizedReactive(floatId, false);
|
|
138
149
|
}
|
|
139
150
|
function listFloats() {
|
|
140
151
|
// Return a snapshot so callers can iterate without racing mutations.
|
|
@@ -148,9 +159,64 @@ function focusFloat(floatId) {
|
|
|
148
159
|
const [entry] = store.splice(idx, 1);
|
|
149
160
|
store.push(entry);
|
|
150
161
|
}
|
|
162
|
+
function maximizeFloat(id) {
|
|
163
|
+
if (maximizedRects.has(id))
|
|
164
|
+
return;
|
|
165
|
+
const entry = activeStore().find((f) => f.id === id);
|
|
166
|
+
if (!entry)
|
|
167
|
+
return;
|
|
168
|
+
maximizedRects.set(id, {
|
|
169
|
+
position: { x: entry.position.x, y: entry.position.y },
|
|
170
|
+
size: { w: entry.size.w, h: entry.size.h },
|
|
171
|
+
});
|
|
172
|
+
setMaximizedReactive(id, true);
|
|
173
|
+
const bounds = getTreeBounds();
|
|
174
|
+
entry.position.x = 0;
|
|
175
|
+
entry.position.y = 0;
|
|
176
|
+
entry.size.w = bounds.w;
|
|
177
|
+
entry.size.h = bounds.h;
|
|
178
|
+
focusFloat(id);
|
|
179
|
+
}
|
|
180
|
+
function restoreFloat(id) {
|
|
181
|
+
const prev = maximizedRects.get(id);
|
|
182
|
+
if (!prev)
|
|
183
|
+
return;
|
|
184
|
+
const entry = activeStore().find((f) => f.id === id);
|
|
185
|
+
if (!entry) {
|
|
186
|
+
maximizedRects.delete(id);
|
|
187
|
+
setMaximizedReactive(id, false);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
entry.position.x = prev.position.x;
|
|
191
|
+
entry.position.y = prev.position.y;
|
|
192
|
+
entry.size.w = prev.size.w;
|
|
193
|
+
entry.size.h = prev.size.h;
|
|
194
|
+
maximizedRects.delete(id);
|
|
195
|
+
setMaximizedReactive(id, false);
|
|
196
|
+
}
|
|
197
|
+
function toggleMaximizeFloat(id) {
|
|
198
|
+
if (maximizedRects.has(id))
|
|
199
|
+
restoreFloat(id);
|
|
200
|
+
else
|
|
201
|
+
maximizeFloat(id);
|
|
202
|
+
}
|
|
203
|
+
function unmaximizeFloat(id) {
|
|
204
|
+
if (!maximizedRects.has(id))
|
|
205
|
+
return;
|
|
206
|
+
maximizedRects.delete(id);
|
|
207
|
+
setMaximizedReactive(id, false);
|
|
208
|
+
}
|
|
209
|
+
function isMaximizedFloat(id) {
|
|
210
|
+
return readMaximizedReactive(id);
|
|
211
|
+
}
|
|
151
212
|
export const floatManager = {
|
|
152
213
|
open: openFloat,
|
|
153
214
|
close: closeFloat,
|
|
154
215
|
list: listFloats,
|
|
155
216
|
focus: focusFloat,
|
|
217
|
+
maximize: maximizeFloat,
|
|
218
|
+
restore: restoreFloat,
|
|
219
|
+
toggleMaximize: toggleMaximizeFloat,
|
|
220
|
+
unmaximize: unmaximizeFloat,
|
|
221
|
+
isMaximized: isMaximizedFloat,
|
|
156
222
|
};
|