@maomaolabs/core 1.0.1 → 1.1.0
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 +223 -110
- package/dist/index.d.ts +41 -16
- package/dist/index.es.js +535 -470
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,61 +1,66 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<h1>@maomaolabs/core</h1>
|
|
3
2
|
|
|
4
|
-
<
|
|
5
|
-
<strong>A standalone lightweight React library that brings a complete, performant, and responsive desktop window management experience to the web.</strong>
|
|
6
|
-
</p>
|
|
3
|
+
<img src="./docs/assets/0.gif" alt="@maomaolabs/core — Desktop Window Management for the Web" width="100%" style="border-radius: 12px;" />
|
|
7
4
|
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
<h1>@maomaolabs/core</h1>
|
|
6
|
+
|
|
7
|
+
<p><strong>A standalone, lightweight React library that brings a complete desktop window management experience to the web.</strong><br/>Drag, resize, snap, minimize, maximize — all performant and mobile-ready out of the box.</p>
|
|
11
8
|
|
|
12
9
|
<p>
|
|
13
10
|
<a href="https://www.npmjs.com/package/@maomaolabs/core"><img src="https://img.shields.io/npm/v/@maomaolabs/core?style=for-the-badge&color=000000" alt="NPM Version" /></a>
|
|
14
|
-
<a href="https://github.com/maomaolabs/core/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@maomaolabs/core?style=for-the-badge&color=
|
|
11
|
+
<a href="https://github.com/maomaolabs/core/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@maomaolabs/core?style=for-the-badge&color=000" alt="License" /></a>
|
|
12
|
+
<a href="./CHANGELOG.md"><img src="https://img.shields.io/badge/Changelog-📖-000000?style=for-the-badge" alt="Changelog" /></a>
|
|
15
13
|
<img src="https://img.shields.io/badge/React-18.0.0+-blue?style=for-the-badge&logo=react&color=000000" alt="React 18+" />
|
|
16
14
|
</p>
|
|
17
|
-
</div>
|
|
18
|
-
|
|
19
|
-
<br />
|
|
20
|
-
|
|
21
|
-
## ✨ Key Features
|
|
22
15
|
|
|
23
|
-
|
|
24
|
-
Zero unnecessary re-renders thanks to context splitting (`useWindows` vs `useWindowActions`).
|
|
25
|
-
<p align="center">
|
|
26
|
-
<img src="./docs/assets/1.png" alt="Performance architecture diagram" width="100%" style="border-radius: 8px;" />
|
|
27
|
-
</p>
|
|
28
|
-
|
|
29
|
-
**Complete window lifecycle**
|
|
30
|
-
Seamlessly open, close, minimize, maximize, resize, and drag windows.
|
|
31
|
-
<p align="center">
|
|
32
|
-
<img src="./docs/assets/4.gif" alt="Window lifecycle demonstration" width="100%" style="border-radius: 8px;" />
|
|
33
|
-
</p>
|
|
16
|
+
</div>
|
|
34
17
|
|
|
35
|
-
|
|
36
|
-
Native-feeling edge snapping (half screen) and corner snapping (quarter screen) functionality.
|
|
37
|
-
<p align="center">
|
|
38
|
-
<img src="./docs/assets/5.gif" alt="Window snapping demonstration" width="100%" style="border-radius: 8px;" />
|
|
39
|
-
</p>
|
|
18
|
+
---
|
|
40
19
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<
|
|
44
|
-
<
|
|
45
|
-
|
|
20
|
+
## ✨ Features
|
|
21
|
+
|
|
22
|
+
<table>
|
|
23
|
+
<tr>
|
|
24
|
+
<td width="50%">
|
|
25
|
+
<h3>⚡ Zero unnecessary re-renders</h3>
|
|
26
|
+
Context is split into <code>useWindows</code> (state) and <code>useWindowActions</code> (actions). Components that only dispatch actions never re-render on state changes.
|
|
27
|
+
<br/><br/>
|
|
28
|
+
<img src="./docs/assets/1.png" alt="Performance architecture" width="100%" style="border-radius: 8px;" />
|
|
29
|
+
</td>
|
|
30
|
+
<td width="50%">
|
|
31
|
+
<h3>🪟 Complete window lifecycle</h3>
|
|
32
|
+
Open, close, minimize, maximize, drag and resize windows with native-feeling interactions on both desktop and mobile.
|
|
33
|
+
<br/><br/>
|
|
34
|
+
<img src="./docs/assets/4.gif" alt="Window lifecycle" width="100%" style="border-radius: 8px;" />
|
|
35
|
+
</td>
|
|
36
|
+
</tr>
|
|
37
|
+
<tr>
|
|
38
|
+
<td width="50%" valign="top">
|
|
39
|
+
<h3>🧲 Built-in snapping</h3>
|
|
40
|
+
Half-screen (edge) and quarter-screen (corner) snapping with real-time preview overlays, just like a native OS.
|
|
41
|
+
<br/><br/>
|
|
42
|
+
<img src="./docs/assets/5.gif" alt="Window snapping" width="100%" style="border-radius: 8px;" />
|
|
43
|
+
</td>
|
|
44
|
+
<td width="50%" valign="top">
|
|
45
|
+
<h3>🧰 Out-of-the-box Toolbar</h3>
|
|
46
|
+
A fully customizable taskbar that handles individual app launchers, folder groupings, and minimized window management.
|
|
47
|
+
<br/><br/>
|
|
48
|
+
<img src="./docs/assets/7.png" alt="Toolbar" width="100%" style="border-radius: 8px;" />
|
|
49
|
+
</td>
|
|
50
|
+
</tr>
|
|
51
|
+
</table>
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
|
|
53
|
+
<div align="center">
|
|
54
|
+
<h3>📱 Responsive by default</h3>
|
|
55
|
+
Interactions automatically adapt between mouse and touch environments. No configuration needed.
|
|
56
|
+
<br/><br/>
|
|
57
|
+
<img src="./docs/assets/6.png" alt="Responsive design" width="320" style="border-radius: 8px;" />
|
|
58
|
+
</div>
|
|
52
59
|
|
|
53
60
|
---
|
|
54
61
|
|
|
55
62
|
## 📦 Installation
|
|
56
63
|
|
|
57
|
-
Install via your preferred package manager (requires `react` and `react-dom` >= 18.0.0):
|
|
58
|
-
|
|
59
64
|
```bash
|
|
60
65
|
npm install @maomaolabs/core
|
|
61
66
|
# or
|
|
@@ -64,24 +69,24 @@ yarn add @maomaolabs/core
|
|
|
64
69
|
pnpm add @maomaolabs/core
|
|
65
70
|
```
|
|
66
71
|
|
|
72
|
+
> Requires `react` and `react-dom` >= 18.0.0 as peer dependencies.
|
|
73
|
+
|
|
67
74
|
---
|
|
68
75
|
|
|
69
76
|
## 🚀 Quick Start
|
|
70
77
|
|
|
71
|
-
Get a window running in under 30 seconds:
|
|
72
|
-
|
|
73
78
|
```tsx
|
|
74
79
|
import { WindowSystemProvider, WindowManager, useWindowActions } from '@maomaolabs/core';
|
|
75
|
-
import '@maomaolabs/core/dist/style.css';
|
|
80
|
+
import '@maomaolabs/core/dist/style.css';
|
|
76
81
|
|
|
77
82
|
const AppLauncher = () => {
|
|
78
83
|
const { openWindow } = useWindowActions();
|
|
79
84
|
|
|
80
85
|
return (
|
|
81
|
-
<button onClick={() => openWindow({
|
|
82
|
-
id: 'hello',
|
|
83
|
-
title: 'Hello',
|
|
84
|
-
component: <div>
|
|
86
|
+
<button onClick={() => openWindow({
|
|
87
|
+
id: 'hello',
|
|
88
|
+
title: 'Hello World',
|
|
89
|
+
component: <div>Hello from a managed window!</div>
|
|
85
90
|
})}>
|
|
86
91
|
Launch App
|
|
87
92
|
</button>
|
|
@@ -98,26 +103,26 @@ export default function App() {
|
|
|
98
103
|
}
|
|
99
104
|
```
|
|
100
105
|
|
|
106
|
+
> ⚠️ Don't forget the CSS import — it's required for drag, resize, and snap overlays to work correctly.
|
|
107
|
+
|
|
101
108
|
---
|
|
102
109
|
|
|
103
|
-
## 📖
|
|
110
|
+
## 📖 Usage Guide
|
|
104
111
|
|
|
105
|
-
###
|
|
112
|
+
### With Toolbar
|
|
106
113
|
|
|
107
|
-
|
|
114
|
+
The `Toolbar` component provides a ready-made taskbar with app launchers, folder support, and minimized window restoration.
|
|
108
115
|
|
|
109
|
-
<
|
|
110
|
-
<img src="./docs/assets/2.png" alt="Toolbar integration overview" width="100%" style="border-radius: 8px;" />
|
|
111
|
-
</p>
|
|
116
|
+
<img src="./docs/assets/2.png" alt="Toolbar integration" width="100%" style="border-radius: 8px;" />
|
|
112
117
|
|
|
113
118
|
```tsx
|
|
114
119
|
import { WindowSystemProvider, WindowManager, Toolbar } from '@maomaolabs/core';
|
|
115
120
|
|
|
116
121
|
const DESKTOP_ITEMS = [
|
|
117
122
|
{
|
|
118
|
-
id: 'browser
|
|
123
|
+
id: 'browser',
|
|
119
124
|
title: 'Browser',
|
|
120
|
-
component: <div />,
|
|
125
|
+
component: <div />,
|
|
121
126
|
initialSize: { width: 800, height: 600 }
|
|
122
127
|
},
|
|
123
128
|
{
|
|
@@ -141,18 +146,18 @@ export default function Desktop() {
|
|
|
141
146
|
|
|
142
147
|
### Accessing Window State
|
|
143
148
|
|
|
144
|
-
|
|
149
|
+
Use `useWindows` when you need to render UI based on open windows (e.g., a custom taskbar or badge counter).
|
|
145
150
|
|
|
146
|
-
<
|
|
147
|
-
|
|
148
|
-
|
|
151
|
+
<img src="./docs/assets/3.png" alt="Window state access" width="100%" style="border-radius: 8px;" />
|
|
152
|
+
|
|
153
|
+
> ⚠️ **Warning:** `useWindows` triggers a re-render on **every** window state change (drag, resize, focus). Only use it where necessary.
|
|
149
154
|
|
|
150
155
|
```tsx
|
|
151
156
|
import { useWindows } from '@maomaolabs/core';
|
|
152
157
|
|
|
153
158
|
const OpenAppCounter = () => {
|
|
154
159
|
const windows = useWindows();
|
|
155
|
-
return <div>Active
|
|
160
|
+
return <div>Active windows: {windows.length}</div>;
|
|
156
161
|
};
|
|
157
162
|
```
|
|
158
163
|
|
|
@@ -160,80 +165,188 @@ const OpenAppCounter = () => {
|
|
|
160
165
|
|
|
161
166
|
## 📚 API Reference
|
|
162
167
|
|
|
163
|
-
###
|
|
168
|
+
### Components
|
|
164
169
|
|
|
165
170
|
| Component | Description | Props |
|
|
166
171
|
| :--- | :--- | :--- |
|
|
167
|
-
| `WindowSystemProvider` |
|
|
168
|
-
| `WindowManager` | Renders active windows and snap overlays.
|
|
169
|
-
| `Toolbar` |
|
|
172
|
+
| `WindowSystemProvider` | Root context provider. Wrap your entire app with this. | `children: ReactNode`, `systemStyle?: SystemStyle` |
|
|
173
|
+
| `WindowManager` | Renders all active windows and snap preview overlays. | — |
|
|
174
|
+
| `Toolbar` | Taskbar with app launchers and folder support. | `toolbarItems: ToolbarItem[]`, `showLogo?: boolean` |
|
|
170
175
|
|
|
171
|
-
###
|
|
176
|
+
### Hooks
|
|
172
177
|
|
|
173
|
-
|
|
174
|
-
Returns
|
|
175
|
-
- `openWindow(window: WindowDefinition): void` - Opens a new window or focuses it if already open.
|
|
176
|
-
- `closeWindow(id: string): void` - Destroys a window instance.
|
|
177
|
-
- `focusWindow(id: string): void` - Brings a window to the top of the z-index stack.
|
|
178
|
-
- `updateWindow(id: string, data: Partial<WindowInstance>): void` - Patches an existing window's state.
|
|
178
|
+
#### `useWindowActions()`
|
|
179
|
+
Returns window manipulation methods. **Does not subscribe to window state** — safe to call anywhere without performance concerns.
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
| Method | Signature | Description |
|
|
182
|
+
| :--- | :--- | :--- |
|
|
183
|
+
| `openWindow` | `(window: WindowDefinition) => void` | Opens a new window, or focuses it if already open. |
|
|
184
|
+
| `closeWindow` | `(id: string) => void` | Destroys a window instance. |
|
|
185
|
+
| `focusWindow` | `(id: string) => void` | Brings a window to the top of the z-index stack. |
|
|
186
|
+
| `updateWindow` | `(id: string, data: Partial<WindowInstance>) => void` | Patches an existing window's state. |
|
|
182
187
|
|
|
183
|
-
|
|
184
|
-
|
|
188
|
+
#### `useWindows()`
|
|
189
|
+
Returns `WindowInstance[]` — the list of all currently active windows. Re-renders on every state change.
|
|
185
190
|
|
|
186
|
-
|
|
191
|
+
#### `useWindowSnap()`
|
|
192
|
+
Returns `{ snapPreview, setSnapPreview }` for reading and controlling the active snap preview overlay.
|
|
187
193
|
|
|
188
|
-
|
|
194
|
+
---
|
|
189
195
|
|
|
190
|
-
|
|
191
|
-
| :--- | :--- | :--- |
|
|
192
|
-
| `id` | `string` | **Required.** Unique identifier for the window instance. |
|
|
193
|
-
| `title` | `string` | **Required.** Text displayed in the window header. |
|
|
194
|
-
| `component` | `React.ReactNode` | **Required.** The view to be rendered inside the window. |
|
|
195
|
-
| `icon` | `React.ReactNode` | Optional element (e.g., SVG/image) for headers/toolbars. |
|
|
196
|
-
| `initialSize` | `{ width: number; height: number }` | Optional starting dimensions. |
|
|
197
|
-
| `initialPosition` | `{ x: number; y: number }` | Optional starting coordinates. |
|
|
198
|
-
| `layer` | `'base' \| 'normal' \| 'alwaysOnTop' \| 'modal'` | Window render priority layer. |
|
|
199
|
-
| `isMaximized` | `boolean` | If true, spawns the window spanning the screen. |
|
|
200
|
-
| `canMinimize` | `boolean` | Allows the user to hide the window. |
|
|
201
|
-
| `canMaximize` | `boolean` | Allows the user to toggle screen-spanning. |
|
|
202
|
-
| `canClose` | `boolean` | Allows the user to destroy the window. |
|
|
203
|
-
|
|
204
|
-
**`FolderDefinition`** *(Used within Toolbars to group apps)*
|
|
205
|
-
|
|
206
|
-
| Property | Type | Description |
|
|
207
|
-
| :--- | :--- | :--- |
|
|
208
|
-
| `id` | `string` | **Required.** Unique identifier for the folder. |
|
|
209
|
-
| `title` | `string` | **Required.** Folder name. |
|
|
210
|
-
| `apps` | `WindowDefinition[]` | **Required.** Array of windows contained within. |
|
|
211
|
-
| `icon` | `React.ReactNode` | Optional visual descriptor. |
|
|
196
|
+
### Interfaces
|
|
212
197
|
|
|
213
|
-
|
|
198
|
+
#### `WindowDefinition`
|
|
199
|
+
|
|
200
|
+
| Property | Type | Required | Description |
|
|
201
|
+
| :--- | :--- | :---: | :--- |
|
|
202
|
+
| `id` | `string` | ✅ | Unique identifier for the window. |
|
|
203
|
+
| `title` | `string` | ✅ | Text shown in the window title bar. |
|
|
204
|
+
| `component` | `ReactNode` | ✅ | Content rendered inside the window. |
|
|
205
|
+
| `icon` | `ReactNode` | — | Icon shown in the title bar and toolbar. |
|
|
206
|
+
| `initialSize` | `{ width: number; height: number }` | — | Starting dimensions in pixels. |
|
|
207
|
+
| `initialPosition` | `{ x: number; y: number }` | — | Starting coordinates in pixels. |
|
|
208
|
+
| `layer` | `'base' \| 'normal' \| 'alwaysOnTop' \| 'modal'` | — | Z-index render layer. |
|
|
209
|
+
| `isMaximized` | `boolean` | — | Spawns the window in maximized state. |
|
|
210
|
+
| `canMinimize` | `boolean` | — | Shows the minimize control. |
|
|
211
|
+
| `canMaximize` | `boolean` | — | Shows the maximize/restore control. |
|
|
212
|
+
| `canClose` | `boolean` | — | Shows the close control. |
|
|
213
|
+
| `className` | `string` | — | Inject custom CSS classes directly into the window container. |
|
|
214
|
+
| `style` | `React.CSSProperties` | — | Inject inline styles overriding or extending window container styles. |
|
|
215
|
+
|
|
216
|
+
#### `FolderDefinition`
|
|
217
|
+
|
|
218
|
+
| Property | Type | Required | Description |
|
|
219
|
+
| :--- | :--- | :---: | :--- |
|
|
220
|
+
| `id` | `string` | ✅ | Unique identifier for the folder. |
|
|
221
|
+
| `title` | `string` | ✅ | Folder display name. |
|
|
222
|
+
| `apps` | `WindowDefinition[]` | ✅ | Windows grouped inside this folder. |
|
|
223
|
+
| `icon` | `ReactNode` | — | Optional visual icon. |
|
|
224
|
+
|
|
225
|
+
> `ToolbarItem = WindowDefinition | FolderDefinition`
|
|
226
|
+
|
|
227
|
+
#### `WindowStyling`
|
|
228
|
+
|
|
229
|
+
Exported type available for reuse in your own components:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
import type { WindowStyling } from '@maomaolabs/core';
|
|
233
|
+
// { className?: string; style?: React.CSSProperties }
|
|
234
|
+
```
|
|
214
235
|
|
|
215
236
|
---
|
|
216
237
|
|
|
217
|
-
## ⚙️
|
|
238
|
+
## ⚙️ Styling
|
|
218
239
|
|
|
219
|
-
|
|
240
|
+
The library requires a single CSS import to function correctly:
|
|
220
241
|
|
|
221
242
|
```tsx
|
|
222
243
|
import '@maomaolabs/core/dist/style.css';
|
|
223
244
|
```
|
|
224
|
-
|
|
245
|
+
|
|
246
|
+
Ensure your bundler (Vite, Webpack, etc.) is configured to process CSS from `node_modules`.
|
|
247
|
+
|
|
248
|
+
### Theming System (`systemStyle`)
|
|
249
|
+
|
|
250
|
+
The context provider accepts a `systemStyle` prop that governs the aesthetics of the entire rendered window manager system:
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
<WindowSystemProvider systemStyle="aero">
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Pre-bundled themes include:
|
|
257
|
+
- `default`
|
|
258
|
+
- `traffic` (colored dot buttons concept)
|
|
259
|
+
- `linux` (modern dark/light gradient adaptation)
|
|
260
|
+
- `yk2000` (classic 90s/00s retro styling)
|
|
261
|
+
- `aero` (translucent glass blurring)
|
|
262
|
+
|
|
263
|
+
**Note on Custom Themes**: `SystemStyle` strictly autocompletes the pre-built themes above, but mathematically permits *any* string to be passed via Type relaxation. You can pass your own `systemStyle="my-custom-theme"` alongside injected custom CSS.
|
|
264
|
+
|
|
265
|
+
### Custom Theme Injection
|
|
266
|
+
|
|
267
|
+
You can define your own theme by creating a CSS file that targets the `data-system-style` attribute.
|
|
268
|
+
|
|
269
|
+
> ⚠️ Use standard CSS attribute selectors — **avoid `:global()`** unless your bundler explicitly supports it (e.g. CSS Modules with PostCSS).
|
|
270
|
+
|
|
271
|
+
```css
|
|
272
|
+
/* my-custom-theme.css */
|
|
273
|
+
[data-system-style="my-custom-theme"] .window-header {
|
|
274
|
+
background: #1a1a2e;
|
|
275
|
+
color: #e0e0e0;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
[data-system-style="my-custom-theme"] .window-controls {
|
|
279
|
+
gap: 6px;
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Import the CSS file anywhere in your app (e.g. `src/index.tsx`) before the provider renders:
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
import './my-custom-theme.css';
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Then pass the identifier to the provider:
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
<WindowSystemProvider systemStyle="my-custom-theme">
|
|
293
|
+
{/* ... */}
|
|
294
|
+
</WindowSystemProvider>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### Available CSS selectors
|
|
298
|
+
|
|
299
|
+
The following global class names are always present on the window DOM and safe to target in your theme:
|
|
300
|
+
|
|
301
|
+
| Selector | Element |
|
|
302
|
+
| :--- | :--- |
|
|
303
|
+
| `.window-container` | Root window wrapper |
|
|
304
|
+
| `.window-header` | Title bar (drag area) |
|
|
305
|
+
| `.window-title` | Title text container |
|
|
306
|
+
| `.window-icon` | Icon inside the title bar |
|
|
307
|
+
| `.window-controls` | Button group (minimize / maximize / close) |
|
|
308
|
+
| `.terminal-btn` | Generic control button |
|
|
309
|
+
| `.window-scrollbar` | Scrollable content area |
|
|
310
|
+
| `.window-resize-handle` | Bottom-right resize grip |
|
|
311
|
+
|
|
312
|
+
You can also target individual buttons via the `data-action` attribute:
|
|
313
|
+
|
|
314
|
+
```css
|
|
315
|
+
[data-system-style="my-custom-theme"] [data-action="close"] { background: red; }
|
|
316
|
+
[data-system-style="my-custom-theme"] [data-action="maximize"] { background: green; }
|
|
317
|
+
[data-system-style="my-custom-theme"] [data-action="minimize"] { background: yellow; }
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Per-window inline overrides
|
|
321
|
+
|
|
322
|
+
Custom `className` and `style` props are accepted on each individual window definition via `openWindow()`, allowing per-instance overrides on top of the global theme:
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
openWindow({
|
|
326
|
+
id: 'my-app',
|
|
327
|
+
title: 'My App',
|
|
328
|
+
component: <div />,
|
|
329
|
+
className: 'my-extra-class',
|
|
330
|
+
style: { borderRadius: '16px', border: '1px solid #444' },
|
|
331
|
+
});
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
These are merged after the global theme styles, so they always take precedence.
|
|
225
335
|
|
|
226
336
|
---
|
|
227
337
|
|
|
228
|
-
## 🤝
|
|
338
|
+
## 🤝 Contributing
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
npm install # Install dependencies
|
|
342
|
+
npm run dev # Start dev server with hot reload
|
|
343
|
+
npm run test # Run test suite (Vitest)
|
|
344
|
+
```
|
|
229
345
|
|
|
230
|
-
|
|
231
|
-
1. `npm install`
|
|
232
|
-
2. `npm run dev` to watch changes and test locally.
|
|
233
|
-
3. `npm run test` before committing to ensure Vitest suites pass.
|
|
346
|
+
PRs are welcome. Please ensure all tests pass before submitting.
|
|
234
347
|
|
|
235
348
|
---
|
|
236
349
|
|
|
237
350
|
## 📝 License
|
|
238
351
|
|
|
239
|
-
MIT
|
|
352
|
+
MIT © [MaoMao Labs](https://github.com/maomaolabs)
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export declare type FolderDefinition = {
|
|
|
9
9
|
apps: WindowDefinition[];
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
declare type SystemStyle = (string & {}) | 'default' | 'traffic' | 'linux' | 'yk2000' | 'aero';
|
|
13
|
+
|
|
12
14
|
/**
|
|
13
15
|
* Main toolbar component. Provides all options available to open windows.
|
|
14
16
|
* @param windows - Array of window instances to be displayed in the toolbar.
|
|
@@ -61,6 +63,12 @@ export declare function useWindowSnap(): {
|
|
|
61
63
|
declare const Window_2: React_2.NamedExoticComponent<WindowProps>;
|
|
62
64
|
export { Window_2 as Window }
|
|
63
65
|
|
|
66
|
+
export declare type WindowBehavior = {
|
|
67
|
+
canMinimize?: boolean;
|
|
68
|
+
canMaximize?: boolean;
|
|
69
|
+
canClose?: boolean;
|
|
70
|
+
};
|
|
71
|
+
|
|
64
72
|
export declare type WindowContextState = {
|
|
65
73
|
size: {
|
|
66
74
|
width: number;
|
|
@@ -83,15 +91,17 @@ export declare type WindowContextState = {
|
|
|
83
91
|
windowRef: React_2.RefObject<HTMLDivElement>;
|
|
84
92
|
};
|
|
85
93
|
|
|
86
|
-
|
|
87
|
-
* WindowDefinition type.
|
|
88
|
-
* Defines the properties of a window.
|
|
89
|
-
*/
|
|
90
|
-
export declare type WindowDefinition = {
|
|
94
|
+
export declare type WindowCore = {
|
|
91
95
|
id: string;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
layer?: 'base' | 'normal' | 'alwaysOnTop' | 'modal';
|
|
97
|
+
isMaximized?: boolean;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export declare type WindowDefinition = WindowCore & WindowPresentation & WindowGeometry & WindowBehavior & WindowStyling;
|
|
101
|
+
|
|
102
|
+
export declare type WindowDispatch = Omit<WindowSystemProvider_2, 'windows' | 'snapPreview' | 'setSnapPreview'>;
|
|
103
|
+
|
|
104
|
+
export declare type WindowGeometry = {
|
|
95
105
|
initialSize?: {
|
|
96
106
|
width: number;
|
|
97
107
|
height: number;
|
|
@@ -100,15 +110,8 @@ export declare type WindowDefinition = {
|
|
|
100
110
|
x: number;
|
|
101
111
|
y: number;
|
|
102
112
|
};
|
|
103
|
-
layer?: 'base' | 'normal' | 'alwaysOnTop' | 'modal';
|
|
104
|
-
isMaximized?: boolean;
|
|
105
|
-
canMinimize?: boolean;
|
|
106
|
-
canMaximize?: boolean;
|
|
107
|
-
canClose?: boolean;
|
|
108
113
|
};
|
|
109
114
|
|
|
110
|
-
export declare type WindowDispatch = Omit<WindowSystemProvider_2, 'windows' | 'snapPreview' | 'setSnapPreview'>;
|
|
111
|
-
|
|
112
115
|
export declare type WindowHeaderProps = {
|
|
113
116
|
onClose: () => void;
|
|
114
117
|
title: string;
|
|
@@ -145,11 +148,31 @@ export declare type WindowInstance = Omit<WindowDefinition, 'initialSize' | 'ini
|
|
|
145
148
|
*/
|
|
146
149
|
export declare function WindowManager(): JSX_2.Element;
|
|
147
150
|
|
|
151
|
+
/**
|
|
152
|
+
* WindowDefinition type.
|
|
153
|
+
* Defines the properties of a window.
|
|
154
|
+
*/
|
|
155
|
+
export declare type WindowPresentation = {
|
|
156
|
+
title: string;
|
|
157
|
+
icon?: React_2.ReactNode;
|
|
158
|
+
component: React_2.ReactNode;
|
|
159
|
+
};
|
|
160
|
+
|
|
148
161
|
export declare type WindowProps = {
|
|
149
162
|
window: WindowInstance;
|
|
150
163
|
};
|
|
151
164
|
|
|
152
|
-
|
|
165
|
+
/**
|
|
166
|
+
* WindowStyling type.
|
|
167
|
+
* Allows consumers to inject custom className and style into the window container.
|
|
168
|
+
* Kept separate from WindowPresentation to avoid collisions with HTML attribute names (e.g. `title`).
|
|
169
|
+
*/
|
|
170
|
+
export declare type WindowStyling = {
|
|
171
|
+
className?: string;
|
|
172
|
+
style?: React_2.CSSProperties;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export declare function WindowSystemProvider({ children, systemStyle }: WindowSystemProviderProps): JSX_2.Element;
|
|
153
176
|
|
|
154
177
|
/**
|
|
155
178
|
* WindowSystemProvider type.
|
|
@@ -167,10 +190,12 @@ declare type WindowSystemProvider_2 = {
|
|
|
167
190
|
closeWindow: (id: string) => void;
|
|
168
191
|
focusWindow: (id: string) => void;
|
|
169
192
|
updateWindow: (id: string, data: Partial<WindowInstance>) => void;
|
|
193
|
+
systemStyle?: SystemStyle;
|
|
170
194
|
};
|
|
171
195
|
|
|
172
196
|
declare interface WindowSystemProviderProps {
|
|
173
197
|
children: ReactNode;
|
|
198
|
+
systemStyle?: SystemStyle;
|
|
174
199
|
}
|
|
175
200
|
|
|
176
201
|
export { }
|