@surdeddd/wmkit 0.7.2 → 0.9.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 +60 -3
- package/README.ru.md +60 -3
- package/dist/angular.cjs +4 -3
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.d.cts +2 -1
- package/dist/angular.d.ts +2 -1
- package/dist/angular.js +2 -1
- package/dist/angular.js.map +1 -1
- package/dist/binder-DGoj0xG1.d.cts +13 -0
- package/dist/binder-Lo13iTVB.d.ts +13 -0
- package/dist/chrome.cjs +122 -0
- package/dist/chrome.cjs.map +1 -0
- package/dist/chrome.d.cts +25 -0
- package/dist/chrome.d.ts +25 -0
- package/dist/chrome.js +114 -0
- package/dist/chrome.js.map +1 -0
- package/dist/chunk-5XVIC5LH.js +140 -0
- package/dist/chunk-5XVIC5LH.js.map +1 -0
- package/dist/chunk-BDHFXEJN.cjs +149 -0
- package/dist/chunk-BDHFXEJN.cjs.map +1 -0
- package/dist/{chunk-NJAI5R4J.cjs → chunk-TUGQX3CX.js} +205 -175
- package/dist/chunk-TUGQX3CX.js.map +1 -0
- package/dist/{chunk-FOWW4LXS.js → chunk-ZWUVWRUS.cjs} +236 -178
- package/dist/chunk-ZWUVWRUS.cjs.map +1 -0
- package/dist/devtools.cjs +330 -0
- package/dist/devtools.cjs.map +1 -0
- package/dist/devtools.d.cts +43 -0
- package/dist/devtools.d.ts +43 -0
- package/dist/devtools.js +326 -0
- package/dist/devtools.js.map +1 -0
- package/dist/gestures.cjs +219 -0
- package/dist/gestures.cjs.map +1 -0
- package/dist/gestures.d.cts +19 -0
- package/dist/gestures.d.ts +19 -0
- package/dist/gestures.js +215 -0
- package/dist/gestures.js.map +1 -0
- package/dist/index.cjs +35 -34
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/react.cjs +4 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -1
- package/dist/react.d.ts +2 -1
- package/dist/react.js +2 -1
- package/dist/react.js.map +1 -1
- package/dist/{binder-DvQFmO3K.d.ts → shared-BoHXlPCu.d.ts} +55 -8
- package/dist/{binder-_L3Iww0u.d.cts → shared-DdGFz3oy.d.cts} +55 -8
- package/dist/solid.cjs +4 -3
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.cts +2 -1
- package/dist/solid.d.ts +2 -1
- package/dist/solid.js +2 -1
- package/dist/solid.js.map +1 -1
- package/dist/svelte.cjs +4 -3
- package/dist/svelte.cjs.map +1 -1
- package/dist/svelte.d.cts +2 -1
- package/dist/svelte.d.ts +2 -1
- package/dist/svelte.js +2 -1
- package/dist/svelte.js.map +1 -1
- package/dist/themes/amber.css +316 -0
- package/dist/themes/aqua.css +285 -0
- package/dist/themes/blueprint.css +303 -0
- package/dist/themes/brutalist.css +307 -0
- package/dist/themes/candy.css +277 -0
- package/dist/themes/carbon.css +297 -0
- package/dist/themes/forest.css +278 -0
- package/dist/themes/frost.css +279 -0
- package/dist/themes/glass.css +2 -1
- package/dist/themes/light.css +2 -1
- package/dist/themes/neon.css +289 -0
- package/dist/themes/noir.css +282 -0
- package/dist/themes/paper.css +258 -0
- package/dist/themes/retro.css +8 -0
- package/dist/themes/synth.css +283 -0
- package/dist/themes/terminal.css +273 -0
- package/dist/themes.cjs +8747 -0
- package/dist/themes.cjs.map +1 -0
- package/dist/themes.d.cts +12 -0
- package/dist/themes.d.ts +12 -0
- package/dist/themes.js +8742 -0
- package/dist/themes.js.map +1 -0
- package/dist/vue.cjs +4 -3
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +2 -1
- package/dist/vue.d.ts +2 -1
- package/dist/vue.js +2 -1
- package/dist/vue.js.map +1 -1
- package/package.json +80 -7
- package/dist/chunk-FOWW4LXS.js.map +0 -1
- package/dist/chunk-NJAI5R4J.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
- ⌨️ **Accessible** — keyboard move/resize/snap, F6 window cycling, focus-trapped modals, `aria-live` announcements
|
|
25
25
|
- ⚡ **Fast** — `transform`-only positioning, rAF-batched pointer input, structural sharing; 50 windows drag at 60fps
|
|
26
26
|
- 💾 **Persistence** — one call to serialize the desktop, one call to restore it, with versioned migrations
|
|
27
|
-
- 🎨 **
|
|
27
|
+
- 🎨 **Sixteen themes** — glass, light, retro, terminal, paper, neon, aqua, frost, candy, carbon, brutalist, blueprint, amber, noir, forest, synth — or bring your own CSS
|
|
28
28
|
- 🖼️ **Popout** *(experimental)* — send a window into Document Picture-in-Picture
|
|
29
29
|
- 📦 **Zero dependencies**, strict TypeScript, ESM + CJS, ~10.7 kB brotli core
|
|
30
30
|
|
|
@@ -68,7 +68,7 @@ The desktop element becomes the coordinate space. Your markup stays yours — wm
|
|
|
68
68
|
| Attribute | Meaning |
|
|
69
69
|
| --- | --- |
|
|
70
70
|
| `data-wm-drag` | drag handle (usually the titlebar); double-click toggles maximize |
|
|
71
|
-
| `data-wm-title` | window title node, linked via `aria-labelledby` |
|
|
71
|
+
| `data-wm-title` | window title node; its text follows the state, and it is linked via `aria-labelledby` when it shares a root with the window |
|
|
72
72
|
| `data-wm-close` / `data-wm-minimize` / `data-wm-maximize` | control buttons, wired by delegation |
|
|
73
73
|
| `data-wm-content` | scrollable content area (styled by themes) |
|
|
74
74
|
|
|
@@ -326,6 +326,61 @@ persist(wm, {
|
|
|
326
326
|
|
|
327
327
|
Moves a window's content into a [Document Picture-in-Picture](https://developer.mozilla.org/docs/Web/API/Document_Picture-in-Picture_API) always-on-top OS window, keeping the same JS context and state. Feature-detect with `isPopoutSupported()`.
|
|
328
328
|
|
|
329
|
+
### `pinch(options?)`, `swipe(options?)`, `touchGestures(options?)` — `@surdeddd/wmkit/gestures`
|
|
330
|
+
|
|
331
|
+
Two-finger gestures, opt-in so the core never pays for them: pinch a window to resize it around the point between your fingers, swipe two fingers sideways to change workspace. 1.46 kB brotlied.
|
|
332
|
+
|
|
333
|
+
```js
|
|
334
|
+
import { attachDesktop } from '@surdeddd/wmkit'
|
|
335
|
+
import { touchGestures } from '@surdeddd/wmkit/gestures'
|
|
336
|
+
|
|
337
|
+
attachDesktop(wm, root, { gestures: [touchGestures({ swipe: { workspaces: 4 } })] })
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
A gesture is just a function that takes a `GestureContext` and returns its teardown, so your own gestures cooperate with the built-in drag and resize through the same `claim`/`busy` pair — see [docs/api.md](docs/api.md).
|
|
341
|
+
|
|
342
|
+
### `skin(spec)`, `defaultSkin`, `barebones` — `@surdeddd/wmkit/chrome`
|
|
343
|
+
|
|
344
|
+
Builds the window itself from a markup string, so a consumer can ship their own chrome and their own buttons without writing a single listener. 802 B brotlied.
|
|
345
|
+
|
|
346
|
+
```js
|
|
347
|
+
import { attachDesktop } from '@surdeddd/wmkit'
|
|
348
|
+
import { skin } from '@surdeddd/wmkit/chrome'
|
|
349
|
+
|
|
350
|
+
const mine = skin({
|
|
351
|
+
name: 'mine',
|
|
352
|
+
template:
|
|
353
|
+
'<section><header data-wm-drag><span data-wm-title>{{title}}</span>' +
|
|
354
|
+
'<button data-wm-close aria-label="Close {{title}}"></button></header>' +
|
|
355
|
+
'<div data-wm-content></div></section>',
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
const desktop = attachDesktop(wm, root, { skins: { mine } })
|
|
359
|
+
desktop.mountWindow('notes', 'mine').content.append(myApp)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
`data-wm-close`, `data-wm-minimize`, `data-wm-maximize`, `data-wm-restore`, `data-wm-center`, `data-wm-send-back`, `data-wm-snap="left"` and `data-wm-to-workspace="2"` are read straight off your markup. Every `{{placeholder}}` is HTML-escaped. `shadow: true` seals the chrome inside an open shadow root without losing grouping, focus trapping or the accessible name — see [docs/recipes.md](docs/recipes.md).
|
|
363
|
+
|
|
364
|
+
### `createDevtools(wm, options?)` — `@surdeddd/wmkit/devtools`
|
|
365
|
+
|
|
366
|
+
An opt-in panel that shows the live window table, an event log and the manager controls, so you can see what the state machine is doing without a debugger. It follows the manager, never the DOM, so it works with any adapter or none.
|
|
367
|
+
|
|
368
|
+
```js
|
|
369
|
+
import { createDevtools, devtoolsMessagesRu } from '@surdeddd/wmkit/devtools'
|
|
370
|
+
|
|
371
|
+
const panel = createDevtools(wm, { logLimit: 100 })
|
|
372
|
+
panel.destroy()
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
| Option | Default | Meaning |
|
|
376
|
+
| --- | --- | --- |
|
|
377
|
+
| `container` | `document.body` | where the panel mounts |
|
|
378
|
+
| `messages` | English catalog | pass `devtoolsMessagesRu` for Russian, or your own strings |
|
|
379
|
+
| `logLimit` | `50` | ring buffer size for the event log |
|
|
380
|
+
| `events` | open, close, focus, stage, workspace, group, modalblocked | which manager events to log |
|
|
381
|
+
|
|
382
|
+
Rows are patched in place rather than re-rendered, so keyboard focus inside the panel survives while windows move. It injects one scoped stylesheet, shared between panels and removed with the last one.
|
|
383
|
+
|
|
329
384
|
## Theming
|
|
330
385
|
|
|
331
386
|
`@surdeddd/wmkit/themes/glass.css` styles the `data-wm-*` attributes and exposes CSS variables:
|
|
@@ -339,7 +394,9 @@ Moves a window's content into a [Document Picture-in-Picture](https://developer.
|
|
|
339
394
|
}
|
|
340
395
|
```
|
|
341
396
|
|
|
342
|
-
|
|
397
|
+
Fifteen more ready-made themes ship alongside — `light`, `retro`, `terminal`, `paper`, `neon`, `aqua`, `frost`, `candy`, `carbon`, `brutalist`, `blueprint`, `amber`, `noir`, `forest` and `synth`. They all style the same `data-wm-*` attributes, so switching is a one-line import swap, and every one of them ships 24px pointer targets plus `prefers-reduced-motion` and `forced-colors` blocks.
|
|
398
|
+
|
|
399
|
+
A theme dresses every window; a variant dresses one. Set `meta.variant` on a window and the desktop mirrors it to `data-wm-variant` for your CSS to pick up — see [docs/theming.md](docs/theming.md).
|
|
343
400
|
|
|
344
401
|
Skip the import entirely and the library stays headless: state attributes (`data-wm-stage`, `data-wm-focused`, `data-wm-dragging`, `data-wm-flash`, `[hidden]`) are yours to style.
|
|
345
402
|
|
package/README.ru.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
- ⌨️ **Доступность** — move/resize/snap с клавиатуры, цикл окон по F6, focus-trap в модалках, `aria-live`-анонсы
|
|
21
21
|
- ⚡ **Производительность** — позиционирование только через `transform`, rAF-батчинг ввода, structural sharing; 50 окон таскаются на 60fps
|
|
22
22
|
- 💾 **Персист** — один вызов сериализует рабочий стол, один — восстанавливает, с версионированием и миграциями
|
|
23
|
-
- 🎨
|
|
23
|
+
- 🎨 **Шестнадцать тем** — glass, light, retro, terminal, paper, neon, aqua, frost, candy, carbon, brutalist, blueprint, amber, noir, forest, synth — либо полностью свой CSS
|
|
24
24
|
- 🖼️ **Popout** *(experimental)* — вынос окна в Document Picture-in-Picture
|
|
25
25
|
- 📦 **Ноль зависимостей**, строгий TypeScript, ESM + CJS, ~10.7 kB brotli
|
|
26
26
|
|
|
@@ -64,7 +64,7 @@ desktop.attachWindow(win.id, el, { removeOnClose: true })
|
|
|
64
64
|
| Атрибут | Смысл |
|
|
65
65
|
| --- | --- |
|
|
66
66
|
| `data-wm-drag` | ручка перетаскивания (обычно тайтлбар); двойной клик — toggle maximize |
|
|
67
|
-
| `data-wm-title` | узел
|
|
67
|
+
| `data-wm-title` | узел заголовка: его текст следует за состоянием, а связь через `aria-labelledby` ставится, когда узел лежит в том же корне, что и окно |
|
|
68
68
|
| `data-wm-close` / `data-wm-minimize` / `data-wm-maximize` | кнопки управления, работают через делегирование |
|
|
69
69
|
| `data-wm-content` | скроллируемая область контента |
|
|
70
70
|
|
|
@@ -262,11 +262,68 @@ if (isPopoutSupported()) await popout(wm, 'docs', contentElement)
|
|
|
262
262
|
|
|
263
263
|
Окно уезжает в настоящее always-on-top окно ОС (Document Picture-in-Picture) с тем же JS-контекстом и состоянием.
|
|
264
264
|
|
|
265
|
+
### `pinch(options?)`, `swipe(options?)`, `touchGestures(options?)` — `@surdeddd/wmkit/gestures`
|
|
266
|
+
|
|
267
|
+
Жесты двумя пальцами, подключаются по желанию — ядро за них не платит: пинч растягивает окно вокруг точки между пальцами, свайп двумя пальцами вбок переключает рабочий стол. 1.46 кБ в brotli.
|
|
268
|
+
|
|
269
|
+
```js
|
|
270
|
+
import { attachDesktop } from '@surdeddd/wmkit'
|
|
271
|
+
import { touchGestures } from '@surdeddd/wmkit/gestures'
|
|
272
|
+
|
|
273
|
+
attachDesktop(wm, root, { gestures: [touchGestures({ swipe: { workspaces: 4 } })] })
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Жест — это просто функция: принимает `GestureContext`, возвращает свою отписку. Свои жесты уживаются со встроенными драгом и ресайзом через ту же пару `claim`/`busy` — подробности в [docs/api.md](docs/api.md).
|
|
277
|
+
|
|
278
|
+
### `skin(spec)`, `defaultSkin`, `barebones` — `@surdeddd/wmkit/chrome`
|
|
279
|
+
|
|
280
|
+
Собирает само окно из строки разметки: можно принести свою обвязку и свои кнопки, не написав ни одного обработчика. 802 Б в brotli.
|
|
281
|
+
|
|
282
|
+
```js
|
|
283
|
+
import { attachDesktop } from '@surdeddd/wmkit'
|
|
284
|
+
import { skin } from '@surdeddd/wmkit/chrome'
|
|
285
|
+
|
|
286
|
+
const mine = skin({
|
|
287
|
+
name: 'mine',
|
|
288
|
+
template:
|
|
289
|
+
'<section><header data-wm-drag><span data-wm-title>{{title}}</span>' +
|
|
290
|
+
'<button data-wm-close aria-label="Закрыть {{title}}"></button></header>' +
|
|
291
|
+
'<div data-wm-content></div></section>',
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
const desktop = attachDesktop(wm, root, { skins: { mine } })
|
|
295
|
+
desktop.mountWindow('notes', 'mine').content.append(myApp)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
`data-wm-close`, `data-wm-minimize`, `data-wm-maximize`, `data-wm-restore`, `data-wm-center`, `data-wm-send-back`, `data-wm-snap="left"` и `data-wm-to-workspace="2"` читаются прямо из вашей разметки. Каждая подстановка `{{...}}` экранируется. `shadow: true` запечатывает обвязку в открытом теневом корне, не теряя ни группировку, ни ловушку фокуса, ни доступное имя — подробности в [docs/recipes.md](docs/recipes.md).
|
|
299
|
+
|
|
300
|
+
### `createDevtools(wm, options?)` — `@surdeddd/wmkit/devtools`
|
|
301
|
+
|
|
302
|
+
Панель, которую подключают по желанию: живая таблица окон, журнал событий и управление менеджером — чтобы видеть, что делает машина состояний, без отладчика. Она следит за менеджером, а не за DOM, поэтому работает с любым адаптером и без него.
|
|
303
|
+
|
|
304
|
+
```js
|
|
305
|
+
import { createDevtools, devtoolsMessagesRu } from '@surdeddd/wmkit/devtools'
|
|
306
|
+
|
|
307
|
+
const panel = createDevtools(wm, { messages: devtoolsMessagesRu })
|
|
308
|
+
panel.destroy()
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
| Опция | По умолчанию | Значение |
|
|
312
|
+
| --- | --- | --- |
|
|
313
|
+
| `container` | `document.body` | куда монтируется панель |
|
|
314
|
+
| `messages` | английский каталог | `devtoolsMessagesRu` для русского или свои строки |
|
|
315
|
+
| `logLimit` | `50` | размер кольцевого буфера журнала |
|
|
316
|
+
| `events` | open, close, focus, stage, workspace, group, modalblocked | какие события менеджера писать |
|
|
317
|
+
|
|
318
|
+
Строки обновляются точечно, а не перерисовываются целиком, поэтому фокус клавиатуры внутри панели переживает перемещение окон. Панель добавляет один изолированный стиль — общий для всех панелей и удаляемый вместе с последней.
|
|
319
|
+
|
|
265
320
|
## Темизация
|
|
266
321
|
|
|
267
322
|
Подключите `@surdeddd/wmkit/themes/glass.css` и переопределяйте CSS-переменные (`--wm-radius`, `--wm-bg`, `--wm-accent`, …) — или не подключайте ничего и стилизуйте `data-wm-stage`, `data-wm-focused`, `data-wm-dragging`, `[hidden]` сами.
|
|
268
323
|
|
|
269
|
-
Ещё
|
|
324
|
+
Ещё пятнадцать готовых тем: `light`, `retro`, `terminal`, `paper`, `neon`, `aqua`, `frost`, `candy`, `carbon`, `brutalist`, `blueprint`, `amber`, `noir`, `forest`, `synth`. Все стилизуют одни и те же `data-wm-*` атрибуты — переключение = замена одного импорта, и у каждой есть 24px тач-цели плюс блоки `prefers-reduced-motion` и `forced-colors`.
|
|
325
|
+
|
|
326
|
+
Тема одевает все окна, вариант — одно. Задайте `meta.variant` у окна, и десктоп отзеркалит его в `data-wm-variant` для вашего CSS — подробности в [docs/theming.md](docs/theming.md).
|
|
270
327
|
|
|
271
328
|
## SSR
|
|
272
329
|
|
package/dist/angular.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkZWUVWRUS_cjs = require('./chunk-ZWUVWRUS.cjs');
|
|
4
|
+
require('./chunk-BDHFXEJN.cjs');
|
|
4
5
|
var core = require('@angular/core');
|
|
5
6
|
|
|
6
7
|
function onDestroy(dispose) {
|
|
@@ -13,7 +14,7 @@ function onDestroy(dispose) {
|
|
|
13
14
|
destroyRef?.onDestroy(dispose);
|
|
14
15
|
}
|
|
15
16
|
function useWindowManager(options) {
|
|
16
|
-
const wm =
|
|
17
|
+
const wm = chunkZWUVWRUS_cjs.createWindowManager(options);
|
|
17
18
|
onDestroy(() => wm.destroy());
|
|
18
19
|
return wm;
|
|
19
20
|
}
|
|
@@ -28,7 +29,7 @@ function useWmWindow(wm, id) {
|
|
|
28
29
|
return core.computed(() => state().windows[id]);
|
|
29
30
|
}
|
|
30
31
|
function createDesktop(wm, options) {
|
|
31
|
-
const binder =
|
|
32
|
+
const binder = chunkZWUVWRUS_cjs.createDesktopBinder(wm, options);
|
|
32
33
|
onDestroy(() => binder.destroy());
|
|
33
34
|
return {
|
|
34
35
|
binder,
|
package/dist/angular.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/angular.ts"],"names":["inject","DestroyRef","createWindowManager","signal","computed","createDesktopBinder"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/adapters/angular.ts"],"names":["inject","DestroyRef","createWindowManager","signal","computed","createDesktopBinder"],"mappings":";;;;;;AAMA,SAAS,UAAU,OAAA,EAA2B;AAC5C,EAAA,IAAI,UAAA,GAAgC,IAAA;AACpC,EAAA,IAAI;AACF,IAAA,UAAA,GAAaA,YAAOC,eAAU,CAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AACN,IAAA,UAAA,GAAa,IAAA;AAAA,EACf;AACA,EAAA,UAAA,EAAY,UAAU,OAAO,CAAA;AAC/B;AAEO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM,EAAA,GAAKC,sCAAoB,OAAO,CAAA;AACtC,EAAA,SAAA,CAAU,MAAM,EAAA,CAAG,OAAA,EAAS,CAAA;AAC5B,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,WAAW,EAAA,EAAyC;AAClE,EAAA,MAAM,KAAA,GAAQC,WAAA,CAAO,EAAA,CAAG,QAAA,EAAU,CAAA;AAClC,EAAA,MAAM,IAAA,GAAO,GAAG,SAAA,CAAU,CAAC,SAAS,KAAA,CAAM,GAAA,CAAI,IAAI,CAAC,CAAA;AACnD,EAAA,SAAA,CAAU,IAAI,CAAA;AACd,EAAA,OAAO,MAAM,UAAA,EAAW;AAC1B;AAEO,SAAS,WAAA,CAAY,IAAmB,EAAA,EAA6C;AAC1F,EAAA,MAAM,KAAA,GAAQ,WAAW,EAAE,CAAA;AAC3B,EAAA,OAAOC,cAAS,MAAM,KAAA,EAAM,CAAE,OAAA,CAAQ,EAAE,CAAC,CAAA;AAC3C;AAQO,SAAS,aAAA,CAAc,IAAmB,OAAA,EAA0C;AACzF,EAAA,MAAM,MAAA,GAASC,qCAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAC9C,EAAA,SAAA,CAAU,MAAM,MAAA,CAAO,OAAA,EAAS,CAAA;AAChC,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,QAAQ,OAAA,EAAS;AACf,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,WAAA,CAAY,OAAO,CAAA;AACzC,MAAA,SAAA,CAAU,MAAM,CAAA;AAAA,IAClB,CAAA;AAAA,IACA,MAAA,CAAO,IAAI,aAAA,EAAe;AACxB,MAAA,OAAO,CAAC,OAAA,KAAY;AAClB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,EAAA,EAAI,SAAS,aAAa,CAAA;AAC3D,QAAA,SAAA,CAAU,MAAM,CAAA;AAAA,MAClB,CAAA;AAAA,IACF;AAAA,GACF;AACF","file":"angular.cjs","sourcesContent":["import { computed, DestroyRef, inject, type Signal, signal } from '@angular/core'\nimport { createWindowManager } from '../core/manager'\nimport type { ManagerOptions, ManagerState, WindowManager, WindowState } from '../core/types'\nimport { createDesktopBinder, type DesktopBinder } from '../dom/binder'\nimport type { DesktopOptions, WindowAttachOptions } from '../dom/shared'\n\nfunction onDestroy(dispose: () => void): void {\n let destroyRef: DestroyRef | null = null\n try {\n destroyRef = inject(DestroyRef)\n } catch {\n destroyRef = null\n }\n destroyRef?.onDestroy(dispose)\n}\n\nexport function useWindowManager(options?: ManagerOptions): WindowManager {\n const wm = createWindowManager(options)\n onDestroy(() => wm.destroy())\n return wm\n}\n\nexport function useWmState(wm: WindowManager): Signal<ManagerState> {\n const state = signal(wm.getState())\n const stop = wm.subscribe((next) => state.set(next))\n onDestroy(stop)\n return state.asReadonly()\n}\n\nexport function useWmWindow(wm: WindowManager, id: string): Signal<WindowState | undefined> {\n const state = useWmState(wm)\n return computed(() => state().windows[id])\n}\n\nexport interface AngularDesktop {\n binder: DesktopBinder\n desktop(element: HTMLElement): void\n window(id: string, options?: WindowAttachOptions): (element: HTMLElement) => void\n}\n\nexport function createDesktop(wm: WindowManager, options?: DesktopOptions): AngularDesktop {\n const binder = createDesktopBinder(wm, options)\n onDestroy(() => binder.destroy())\n return {\n binder,\n desktop(element) {\n const unbind = binder.bindDesktop(element)\n onDestroy(unbind)\n },\n window(id, windowOptions) {\n return (element) => {\n const unbind = binder.bindWindow(id, element, windowOptions)\n onDestroy(unbind)\n }\n },\n }\n}\n"]}
|
package/dist/angular.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Signal } from '@angular/core';
|
|
2
2
|
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-jG2lHGcA.cjs';
|
|
3
|
-
import { D as DesktopBinder
|
|
3
|
+
import { D as DesktopBinder } from './binder-DGoj0xG1.cjs';
|
|
4
|
+
import { W as WindowAttachOptions, D as DesktopOptions } from './shared-DdGFz3oy.cjs';
|
|
4
5
|
|
|
5
6
|
declare function useWindowManager(options?: ManagerOptions): WindowManager;
|
|
6
7
|
declare function useWmState(wm: WindowManager): Signal<ManagerState>;
|
package/dist/angular.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Signal } from '@angular/core';
|
|
2
2
|
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-jG2lHGcA.js';
|
|
3
|
-
import { D as DesktopBinder
|
|
3
|
+
import { D as DesktopBinder } from './binder-Lo13iTVB.js';
|
|
4
|
+
import { W as WindowAttachOptions, D as DesktopOptions } from './shared-BoHXlPCu.js';
|
|
4
5
|
|
|
5
6
|
declare function useWindowManager(options?: ManagerOptions): WindowManager;
|
|
6
7
|
declare function useWmState(wm: WindowManager): Signal<ManagerState>;
|
package/dist/angular.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { createWindowManager, createDesktopBinder } from './chunk-
|
|
1
|
+
import { createWindowManager, createDesktopBinder } from './chunk-TUGQX3CX.js';
|
|
2
|
+
import './chunk-5XVIC5LH.js';
|
|
2
3
|
import { signal, computed, inject, DestroyRef } from '@angular/core';
|
|
3
4
|
|
|
4
5
|
function onDestroy(dispose) {
|
package/dist/angular.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/angular.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/adapters/angular.ts"],"names":[],"mappings":";;;;AAMA,SAAS,UAAU,OAAA,EAA2B;AAC5C,EAAA,IAAI,UAAA,GAAgC,IAAA;AACpC,EAAA,IAAI;AACF,IAAA,UAAA,GAAa,OAAO,UAAU,CAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AACN,IAAA,UAAA,GAAa,IAAA;AAAA,EACf;AACA,EAAA,UAAA,EAAY,UAAU,OAAO,CAAA;AAC/B;AAEO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM,EAAA,GAAK,oBAAoB,OAAO,CAAA;AACtC,EAAA,SAAA,CAAU,MAAM,EAAA,CAAG,OAAA,EAAS,CAAA;AAC5B,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,WAAW,EAAA,EAAyC;AAClE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,EAAA,CAAG,QAAA,EAAU,CAAA;AAClC,EAAA,MAAM,IAAA,GAAO,GAAG,SAAA,CAAU,CAAC,SAAS,KAAA,CAAM,GAAA,CAAI,IAAI,CAAC,CAAA;AACnD,EAAA,SAAA,CAAU,IAAI,CAAA;AACd,EAAA,OAAO,MAAM,UAAA,EAAW;AAC1B;AAEO,SAAS,WAAA,CAAY,IAAmB,EAAA,EAA6C;AAC1F,EAAA,MAAM,KAAA,GAAQ,WAAW,EAAE,CAAA;AAC3B,EAAA,OAAO,SAAS,MAAM,KAAA,EAAM,CAAE,OAAA,CAAQ,EAAE,CAAC,CAAA;AAC3C;AAQO,SAAS,aAAA,CAAc,IAAmB,OAAA,EAA0C;AACzF,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAC9C,EAAA,SAAA,CAAU,MAAM,MAAA,CAAO,OAAA,EAAS,CAAA;AAChC,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,QAAQ,OAAA,EAAS;AACf,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,WAAA,CAAY,OAAO,CAAA;AACzC,MAAA,SAAA,CAAU,MAAM,CAAA;AAAA,IAClB,CAAA;AAAA,IACA,MAAA,CAAO,IAAI,aAAA,EAAe;AACxB,MAAA,OAAO,CAAC,OAAA,KAAY;AAClB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,EAAA,EAAI,SAAS,aAAa,CAAA;AAC3D,QAAA,SAAA,CAAU,MAAM,CAAA;AAAA,MAClB,CAAA;AAAA,IACF;AAAA,GACF;AACF","file":"angular.js","sourcesContent":["import { computed, DestroyRef, inject, type Signal, signal } from '@angular/core'\nimport { createWindowManager } from '../core/manager'\nimport type { ManagerOptions, ManagerState, WindowManager, WindowState } from '../core/types'\nimport { createDesktopBinder, type DesktopBinder } from '../dom/binder'\nimport type { DesktopOptions, WindowAttachOptions } from '../dom/shared'\n\nfunction onDestroy(dispose: () => void): void {\n let destroyRef: DestroyRef | null = null\n try {\n destroyRef = inject(DestroyRef)\n } catch {\n destroyRef = null\n }\n destroyRef?.onDestroy(dispose)\n}\n\nexport function useWindowManager(options?: ManagerOptions): WindowManager {\n const wm = createWindowManager(options)\n onDestroy(() => wm.destroy())\n return wm\n}\n\nexport function useWmState(wm: WindowManager): Signal<ManagerState> {\n const state = signal(wm.getState())\n const stop = wm.subscribe((next) => state.set(next))\n onDestroy(stop)\n return state.asReadonly()\n}\n\nexport function useWmWindow(wm: WindowManager, id: string): Signal<WindowState | undefined> {\n const state = useWmState(wm)\n return computed(() => state().windows[id])\n}\n\nexport interface AngularDesktop {\n binder: DesktopBinder\n desktop(element: HTMLElement): void\n window(id: string, options?: WindowAttachOptions): (element: HTMLElement) => void\n}\n\nexport function createDesktop(wm: WindowManager, options?: DesktopOptions): AngularDesktop {\n const binder = createDesktopBinder(wm, options)\n onDestroy(() => binder.destroy())\n return {\n binder,\n desktop(element) {\n const unbind = binder.bindDesktop(element)\n onDestroy(unbind)\n },\n window(id, windowOptions) {\n return (element) => {\n const unbind = binder.bindWindow(id, element, windowOptions)\n onDestroy(unbind)\n }\n },\n }\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { W as WindowManager } from './types-jG2lHGcA.cjs';
|
|
2
|
+
import { a as DesktopController, W as WindowAttachOptions, D as DesktopOptions } from './shared-DdGFz3oy.cjs';
|
|
3
|
+
|
|
4
|
+
interface DesktopBinder {
|
|
5
|
+
wm: WindowManager;
|
|
6
|
+
controller(): DesktopController | null;
|
|
7
|
+
bindDesktop(element: HTMLElement): () => void;
|
|
8
|
+
bindWindow(id: string, element: HTMLElement, options?: WindowAttachOptions): () => void;
|
|
9
|
+
destroy(): void;
|
|
10
|
+
}
|
|
11
|
+
declare function createDesktopBinder(wm: WindowManager, options?: DesktopOptions): DesktopBinder;
|
|
12
|
+
|
|
13
|
+
export { type DesktopBinder as D, createDesktopBinder as c };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { W as WindowManager } from './types-jG2lHGcA.js';
|
|
2
|
+
import { a as DesktopController, W as WindowAttachOptions, D as DesktopOptions } from './shared-BoHXlPCu.js';
|
|
3
|
+
|
|
4
|
+
interface DesktopBinder {
|
|
5
|
+
wm: WindowManager;
|
|
6
|
+
controller(): DesktopController | null;
|
|
7
|
+
bindDesktop(element: HTMLElement): () => void;
|
|
8
|
+
bindWindow(id: string, element: HTMLElement, options?: WindowAttachOptions): () => void;
|
|
9
|
+
destroy(): void;
|
|
10
|
+
}
|
|
11
|
+
declare function createDesktopBinder(wm: WindowManager, options?: DesktopOptions): DesktopBinder;
|
|
12
|
+
|
|
13
|
+
export { type DesktopBinder as D, createDesktopBinder as c };
|
package/dist/chrome.cjs
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/plugins/chrome/messages.ts
|
|
4
|
+
var chromeMessages = {
|
|
5
|
+
minimize: "Minimize",
|
|
6
|
+
maximize: "Maximize",
|
|
7
|
+
close: "Close"
|
|
8
|
+
};
|
|
9
|
+
var chromeMessagesRu = {
|
|
10
|
+
minimize: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
11
|
+
maximize: "\u0420\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
12
|
+
close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/plugins/chrome/template.ts
|
|
16
|
+
var ESCAPES = {
|
|
17
|
+
"&": "&",
|
|
18
|
+
"<": "<",
|
|
19
|
+
">": ">",
|
|
20
|
+
'"': """,
|
|
21
|
+
"'": "'"
|
|
22
|
+
};
|
|
23
|
+
function escapeHtml(value) {
|
|
24
|
+
return value.replace(/[&<>"']/g, (char) => ESCAPES[char]);
|
|
25
|
+
}
|
|
26
|
+
function compileTemplate(template) {
|
|
27
|
+
const parts = template.split(/\{\{\s*([a-z]+)\s*\}\}/i);
|
|
28
|
+
return (values) => parts.map((part, index) => index % 2 === 0 ? part : escapeHtml(values[part] ?? "")).join("");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/plugins/chrome/index.ts
|
|
32
|
+
var SLOT = "[data-wm-content]";
|
|
33
|
+
var SLOT_PATTERN = /data-wm-content\b/g;
|
|
34
|
+
var BAD_SLOT_COUNT = "wmkit: a skin template needs exactly one [data-wm-content]";
|
|
35
|
+
var BAD_STRUCTURE = "wmkit: a skin template needs a single root element that holds its [data-wm-content]";
|
|
36
|
+
var UNSCOPED_STYLES = "wmkit: a skin with styles needs a name to scope them to";
|
|
37
|
+
function valuesOf(win) {
|
|
38
|
+
const variant = win.meta.variant;
|
|
39
|
+
return {
|
|
40
|
+
id: win.id,
|
|
41
|
+
title: win.title,
|
|
42
|
+
stage: win.stage,
|
|
43
|
+
layer: win.layer,
|
|
44
|
+
workspace: String(win.workspace),
|
|
45
|
+
variant: typeof variant === "string" ? variant : ""
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function injectStyles(doc, name, styles) {
|
|
49
|
+
if (doc.head.querySelector(`style[data-wm-skin-styles="${name}"]`)) return;
|
|
50
|
+
const tag = doc.createElement("style");
|
|
51
|
+
tag.dataset.wmSkinStyles = name;
|
|
52
|
+
tag.textContent = styles;
|
|
53
|
+
doc.head.append(tag);
|
|
54
|
+
}
|
|
55
|
+
function skin(spec) {
|
|
56
|
+
if ((spec.template.match(SLOT_PATTERN) ?? []).length !== 1) throw new Error(BAD_SLOT_COUNT);
|
|
57
|
+
if (spec.styles !== void 0 && spec.name === void 0) throw new Error(UNSCOPED_STYLES);
|
|
58
|
+
const render = compileTemplate(spec.template);
|
|
59
|
+
const sheets = /* @__PURE__ */ new WeakMap();
|
|
60
|
+
function adopt(root, doc, css) {
|
|
61
|
+
if (typeof CSSStyleSheet.prototype.replaceSync !== "function") {
|
|
62
|
+
const tag = doc.createElement("style");
|
|
63
|
+
tag.textContent = css;
|
|
64
|
+
root.prepend(tag);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let sheet = sheets.get(doc);
|
|
68
|
+
if (!sheet) {
|
|
69
|
+
sheet = new CSSStyleSheet();
|
|
70
|
+
sheet.replaceSync(css);
|
|
71
|
+
sheets.set(doc, sheet);
|
|
72
|
+
}
|
|
73
|
+
root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];
|
|
74
|
+
}
|
|
75
|
+
return ({ doc, window: win }) => {
|
|
76
|
+
const holder = doc.createElement("template");
|
|
77
|
+
holder.innerHTML = render(valuesOf(win));
|
|
78
|
+
const built = holder.content.firstElementChild;
|
|
79
|
+
const slot = built === null ? null : built.matches(SLOT) ? built : built.querySelector(SLOT);
|
|
80
|
+
if (built === null || slot === null) throw new Error(BAD_STRUCTURE);
|
|
81
|
+
if (spec.shadow !== true) {
|
|
82
|
+
if (spec.name !== void 0) built.dataset.wmSkin = spec.name;
|
|
83
|
+
if (spec.styles !== void 0) injectStyles(doc, spec.name, spec.styles);
|
|
84
|
+
return { element: built, content: slot };
|
|
85
|
+
}
|
|
86
|
+
const element = doc.createElement("div");
|
|
87
|
+
if (spec.name !== void 0) element.dataset.wmSkin = spec.name;
|
|
88
|
+
const root = element.attachShadow({ mode: "open" });
|
|
89
|
+
const projection = doc.createElement("slot");
|
|
90
|
+
if (slot === built) root.append(projection);
|
|
91
|
+
else {
|
|
92
|
+
slot.replaceWith(projection);
|
|
93
|
+
root.append(...built.childNodes);
|
|
94
|
+
}
|
|
95
|
+
if (spec.styles !== void 0) adopt(root, doc, spec.styles);
|
|
96
|
+
const content = doc.createElement("div");
|
|
97
|
+
content.dataset.wmContent = "";
|
|
98
|
+
element.append(content);
|
|
99
|
+
return { element, content };
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function windowChrome(messages = chromeMessages) {
|
|
103
|
+
return skin({
|
|
104
|
+
name: "wmkit",
|
|
105
|
+
template: `<section><header data-wm-drag><span data-wm-title>{{title}}</span><span data-wm-controls><button type="button" data-wm-minimize aria-label="${messages.minimize}"></button><button type="button" data-wm-maximize aria-label="${messages.maximize}"></button><button type="button" data-wm-close aria-label="${messages.close}"></button></span></header><div data-wm-content></div></section>`
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
var defaultSkin = windowChrome();
|
|
109
|
+
var barebones = skin({
|
|
110
|
+
name: "barebones",
|
|
111
|
+
template: "<section><header data-wm-drag><span data-wm-title>{{title}}</span></header><div data-wm-content></div></section>"
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
exports.barebones = barebones;
|
|
115
|
+
exports.chromeMessages = chromeMessages;
|
|
116
|
+
exports.chromeMessagesRu = chromeMessagesRu;
|
|
117
|
+
exports.compileTemplate = compileTemplate;
|
|
118
|
+
exports.defaultSkin = defaultSkin;
|
|
119
|
+
exports.skin = skin;
|
|
120
|
+
exports.windowChrome = windowChrome;
|
|
121
|
+
//# sourceMappingURL=chrome.cjs.map
|
|
122
|
+
//# sourceMappingURL=chrome.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/chrome/messages.ts","../src/plugins/chrome/template.ts","../src/plugins/chrome/index.ts"],"names":[],"mappings":";;;AAMO,IAAM,cAAA,GAAiC;AAAA,EAC5C,QAAA,EAAU,UAAA;AAAA,EACV,QAAA,EAAU,UAAA;AAAA,EACV,KAAA,EAAO;AACT;AAEO,IAAM,gBAAA,GAAmC;AAAA,EAC9C,QAAA,EAAU,kDAAA;AAAA,EACV,QAAA,EAAU,8DAAA;AAAA,EACV,KAAA,EAAO;AACT;;;AChBA,IAAM,OAAA,GAAkC;AAAA,EACtC,GAAA,EAAK,OAAA;AAAA,EACL,GAAA,EAAK,MAAA;AAAA,EACL,GAAA,EAAK,MAAA;AAAA,EACL,GAAA,EAAK,QAAA;AAAA,EACL,GAAA,EAAK;AACP,CAAA;AAEA,SAAS,WAAW,KAAA,EAAuB;AACzC,EAAA,OAAO,MAAM,OAAA,CAAQ,UAAA,EAAY,CAAC,IAAA,KAAS,OAAA,CAAQ,IAAI,CAAW,CAAA;AACpE;AAEO,SAAS,gBAAgB,QAAA,EAA8D;AAC5F,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,yBAAyB,CAAA;AACtD,EAAA,OAAO,CAAC,MAAA,KACN,KAAA,CAAM,IAAI,CAAC,IAAA,EAAM,UAAW,KAAA,GAAQ,CAAA,KAAM,IAAI,IAAA,GAAO,UAAA,CAAW,OAAO,IAAI,CAAA,IAAK,EAAE,CAAE,CAAA,CAAE,KAAK,EAAE,CAAA;AACjG;;;ACAA,IAAM,IAAA,GAAO,mBAAA;AACb,IAAM,YAAA,GAAe,oBAAA;AAErB,IAAM,cAAA,GAAiB,4DAAA;AACvB,IAAM,aAAA,GACJ,qFAAA;AACF,IAAM,eAAA,GAAkB,yDAAA;AAExB,SAAS,SAAS,GAAA,EAA0C;AAC1D,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,CAAK,OAAA;AACzB,EAAA,OAAO;AAAA,IACL,IAAI,GAAA,CAAI,EAAA;AAAA,IACR,OAAO,GAAA,CAAI,KAAA;AAAA,IACX,OAAO,GAAA,CAAI,KAAA;AAAA,IACX,OAAO,GAAA,CAAI,KAAA;AAAA,IACX,SAAA,EAAW,MAAA,CAAO,GAAA,CAAI,SAAS,CAAA;AAAA,IAC/B,OAAA,EAAS,OAAO,OAAA,KAAY,QAAA,GAAW,OAAA,GAAU;AAAA,GACnD;AACF;AAEA,SAAS,YAAA,CAAa,GAAA,EAAe,IAAA,EAAc,MAAA,EAAsB;AACvE,EAAA,IAAI,IAAI,IAAA,CAAK,aAAA,CAAc,CAAA,2BAAA,EAA8B,IAAI,IAAI,CAAA,EAAG;AACpE,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,aAAA,CAAc,OAAO,CAAA;AACrC,EAAA,GAAA,CAAI,QAAQ,YAAA,GAAe,IAAA;AAC3B,EAAA,GAAA,CAAI,WAAA,GAAc,MAAA;AAClB,EAAA,GAAA,CAAI,IAAA,CAAK,OAAO,GAAG,CAAA;AACrB;AAEO,SAAS,KAAK,IAAA,EAA4B;AAC/C,EAAA,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,YAAY,CAAA,IAAK,EAAC,EAAG,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,cAAc,CAAA;AAC1F,EAAA,IAAI,IAAA,CAAK,WAAW,MAAA,IAAa,IAAA,CAAK,SAAS,MAAA,EAAW,MAAM,IAAI,KAAA,CAAM,eAAe,CAAA;AACzF,EAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,IAAA,CAAK,QAAQ,CAAA;AAC5C,EAAA,MAAM,MAAA,uBAAa,OAAA,EAAiC;AAEpD,EAAA,SAAS,KAAA,CAAM,IAAA,EAAkB,GAAA,EAAe,GAAA,EAAmB;AACjE,IAAA,IAAI,OAAO,aAAA,CAAc,SAAA,CAAU,WAAA,KAAgB,UAAA,EAAY;AAC7D,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,aAAA,CAAc,OAAO,CAAA;AACrC,MAAA,GAAA,CAAI,WAAA,GAAc,GAAA;AAClB,MAAA,IAAA,CAAK,QAAQ,GAAG,CAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,KAAA,GAAQ,IAAI,aAAA,EAAc;AAC1B,MAAA,KAAA,CAAM,YAAY,GAAG,CAAA;AACrB,MAAA,MAAA,CAAO,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,IACvB;AACA,IAAA,IAAA,CAAK,kBAAA,GAAqB,CAAC,GAAG,IAAA,CAAK,oBAAoB,KAAK,CAAA;AAAA,EAC9D;AAEA,EAAA,OAAO,CAAC,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAI,KAAiB;AAC1C,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,aAAA,CAAc,UAAU,CAAA;AAC3C,IAAA,MAAA,CAAO,SAAA,GAAY,MAAA,CAAO,QAAA,CAAS,GAAG,CAAC,CAAA;AACvC,IAAA,MAAM,KAAA,GAAQ,OAAO,OAAA,CAAQ,iBAAA;AAC7B,IAAA,MAAM,IAAA,GACJ,KAAA,KAAU,IAAA,GAAO,IAAA,GAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAI,KAAA,GAAQ,KAAA,CAAM,aAAA,CAA2B,IAAI,CAAA;AAC7F,IAAA,IAAI,UAAU,IAAA,IAAQ,IAAA,KAAS,MAAM,MAAM,IAAI,MAAM,aAAa,CAAA;AAElE,IAAA,IAAI,IAAA,CAAK,WAAW,IAAA,EAAM;AACxB,MAAA,IAAI,KAAK,IAAA,KAAS,MAAA,EAAW,KAAA,CAAM,OAAA,CAAQ,SAAS,IAAA,CAAK,IAAA;AACzD,MAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW,YAAA,CAAa,KAAK,IAAA,CAAK,IAAA,EAAgB,KAAK,MAAM,CAAA;AACjF,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,IAAA,EAAK;AAAA,IACzC;AAEA,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,aAAA,CAAc,KAAK,CAAA;AACvC,IAAA,IAAI,KAAK,IAAA,KAAS,MAAA,EAAW,OAAA,CAAQ,OAAA,CAAQ,SAAS,IAAA,CAAK,IAAA;AAC3D,IAAA,MAAM,OAAO,OAAA,CAAQ,YAAA,CAAa,EAAE,IAAA,EAAM,QAAQ,CAAA;AAClD,IAAA,MAAM,UAAA,GAAa,GAAA,CAAI,aAAA,CAAc,MAAM,CAAA;AAC3C,IAAA,IAAI,IAAA,KAAS,KAAA,EAAO,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA;AAAA,SACrC;AACH,MAAA,IAAA,CAAK,YAAY,UAAU,CAAA;AAC3B,MAAA,IAAA,CAAK,MAAA,CAAO,GAAG,KAAA,CAAM,UAAU,CAAA;AAAA,IACjC;AACA,IAAA,IAAI,KAAK,MAAA,KAAW,MAAA,QAAiB,IAAA,EAAM,GAAA,EAAK,KAAK,MAAM,CAAA;AAC3D,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,aAAA,CAAc,KAAK,CAAA;AACvC,IAAA,OAAA,CAAQ,QAAQ,SAAA,GAAY,EAAA;AAC5B,IAAA,OAAA,CAAQ,OAAO,OAAO,CAAA;AACtB,IAAA,OAAO,EAAE,SAAS,OAAA,EAAQ;AAAA,EAC5B,CAAA;AACF;AAEO,SAAS,YAAA,CAAa,WAA2B,cAAA,EAA4B;AAClF,EAAA,OAAO,IAAA,CAAK;AAAA,IACV,IAAA,EAAM,OAAA;AAAA,IACN,QAAA,EACE,+IAIsD,QAAA,CAAS,QAAQ,iEACjB,QAAA,CAAS,QAAQ,CAAA,2DAAA,EACpB,QAAA,CAAS,KAAK,CAAA,gEAAA;AAAA,GAKpE,CAAA;AACH;AAEO,IAAM,cAA0B,YAAA;AAEhC,IAAM,YAAwB,IAAA,CAAK;AAAA,EACxC,IAAA,EAAM,WAAA;AAAA,EACN,QAAA,EACE;AAIJ,CAAC","file":"chrome.cjs","sourcesContent":["export interface ChromeMessages {\n minimize: string\n maximize: string\n close: string\n}\n\nexport const chromeMessages: ChromeMessages = {\n minimize: 'Minimize',\n maximize: 'Maximize',\n close: 'Close',\n}\n\nexport const chromeMessagesRu: ChromeMessages = {\n minimize: 'Свернуть',\n maximize: 'Развернуть',\n close: 'Закрыть',\n}\n","const ESCAPES: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n}\n\nfunction escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (char) => ESCAPES[char] as string)\n}\n\nexport function compileTemplate(template: string): (values: Record<string, string>) => string {\n const parts = template.split(/\\{\\{\\s*([a-z]+)\\s*\\}\\}/i)\n return (values) =>\n parts.map((part, index) => (index % 2 === 0 ? part : escapeHtml(values[part] ?? ''))).join('')\n}\n","import type { WindowState } from '../../core/types'\nimport type { SkinMount, WindowSkin } from '../../dom/shared'\nimport { type ChromeMessages, chromeMessages } from './messages'\nimport { compileTemplate } from './template'\n\nexport type { ChromeMessages } from './messages'\nexport { chromeMessages, chromeMessagesRu } from './messages'\nexport { compileTemplate } from './template'\n\nexport interface SkinSpec {\n template: string\n styles?: string\n shadow?: boolean\n name?: string\n}\n\nconst SLOT = '[data-wm-content]'\nconst SLOT_PATTERN = /data-wm-content\\b/g\n\nconst BAD_SLOT_COUNT = 'wmkit: a skin template needs exactly one [data-wm-content]'\nconst BAD_STRUCTURE =\n 'wmkit: a skin template needs a single root element that holds its [data-wm-content]'\nconst UNSCOPED_STYLES = 'wmkit: a skin with styles needs a name to scope them to'\n\nfunction valuesOf(win: WindowState): Record<string, string> {\n const variant = win.meta.variant\n return {\n id: win.id,\n title: win.title,\n stage: win.stage,\n layer: win.layer,\n workspace: String(win.workspace),\n variant: typeof variant === 'string' ? variant : '',\n }\n}\n\nfunction injectStyles(doc: Document, name: string, styles: string): void {\n if (doc.head.querySelector(`style[data-wm-skin-styles=\"${name}\"]`)) return\n const tag = doc.createElement('style')\n tag.dataset.wmSkinStyles = name\n tag.textContent = styles\n doc.head.append(tag)\n}\n\nexport function skin(spec: SkinSpec): WindowSkin {\n if ((spec.template.match(SLOT_PATTERN) ?? []).length !== 1) throw new Error(BAD_SLOT_COUNT)\n if (spec.styles !== undefined && spec.name === undefined) throw new Error(UNSCOPED_STYLES)\n const render = compileTemplate(spec.template)\n const sheets = new WeakMap<Document, CSSStyleSheet>()\n\n function adopt(root: ShadowRoot, doc: Document, css: string): void {\n if (typeof CSSStyleSheet.prototype.replaceSync !== 'function') {\n const tag = doc.createElement('style')\n tag.textContent = css\n root.prepend(tag)\n return\n }\n let sheet = sheets.get(doc)\n if (!sheet) {\n sheet = new CSSStyleSheet()\n sheet.replaceSync(css)\n sheets.set(doc, sheet)\n }\n root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet]\n }\n\n return ({ doc, window: win }): SkinMount => {\n const holder = doc.createElement('template')\n holder.innerHTML = render(valuesOf(win))\n const built = holder.content.firstElementChild as HTMLElement | null\n const slot =\n built === null ? null : built.matches(SLOT) ? built : built.querySelector<HTMLElement>(SLOT)\n if (built === null || slot === null) throw new Error(BAD_STRUCTURE)\n\n if (spec.shadow !== true) {\n if (spec.name !== undefined) built.dataset.wmSkin = spec.name\n if (spec.styles !== undefined) injectStyles(doc, spec.name as string, spec.styles)\n return { element: built, content: slot }\n }\n\n const element = doc.createElement('div')\n if (spec.name !== undefined) element.dataset.wmSkin = spec.name\n const root = element.attachShadow({ mode: 'open' })\n const projection = doc.createElement('slot')\n if (slot === built) root.append(projection)\n else {\n slot.replaceWith(projection)\n root.append(...built.childNodes)\n }\n if (spec.styles !== undefined) adopt(root, doc, spec.styles)\n const content = doc.createElement('div')\n content.dataset.wmContent = ''\n element.append(content)\n return { element, content }\n }\n}\n\nexport function windowChrome(messages: ChromeMessages = chromeMessages): WindowSkin {\n return skin({\n name: 'wmkit',\n template:\n '<section>' +\n '<header data-wm-drag>' +\n '<span data-wm-title>{{title}}</span>' +\n '<span data-wm-controls>' +\n `<button type=\"button\" data-wm-minimize aria-label=\"${messages.minimize}\"></button>` +\n `<button type=\"button\" data-wm-maximize aria-label=\"${messages.maximize}\"></button>` +\n `<button type=\"button\" data-wm-close aria-label=\"${messages.close}\"></button>` +\n '</span>' +\n '</header>' +\n '<div data-wm-content></div>' +\n '</section>',\n })\n}\n\nexport const defaultSkin: WindowSkin = windowChrome()\n\nexport const barebones: WindowSkin = skin({\n name: 'barebones',\n template:\n '<section>' +\n '<header data-wm-drag><span data-wm-title>{{title}}</span></header>' +\n '<div data-wm-content></div>' +\n '</section>',\n})\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { l as WindowSkin } from './shared-DdGFz3oy.cjs';
|
|
2
|
+
import './types-jG2lHGcA.cjs';
|
|
3
|
+
|
|
4
|
+
interface ChromeMessages {
|
|
5
|
+
minimize: string;
|
|
6
|
+
maximize: string;
|
|
7
|
+
close: string;
|
|
8
|
+
}
|
|
9
|
+
declare const chromeMessages: ChromeMessages;
|
|
10
|
+
declare const chromeMessagesRu: ChromeMessages;
|
|
11
|
+
|
|
12
|
+
declare function compileTemplate(template: string): (values: Record<string, string>) => string;
|
|
13
|
+
|
|
14
|
+
interface SkinSpec {
|
|
15
|
+
template: string;
|
|
16
|
+
styles?: string;
|
|
17
|
+
shadow?: boolean;
|
|
18
|
+
name?: string;
|
|
19
|
+
}
|
|
20
|
+
declare function skin(spec: SkinSpec): WindowSkin;
|
|
21
|
+
declare function windowChrome(messages?: ChromeMessages): WindowSkin;
|
|
22
|
+
declare const defaultSkin: WindowSkin;
|
|
23
|
+
declare const barebones: WindowSkin;
|
|
24
|
+
|
|
25
|
+
export { type ChromeMessages, type SkinSpec, barebones, chromeMessages, chromeMessagesRu, compileTemplate, defaultSkin, skin, windowChrome };
|
package/dist/chrome.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { l as WindowSkin } from './shared-BoHXlPCu.js';
|
|
2
|
+
import './types-jG2lHGcA.js';
|
|
3
|
+
|
|
4
|
+
interface ChromeMessages {
|
|
5
|
+
minimize: string;
|
|
6
|
+
maximize: string;
|
|
7
|
+
close: string;
|
|
8
|
+
}
|
|
9
|
+
declare const chromeMessages: ChromeMessages;
|
|
10
|
+
declare const chromeMessagesRu: ChromeMessages;
|
|
11
|
+
|
|
12
|
+
declare function compileTemplate(template: string): (values: Record<string, string>) => string;
|
|
13
|
+
|
|
14
|
+
interface SkinSpec {
|
|
15
|
+
template: string;
|
|
16
|
+
styles?: string;
|
|
17
|
+
shadow?: boolean;
|
|
18
|
+
name?: string;
|
|
19
|
+
}
|
|
20
|
+
declare function skin(spec: SkinSpec): WindowSkin;
|
|
21
|
+
declare function windowChrome(messages?: ChromeMessages): WindowSkin;
|
|
22
|
+
declare const defaultSkin: WindowSkin;
|
|
23
|
+
declare const barebones: WindowSkin;
|
|
24
|
+
|
|
25
|
+
export { type ChromeMessages, type SkinSpec, barebones, chromeMessages, chromeMessagesRu, compileTemplate, defaultSkin, skin, windowChrome };
|
package/dist/chrome.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// src/plugins/chrome/messages.ts
|
|
2
|
+
var chromeMessages = {
|
|
3
|
+
minimize: "Minimize",
|
|
4
|
+
maximize: "Maximize",
|
|
5
|
+
close: "Close"
|
|
6
|
+
};
|
|
7
|
+
var chromeMessagesRu = {
|
|
8
|
+
minimize: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
9
|
+
maximize: "\u0420\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
10
|
+
close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/plugins/chrome/template.ts
|
|
14
|
+
var ESCAPES = {
|
|
15
|
+
"&": "&",
|
|
16
|
+
"<": "<",
|
|
17
|
+
">": ">",
|
|
18
|
+
'"': """,
|
|
19
|
+
"'": "'"
|
|
20
|
+
};
|
|
21
|
+
function escapeHtml(value) {
|
|
22
|
+
return value.replace(/[&<>"']/g, (char) => ESCAPES[char]);
|
|
23
|
+
}
|
|
24
|
+
function compileTemplate(template) {
|
|
25
|
+
const parts = template.split(/\{\{\s*([a-z]+)\s*\}\}/i);
|
|
26
|
+
return (values) => parts.map((part, index) => index % 2 === 0 ? part : escapeHtml(values[part] ?? "")).join("");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/plugins/chrome/index.ts
|
|
30
|
+
var SLOT = "[data-wm-content]";
|
|
31
|
+
var SLOT_PATTERN = /data-wm-content\b/g;
|
|
32
|
+
var BAD_SLOT_COUNT = "wmkit: a skin template needs exactly one [data-wm-content]";
|
|
33
|
+
var BAD_STRUCTURE = "wmkit: a skin template needs a single root element that holds its [data-wm-content]";
|
|
34
|
+
var UNSCOPED_STYLES = "wmkit: a skin with styles needs a name to scope them to";
|
|
35
|
+
function valuesOf(win) {
|
|
36
|
+
const variant = win.meta.variant;
|
|
37
|
+
return {
|
|
38
|
+
id: win.id,
|
|
39
|
+
title: win.title,
|
|
40
|
+
stage: win.stage,
|
|
41
|
+
layer: win.layer,
|
|
42
|
+
workspace: String(win.workspace),
|
|
43
|
+
variant: typeof variant === "string" ? variant : ""
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function injectStyles(doc, name, styles) {
|
|
47
|
+
if (doc.head.querySelector(`style[data-wm-skin-styles="${name}"]`)) return;
|
|
48
|
+
const tag = doc.createElement("style");
|
|
49
|
+
tag.dataset.wmSkinStyles = name;
|
|
50
|
+
tag.textContent = styles;
|
|
51
|
+
doc.head.append(tag);
|
|
52
|
+
}
|
|
53
|
+
function skin(spec) {
|
|
54
|
+
if ((spec.template.match(SLOT_PATTERN) ?? []).length !== 1) throw new Error(BAD_SLOT_COUNT);
|
|
55
|
+
if (spec.styles !== void 0 && spec.name === void 0) throw new Error(UNSCOPED_STYLES);
|
|
56
|
+
const render = compileTemplate(spec.template);
|
|
57
|
+
const sheets = /* @__PURE__ */ new WeakMap();
|
|
58
|
+
function adopt(root, doc, css) {
|
|
59
|
+
if (typeof CSSStyleSheet.prototype.replaceSync !== "function") {
|
|
60
|
+
const tag = doc.createElement("style");
|
|
61
|
+
tag.textContent = css;
|
|
62
|
+
root.prepend(tag);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
let sheet = sheets.get(doc);
|
|
66
|
+
if (!sheet) {
|
|
67
|
+
sheet = new CSSStyleSheet();
|
|
68
|
+
sheet.replaceSync(css);
|
|
69
|
+
sheets.set(doc, sheet);
|
|
70
|
+
}
|
|
71
|
+
root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];
|
|
72
|
+
}
|
|
73
|
+
return ({ doc, window: win }) => {
|
|
74
|
+
const holder = doc.createElement("template");
|
|
75
|
+
holder.innerHTML = render(valuesOf(win));
|
|
76
|
+
const built = holder.content.firstElementChild;
|
|
77
|
+
const slot = built === null ? null : built.matches(SLOT) ? built : built.querySelector(SLOT);
|
|
78
|
+
if (built === null || slot === null) throw new Error(BAD_STRUCTURE);
|
|
79
|
+
if (spec.shadow !== true) {
|
|
80
|
+
if (spec.name !== void 0) built.dataset.wmSkin = spec.name;
|
|
81
|
+
if (spec.styles !== void 0) injectStyles(doc, spec.name, spec.styles);
|
|
82
|
+
return { element: built, content: slot };
|
|
83
|
+
}
|
|
84
|
+
const element = doc.createElement("div");
|
|
85
|
+
if (spec.name !== void 0) element.dataset.wmSkin = spec.name;
|
|
86
|
+
const root = element.attachShadow({ mode: "open" });
|
|
87
|
+
const projection = doc.createElement("slot");
|
|
88
|
+
if (slot === built) root.append(projection);
|
|
89
|
+
else {
|
|
90
|
+
slot.replaceWith(projection);
|
|
91
|
+
root.append(...built.childNodes);
|
|
92
|
+
}
|
|
93
|
+
if (spec.styles !== void 0) adopt(root, doc, spec.styles);
|
|
94
|
+
const content = doc.createElement("div");
|
|
95
|
+
content.dataset.wmContent = "";
|
|
96
|
+
element.append(content);
|
|
97
|
+
return { element, content };
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function windowChrome(messages = chromeMessages) {
|
|
101
|
+
return skin({
|
|
102
|
+
name: "wmkit",
|
|
103
|
+
template: `<section><header data-wm-drag><span data-wm-title>{{title}}</span><span data-wm-controls><button type="button" data-wm-minimize aria-label="${messages.minimize}"></button><button type="button" data-wm-maximize aria-label="${messages.maximize}"></button><button type="button" data-wm-close aria-label="${messages.close}"></button></span></header><div data-wm-content></div></section>`
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
var defaultSkin = windowChrome();
|
|
107
|
+
var barebones = skin({
|
|
108
|
+
name: "barebones",
|
|
109
|
+
template: "<section><header data-wm-drag><span data-wm-title>{{title}}</span></header><div data-wm-content></div></section>"
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export { barebones, chromeMessages, chromeMessagesRu, compileTemplate, defaultSkin, skin, windowChrome };
|
|
113
|
+
//# sourceMappingURL=chrome.js.map
|
|
114
|
+
//# sourceMappingURL=chrome.js.map
|