@surdeddd/wmkit 0.4.0 → 0.4.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 +13 -1
- package/README.ru.md +135 -2
- package/dist/angular.cjs +3 -3
- package/dist/angular.js +1 -1
- package/dist/{chunk-FPZDAKNP.js → chunk-OOEDFA7K.js} +6 -2
- package/dist/chunk-OOEDFA7K.js.map +1 -0
- package/dist/{chunk-3KZZOLHW.cjs → chunk-TJ6QOOJ2.cjs} +6 -2
- package/dist/chunk-TJ6QOOJ2.cjs.map +1 -0
- package/dist/index.cjs +18 -18
- package/dist/index.js +1 -1
- package/dist/react.cjs +3 -3
- package/dist/react.js +1 -1
- package/dist/solid.cjs +3 -3
- package/dist/solid.js +1 -1
- package/dist/svelte.cjs +3 -3
- package/dist/svelte.js +1 -1
- package/dist/vue.cjs +3 -3
- package/dist/vue.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-3KZZOLHW.cjs.map +0 -1
- package/dist/chunk-FPZDAKNP.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Headless window manager for the web.** Draggable, resizable, snappable windows with a taskbar model, keyboard accessibility and state persistence — for vanilla JS and every major framework.
|
|
4
4
|
|
|
5
|
-
[Русская версия](./README.ru.md) · [Live demo](https://wmkit.vercel.app) · [Mirror (Pages)](https://surdeddd.github.io/wmkit/) · [GitHub](https://github.com/Surdeddd/wmkit)
|
|
5
|
+
[Русская версия](./README.ru.md) · [Live demo](https://wmkit.vercel.app) · [Mirror (Pages)](https://surdeddd.github.io/wmkit/) · [Docs](./docs/README.md) · [GitHub](https://github.com/Surdeddd/wmkit)
|
|
6
6
|
|
|
7
7
|
[](https://github.com/Surdeddd/wmkit/actions/workflows/ci.yml)
|
|
8
8
|
[](https://www.npmjs.com/package/@surdeddd/wmkit)
|
|
@@ -346,6 +346,18 @@ Skip the import entirely and the library stays headless: state attributes (`data
|
|
|
346
346
|
|
|
347
347
|
The core never touches `window`/`document` — create managers and even `hydrate()` state on the server, then call `attachDesktop` after mount. `persist` no-ops without usable storage.
|
|
348
348
|
|
|
349
|
+
## Documentation
|
|
350
|
+
|
|
351
|
+
This README is the tour. The reference lives in [`docs/`](./docs/README.md):
|
|
352
|
+
|
|
353
|
+
| Page | What is in it |
|
|
354
|
+
| --- | --- |
|
|
355
|
+
| [API reference](./docs/api.md) | every export, option, method, event and type |
|
|
356
|
+
| [Adapters](./docs/adapters.md) | complete React, Vue, Svelte, Solid and Angular integrations |
|
|
357
|
+
| [Theming](./docs/theming.md) | `data-wm-*` contract, CSS variables, writing a theme from scratch |
|
|
358
|
+
| [Recipes](./docs/recipes.md) | taskbar, modals, persistence, workspaces, SSR, testing, performance |
|
|
359
|
+
| [Browser support](./docs/browser-support.md) | baselines per entry point and what degrades where |
|
|
360
|
+
|
|
349
361
|
## Comparison
|
|
350
362
|
|
|
351
363
|
| | wmkit | WinBox | jsPanel4 | Dockview | Zag floating-panel |
|
package/README.ru.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Headless оконный менеджер для веба.** Перетаскиваемые окна с ресайзом, снэпом, таскбаром, клавиатурной доступностью и персистом состояния — для vanilla JS и всех основных фреймворков.
|
|
4
4
|
|
|
5
|
-
[English version](./README.md) · [Живое демо](https://wmkit.vercel.app) · [Зеркало (Pages)](https://surdeddd.github.io/wmkit/) · [GitHub](https://github.com/Surdeddd/wmkit)
|
|
5
|
+
[English version](./README.md) · [Живое демо](https://wmkit.vercel.app) · [Зеркало (Pages)](https://surdeddd.github.io/wmkit/) · [Документация](./docs/README.md) · [GitHub](https://github.com/Surdeddd/wmkit)
|
|
6
6
|
|
|
7
7
|
[](https://surdeddd.github.io/wmkit/)
|
|
8
8
|
|
|
@@ -73,7 +73,140 @@ desktop.attachWindow(win.id, el, { removeOnClose: true })
|
|
|
73
73
|
|
|
74
74
|
## Адаптеры
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
Каждый адаптер — тонкая обёртка над тем же ядром и тем же DOM-контроллером, около 60 строк. Они нужны только чтобы привязаться и отвязаться в нужный момент жизненного цикла компонента. Контент окна всегда живёт в дереве вашего фреймворка: никакого innerHTML, порталов и переноса узлов.
|
|
77
|
+
|
|
78
|
+
### React
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { useWindowManager, useDesktop, useWmState, useWmWindowRef } from '@surdeddd/wmkit/react'
|
|
82
|
+
|
|
83
|
+
function Desktop() {
|
|
84
|
+
const wm = useWindowManager()
|
|
85
|
+
const { ref, binder } = useDesktop(wm)
|
|
86
|
+
const state = useWmState(wm)
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<div ref={ref} style={{ position: 'relative', height: '100vh' }}>
|
|
90
|
+
<button type="button" onClick={() => wm.open({ title: 'Окно' })}>открыть</button>
|
|
91
|
+
{state.order.map((id) => (
|
|
92
|
+
<Win key={id} binder={binder} win={state.windows[id]} />
|
|
93
|
+
))}
|
|
94
|
+
</div>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function Win({ binder, win }) {
|
|
99
|
+
const ref = useWmWindowRef(binder, win.id, { removeOnClose: true })
|
|
100
|
+
return (
|
|
101
|
+
<section ref={ref}>
|
|
102
|
+
<header data-wm-drag><span data-wm-title>{win.title}</span></header>
|
|
103
|
+
<div data-wm-content>ваше дерево компонентов</div>
|
|
104
|
+
</section>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Vue
|
|
110
|
+
|
|
111
|
+
```vue
|
|
112
|
+
<script setup lang="ts">
|
|
113
|
+
import { ref } from 'vue'
|
|
114
|
+
import { useWindowManager, useDesktop, useWmWindowEl } from '@surdeddd/wmkit/vue'
|
|
115
|
+
|
|
116
|
+
const host = ref<HTMLElement>()
|
|
117
|
+
const panel = ref<HTMLElement>()
|
|
118
|
+
const wm = useWindowManager()
|
|
119
|
+
const binder = useDesktop(wm, host)
|
|
120
|
+
useWmWindowEl(binder, 'notes', panel)
|
|
121
|
+
wm.open({ id: 'notes', title: 'Заметки' })
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<template>
|
|
125
|
+
<div ref="host" style="position: relative; height: 100vh">
|
|
126
|
+
<section ref="panel">
|
|
127
|
+
<header data-wm-drag><span data-wm-title>Заметки</span></header>
|
|
128
|
+
<div data-wm-content>композаблы</div>
|
|
129
|
+
</section>
|
|
130
|
+
</div>
|
|
131
|
+
</template>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Svelte
|
|
135
|
+
|
|
136
|
+
```svelte
|
|
137
|
+
<script lang="ts">
|
|
138
|
+
import { createManager, createDesktop, wmWindowStore } from '@surdeddd/wmkit/svelte'
|
|
139
|
+
|
|
140
|
+
const wm = createManager()
|
|
141
|
+
const dk = createDesktop(wm)
|
|
142
|
+
wm.open({ id: 'notes', title: 'Заметки' })
|
|
143
|
+
const notes = wmWindowStore(wm, 'notes')
|
|
144
|
+
</script>
|
|
145
|
+
|
|
146
|
+
<div use:dk.desktop style="position: relative; height: 100vh">
|
|
147
|
+
<section use:dk.window={{ id: 'notes' }}>
|
|
148
|
+
<header data-wm-drag><span data-wm-title>{$notes?.title}</span></header>
|
|
149
|
+
<div data-wm-content>сторы и экшены</div>
|
|
150
|
+
</section>
|
|
151
|
+
</div>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Solid
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import { useWindowManager, createDesktop, useWmState } from '@surdeddd/wmkit/solid'
|
|
158
|
+
|
|
159
|
+
function Desktop() {
|
|
160
|
+
const wm = useWindowManager()
|
|
161
|
+
const dk = createDesktop(wm)
|
|
162
|
+
const state = useWmState(wm)
|
|
163
|
+
wm.open({ id: 'notes', title: 'Заметки' })
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<div ref={dk.desktop} style={{ position: 'relative', height: '100vh' }}>
|
|
167
|
+
<section ref={dk.window('notes')}>
|
|
168
|
+
<header data-wm-drag><span data-wm-title>Заметки</span></header>
|
|
169
|
+
<div data-wm-content>{state().order.length} окон</div>
|
|
170
|
+
</section>
|
|
171
|
+
</div>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Angular
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import { Component, ElementRef, afterNextRender, viewChild } from '@angular/core'
|
|
180
|
+
import { useWindowManager, createDesktop, useWmState } from '@surdeddd/wmkit/angular'
|
|
181
|
+
|
|
182
|
+
@Component({
|
|
183
|
+
selector: 'app-desktop',
|
|
184
|
+
template: `
|
|
185
|
+
<div #host style="position: relative; height: 100vh">
|
|
186
|
+
<section #panel>
|
|
187
|
+
<header data-wm-drag><span data-wm-title>Заметки</span></header>
|
|
188
|
+
<div data-wm-content>{{ state().order.length }} окон</div>
|
|
189
|
+
</section>
|
|
190
|
+
</div>`,
|
|
191
|
+
})
|
|
192
|
+
export class DesktopComponent {
|
|
193
|
+
private host = viewChild.required<ElementRef>('host')
|
|
194
|
+
private panel = viewChild.required<ElementRef>('panel')
|
|
195
|
+
wm = useWindowManager()
|
|
196
|
+
state = useWmState(this.wm)
|
|
197
|
+
|
|
198
|
+
constructor() {
|
|
199
|
+
const dk = createDesktop(this.wm)
|
|
200
|
+
afterNextRender(() => {
|
|
201
|
+
dk.desktop(this.host().nativeElement)
|
|
202
|
+
this.wm.open({ id: 'notes', title: 'Заметки' })
|
|
203
|
+
dk.window('notes')(this.panel().nativeElement)
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Полные примеры с таскбаром, модалками и сигнатурами всех хуков — в [docs/adapters.md](./docs/adapters.md).
|
|
77
210
|
|
|
78
211
|
## API ядра — кратко
|
|
79
212
|
|
package/dist/angular.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkTJ6QOOJ2_cjs = require('./chunk-TJ6QOOJ2.cjs');
|
|
4
4
|
var core = require('@angular/core');
|
|
5
5
|
|
|
6
6
|
function onDestroy(dispose) {
|
|
@@ -13,7 +13,7 @@ function onDestroy(dispose) {
|
|
|
13
13
|
destroyRef?.onDestroy(dispose);
|
|
14
14
|
}
|
|
15
15
|
function useWindowManager(options) {
|
|
16
|
-
const wm =
|
|
16
|
+
const wm = chunkTJ6QOOJ2_cjs.createWindowManager(options);
|
|
17
17
|
onDestroy(() => wm.destroy());
|
|
18
18
|
return wm;
|
|
19
19
|
}
|
|
@@ -28,7 +28,7 @@ function useWmWindow(wm, id) {
|
|
|
28
28
|
return core.computed(() => state().windows[id]);
|
|
29
29
|
}
|
|
30
30
|
function createDesktop(wm, options) {
|
|
31
|
-
const binder =
|
|
31
|
+
const binder = chunkTJ6QOOJ2_cjs.createDesktopBinder(wm, options);
|
|
32
32
|
onDestroy(() => binder.destroy());
|
|
33
33
|
return {
|
|
34
34
|
binder,
|
package/dist/angular.js
CHANGED
|
@@ -1504,6 +1504,7 @@ var SNAP_SHORTCUTS = {
|
|
|
1504
1504
|
ArrowLeft: "left",
|
|
1505
1505
|
ArrowRight: "right"
|
|
1506
1506
|
};
|
|
1507
|
+
var LANDMARK_TAGS = /* @__PURE__ */ new Set(["header", "footer", "aside", "nav"]);
|
|
1507
1508
|
var FOCUSABLE_SELECTOR = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
1508
1509
|
function attachDesktop(wm, element, options = {}) {
|
|
1509
1510
|
const doc = element.ownerDocument;
|
|
@@ -1778,6 +1779,9 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1778
1779
|
}
|
|
1779
1780
|
const handle = typeof windowOptions.handle === "string" ? windowElement.querySelector(windowOptions.handle) : windowOptions.handle ?? windowElement.querySelector("[data-wm-drag]");
|
|
1780
1781
|
attached.handle = handle;
|
|
1782
|
+
if (handle && !handle.hasAttribute("role") && LANDMARK_TAGS.has(handle.localName)) {
|
|
1783
|
+
handle.setAttribute("role", "presentation");
|
|
1784
|
+
}
|
|
1781
1785
|
const onPointerDownFocus = () => {
|
|
1782
1786
|
wm.focus(id);
|
|
1783
1787
|
};
|
|
@@ -1983,5 +1987,5 @@ function createDesktopBinder(wm, options = {}) {
|
|
|
1983
1987
|
}
|
|
1984
1988
|
|
|
1985
1989
|
export { applyAspect, attachDesktop, boundsEqual, clamp, clampSize, clampToViewport, createAnnouncer, createDesktopBinder, createEmitter, createWindowManager, defaultMessages, detectSnapZone, flipFromTarget, flipToTarget, magnetize, prefersReducedMotion, zoneBounds };
|
|
1986
|
-
//# sourceMappingURL=chunk-
|
|
1987
|
-
//# sourceMappingURL=chunk-
|
|
1990
|
+
//# sourceMappingURL=chunk-OOEDFA7K.js.map
|
|
1991
|
+
//# sourceMappingURL=chunk-OOEDFA7K.js.map
|