feat: Phase 1 — extract the client (web SPA + desktop) to dtoro/oikos-web
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled

Problem: the hexagonal refactor churns the backend tree for nine more
phases; the UI delivery stack (web/ SPA, cmd/desktop Wails wrapper,
compose/web image) must move to its own repo first so doc/layout
rewrites land once on a backend-only tree.

Change:
- New repo git.hubris.network/dtoro/oikos-web (v0.33.0): web/, desktop/
  (updateURL repointed to oikos-web releases), compose/, own CI (web +
  desktop jobs), own deploy script (CI-green gate, TOCTOU guard,
  version-tagged images, prune-to-3), own webhook receiver on :9798 +
  launchd unit, own compose project publishing the same 8091:80.
- Cutover executed on mac-mini in order: oikos stack's web service
  stopped+removed, oikos-web project brought up on 8091; outer Caddy
  untouched (targets the published port) — serving + Authentik flow +
  /wails 404 quirk verified post-cutover.
- Stripped from oikos: web/, cmd/desktop/, compose/web/, desktop CI
  workflow, ci.yml web job, Makefile ui/desktop/desktop-package/install
  targets, the compose web service, oikos-web from deploy.sh's fallback
  prune list; wails + go-keyring dropped from go.mod, vendor synced.
- README / CONTRIBUTING / AGENTS.md / .agents dev+operations docs now
  point at the new repo; mbse + mascot design docs carry a path note.

Risk: production SPA serving depends on the new pipeline now; rollback
is versioned-image re-up of the old web service from a pre-split
checkout (port 8091). Desktop builds installed before the split still
check dtoro/oikos releases — one manual reinstall, noted in the
oikos-web release notes.

Verification: go vet, make test (race), make generate-check, golangci
(no new findings; baseline down 400→365); post-cutover curls —
localhost:8091 200, /wails/runtime.js 404, outer Caddy 302 Authentik.
This commit is contained in:
2026-08-15 22:27:52 +02:00
parent e074f04bdf
commit d4d99a7473
18854 changed files with 2615729 additions and 173735 deletions

21
web/node_modules/@surdeddd/wmkit/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Maksim Kravcov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

370
web/node_modules/@surdeddd/wmkit/README.md generated vendored Normal file
View File

@@ -0,0 +1,370 @@
# wmkit
**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.
[Русская версия](./README.ru.md) · [Live demo](https://wmkit.vercel.app) · [Mirror (Pages)](https://surdeddd.github.io/wmkit/) · [GitHub](https://github.com/Surdeddd/wmkit)
[![CI](https://github.com/Surdeddd/wmkit/actions/workflows/ci.yml/badge.svg)](https://github.com/Surdeddd/wmkit/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/@surdeddd/wmkit)](https://www.npmjs.com/package/@surdeddd/wmkit)
[![license](https://img.shields.io/badge/license-MIT-2dd4a8)](./LICENSE)
[![wmkit — live demo desktop](https://raw.githubusercontent.com/Surdeddd/wmkit/main/.github/assets/hero.png)](https://surdeddd.github.io/wmkit/)
<p align="center"><em>Every window above is real — <a href="https://surdeddd.github.io/wmkit/">open the demo</a> and drag one.</em></p>
- 🪟 **Full window lifecycle** — open, close, focus, minimize, maximize, restore, drag, 8-direction resize
- 🧠 **Headless core** — a serializable state machine plus a DOM controller; bring your own markup or use the glass theme
- ⚛️ **Official adapters**`@surdeddd/wmkit/react`, `/vue`, `/svelte`, `/solid`, `/angular`, all thin sugar over one core
-**Snap zones** — halves, quarters and drag-to-top maximize with a live preview
- 🧲 **Magnetism** — window edges align to neighbours and the viewport while dragging
- ↩️ **Undo/redo** — every mutation is one step; a whole drag collapses into a single history entry
- 🗂️ **Named layouts & arrange** — save/load desktop snapshots, `cascade`/`tile` in one call
- ⌨️ **Accessible** — keyboard move/resize, F6 window cycling, focus-trapped modals, `aria-live` announcements
-**Fast**`transform`-only positioning, rAF-batched pointer input, structural sharing; 50 windows drag at 60fps
- 💾 **Persistence** — one call to serialize the desktop, one call to restore it
- 🎨 **Three themes** — dark glass, light glass and Win98 retro, or bring your own CSS
- 🖼️ **Popout** *(experimental)* — send a window into Document Picture-in-Picture
- 📦 **Zero dependencies**, strict TypeScript, ESM + CJS, ~9.3 kB brotli core
## Install
```bash
npm install @surdeddd/wmkit
# or
pnpm add @surdeddd/wmkit
```
## Quick start (vanilla)
```js
import { createWindowManager, attachDesktop } from '@surdeddd/wmkit'
import '@surdeddd/wmkit/themes/glass.css'
const wm = createWindowManager()
const desktop = attachDesktop(wm, document.querySelector('#desktop'))
const win = wm.open({ title: 'Hello', width: 420, height: 280 })
const el = document.createElement('section')
el.innerHTML = `
<header data-wm-drag>
<span data-wm-title>Hello</span>
<span data-wm-controls>
<button data-wm-minimize aria-label="Minimize"></button>
<button data-wm-maximize aria-label="Maximize"></button>
<button data-wm-close aria-label="Close"></button>
</span>
</header>
<div data-wm-content>Anything you want.</div>
`
document.querySelector('#desktop').append(el)
desktop.attachWindow(win.id, el, { removeOnClose: true })
```
The desktop element becomes the coordinate space. Your markup stays yours — wmkit wires behavior onto `data-wm-*` attributes:
| Attribute | Meaning |
| --- | --- |
| `data-wm-drag` | drag handle (usually the titlebar); double-click toggles maximize |
| `data-wm-title` | window title node, linked via `aria-labelledby` |
| `data-wm-close` / `data-wm-minimize` / `data-wm-maximize` | control buttons, wired by delegation |
| `data-wm-content` | scrollable content area (styled by themes) |
`removeOnClose` detaches the controller and removes the element when the window closes. Touch devices get larger resize hit areas and snap thresholds automatically (`pointer: coarse`); tune via `attachDesktop(wm, el, { hitAreas: { edge, corner } })`.
The controller adds resize handles (`[data-wm-resize]`), a snap preview (`[data-wm-snap-preview]`) and a visually hidden live region for screen readers.
## React
```tsx
import { useWindowManager, useDesktop, useWmState, useWmWindowRef } from '@surdeddd/wmkit/react'
import '@surdeddd/wmkit/themes/glass.css'
function Desktop() {
const wm = useWindowManager()
const { ref, binder } = useDesktop(wm)
const state = useWmState(wm)
return (
<div ref={ref} style={{ position: 'relative', height: '100vh' }}>
<button onClick={() => wm.open({ title: 'New window' })}>open</button>
{state.order.map((id) => {
const win = state.windows[id]
return win ? <Win key={id} binder={binder} win={win} /> : null
})}
</div>
)
}
function Win({ binder, win }) {
const ref = useWmWindowRef(binder, win.id)
return (
<section ref={ref}>
<header data-wm-drag>
<span data-wm-title>{win.title}</span>
<span data-wm-controls>
<button data-wm-minimize aria-label="Minimize" />
<button data-wm-maximize aria-label="Maximize" />
<button data-wm-close aria-label="Close" />
</span>
</header>
<div data-wm-content>Your React tree lives here no portals, no innerHTML.</div>
</section>
)
}
```
`useWmState` subscribes through `useSyncExternalStore`; unchanged windows keep referential identity, so memoized children skip re-renders.
## Vue
```vue
<script setup>
import { ref } from 'vue'
import { useWindowManager, useDesktop, useWmWindowEl, useWmState } from '@surdeddd/wmkit/vue'
import '@surdeddd/wmkit/themes/glass.css'
const wm = useWindowManager()
const desktopEl = ref(null)
const binder = useDesktop(wm, desktopEl)
const state = useWmState(wm)
const noteEl = ref(null)
useWmWindowEl(binder, 'note', noteEl)
wm.open({ id: 'note', title: 'Note' })
</script>
<template>
<div ref="desktopEl" style="position: relative; height: 100vh">
<section ref="noteEl">
<header data-wm-drag><span data-wm-title>{{ state.windows.note?.title }}</span></header>
<div data-wm-content>composables all the way down</div>
</section>
</div>
</template>
```
## Svelte
```svelte
<script>
import { createManager, createDesktop, wmWindowStore } from '@surdeddd/wmkit/svelte'
import '@surdeddd/wmkit/themes/glass.css'
const wm = createManager()
const dk = createDesktop(wm)
wm.open({ id: 'main', title: 'Hello' })
const main = wmWindowStore(wm, 'main')
</script>
<div use:dk.desktop style="position: relative; height: 100vh">
<section use:dk.window={{ id: 'main' }}>
<header data-wm-drag><span data-wm-title>{$main?.title}</span></header>
<div data-wm-content>stores and actions, no wrapper components</div>
</section>
</div>
```
## Solid
```tsx
import { For } from 'solid-js'
import { useWindowManager, createDesktop, useWmState } from '@surdeddd/wmkit/solid'
function Desktop() {
const wm = useWindowManager()
const dk = createDesktop(wm)
const state = useWmState(wm)
wm.open({ title: 'Hello' })
return (
<div ref={dk.desktop} style={{ position: 'relative', height: '100vh' }}>
<For each={state().order}>
{(id) => (
<section ref={dk.window(id)}>
<header data-wm-drag>
<span data-wm-title>{state().windows[id]?.title}</span>
</header>
<div data-wm-content>fine-grained, obviously</div>
</section>
)}
</For>
</div>
)
}
```
## Angular
```ts
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core'
import { useWindowManager, createDesktop, useWmState } from '@surdeddd/wmkit/angular'
@Component({
selector: 'app-desktop',
standalone: true,
template: `
<div #desktop style="position: relative; height: 100vh">
<section #hello>
<header data-wm-drag><span data-wm-title>Hello</span></header>
<div data-wm-content>signals inside</div>
</section>
</div>
`,
})
export class DesktopComponent implements AfterViewInit {
wm = useWindowManager()
dk = createDesktop(this.wm)
state = useWmState(this.wm)
@ViewChild('desktop') desktopRef!: ElementRef<HTMLElement>
@ViewChild('hello') helloRef!: ElementRef<HTMLElement>
ngAfterViewInit(): void {
this.wm.open({ id: 'hello', title: 'Hello' })
this.dk.desktop(this.desktopRef.nativeElement)
this.dk.window('hello')(this.helloRef.nativeElement)
}
}
```
`useWmState` returns a read-only `Signal<ManagerState>` and `useWmWindow(wm, id)` a computed per-window signal, so templates track updates fine-grained. Hooks called in an injection context clean up through `DestroyRef` automatically; outside one they simply skip auto-cleanup.
## Snap zones in action
[![Snap zones — window tiled to the left half](https://raw.githubusercontent.com/Surdeddd/wmkit/main/.github/assets/snap.png)](https://surdeddd.github.io/wmkit/)
Throw a window against an edge or corner — a live preview shows the target zone, releasing tiles it. Halves, quarters, and drag-to-top maximize.
## Core API
### `createWindowManager(options?)`
Pure state machine — no DOM access, safe to create during SSR.
```ts
interface ManagerOptions {
viewport?: { width: number; height: number }
keepInViewport?: boolean // clamp windows so the titlebar stays reachable (default true)
minVisible?: number // minimum visible strip in px (default 48)
defaultSize?: { width: number; height: number }
cascadeOffset?: number // auto-position step for new windows (default 32)
cascadeOrigin?: { x: number; y: number }
idPrefix?: string
historyLimit?: number // undo/redo depth (default 50, 0 disables history)
}
```
Manager methods:
| Method | Notes |
| --- | --- |
| `open(init?)``WindowState` | throws on duplicate `id`; cascades position when `x`/`y` omitted |
| `close(id)` / `closeAll()` | focus moves to the next eligible window |
| `focus(id)` / `blur()` / `cycleFocus(dir?)` | focusing a minimized window restores it; modals block focus below them |
| `minimize(id)` / `maximize(id)` / `restore(id)` / `toggleMaximize(id)` | restore returns to the pre-minimize stage, including maximized/snapped |
| `snap(id, zone)` | `'left' \| 'right' \| 'top' \| 'bottom' \| 'top-left' \| …` |
| `move(id, x, y)` / `moveBy(id, dx, dy)` / `resize(id, patch)` | resizing a snapped window unsnaps it |
| `restoreTo(id, bounds)` | used for drag-off-snap; stage → `normal` at explicit bounds |
| `update(id, patch)` | title, layer, min/max size, per-window flags, `meta` |
| `setViewport(size)` | re-derives maximized/snapped bounds, clamps the rest |
| `serialize()` / `hydrate(data)` | JSON-safe snapshot of the whole desktop |
| `undo()` / `redo()` / `canUndo()` / `canRedo()` / `clearHistory()` | every mutation is one step; a whole drag or resize collapses into a single entry |
| `saveLayout(name)` / `loadLayout(name)` / `deleteLayout(name)` / `layoutNames()` | named desktop snapshots; `getLayout`/`setLayout` for external storage |
| `arrange('cascade' \| 'tile')` | cascade staggers restored sizes, tile fills the viewport in a grid |
| `minimizeAll()` / `restoreAll()` | bulk stage switches in one history step |
| `subscribe(fn)` / `on(event, fn)` | granular events: `open, close, focus, move, resize, stage, update, order, modalblocked` |
| `batch(fn)` | coalesce many operations into one `change` notification |
Windows carry `layer: 'normal' | 'floating' | 'modal'` — floating stays on top, modals trap focus and block interaction below (blocked attempts emit `modalblocked` and flash the modal).
### `attachDesktop(wm, element, options?)`
DOM controller: pointer drag with capture (touch/pen included), 8-direction resize, snap detection with preview, keyboard handling, ARIA wiring, FLIP-to-taskbar animation.
```ts
interface DesktopOptions {
snap?: boolean | { threshold?: number; cornerSize?: number; preview?: boolean; topEdge?: 'maximize' | 'top' | 'none' }
keyboard?: boolean | { moveStep?: number; cycle?: boolean }
announce?: boolean | Partial<AnnouncerMessages> // localize screen-reader strings here
autoViewport?: boolean // ResizeObserver → wm.setViewport (default true)
magnetism?: boolean | { threshold?: number } // edge-align to neighbours + viewport while dragging (default on, 8 px / 12 px coarse)
hitAreas?: { edge?: number; corner?: number } // resize handle thickness (auto-doubles on touch)
minimizeTarget?: (win: WindowState) => Element | null // FLIP ghost target on minimize
onTitlebarContextMenu?: (win: WindowState, event: MouseEvent) => void // right-click / long-press hook for your own menu
}
```
Keyboard defaults: arrows move the focused window (16 px), `Alt` for 1 px steps, `Shift+arrows` resize, `F6` / `Shift+F6` cycle windows, `Escape` cancels an in-flight drag or resize.
### `persist(wm, options?)` — `@surdeddd/wmkit/persist`
```js
import { persist } from '@surdeddd/wmkit/persist'
const store = persist(wm, { key: 'my-desktop' }) // auto-restores, then debounce-saves on change
store.clear()
```
Storage defaults to `localStorage` (probed safely — SSR and private-mode friendly) and accepts any `getItem/setItem/removeItem` implementation.
### `popout(wm, id, contentEl, options?)` — `@surdeddd/wmkit/popout` *(experimental)*
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()`.
## Theming
`@surdeddd/wmkit/themes/glass.css` styles the `data-wm-*` attributes and exposes CSS variables:
```css
[data-wm-desktop] {
--wm-radius: 14px;
--wm-bg: rgba(22, 24, 34, 0.55);
--wm-accent: #7c6cff;
/* --wm-border, --wm-shadow, --wm-titlebar-bg, --wm-text, --wm-blur, --wm-transition … */
}
```
Two more ready-made themes ship alongside: `themes/light.css` (light glass) and `themes/retro.css` (pixel-perfect Win98 nostalgia). All three style the same `data-wm-*` attributes, so switching is a one-line import swap.
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.
## SSR
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.
## Comparison
| | wmkit | WinBox | jsPanel4 | Dockview | Zag floating-panel |
| --- | --- | --- | --- | --- | --- |
| Maintained | ✓ 2026 | ✗ since 2023 | ✗ since 2022 | ✓ | ✓ |
| Headless core | ✓ | ✗ | ✗ | ~ own UI | ✓ |
| Official adapters | React·Vue·Svelte·Solid·Angular | community | ✗ | React·Vue·Angular | via Ark UI |
| Multi-window (z-order, taskbar, modals) | ✓ | partial | partial | dock groups | ✗ single panel |
| Snap zones + preview | ✓ | ✗ | ✗ | — | ✗ |
| Keyboard + screen reader | ✓ | ✗ | ✗ | partial | partial |
| Persistence built in | ✓ | ✗ | ✗ | ✓ | ✗ |
| Document PiP popout | ✓ | ✗ | ✗ | window.open | ✗ |
| TypeScript | strict | @types | ✗ | ✓ | ✓ |
*(checked July 2026: commit history, npm downloads, open feature requests)*
## Quality
- 172 unit tests, **100%** line/branch/function/statement coverage on the core state machine and persistence
- 178+ Playwright scenarios on Chromium, WebKit and mobile emulation: drag, 8-way resize, snap, magnetism, undo after drag, keyboard, touch, persistence across reloads, 50-window stress, modal traps, axe accessibility scans, visual regression screenshots
- performance benchmarks run in CI on every push (`vitest bench`): 1 000 windows open in ~150 ms, a move among 50 windows costs ~1.2 µs, a full 100-step undo/redo sweep ~52 µs
- `publint` + `@arethetypeswrong/cli` validate the published package, `size-limit` guards bundle budgets
## Development
```bash
pnpm install
pnpm dev # landing + playground on Vite
pnpm test # unit tests
pnpm test:e2e # Playwright matrix
pnpm verify # the full gate: lint, types, coverage, build, size, publint, e2e
```
## License
[MIT](./LICENSE) © Maksim Kravcov

139
web/node_modules/@surdeddd/wmkit/README.ru.md generated vendored Normal file
View File

@@ -0,0 +1,139 @@
# wmkit
**Headless оконный менеджер для веба.** Перетаскиваемые окна с ресайзом, снэпом, таскбаром, клавиатурной доступностью и персистом состояния — для vanilla JS и всех основных фреймворков.
[English version](./README.md) · [Живое демо](https://wmkit.vercel.app) · [Зеркало (Pages)](https://surdeddd.github.io/wmkit/) · [GitHub](https://github.com/Surdeddd/wmkit)
[![wmkit — живой демо-десктоп](https://raw.githubusercontent.com/Surdeddd/wmkit/main/.github/assets/hero.png)](https://surdeddd.github.io/wmkit/)
<p align="center"><em>Все окна выше настоящие — <a href="https://surdeddd.github.io/wmkit/">откройте демо</a> и потаскайте.</em></p>
- 🪟 **Полный жизненный цикл окна** — открытие, закрытие, фокус, сворачивание, разворачивание, восстановление, drag, ресайз в 8 направлениях
- 🧠 **Headless-ядро** — сериализуемая стейт-машина плюс DOM-контроллер; своя разметка или готовая стеклянная тема
- ⚛️ **Родные адаптеры**`@surdeddd/wmkit/react`, `/vue`, `/svelte`, `/solid`, `/angular`, тонкий сахар над одним ядром
-**Snap-зоны** — половины, четверти и максимизация от верхнего края с живым превью
- 🧲 **Магнетизм** — края окна прилипают к соседям и вьюпорту при перетаскивании
- ↩️ **Undo/redo** — каждая мутация = один шаг; целый drag схлопывается в одну запись истории
- 🗂️ **Именованные layout'ы и arrange** — снапшоты рабочего стола, `cascade`/`tile` одним вызовом
- ⌨️ **Доступность** — move/resize с клавиатуры, цикл окон по F6, focus-trap в модалках, `aria-live`-анонсы
-**Производительность** — позиционирование только через `transform`, rAF-батчинг ввода, structural sharing; 50 окон таскаются на 60fps
- 💾 **Персист** — один вызов сериализует рабочий стол, один — восстанавливает
- 🎨 **Три темы** — тёмное стекло, светлое стекло и Win98-ретро, либо полностью свой CSS
- 🖼️ **Popout** *(experimental)* — вынос окна в Document Picture-in-Picture
- 📦 **Ноль зависимостей**, строгий TypeScript, ESM + CJS, ~9.3 kB brotli
## Установка
```bash
npm install @surdeddd/wmkit
# или
pnpm add @surdeddd/wmkit
```
## Быстрый старт (vanilla)
```js
import { createWindowManager, attachDesktop } from '@surdeddd/wmkit'
import '@surdeddd/wmkit/themes/glass.css'
const wm = createWindowManager()
const desktop = attachDesktop(wm, document.querySelector('#desktop'))
const win = wm.open({ title: 'Привет', width: 420, height: 280 })
const el = document.createElement('section')
el.innerHTML = `
<header data-wm-drag>
<span data-wm-title>Привет</span>
<span data-wm-controls>
<button data-wm-minimize aria-label="Свернуть"></button>
<button data-wm-maximize aria-label="Развернуть"></button>
<button data-wm-close aria-label="Закрыть"></button>
</span>
</header>
<div data-wm-content>Что угодно.</div>
`
document.querySelector('#desktop').append(el)
desktop.attachWindow(win.id, el, { removeOnClose: true })
```
Элемент рабочего стола становится системой координат. Разметка остаётся вашей — wmkit вешает поведение на `data-wm-*` атрибуты:
| Атрибут | Смысл |
| --- | --- |
| `data-wm-drag` | ручка перетаскивания (обычно тайтлбар); двойной клик — toggle maximize |
| `data-wm-title` | узел заголовка, связывается через `aria-labelledby` |
| `data-wm-close` / `data-wm-minimize` / `data-wm-maximize` | кнопки управления, работают через делегирование |
| `data-wm-content` | скроллируемая область контента |
`removeOnClose` сам отвязывает контроллер и удаляет элемент при закрытии окна. На тач-устройствах хит-зоны ресайза и порог снэпа автоматически крупнее (`pointer: coarse`); настраиваются через `attachDesktop(wm, el, { hitAreas: { edge, corner } })`.
Контроллер добавляет ресайз-хендлы (`[data-wm-resize]`), превью снэпа (`[data-wm-snap-preview]`) и скрытый live-регион для скринридеров.
## Адаптеры
Примеры для React, Vue, Svelte, Solid и Angular — в [английском README](./README.md#react) и на [лендинге](https://surdeddd.github.io/wmkit/) (табы «Фреймворки»). Принцип один: контент окна живёт в дереве вашего фреймворка, никакого innerHTML.
## API ядра — кратко
```ts
const wm = createWindowManager({ keepInViewport: true, defaultSize: { width: 480, height: 320 } })
wm.open({ id: 'docs', title: 'Документы', layer: 'floating' })
wm.snap('docs', 'left') // 'right' | 'top-left' | 'bottom-right' | …
wm.minimize('docs') // restore вернёт предыдущий stage, включая maximized/snapped
wm.update('docs', { title: 'Новый заголовок', meta: { pinned: true } })
const json = wm.serialize() // JSON-безопасный снапшот
wm.hydrate(json)
wm.on('stage', ({ window, previous }) => console.log(previous, '→', window.stage))
wm.batch(() => { /* много операций — одно уведомление */ })
wm.undo(); wm.redo() // история изменений, drag = одна запись (historyLimit, default 50)
wm.saveLayout('работа'); wm.loadLayout('работа') // именованные снапшоты рабочего стола
wm.arrange('tile') // или 'cascade'; плюс minimizeAll() / restoreAll()
```
Слои: `normal` < `floating` (always-on-top) < `modal`. Модалка блокирует фокус нижних окон (попытка — событие `modalblocked` и flash-анимация), Tab заперт внутри.
Клавиатура по умолчанию: стрелки двигают сфокусированное окно (16 px), `Alt` — шаг 1 px, `Shift+стрелки` — ресайз, `F6`/`Shift+F6` — цикл по окнам, `Escape` отменяет активный drag/resize.
Магнетизм включён из коробки (порог 8 px, на тач-устройствах 12 px): `attachDesktop(wm, el, { magnetism: { threshold: 16 } })` или `magnetism: false`. Свой контекст-меню тайтлбара — через `onTitlebarContextMenu(win, event)` (правый клик и long-press на таче).
### Персист
```js
import { persist } from '@surdeddd/wmkit/persist'
persist(wm, { key: 'my-desktop' }) // авто-восстановление + debounce-сохранение
```
### Popout (experimental)
```js
import { popout, isPopoutSupported } from '@surdeddd/wmkit/popout'
if (isPopoutSupported()) await popout(wm, 'docs', contentElement)
```
Окно уезжает в настоящее always-on-top окно ОС (Document Picture-in-Picture) с тем же JS-контекстом и состоянием.
## Темизация
Подключите `@surdeddd/wmkit/themes/glass.css` и переопределяйте CSS-переменные (`--wm-radius`, `--wm-bg`, `--wm-accent`, …) — или не подключайте ничего и стилизуйте `data-wm-stage`, `data-wm-focused`, `data-wm-dragging`, `[hidden]` сами.
Ещё две готовые темы: `themes/light.css` (светлое стекло) и `themes/retro.css` (Win98-ностальгия). Все три стилизуют одни и те же `data-wm-*` атрибуты — переключение = замена одного импорта.
## SSR
Ядро не трогает `window`/`document`: менеджер можно создавать и гидрейтить на сервере, `attachDesktop` вызывается после маунта. `persist` тихо выключается без доступного storage.
## Качество
- 172 юнит-теста, **100%** покрытие стейт-машины и persist по строкам/веткам/функциям
- 178+ Playwright-сценариев на Chromium, WebKit и мобильной эмуляции: drag, ресайз во все стороны, снэп, магнетизм, undo после drag, клавиатура, touch, персист через перезагрузку, стресс на 50 окон, модальные ловушки, axe-аудиты доступности, визуальная регрессия по скриншотам
- перф-бенчмарки в CI на каждый push (`vitest bench`): 1 000 окон открываются за ~150 мс, move среди 50 окон ~1.2 мкс, полный undo/redo-проход на 100 шагов ~52 мкс
- `publint` + `@arethetypeswrong/cli` проверяют валидность пакета, `size-limit` следит за бюджетами
## Лицензия
[MIT](./LICENSE) © Максим Кравцов

52
web/node_modules/@surdeddd/wmkit/dist/angular.cjs generated vendored Normal file
View File

@@ -0,0 +1,52 @@
'use strict';
var chunkB35DANTX_cjs = require('./chunk-B35DANTX.cjs');
var core = require('@angular/core');
function onDestroy(dispose) {
let destroyRef = null;
try {
destroyRef = core.inject(core.DestroyRef);
} catch {
destroyRef = null;
}
destroyRef?.onDestroy(dispose);
}
function useWindowManager(options) {
const wm = chunkB35DANTX_cjs.createWindowManager(options);
onDestroy(() => wm.destroy());
return wm;
}
function useWmState(wm) {
const state = core.signal(wm.getState());
const stop = wm.subscribe((next) => state.set(next));
onDestroy(stop);
return state.asReadonly();
}
function useWmWindow(wm, id) {
const state = useWmState(wm);
return core.computed(() => state().windows[id]);
}
function createDesktop(wm, options) {
const binder = chunkB35DANTX_cjs.createDesktopBinder(wm, options);
return {
binder,
desktop(element) {
const unbind = binder.bindDesktop(element);
onDestroy(unbind);
},
window(id, windowOptions) {
return (element) => {
const unbind = binder.bindWindow(id, element, windowOptions);
onDestroy(unbind);
};
}
};
}
exports.createDesktop = createDesktop;
exports.useWindowManager = useWindowManager;
exports.useWmState = useWmState;
exports.useWmWindow = useWmWindow;
//# sourceMappingURL=angular.cjs.map
//# sourceMappingURL=angular.cjs.map

View File

@@ -0,0 +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,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 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"]}

15
web/node_modules/@surdeddd/wmkit/dist/angular.d.cts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import { Signal } from '@angular/core';
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.cjs';
import { D as DesktopBinder, W as WindowAttachOptions, a as DesktopOptions } from './binder-Dq_AZRbo.cjs';
declare function useWindowManager(options?: ManagerOptions): WindowManager;
declare function useWmState(wm: WindowManager): Signal<ManagerState>;
declare function useWmWindow(wm: WindowManager, id: string): Signal<WindowState | undefined>;
interface AngularDesktop {
binder: DesktopBinder;
desktop(element: HTMLElement): void;
window(id: string, options?: WindowAttachOptions): (element: HTMLElement) => void;
}
declare function createDesktop(wm: WindowManager, options?: DesktopOptions): AngularDesktop;
export { type AngularDesktop, createDesktop, useWindowManager, useWmState, useWmWindow };

15
web/node_modules/@surdeddd/wmkit/dist/angular.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import { Signal } from '@angular/core';
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.js';
import { D as DesktopBinder, W as WindowAttachOptions, a as DesktopOptions } from './binder-0Oku22Nc.js';
declare function useWindowManager(options?: ManagerOptions): WindowManager;
declare function useWmState(wm: WindowManager): Signal<ManagerState>;
declare function useWmWindow(wm: WindowManager, id: string): Signal<WindowState | undefined>;
interface AngularDesktop {
binder: DesktopBinder;
desktop(element: HTMLElement): void;
window(id: string, options?: WindowAttachOptions): (element: HTMLElement) => void;
}
declare function createDesktop(wm: WindowManager, options?: DesktopOptions): AngularDesktop;
export { type AngularDesktop, createDesktop, useWindowManager, useWmState, useWmWindow };

47
web/node_modules/@surdeddd/wmkit/dist/angular.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import { createWindowManager, createDesktopBinder } from './chunk-YCHJXSTC.js';
import { signal, computed, inject, DestroyRef } from '@angular/core';
function onDestroy(dispose) {
let destroyRef = null;
try {
destroyRef = inject(DestroyRef);
} catch {
destroyRef = null;
}
destroyRef?.onDestroy(dispose);
}
function useWindowManager(options) {
const wm = createWindowManager(options);
onDestroy(() => wm.destroy());
return wm;
}
function useWmState(wm) {
const state = signal(wm.getState());
const stop = wm.subscribe((next) => state.set(next));
onDestroy(stop);
return state.asReadonly();
}
function useWmWindow(wm, id) {
const state = useWmState(wm);
return computed(() => state().windows[id]);
}
function createDesktop(wm, options) {
const binder = createDesktopBinder(wm, options);
return {
binder,
desktop(element) {
const unbind = binder.bindDesktop(element);
onDestroy(unbind);
},
window(id, windowOptions) {
return (element) => {
const unbind = binder.bindWindow(id, element, windowOptions);
onDestroy(unbind);
};
}
};
}
export { createDesktop, useWindowManager, useWmState, useWmWindow };
//# sourceMappingURL=angular.js.map
//# sourceMappingURL=angular.js.map

1
web/node_modules/@surdeddd/wmkit/dist/angular.js.map generated vendored Normal file
View File

@@ -0,0 +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,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 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"]}

View File

@@ -0,0 +1,83 @@
import { B as Bounds, f as Size, g as SnapZone, W as WindowManager, b as WindowState } from './types-DdCtDHgt.js';
declare function clamp(value: number, min: number, max: number): number;
declare function clampSize(size: Size, min: Size, max: Size | null): Size;
declare function clampToViewport(bounds: Bounds, viewport: Size, minVisible: number): Bounds;
declare function boundsEqual(a: Bounds, b: Bounds): boolean;
declare function zoneBounds(zone: SnapZone, viewport: Size): Bounds;
interface SnapDetectOptions {
threshold?: number;
cornerSize?: number;
}
declare function detectSnapZone(x: number, y: number, viewport: Size, options?: SnapDetectOptions): SnapZone | null;
interface MagnetResult {
x: number;
y: number;
snappedX: boolean;
snappedY: boolean;
}
declare function magnetize(bounds: Bounds, targets: readonly Bounds[], threshold: number): MagnetResult;
interface AnnouncerMessages {
opened(title: string): string;
closed(title: string): string;
minimized(title: string): string;
restored(title: string): string;
maximized(title: string): string;
snapped(title: string, zone: string): string;
focused(title: string): string;
}
declare const defaultMessages: AnnouncerMessages;
interface Announcer {
element: HTMLElement;
announce(message: string): void;
destroy(): void;
}
declare function createAnnouncer(wm: WindowManager, container: HTMLElement, messages?: Partial<AnnouncerMessages>): Announcer;
interface DesktopSnapOptions extends SnapDetectOptions {
preview?: boolean;
topEdge?: 'maximize' | 'top' | 'none';
}
interface DesktopKeyboardOptions {
moveStep?: number;
cycle?: boolean;
}
interface HitAreaOptions {
edge?: number;
corner?: number;
}
interface MagnetismOptions {
threshold?: number;
}
interface DesktopOptions {
snap?: boolean | DesktopSnapOptions;
keyboard?: boolean | DesktopKeyboardOptions;
announce?: boolean | Partial<AnnouncerMessages>;
autoViewport?: boolean;
hitAreas?: HitAreaOptions;
magnetism?: boolean | MagnetismOptions;
minimizeTarget?: (window: WindowState) => Element | null;
onTitlebarContextMenu?: (window: WindowState, event: MouseEvent) => void;
}
interface WindowAttachOptions {
handle?: HTMLElement | string;
resizeHandles?: boolean;
removeOnClose?: boolean;
}
interface DesktopController {
element: HTMLElement;
wm: WindowManager;
attachWindow(id: string, element: HTMLElement, options?: WindowAttachOptions): () => void;
destroy(): void;
}
interface DesktopBinder {
wm: WindowManager;
controller(): DesktopController | null;
bindDesktop(element: HTMLElement): () => void;
bindWindow(id: string, element: HTMLElement, options?: WindowAttachOptions): () => void;
}
declare function createDesktopBinder(wm: WindowManager, options?: DesktopOptions): DesktopBinder;
export { type Announcer as A, type DesktopBinder as D, type HitAreaOptions as H, type MagnetResult as M, type SnapDetectOptions as S, type WindowAttachOptions as W, type DesktopOptions as a, type DesktopController as b, type AnnouncerMessages as c, type DesktopKeyboardOptions as d, type DesktopSnapOptions as e, type MagnetismOptions as f, boundsEqual as g, clamp as h, clampSize as i, clampToViewport as j, createAnnouncer as k, createDesktopBinder as l, defaultMessages as m, detectSnapZone as n, magnetize as o, zoneBounds as z };

View File

@@ -0,0 +1,83 @@
import { B as Bounds, f as Size, g as SnapZone, W as WindowManager, b as WindowState } from './types-DdCtDHgt.cjs';
declare function clamp(value: number, min: number, max: number): number;
declare function clampSize(size: Size, min: Size, max: Size | null): Size;
declare function clampToViewport(bounds: Bounds, viewport: Size, minVisible: number): Bounds;
declare function boundsEqual(a: Bounds, b: Bounds): boolean;
declare function zoneBounds(zone: SnapZone, viewport: Size): Bounds;
interface SnapDetectOptions {
threshold?: number;
cornerSize?: number;
}
declare function detectSnapZone(x: number, y: number, viewport: Size, options?: SnapDetectOptions): SnapZone | null;
interface MagnetResult {
x: number;
y: number;
snappedX: boolean;
snappedY: boolean;
}
declare function magnetize(bounds: Bounds, targets: readonly Bounds[], threshold: number): MagnetResult;
interface AnnouncerMessages {
opened(title: string): string;
closed(title: string): string;
minimized(title: string): string;
restored(title: string): string;
maximized(title: string): string;
snapped(title: string, zone: string): string;
focused(title: string): string;
}
declare const defaultMessages: AnnouncerMessages;
interface Announcer {
element: HTMLElement;
announce(message: string): void;
destroy(): void;
}
declare function createAnnouncer(wm: WindowManager, container: HTMLElement, messages?: Partial<AnnouncerMessages>): Announcer;
interface DesktopSnapOptions extends SnapDetectOptions {
preview?: boolean;
topEdge?: 'maximize' | 'top' | 'none';
}
interface DesktopKeyboardOptions {
moveStep?: number;
cycle?: boolean;
}
interface HitAreaOptions {
edge?: number;
corner?: number;
}
interface MagnetismOptions {
threshold?: number;
}
interface DesktopOptions {
snap?: boolean | DesktopSnapOptions;
keyboard?: boolean | DesktopKeyboardOptions;
announce?: boolean | Partial<AnnouncerMessages>;
autoViewport?: boolean;
hitAreas?: HitAreaOptions;
magnetism?: boolean | MagnetismOptions;
minimizeTarget?: (window: WindowState) => Element | null;
onTitlebarContextMenu?: (window: WindowState, event: MouseEvent) => void;
}
interface WindowAttachOptions {
handle?: HTMLElement | string;
resizeHandles?: boolean;
removeOnClose?: boolean;
}
interface DesktopController {
element: HTMLElement;
wm: WindowManager;
attachWindow(id: string, element: HTMLElement, options?: WindowAttachOptions): () => void;
destroy(): void;
}
interface DesktopBinder {
wm: WindowManager;
controller(): DesktopController | null;
bindDesktop(element: HTMLElement): () => void;
bindWindow(id: string, element: HTMLElement, options?: WindowAttachOptions): () => void;
}
declare function createDesktopBinder(wm: WindowManager, options?: DesktopOptions): DesktopBinder;
export { type Announcer as A, type DesktopBinder as D, type HitAreaOptions as H, type MagnetResult as M, type SnapDetectOptions as S, type WindowAttachOptions as W, type DesktopOptions as a, type DesktopController as b, type AnnouncerMessages as c, type DesktopKeyboardOptions as d, type DesktopSnapOptions as e, type MagnetismOptions as f, boundsEqual as g, clamp as h, clampSize as i, clampToViewport as j, createAnnouncer as k, createDesktopBinder as l, defaultMessages as m, detectSnapZone as n, magnetize as o, zoneBounds as z };

1738
web/node_modules/@surdeddd/wmkit/dist/chunk-B35DANTX.cjs generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1722
web/node_modules/@surdeddd/wmkit/dist/chunk-YCHJXSTC.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

68
web/node_modules/@surdeddd/wmkit/dist/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,68 @@
'use strict';
var chunkB35DANTX_cjs = require('./chunk-B35DANTX.cjs');
Object.defineProperty(exports, "attachDesktop", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.attachDesktop; }
});
Object.defineProperty(exports, "boundsEqual", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.boundsEqual; }
});
Object.defineProperty(exports, "clamp", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.clamp; }
});
Object.defineProperty(exports, "clampSize", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.clampSize; }
});
Object.defineProperty(exports, "clampToViewport", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.clampToViewport; }
});
Object.defineProperty(exports, "createAnnouncer", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.createAnnouncer; }
});
Object.defineProperty(exports, "createDesktopBinder", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.createDesktopBinder; }
});
Object.defineProperty(exports, "createEmitter", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.createEmitter; }
});
Object.defineProperty(exports, "createWindowManager", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.createWindowManager; }
});
Object.defineProperty(exports, "defaultMessages", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.defaultMessages; }
});
Object.defineProperty(exports, "detectSnapZone", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.detectSnapZone; }
});
Object.defineProperty(exports, "flipToTarget", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.flipToTarget; }
});
Object.defineProperty(exports, "magnetize", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.magnetize; }
});
Object.defineProperty(exports, "prefersReducedMotion", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.prefersReducedMotion; }
});
Object.defineProperty(exports, "zoneBounds", {
enumerable: true,
get: function () { return chunkB35DANTX_cjs.zoneBounds; }
});
//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map

1
web/node_modules/@surdeddd/wmkit/dist/index.cjs.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}

25
web/node_modules/@surdeddd/wmkit/dist/index.d.cts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
import { a as DesktopOptions, b as DesktopController } from './binder-Dq_AZRbo.cjs';
export { A as Announcer, c as AnnouncerMessages, D as DesktopBinder, d as DesktopKeyboardOptions, e as DesktopSnapOptions, H as HitAreaOptions, M as MagnetResult, f as MagnetismOptions, S as SnapDetectOptions, W as WindowAttachOptions, g as boundsEqual, h as clamp, i as clampSize, j as clampToViewport, k as createAnnouncer, l as createDesktopBinder, m as defaultMessages, n as detectSnapZone, o as magnetize, z as zoneBounds } from './binder-Dq_AZRbo.cjs';
import { M as ManagerOptions, W as WindowManager } from './types-DdCtDHgt.cjs';
export { A as ArrangeMode, B as Bounds, H as HistoryEntry, c as ManagerEvents, a as ManagerState, S as SerializedMaxSize, d as SerializedState, e as SerializedWindowState, f as Size, g as SnapZone, h as WindowFlags, i as WindowInit, j as WindowLayer, k as WindowStage, b as WindowState, l as WindowUpdate } from './types-DdCtDHgt.cjs';
type Listener<T> = (payload: T) => void;
interface Emitter<Events extends Record<keyof Events, unknown>> {
on<K extends keyof Events>(event: K, listener: Listener<Events[K]>): () => void;
emit<K extends keyof Events>(event: K, payload: Events[K]): void;
clear(): void;
}
declare function createEmitter<Events extends Record<keyof Events, unknown>>(): Emitter<Events>;
declare function createWindowManager(options?: ManagerOptions): WindowManager;
declare function prefersReducedMotion(win: Window): boolean;
interface FlipGhostOptions {
duration?: number;
easing?: string;
}
declare function flipToTarget(source: HTMLElement, target: Element, options?: FlipGhostOptions): void;
declare function attachDesktop(wm: WindowManager, element: HTMLElement, options?: DesktopOptions): DesktopController;
export { DesktopController, DesktopOptions, type Emitter, type FlipGhostOptions, type Listener, ManagerOptions, WindowManager, attachDesktop, createEmitter, createWindowManager, flipToTarget, prefersReducedMotion };

25
web/node_modules/@surdeddd/wmkit/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
import { a as DesktopOptions, b as DesktopController } from './binder-0Oku22Nc.js';
export { A as Announcer, c as AnnouncerMessages, D as DesktopBinder, d as DesktopKeyboardOptions, e as DesktopSnapOptions, H as HitAreaOptions, M as MagnetResult, f as MagnetismOptions, S as SnapDetectOptions, W as WindowAttachOptions, g as boundsEqual, h as clamp, i as clampSize, j as clampToViewport, k as createAnnouncer, l as createDesktopBinder, m as defaultMessages, n as detectSnapZone, o as magnetize, z as zoneBounds } from './binder-0Oku22Nc.js';
import { M as ManagerOptions, W as WindowManager } from './types-DdCtDHgt.js';
export { A as ArrangeMode, B as Bounds, H as HistoryEntry, c as ManagerEvents, a as ManagerState, S as SerializedMaxSize, d as SerializedState, e as SerializedWindowState, f as Size, g as SnapZone, h as WindowFlags, i as WindowInit, j as WindowLayer, k as WindowStage, b as WindowState, l as WindowUpdate } from './types-DdCtDHgt.js';
type Listener<T> = (payload: T) => void;
interface Emitter<Events extends Record<keyof Events, unknown>> {
on<K extends keyof Events>(event: K, listener: Listener<Events[K]>): () => void;
emit<K extends keyof Events>(event: K, payload: Events[K]): void;
clear(): void;
}
declare function createEmitter<Events extends Record<keyof Events, unknown>>(): Emitter<Events>;
declare function createWindowManager(options?: ManagerOptions): WindowManager;
declare function prefersReducedMotion(win: Window): boolean;
interface FlipGhostOptions {
duration?: number;
easing?: string;
}
declare function flipToTarget(source: HTMLElement, target: Element, options?: FlipGhostOptions): void;
declare function attachDesktop(wm: WindowManager, element: HTMLElement, options?: DesktopOptions): DesktopController;
export { DesktopController, DesktopOptions, type Emitter, type FlipGhostOptions, type Listener, ManagerOptions, WindowManager, attachDesktop, createEmitter, createWindowManager, flipToTarget, prefersReducedMotion };

3
web/node_modules/@surdeddd/wmkit/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
export { attachDesktop, boundsEqual, clamp, clampSize, clampToViewport, createAnnouncer, createDesktopBinder, createEmitter, createWindowManager, defaultMessages, detectSnapZone, flipToTarget, magnetize, prefersReducedMotion, zoneBounds } from './chunk-YCHJXSTC.js';
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map

1
web/node_modules/@surdeddd/wmkit/dist/index.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}

74
web/node_modules/@surdeddd/wmkit/dist/persist.cjs generated vendored Normal file
View File

@@ -0,0 +1,74 @@
'use strict';
// src/plugins/persist.ts
function defaultStorage() {
try {
const storage = globalThis.localStorage;
const probe = "__wmkit_probe__";
storage.setItem(probe, "1");
storage.removeItem(probe);
return storage;
} catch {
return null;
}
}
function persist(wm, options = {}) {
const key = options.key ?? "wmkit";
const storage = options.storage ?? defaultStorage();
const debounce = options.debounce ?? 150;
let timer;
let suspended = false;
function save() {
if (!storage) return;
try {
storage.setItem(key, JSON.stringify(wm.serialize()));
} catch {
}
}
function restore() {
if (!storage) return false;
let raw = null;
try {
raw = storage.getItem(key);
} catch {
return false;
}
if (!raw) return false;
let data;
try {
data = JSON.parse(raw);
} catch {
return false;
}
suspended = true;
const restored = wm.hydrate(data);
suspended = false;
return restored;
}
function clear() {
if (!storage) return;
try {
storage.removeItem(key);
} catch {
}
}
const unsubscribe = wm.subscribe(() => {
if (suspended || !storage) return;
if (timer !== void 0) clearTimeout(timer);
timer = setTimeout(save, debounce);
});
if (options.autoRestore !== false) restore();
return {
restore,
save,
clear,
destroy() {
unsubscribe();
if (timer !== void 0) clearTimeout(timer);
}
};
}
exports.persist = persist;
//# sourceMappingURL=persist.cjs.map
//# sourceMappingURL=persist.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/plugins/persist.ts"],"names":[],"mappings":";;;AAsBA,SAAS,cAAA,GAAwC;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,UAAA,CAAW,YAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,iBAAA;AACd,IAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,GAAG,CAAA;AAC1B,IAAA,OAAA,CAAQ,WAAW,KAAK,CAAA;AACxB,IAAA,OAAO,OAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,OAAA,CAAQ,EAAA,EAAmB,OAAA,GAA0B,EAAC,EAAsB;AAC1F,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,IAAO,OAAA;AAC3B,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,cAAA,EAAe;AAClD,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,GAAA;AACrC,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,EAAA,SAAS,IAAA,GAAa;AACpB,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,QAAQ,GAAA,EAAK,IAAA,CAAK,UAAU,EAAA,CAAG,SAAA,EAAW,CAAC,CAAA;AAAA,IACrD,CAAA,CAAA,MAAQ;AAAA,IAAC;AAAA,EACX;AAEA,EAAA,SAAS,OAAA,GAAmB;AAC1B,IAAA,IAAI,CAAC,SAAS,OAAO,KAAA;AACrB,IAAA,IAAI,GAAA,GAAqB,IAAA;AACzB,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,IAC3B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI;AACF,MAAA,IAAA,GAAO,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,IACvB,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,SAAA,GAAY,IAAA;AACZ,IAAA,MAAM,QAAA,GAAW,EAAA,CAAG,OAAA,CAAQ,IAAI,CAAA;AAChC,IAAA,SAAA,GAAY,KAAA;AACZ,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,SAAS,KAAA,GAAc;AACrB,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,WAAW,GAAG,CAAA;AAAA,IACxB,CAAA,CAAA,MAAQ;AAAA,IAAC;AAAA,EACX;AAEA,EAAA,MAAM,WAAA,GAAc,EAAA,CAAG,SAAA,CAAU,MAAM;AACrC,IAAA,IAAI,SAAA,IAAa,CAAC,OAAA,EAAS;AAC3B,IAAA,IAAI,KAAA,KAAU,MAAA,EAAW,YAAA,CAAa,KAAK,CAAA;AAC3C,IAAA,KAAA,GAAQ,UAAA,CAAW,MAAM,QAAQ,CAAA;AAAA,EACnC,CAAC,CAAA;AAED,EAAA,IAAI,OAAA,CAAQ,WAAA,KAAgB,KAAA,EAAO,OAAA,EAAQ;AAE3C,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA,GAAU;AACR,MAAA,WAAA,EAAY;AACZ,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,YAAA,CAAa,KAAK,CAAA;AAAA,IAC7C;AAAA,GACF;AACF","file":"persist.cjs","sourcesContent":["import type { SerializedState, WindowManager } from '../core/types'\n\nexport interface PersistStorage {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\nexport interface PersistOptions {\n key?: string\n storage?: PersistStorage\n debounce?: number\n autoRestore?: boolean\n}\n\nexport interface PersistController {\n restore(): boolean\n save(): void\n clear(): void\n destroy(): void\n}\n\nfunction defaultStorage(): PersistStorage | null {\n try {\n const storage = globalThis.localStorage\n const probe = '__wmkit_probe__'\n storage.setItem(probe, '1')\n storage.removeItem(probe)\n return storage\n } catch {\n return null\n }\n}\n\nexport function persist(wm: WindowManager, options: PersistOptions = {}): PersistController {\n const key = options.key ?? 'wmkit'\n const storage = options.storage ?? defaultStorage()\n const debounce = options.debounce ?? 150\n let timer: ReturnType<typeof setTimeout> | undefined\n let suspended = false\n\n function save(): void {\n if (!storage) return\n try {\n storage.setItem(key, JSON.stringify(wm.serialize()))\n } catch {}\n }\n\n function restore(): boolean {\n if (!storage) return false\n let raw: string | null = null\n try {\n raw = storage.getItem(key)\n } catch {\n return false\n }\n if (!raw) return false\n let data: SerializedState\n try {\n data = JSON.parse(raw) as SerializedState\n } catch {\n return false\n }\n suspended = true\n const restored = wm.hydrate(data)\n suspended = false\n return restored\n }\n\n function clear(): void {\n if (!storage) return\n try {\n storage.removeItem(key)\n } catch {}\n }\n\n const unsubscribe = wm.subscribe(() => {\n if (suspended || !storage) return\n if (timer !== undefined) clearTimeout(timer)\n timer = setTimeout(save, debounce)\n })\n\n if (options.autoRestore !== false) restore()\n\n return {\n restore,\n save,\n clear,\n destroy() {\n unsubscribe()\n if (timer !== undefined) clearTimeout(timer)\n },\n }\n}\n"]}

22
web/node_modules/@surdeddd/wmkit/dist/persist.d.cts generated vendored Normal file
View File

@@ -0,0 +1,22 @@
import { W as WindowManager } from './types-DdCtDHgt.cjs';
interface PersistStorage {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
removeItem(key: string): void;
}
interface PersistOptions {
key?: string;
storage?: PersistStorage;
debounce?: number;
autoRestore?: boolean;
}
interface PersistController {
restore(): boolean;
save(): void;
clear(): void;
destroy(): void;
}
declare function persist(wm: WindowManager, options?: PersistOptions): PersistController;
export { type PersistController, type PersistOptions, type PersistStorage, persist };

22
web/node_modules/@surdeddd/wmkit/dist/persist.d.ts generated vendored Normal file
View File

@@ -0,0 +1,22 @@
import { W as WindowManager } from './types-DdCtDHgt.js';
interface PersistStorage {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
removeItem(key: string): void;
}
interface PersistOptions {
key?: string;
storage?: PersistStorage;
debounce?: number;
autoRestore?: boolean;
}
interface PersistController {
restore(): boolean;
save(): void;
clear(): void;
destroy(): void;
}
declare function persist(wm: WindowManager, options?: PersistOptions): PersistController;
export { type PersistController, type PersistOptions, type PersistStorage, persist };

72
web/node_modules/@surdeddd/wmkit/dist/persist.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
// src/plugins/persist.ts
function defaultStorage() {
try {
const storage = globalThis.localStorage;
const probe = "__wmkit_probe__";
storage.setItem(probe, "1");
storage.removeItem(probe);
return storage;
} catch {
return null;
}
}
function persist(wm, options = {}) {
const key = options.key ?? "wmkit";
const storage = options.storage ?? defaultStorage();
const debounce = options.debounce ?? 150;
let timer;
let suspended = false;
function save() {
if (!storage) return;
try {
storage.setItem(key, JSON.stringify(wm.serialize()));
} catch {
}
}
function restore() {
if (!storage) return false;
let raw = null;
try {
raw = storage.getItem(key);
} catch {
return false;
}
if (!raw) return false;
let data;
try {
data = JSON.parse(raw);
} catch {
return false;
}
suspended = true;
const restored = wm.hydrate(data);
suspended = false;
return restored;
}
function clear() {
if (!storage) return;
try {
storage.removeItem(key);
} catch {
}
}
const unsubscribe = wm.subscribe(() => {
if (suspended || !storage) return;
if (timer !== void 0) clearTimeout(timer);
timer = setTimeout(save, debounce);
});
if (options.autoRestore !== false) restore();
return {
restore,
save,
clear,
destroy() {
unsubscribe();
if (timer !== void 0) clearTimeout(timer);
}
};
}
export { persist };
//# sourceMappingURL=persist.js.map
//# sourceMappingURL=persist.js.map

1
web/node_modules/@surdeddd/wmkit/dist/persist.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/plugins/persist.ts"],"names":[],"mappings":";AAsBA,SAAS,cAAA,GAAwC;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,UAAA,CAAW,YAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,iBAAA;AACd,IAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,GAAG,CAAA;AAC1B,IAAA,OAAA,CAAQ,WAAW,KAAK,CAAA;AACxB,IAAA,OAAO,OAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,OAAA,CAAQ,EAAA,EAAmB,OAAA,GAA0B,EAAC,EAAsB;AAC1F,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,IAAO,OAAA;AAC3B,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,cAAA,EAAe;AAClD,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,GAAA;AACrC,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,EAAA,SAAS,IAAA,GAAa;AACpB,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,QAAQ,GAAA,EAAK,IAAA,CAAK,UAAU,EAAA,CAAG,SAAA,EAAW,CAAC,CAAA;AAAA,IACrD,CAAA,CAAA,MAAQ;AAAA,IAAC;AAAA,EACX;AAEA,EAAA,SAAS,OAAA,GAAmB;AAC1B,IAAA,IAAI,CAAC,SAAS,OAAO,KAAA;AACrB,IAAA,IAAI,GAAA,GAAqB,IAAA;AACzB,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,IAC3B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI;AACF,MAAA,IAAA,GAAO,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,IACvB,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,SAAA,GAAY,IAAA;AACZ,IAAA,MAAM,QAAA,GAAW,EAAA,CAAG,OAAA,CAAQ,IAAI,CAAA;AAChC,IAAA,SAAA,GAAY,KAAA;AACZ,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,SAAS,KAAA,GAAc;AACrB,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,WAAW,GAAG,CAAA;AAAA,IACxB,CAAA,CAAA,MAAQ;AAAA,IAAC;AAAA,EACX;AAEA,EAAA,MAAM,WAAA,GAAc,EAAA,CAAG,SAAA,CAAU,MAAM;AACrC,IAAA,IAAI,SAAA,IAAa,CAAC,OAAA,EAAS;AAC3B,IAAA,IAAI,KAAA,KAAU,MAAA,EAAW,YAAA,CAAa,KAAK,CAAA;AAC3C,IAAA,KAAA,GAAQ,UAAA,CAAW,MAAM,QAAQ,CAAA;AAAA,EACnC,CAAC,CAAA;AAED,EAAA,IAAI,OAAA,CAAQ,WAAA,KAAgB,KAAA,EAAO,OAAA,EAAQ;AAE3C,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA,GAAU;AACR,MAAA,WAAA,EAAY;AACZ,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,YAAA,CAAa,KAAK,CAAA;AAAA,IAC7C;AAAA,GACF;AACF","file":"persist.js","sourcesContent":["import type { SerializedState, WindowManager } from '../core/types'\n\nexport interface PersistStorage {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\nexport interface PersistOptions {\n key?: string\n storage?: PersistStorage\n debounce?: number\n autoRestore?: boolean\n}\n\nexport interface PersistController {\n restore(): boolean\n save(): void\n clear(): void\n destroy(): void\n}\n\nfunction defaultStorage(): PersistStorage | null {\n try {\n const storage = globalThis.localStorage\n const probe = '__wmkit_probe__'\n storage.setItem(probe, '1')\n storage.removeItem(probe)\n return storage\n } catch {\n return null\n }\n}\n\nexport function persist(wm: WindowManager, options: PersistOptions = {}): PersistController {\n const key = options.key ?? 'wmkit'\n const storage = options.storage ?? defaultStorage()\n const debounce = options.debounce ?? 150\n let timer: ReturnType<typeof setTimeout> | undefined\n let suspended = false\n\n function save(): void {\n if (!storage) return\n try {\n storage.setItem(key, JSON.stringify(wm.serialize()))\n } catch {}\n }\n\n function restore(): boolean {\n if (!storage) return false\n let raw: string | null = null\n try {\n raw = storage.getItem(key)\n } catch {\n return false\n }\n if (!raw) return false\n let data: SerializedState\n try {\n data = JSON.parse(raw) as SerializedState\n } catch {\n return false\n }\n suspended = true\n const restored = wm.hydrate(data)\n suspended = false\n return restored\n }\n\n function clear(): void {\n if (!storage) return\n try {\n storage.removeItem(key)\n } catch {}\n }\n\n const unsubscribe = wm.subscribe(() => {\n if (suspended || !storage) return\n if (timer !== undefined) clearTimeout(timer)\n timer = setTimeout(save, debounce)\n })\n\n if (options.autoRestore !== false) restore()\n\n return {\n restore,\n save,\n clear,\n destroy() {\n unsubscribe()\n if (timer !== undefined) clearTimeout(timer)\n },\n }\n}\n"]}

66
web/node_modules/@surdeddd/wmkit/dist/popout.cjs generated vendored Normal file
View File

@@ -0,0 +1,66 @@
'use strict';
// src/plugins/popout.ts
function isPopoutSupported() {
return typeof window !== "undefined" && window.documentPictureInPicture !== void 0;
}
function copyStylesInto(pipWindow, source) {
for (const sheet of Array.from(source.styleSheets)) {
const owner = sheet.ownerNode;
if (!owner) continue;
try {
const rules = Array.from(sheet.cssRules).map((rule) => rule.cssText).join("\n");
const style = pipWindow.document.createElement("style");
style.textContent = rules;
pipWindow.document.head.append(style);
} catch {
if (owner instanceof HTMLLinkElement && owner.href) {
const link = pipWindow.document.createElement("link");
link.rel = "stylesheet";
link.href = owner.href;
pipWindow.document.head.append(link);
}
}
}
}
async function popout(wm, id, content, options = {}) {
const win = wm.get(id);
if (!win) throw new Error(`wmkit: cannot pop out unknown window "${id}"`);
const api = typeof window !== "undefined" ? window.documentPictureInPicture : void 0;
if (!api) throw new Error("wmkit: Document Picture-in-Picture is not supported in this browser");
const pipWindow = await api.requestWindow({
width: options.width ?? Math.round(win.bounds.width),
height: options.height ?? Math.round(win.bounds.height)
});
if (options.copyStyles !== false) copyStylesInto(pipWindow, content.ownerDocument);
const parent = content.parentNode;
const marker = content.ownerDocument.createComment("wmkit-popout");
parent?.insertBefore(marker, content);
pipWindow.document.body.append(content);
pipWindow.document.title = win.title;
const minimizeWhilePopped = options.minimizeWhilePopped !== false;
if (minimizeWhilePopped) wm.minimize(id);
let closed = false;
function handleReturn() {
if (closed) return;
closed = true;
if (marker.parentNode) {
marker.parentNode.insertBefore(content, marker);
marker.remove();
}
if (minimizeWhilePopped && wm.get(id)) wm.restore(id);
}
pipWindow.addEventListener("pagehide", handleReturn);
return {
pipWindow,
close() {
pipWindow.close();
handleReturn();
}
};
}
exports.isPopoutSupported = isPopoutSupported;
exports.popout = popout;
//# sourceMappingURL=popout.cjs.map
//# sourceMappingURL=popout.cjs.map

1
web/node_modules/@surdeddd/wmkit/dist/popout.cjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

28
web/node_modules/@surdeddd/wmkit/dist/popout.d.cts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
import { W as WindowManager } from './types-DdCtDHgt.cjs';
interface DocumentPictureInPictureApi {
requestWindow(options?: {
width?: number;
height?: number;
disallowReturnToOpener?: boolean;
}): Promise<Window>;
}
declare global {
interface Window {
documentPictureInPicture?: DocumentPictureInPictureApi;
}
}
interface PopoutOptions {
width?: number;
height?: number;
copyStyles?: boolean;
minimizeWhilePopped?: boolean;
}
interface PopoutHandle {
pipWindow: Window;
close(): void;
}
declare function isPopoutSupported(): boolean;
declare function popout(wm: WindowManager, id: string, content: HTMLElement, options?: PopoutOptions): Promise<PopoutHandle>;
export { type PopoutHandle, type PopoutOptions, isPopoutSupported, popout };

28
web/node_modules/@surdeddd/wmkit/dist/popout.d.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
import { W as WindowManager } from './types-DdCtDHgt.js';
interface DocumentPictureInPictureApi {
requestWindow(options?: {
width?: number;
height?: number;
disallowReturnToOpener?: boolean;
}): Promise<Window>;
}
declare global {
interface Window {
documentPictureInPicture?: DocumentPictureInPictureApi;
}
}
interface PopoutOptions {
width?: number;
height?: number;
copyStyles?: boolean;
minimizeWhilePopped?: boolean;
}
interface PopoutHandle {
pipWindow: Window;
close(): void;
}
declare function isPopoutSupported(): boolean;
declare function popout(wm: WindowManager, id: string, content: HTMLElement, options?: PopoutOptions): Promise<PopoutHandle>;
export { type PopoutHandle, type PopoutOptions, isPopoutSupported, popout };

63
web/node_modules/@surdeddd/wmkit/dist/popout.js generated vendored Normal file
View File

@@ -0,0 +1,63 @@
// src/plugins/popout.ts
function isPopoutSupported() {
return typeof window !== "undefined" && window.documentPictureInPicture !== void 0;
}
function copyStylesInto(pipWindow, source) {
for (const sheet of Array.from(source.styleSheets)) {
const owner = sheet.ownerNode;
if (!owner) continue;
try {
const rules = Array.from(sheet.cssRules).map((rule) => rule.cssText).join("\n");
const style = pipWindow.document.createElement("style");
style.textContent = rules;
pipWindow.document.head.append(style);
} catch {
if (owner instanceof HTMLLinkElement && owner.href) {
const link = pipWindow.document.createElement("link");
link.rel = "stylesheet";
link.href = owner.href;
pipWindow.document.head.append(link);
}
}
}
}
async function popout(wm, id, content, options = {}) {
const win = wm.get(id);
if (!win) throw new Error(`wmkit: cannot pop out unknown window "${id}"`);
const api = typeof window !== "undefined" ? window.documentPictureInPicture : void 0;
if (!api) throw new Error("wmkit: Document Picture-in-Picture is not supported in this browser");
const pipWindow = await api.requestWindow({
width: options.width ?? Math.round(win.bounds.width),
height: options.height ?? Math.round(win.bounds.height)
});
if (options.copyStyles !== false) copyStylesInto(pipWindow, content.ownerDocument);
const parent = content.parentNode;
const marker = content.ownerDocument.createComment("wmkit-popout");
parent?.insertBefore(marker, content);
pipWindow.document.body.append(content);
pipWindow.document.title = win.title;
const minimizeWhilePopped = options.minimizeWhilePopped !== false;
if (minimizeWhilePopped) wm.minimize(id);
let closed = false;
function handleReturn() {
if (closed) return;
closed = true;
if (marker.parentNode) {
marker.parentNode.insertBefore(content, marker);
marker.remove();
}
if (minimizeWhilePopped && wm.get(id)) wm.restore(id);
}
pipWindow.addEventListener("pagehide", handleReturn);
return {
pipWindow,
close() {
pipWindow.close();
handleReturn();
}
};
}
export { isPopoutSupported, popout };
//# sourceMappingURL=popout.js.map
//# sourceMappingURL=popout.js.map

1
web/node_modules/@surdeddd/wmkit/dist/popout.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

57
web/node_modules/@surdeddd/wmkit/dist/react.cjs generated vendored Normal file
View File

@@ -0,0 +1,57 @@
'use strict';
var chunkB35DANTX_cjs = require('./chunk-B35DANTX.cjs');
var react = require('react');
function useWindowManager(options) {
const [wm] = react.useState(() => chunkB35DANTX_cjs.createWindowManager(options));
react.useEffect(() => () => wm.destroy(), [wm]);
return wm;
}
function useWmState(wm) {
return react.useSyncExternalStore(wm.subscribe, wm.getState, wm.getState);
}
function useWmWindow(wm, id) {
const getSnapshot = react.useCallback(() => wm.get(id), [wm, id]);
return react.useSyncExternalStore(wm.subscribe, getSnapshot, getSnapshot);
}
function useDesktop(wm, options) {
const optionsRef = react.useRef(options);
const binder = react.useMemo(() => chunkB35DANTX_cjs.createDesktopBinder(wm, optionsRef.current), [wm]);
const cleanupRef = react.useRef(null);
const ref = react.useCallback(
(node) => {
if (node) {
cleanupRef.current = binder.bindDesktop(node);
} else {
cleanupRef.current?.();
cleanupRef.current = null;
}
},
[binder]
);
return { ref, binder, controller: binder.controller };
}
function useWmWindowRef(binder, id, options) {
const optionsRef = react.useRef(options);
const cleanupRef = react.useRef(null);
return react.useCallback(
(node) => {
if (node) {
cleanupRef.current = binder.bindWindow(id, node, optionsRef.current);
} else {
cleanupRef.current?.();
cleanupRef.current = null;
}
},
[binder, id]
);
}
exports.useDesktop = useDesktop;
exports.useWindowManager = useWindowManager;
exports.useWmState = useWmState;
exports.useWmWindow = useWmWindow;
exports.useWmWindowRef = useWmWindowRef;
//# sourceMappingURL=react.cjs.map
//# sourceMappingURL=react.cjs.map

1
web/node_modules/@surdeddd/wmkit/dist/react.cjs.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/adapters/react.ts"],"names":["useState","createWindowManager","useEffect","useSyncExternalStore","useCallback","useRef","useMemo","createDesktopBinder"],"mappings":";;;;;AAQO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM,CAAC,EAAE,CAAA,GAAIA,eAAS,MAAMC,qCAAA,CAAoB,OAAO,CAAC,CAAA;AACxD,EAAAC,eAAA,CAAU,MAAM,MAAM,EAAA,CAAG,SAAQ,EAAG,CAAC,EAAE,CAAC,CAAA;AACxC,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,WAAW,EAAA,EAAiC;AAC1D,EAAA,OAAOC,2BAAqB,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,GAAG,QAAQ,CAAA;AACpE;AAEO,SAAS,WAAA,CAAY,IAAmB,EAAA,EAAqC;AAClF,EAAA,MAAM,WAAA,GAAcC,iBAAA,CAAY,MAAM,EAAA,CAAG,GAAA,CAAI,EAAE,CAAA,EAAG,CAAC,EAAA,EAAI,EAAE,CAAC,CAAA;AAC1D,EAAA,OAAOD,0BAAA,CAAqB,EAAA,CAAG,SAAA,EAAW,WAAA,EAAa,WAAW,CAAA;AACpE;AAQO,SAAS,UAAA,CAAW,IAAmB,OAAA,EAA4C;AACxF,EAAA,MAAM,UAAA,GAAaE,aAAO,OAAO,CAAA;AACjC,EAAA,MAAM,MAAA,GAASC,aAAA,CAAQ,MAAMC,qCAAA,CAAoB,EAAA,EAAI,WAAW,OAAO,CAAA,EAAG,CAAC,EAAE,CAAC,CAAA;AAC9E,EAAA,MAAM,UAAA,GAAaF,aAA4B,IAAI,CAAA;AACnD,EAAA,MAAM,GAAA,GAAMD,iBAAA;AAAA,IACV,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,OAAA,GAAU,MAAA,CAAO,WAAA,CAAY,IAAI,CAAA;AAAA,MAC9C,CAAA,MAAO;AACL,QAAA,UAAA,CAAW,OAAA,IAAU;AACrB,QAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,MACvB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AACA,EAAA,OAAO,EAAE,GAAA,EAAK,MAAA,EAAQ,UAAA,EAAY,OAAO,UAAA,EAAW;AACtD;AAEO,SAAS,cAAA,CACd,MAAA,EACA,EAAA,EACA,OAAA,EACY;AACZ,EAAA,MAAM,UAAA,GAAaC,aAAO,OAAO,CAAA;AACjC,EAAA,MAAM,UAAA,GAAaA,aAA4B,IAAI,CAAA;AACnD,EAAA,OAAOD,iBAAA;AAAA,IACL,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,UAAU,MAAA,CAAO,UAAA,CAAW,EAAA,EAAI,IAAA,EAAM,WAAW,OAAO,CAAA;AAAA,MACrE,CAAA,MAAO;AACL,QAAA,UAAA,CAAW,OAAA,IAAU;AACrB,QAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,MACvB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,QAAQ,EAAE;AAAA,GACb;AACF","file":"react.cjs","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport { createWindowManager } from '../core/manager'\nimport type { ManagerOptions, ManagerState, WindowManager, WindowState } from '../core/types'\nimport { createDesktopBinder, type DesktopBinder } from '../dom/binder'\nimport type { DesktopController, DesktopOptions, WindowAttachOptions } from '../dom/shared'\n\nexport type ElementRef = (node: HTMLElement | null) => void\n\nexport function useWindowManager(options?: ManagerOptions): WindowManager {\n const [wm] = useState(() => createWindowManager(options))\n useEffect(() => () => wm.destroy(), [wm])\n return wm\n}\n\nexport function useWmState(wm: WindowManager): ManagerState {\n return useSyncExternalStore(wm.subscribe, wm.getState, wm.getState)\n}\n\nexport function useWmWindow(wm: WindowManager, id: string): WindowState | undefined {\n const getSnapshot = useCallback(() => wm.get(id), [wm, id])\n return useSyncExternalStore(wm.subscribe, getSnapshot, getSnapshot)\n}\n\nexport interface UseDesktopResult {\n ref: ElementRef\n binder: DesktopBinder\n controller(): DesktopController | null\n}\n\nexport function useDesktop(wm: WindowManager, options?: DesktopOptions): UseDesktopResult {\n const optionsRef = useRef(options)\n const binder = useMemo(() => createDesktopBinder(wm, optionsRef.current), [wm])\n const cleanupRef = useRef<(() => void) | null>(null)\n const ref = useCallback<ElementRef>(\n (node) => {\n if (node) {\n cleanupRef.current = binder.bindDesktop(node)\n } else {\n cleanupRef.current?.()\n cleanupRef.current = null\n }\n },\n [binder],\n )\n return { ref, binder, controller: binder.controller }\n}\n\nexport function useWmWindowRef(\n binder: DesktopBinder,\n id: string,\n options?: WindowAttachOptions,\n): ElementRef {\n const optionsRef = useRef(options)\n const cleanupRef = useRef<(() => void) | null>(null)\n return useCallback<ElementRef>(\n (node) => {\n if (node) {\n cleanupRef.current = binder.bindWindow(id, node, optionsRef.current)\n } else {\n cleanupRef.current?.()\n cleanupRef.current = null\n }\n },\n [binder, id],\n )\n}\n"]}

16
web/node_modules/@surdeddd/wmkit/dist/react.d.cts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.cjs';
import { D as DesktopBinder, b as DesktopController, a as DesktopOptions, W as WindowAttachOptions } from './binder-Dq_AZRbo.cjs';
type ElementRef = (node: HTMLElement | null) => void;
declare function useWindowManager(options?: ManagerOptions): WindowManager;
declare function useWmState(wm: WindowManager): ManagerState;
declare function useWmWindow(wm: WindowManager, id: string): WindowState | undefined;
interface UseDesktopResult {
ref: ElementRef;
binder: DesktopBinder;
controller(): DesktopController | null;
}
declare function useDesktop(wm: WindowManager, options?: DesktopOptions): UseDesktopResult;
declare function useWmWindowRef(binder: DesktopBinder, id: string, options?: WindowAttachOptions): ElementRef;
export { type ElementRef, type UseDesktopResult, useDesktop, useWindowManager, useWmState, useWmWindow, useWmWindowRef };

16
web/node_modules/@surdeddd/wmkit/dist/react.d.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.js';
import { D as DesktopBinder, b as DesktopController, a as DesktopOptions, W as WindowAttachOptions } from './binder-0Oku22Nc.js';
type ElementRef = (node: HTMLElement | null) => void;
declare function useWindowManager(options?: ManagerOptions): WindowManager;
declare function useWmState(wm: WindowManager): ManagerState;
declare function useWmWindow(wm: WindowManager, id: string): WindowState | undefined;
interface UseDesktopResult {
ref: ElementRef;
binder: DesktopBinder;
controller(): DesktopController | null;
}
declare function useDesktop(wm: WindowManager, options?: DesktopOptions): UseDesktopResult;
declare function useWmWindowRef(binder: DesktopBinder, id: string, options?: WindowAttachOptions): ElementRef;
export { type ElementRef, type UseDesktopResult, useDesktop, useWindowManager, useWmState, useWmWindow, useWmWindowRef };

51
web/node_modules/@surdeddd/wmkit/dist/react.js generated vendored Normal file
View File

@@ -0,0 +1,51 @@
import { createWindowManager, createDesktopBinder } from './chunk-YCHJXSTC.js';
import { useState, useEffect, useSyncExternalStore, useCallback, useRef, useMemo } from 'react';
function useWindowManager(options) {
const [wm] = useState(() => createWindowManager(options));
useEffect(() => () => wm.destroy(), [wm]);
return wm;
}
function useWmState(wm) {
return useSyncExternalStore(wm.subscribe, wm.getState, wm.getState);
}
function useWmWindow(wm, id) {
const getSnapshot = useCallback(() => wm.get(id), [wm, id]);
return useSyncExternalStore(wm.subscribe, getSnapshot, getSnapshot);
}
function useDesktop(wm, options) {
const optionsRef = useRef(options);
const binder = useMemo(() => createDesktopBinder(wm, optionsRef.current), [wm]);
const cleanupRef = useRef(null);
const ref = useCallback(
(node) => {
if (node) {
cleanupRef.current = binder.bindDesktop(node);
} else {
cleanupRef.current?.();
cleanupRef.current = null;
}
},
[binder]
);
return { ref, binder, controller: binder.controller };
}
function useWmWindowRef(binder, id, options) {
const optionsRef = useRef(options);
const cleanupRef = useRef(null);
return useCallback(
(node) => {
if (node) {
cleanupRef.current = binder.bindWindow(id, node, optionsRef.current);
} else {
cleanupRef.current?.();
cleanupRef.current = null;
}
},
[binder, id]
);
}
export { useDesktop, useWindowManager, useWmState, useWmWindow, useWmWindowRef };
//# sourceMappingURL=react.js.map
//# sourceMappingURL=react.js.map

1
web/node_modules/@surdeddd/wmkit/dist/react.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/adapters/react.ts"],"names":[],"mappings":";;;AAQO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM,CAAC,EAAE,CAAA,GAAI,SAAS,MAAM,mBAAA,CAAoB,OAAO,CAAC,CAAA;AACxD,EAAA,SAAA,CAAU,MAAM,MAAM,EAAA,CAAG,SAAQ,EAAG,CAAC,EAAE,CAAC,CAAA;AACxC,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,WAAW,EAAA,EAAiC;AAC1D,EAAA,OAAO,qBAAqB,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,GAAG,QAAQ,CAAA;AACpE;AAEO,SAAS,WAAA,CAAY,IAAmB,EAAA,EAAqC;AAClF,EAAA,MAAM,WAAA,GAAc,WAAA,CAAY,MAAM,EAAA,CAAG,GAAA,CAAI,EAAE,CAAA,EAAG,CAAC,EAAA,EAAI,EAAE,CAAC,CAAA;AAC1D,EAAA,OAAO,oBAAA,CAAqB,EAAA,CAAG,SAAA,EAAW,WAAA,EAAa,WAAW,CAAA;AACpE;AAQO,SAAS,UAAA,CAAW,IAAmB,OAAA,EAA4C;AACxF,EAAA,MAAM,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAM,mBAAA,CAAoB,EAAA,EAAI,WAAW,OAAO,CAAA,EAAG,CAAC,EAAE,CAAC,CAAA;AAC9E,EAAA,MAAM,UAAA,GAAa,OAA4B,IAAI,CAAA;AACnD,EAAA,MAAM,GAAA,GAAM,WAAA;AAAA,IACV,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,OAAA,GAAU,MAAA,CAAO,WAAA,CAAY,IAAI,CAAA;AAAA,MAC9C,CAAA,MAAO;AACL,QAAA,UAAA,CAAW,OAAA,IAAU;AACrB,QAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,MACvB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AACA,EAAA,OAAO,EAAE,GAAA,EAAK,MAAA,EAAQ,UAAA,EAAY,OAAO,UAAA,EAAW;AACtD;AAEO,SAAS,cAAA,CACd,MAAA,EACA,EAAA,EACA,OAAA,EACY;AACZ,EAAA,MAAM,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAA,MAAM,UAAA,GAAa,OAA4B,IAAI,CAAA;AACnD,EAAA,OAAO,WAAA;AAAA,IACL,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,UAAU,MAAA,CAAO,UAAA,CAAW,EAAA,EAAI,IAAA,EAAM,WAAW,OAAO,CAAA;AAAA,MACrE,CAAA,MAAO;AACL,QAAA,UAAA,CAAW,OAAA,IAAU;AACrB,QAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,MACvB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,QAAQ,EAAE;AAAA,GACb;AACF","file":"react.js","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport { createWindowManager } from '../core/manager'\nimport type { ManagerOptions, ManagerState, WindowManager, WindowState } from '../core/types'\nimport { createDesktopBinder, type DesktopBinder } from '../dom/binder'\nimport type { DesktopController, DesktopOptions, WindowAttachOptions } from '../dom/shared'\n\nexport type ElementRef = (node: HTMLElement | null) => void\n\nexport function useWindowManager(options?: ManagerOptions): WindowManager {\n const [wm] = useState(() => createWindowManager(options))\n useEffect(() => () => wm.destroy(), [wm])\n return wm\n}\n\nexport function useWmState(wm: WindowManager): ManagerState {\n return useSyncExternalStore(wm.subscribe, wm.getState, wm.getState)\n}\n\nexport function useWmWindow(wm: WindowManager, id: string): WindowState | undefined {\n const getSnapshot = useCallback(() => wm.get(id), [wm, id])\n return useSyncExternalStore(wm.subscribe, getSnapshot, getSnapshot)\n}\n\nexport interface UseDesktopResult {\n ref: ElementRef\n binder: DesktopBinder\n controller(): DesktopController | null\n}\n\nexport function useDesktop(wm: WindowManager, options?: DesktopOptions): UseDesktopResult {\n const optionsRef = useRef(options)\n const binder = useMemo(() => createDesktopBinder(wm, optionsRef.current), [wm])\n const cleanupRef = useRef<(() => void) | null>(null)\n const ref = useCallback<ElementRef>(\n (node) => {\n if (node) {\n cleanupRef.current = binder.bindDesktop(node)\n } else {\n cleanupRef.current?.()\n cleanupRef.current = null\n }\n },\n [binder],\n )\n return { ref, binder, controller: binder.controller }\n}\n\nexport function useWmWindowRef(\n binder: DesktopBinder,\n id: string,\n options?: WindowAttachOptions,\n): ElementRef {\n const optionsRef = useRef(options)\n const cleanupRef = useRef<(() => void) | null>(null)\n return useCallback<ElementRef>(\n (node) => {\n if (node) {\n cleanupRef.current = binder.bindWindow(id, node, optionsRef.current)\n } else {\n cleanupRef.current?.()\n cleanupRef.current = null\n }\n },\n [binder, id],\n )\n}\n"]}

45
web/node_modules/@surdeddd/wmkit/dist/solid.cjs generated vendored Normal file
View File

@@ -0,0 +1,45 @@
'use strict';
var chunkB35DANTX_cjs = require('./chunk-B35DANTX.cjs');
var solidJs = require('solid-js');
function disposeWithOwner(dispose) {
if (solidJs.getOwner()) solidJs.onCleanup(dispose);
}
function useWindowManager(options) {
const wm = chunkB35DANTX_cjs.createWindowManager(options);
disposeWithOwner(() => wm.destroy());
return wm;
}
function useWmState(wm) {
const [state, setState] = solidJs.createSignal(wm.getState());
disposeWithOwner(wm.subscribe((next) => setState(next)));
return state;
}
function useWmWindow(wm, id) {
const state = useWmState(wm);
return () => state().windows[typeof id === "function" ? id() : id];
}
function createDesktop(wm, options) {
const binder = chunkB35DANTX_cjs.createDesktopBinder(wm, options);
return {
binder,
desktop(element) {
const unbind = binder.bindDesktop(element);
disposeWithOwner(unbind);
},
window(id, options2) {
return (element) => {
const unbind = binder.bindWindow(id, element, options2);
disposeWithOwner(unbind);
};
}
};
}
exports.createDesktop = createDesktop;
exports.useWindowManager = useWindowManager;
exports.useWmState = useWmState;
exports.useWmWindow = useWmWindow;
//# sourceMappingURL=solid.cjs.map
//# sourceMappingURL=solid.cjs.map

1
web/node_modules/@surdeddd/wmkit/dist/solid.cjs.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/adapters/solid.ts"],"names":["getOwner","onCleanup","createWindowManager","createSignal","createDesktopBinder","options"],"mappings":";;;;;AAMA,SAAS,iBAAiB,OAAA,EAA2B;AACnD,EAAA,IAAIA,gBAAA,EAAS,EAAGC,iBAAA,CAAU,OAAO,CAAA;AACnC;AAEO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM,EAAA,GAAKC,sCAAoB,OAAO,CAAA;AACtC,EAAA,gBAAA,CAAiB,MAAM,EAAA,CAAG,OAAA,EAAS,CAAA;AACnC,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,WAAW,EAAA,EAA2C;AACpE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAIC,oBAAA,CAAa,EAAA,CAAG,UAAU,CAAA;AACpD,EAAA,gBAAA,CAAiB,GAAG,SAAA,CAAU,CAAC,SAAS,QAAA,CAAS,IAAI,CAAC,CAAC,CAAA;AACvD,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,WAAA,CACd,IACA,EAAA,EACmC;AACnC,EAAA,MAAM,KAAA,GAAQ,WAAW,EAAE,CAAA;AAC3B,EAAA,OAAO,MAAM,OAAM,CAAE,OAAA,CAAQ,OAAO,EAAA,KAAO,UAAA,GAAa,EAAA,EAAG,GAAI,EAAE,CAAA;AACnE;AAQO,SAAS,aAAA,CAAc,IAAmB,OAAA,EAAwC;AACvF,EAAA,MAAM,MAAA,GAASC,qCAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAC9C,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,QAAQ,OAAA,EAAS;AACf,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,WAAA,CAAY,OAAO,CAAA;AACzC,MAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,IACzB,CAAA;AAAA,IACA,MAAA,CAAO,IAAIC,QAAAA,EAAS;AAClB,MAAA,OAAO,CAAC,OAAA,KAAY;AAClB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,EAAA,EAAI,SAASA,QAAO,CAAA;AACrD,QAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,MACzB,CAAA;AAAA,IACF;AAAA,GACF;AACF","file":"solid.cjs","sourcesContent":["import { type Accessor, createSignal, getOwner, onCleanup } from 'solid-js'\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 disposeWithOwner(dispose: () => void): void {\n if (getOwner()) onCleanup(dispose)\n}\n\nexport function useWindowManager(options?: ManagerOptions): WindowManager {\n const wm = createWindowManager(options)\n disposeWithOwner(() => wm.destroy())\n return wm\n}\n\nexport function useWmState(wm: WindowManager): Accessor<ManagerState> {\n const [state, setState] = createSignal(wm.getState())\n disposeWithOwner(wm.subscribe((next) => setState(next)))\n return state\n}\n\nexport function useWmWindow(\n wm: WindowManager,\n id: string | Accessor<string>,\n): Accessor<WindowState | undefined> {\n const state = useWmState(wm)\n return () => state().windows[typeof id === 'function' ? id() : id]\n}\n\nexport interface SolidDesktop {\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): SolidDesktop {\n const binder = createDesktopBinder(wm, options)\n return {\n binder,\n desktop(element) {\n const unbind = binder.bindDesktop(element)\n disposeWithOwner(unbind)\n },\n window(id, options) {\n return (element) => {\n const unbind = binder.bindWindow(id, element, options)\n disposeWithOwner(unbind)\n }\n },\n }\n}\n"]}

15
web/node_modules/@surdeddd/wmkit/dist/solid.d.cts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import { Accessor } from 'solid-js';
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.cjs';
import { D as DesktopBinder, W as WindowAttachOptions, a as DesktopOptions } from './binder-Dq_AZRbo.cjs';
declare function useWindowManager(options?: ManagerOptions): WindowManager;
declare function useWmState(wm: WindowManager): Accessor<ManagerState>;
declare function useWmWindow(wm: WindowManager, id: string | Accessor<string>): Accessor<WindowState | undefined>;
interface SolidDesktop {
binder: DesktopBinder;
desktop(element: HTMLElement): void;
window(id: string, options?: WindowAttachOptions): (element: HTMLElement) => void;
}
declare function createDesktop(wm: WindowManager, options?: DesktopOptions): SolidDesktop;
export { type SolidDesktop, createDesktop, useWindowManager, useWmState, useWmWindow };

15
web/node_modules/@surdeddd/wmkit/dist/solid.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import { Accessor } from 'solid-js';
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.js';
import { D as DesktopBinder, W as WindowAttachOptions, a as DesktopOptions } from './binder-0Oku22Nc.js';
declare function useWindowManager(options?: ManagerOptions): WindowManager;
declare function useWmState(wm: WindowManager): Accessor<ManagerState>;
declare function useWmWindow(wm: WindowManager, id: string | Accessor<string>): Accessor<WindowState | undefined>;
interface SolidDesktop {
binder: DesktopBinder;
desktop(element: HTMLElement): void;
window(id: string, options?: WindowAttachOptions): (element: HTMLElement) => void;
}
declare function createDesktop(wm: WindowManager, options?: DesktopOptions): SolidDesktop;
export { type SolidDesktop, createDesktop, useWindowManager, useWmState, useWmWindow };

40
web/node_modules/@surdeddd/wmkit/dist/solid.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
import { createWindowManager, createDesktopBinder } from './chunk-YCHJXSTC.js';
import { createSignal, getOwner, onCleanup } from 'solid-js';
function disposeWithOwner(dispose) {
if (getOwner()) onCleanup(dispose);
}
function useWindowManager(options) {
const wm = createWindowManager(options);
disposeWithOwner(() => wm.destroy());
return wm;
}
function useWmState(wm) {
const [state, setState] = createSignal(wm.getState());
disposeWithOwner(wm.subscribe((next) => setState(next)));
return state;
}
function useWmWindow(wm, id) {
const state = useWmState(wm);
return () => state().windows[typeof id === "function" ? id() : id];
}
function createDesktop(wm, options) {
const binder = createDesktopBinder(wm, options);
return {
binder,
desktop(element) {
const unbind = binder.bindDesktop(element);
disposeWithOwner(unbind);
},
window(id, options2) {
return (element) => {
const unbind = binder.bindWindow(id, element, options2);
disposeWithOwner(unbind);
};
}
};
}
export { createDesktop, useWindowManager, useWmState, useWmWindow };
//# sourceMappingURL=solid.js.map
//# sourceMappingURL=solid.js.map

1
web/node_modules/@surdeddd/wmkit/dist/solid.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/adapters/solid.ts"],"names":["options"],"mappings":";;;AAMA,SAAS,iBAAiB,OAAA,EAA2B;AACnD,EAAA,IAAI,QAAA,EAAS,EAAG,SAAA,CAAU,OAAO,CAAA;AACnC;AAEO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM,EAAA,GAAK,oBAAoB,OAAO,CAAA;AACtC,EAAA,gBAAA,CAAiB,MAAM,EAAA,CAAG,OAAA,EAAS,CAAA;AACnC,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,WAAW,EAAA,EAA2C;AACpE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAI,YAAA,CAAa,EAAA,CAAG,UAAU,CAAA;AACpD,EAAA,gBAAA,CAAiB,GAAG,SAAA,CAAU,CAAC,SAAS,QAAA,CAAS,IAAI,CAAC,CAAC,CAAA;AACvD,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,WAAA,CACd,IACA,EAAA,EACmC;AACnC,EAAA,MAAM,KAAA,GAAQ,WAAW,EAAE,CAAA;AAC3B,EAAA,OAAO,MAAM,OAAM,CAAE,OAAA,CAAQ,OAAO,EAAA,KAAO,UAAA,GAAa,EAAA,EAAG,GAAI,EAAE,CAAA;AACnE;AAQO,SAAS,aAAA,CAAc,IAAmB,OAAA,EAAwC;AACvF,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAC9C,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,QAAQ,OAAA,EAAS;AACf,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,WAAA,CAAY,OAAO,CAAA;AACzC,MAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,IACzB,CAAA;AAAA,IACA,MAAA,CAAO,IAAIA,QAAAA,EAAS;AAClB,MAAA,OAAO,CAAC,OAAA,KAAY;AAClB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,EAAA,EAAI,SAASA,QAAO,CAAA;AACrD,QAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,MACzB,CAAA;AAAA,IACF;AAAA,GACF;AACF","file":"solid.js","sourcesContent":["import { type Accessor, createSignal, getOwner, onCleanup } from 'solid-js'\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 disposeWithOwner(dispose: () => void): void {\n if (getOwner()) onCleanup(dispose)\n}\n\nexport function useWindowManager(options?: ManagerOptions): WindowManager {\n const wm = createWindowManager(options)\n disposeWithOwner(() => wm.destroy())\n return wm\n}\n\nexport function useWmState(wm: WindowManager): Accessor<ManagerState> {\n const [state, setState] = createSignal(wm.getState())\n disposeWithOwner(wm.subscribe((next) => setState(next)))\n return state\n}\n\nexport function useWmWindow(\n wm: WindowManager,\n id: string | Accessor<string>,\n): Accessor<WindowState | undefined> {\n const state = useWmState(wm)\n return () => state().windows[typeof id === 'function' ? id() : id]\n}\n\nexport interface SolidDesktop {\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): SolidDesktop {\n const binder = createDesktopBinder(wm, options)\n return {\n binder,\n desktop(element) {\n const unbind = binder.bindDesktop(element)\n disposeWithOwner(unbind)\n },\n window(id, options) {\n return (element) => {\n const unbind = binder.bindWindow(id, element, options)\n disposeWithOwner(unbind)\n }\n },\n }\n}\n"]}

60
web/node_modules/@surdeddd/wmkit/dist/svelte.cjs generated vendored Normal file
View File

@@ -0,0 +1,60 @@
'use strict';
var chunkB35DANTX_cjs = require('./chunk-B35DANTX.cjs');
// src/adapters/svelte.ts
function createManager(options) {
return chunkB35DANTX_cjs.createWindowManager(options);
}
function wmStore(wm) {
return {
subscribe(run) {
run(wm.getState());
return wm.subscribe(run);
}
};
}
function wmWindowStore(wm, id) {
return {
subscribe(run) {
run(wm.get(id));
let last = wm.get(id);
return wm.subscribe(() => {
const next = wm.get(id);
if (next !== last) {
last = next;
run(next);
}
});
}
};
}
function createDesktop(wm, options) {
const binder = chunkB35DANTX_cjs.createDesktopBinder(wm, options);
return {
binder,
desktop(node) {
const unbind = binder.bindDesktop(node);
return { destroy: unbind };
},
window(node, params) {
let unbind = binder.bindWindow(params.id, node, params);
return {
update(next) {
unbind();
unbind = binder.bindWindow(next.id, node, next);
},
destroy() {
unbind();
}
};
}
};
}
exports.createDesktop = createDesktop;
exports.createManager = createManager;
exports.wmStore = wmStore;
exports.wmWindowStore = wmWindowStore;
//# sourceMappingURL=svelte.cjs.map
//# sourceMappingURL=svelte.cjs.map

1
web/node_modules/@surdeddd/wmkit/dist/svelte.cjs.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/adapters/svelte.ts"],"names":["createWindowManager","createDesktopBinder"],"mappings":";;;;;AAkBO,SAAS,cAAc,OAAA,EAAyC;AACrE,EAAA,OAAOA,sCAAoB,OAAO,CAAA;AACpC;AAEO,SAAS,QAAQ,EAAA,EAAgD;AACtE,EAAA,OAAO;AAAA,IACL,UAAU,GAAA,EAAK;AACb,MAAA,GAAA,CAAI,EAAA,CAAG,UAAU,CAAA;AACjB,MAAA,OAAO,EAAA,CAAG,UAAU,GAAG,CAAA;AAAA,IACzB;AAAA,GACF;AACF;AAEO,SAAS,aAAA,CACd,IACA,EAAA,EACwC;AACxC,EAAA,OAAO;AAAA,IACL,UAAU,GAAA,EAAK;AACb,MAAA,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,EAAE,CAAC,CAAA;AACd,MAAA,IAAI,IAAA,GAAO,EAAA,CAAG,GAAA,CAAI,EAAE,CAAA;AACpB,MAAA,OAAO,EAAA,CAAG,UAAU,MAAM;AACxB,QAAA,MAAM,IAAA,GAAO,EAAA,CAAG,GAAA,CAAI,EAAE,CAAA;AACtB,QAAA,IAAI,SAAS,IAAA,EAAM;AACjB,UAAA,IAAA,GAAO,IAAA;AACP,UAAA,GAAA,CAAI,IAAI,CAAA;AAAA,QACV;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;AAQO,SAAS,aAAA,CAAc,IAAmB,OAAA,EAAyC;AACxF,EAAA,MAAM,MAAA,GAASC,qCAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAC9C,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,QAAQ,IAAA,EAAM;AACZ,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,WAAA,CAAY,IAAI,CAAA;AACtC,MAAA,OAAO,EAAE,SAAS,MAAA,EAAO;AAAA,IAC3B,CAAA;AAAA,IACA,MAAA,CAAO,MAAM,MAAA,EAAQ;AACnB,MAAA,IAAI,SAAS,MAAA,CAAO,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,MAAM,MAAM,CAAA;AACtD,MAAA,OAAO;AAAA,QACL,OAAO,IAAA,EAAM;AACX,UAAA,MAAA,EAAO;AACP,UAAA,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,EAAA,EAAI,MAAM,IAAI,CAAA;AAAA,QAChD,CAAA;AAAA,QACA,OAAA,GAAU;AACR,UAAA,MAAA,EAAO;AAAA,QACT;AAAA,OACF;AAAA,IACF;AAAA,GACF;AACF","file":"svelte.cjs","sourcesContent":["import { 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\nexport interface ReadableStore<T> {\n subscribe(run: (value: T) => void): () => void\n}\n\nexport interface ActionResult {\n update?(params: WindowActionParams): void\n destroy(): void\n}\n\nexport interface WindowActionParams extends WindowAttachOptions {\n id: string\n}\n\nexport function createManager(options?: ManagerOptions): WindowManager {\n return createWindowManager(options)\n}\n\nexport function wmStore(wm: WindowManager): ReadableStore<ManagerState> {\n return {\n subscribe(run) {\n run(wm.getState())\n return wm.subscribe(run)\n },\n }\n}\n\nexport function wmWindowStore(\n wm: WindowManager,\n id: string,\n): ReadableStore<WindowState | undefined> {\n return {\n subscribe(run) {\n run(wm.get(id))\n let last = wm.get(id)\n return wm.subscribe(() => {\n const next = wm.get(id)\n if (next !== last) {\n last = next\n run(next)\n }\n })\n },\n }\n}\n\nexport interface SvelteDesktop {\n binder: DesktopBinder\n desktop(node: HTMLElement): ActionResult\n window(node: HTMLElement, params: WindowActionParams): ActionResult\n}\n\nexport function createDesktop(wm: WindowManager, options?: DesktopOptions): SvelteDesktop {\n const binder = createDesktopBinder(wm, options)\n return {\n binder,\n desktop(node) {\n const unbind = binder.bindDesktop(node)\n return { destroy: unbind }\n },\n window(node, params) {\n let unbind = binder.bindWindow(params.id, node, params)\n return {\n update(next) {\n unbind()\n unbind = binder.bindWindow(next.id, node, next)\n },\n destroy() {\n unbind()\n },\n }\n },\n }\n}\n"]}

24
web/node_modules/@surdeddd/wmkit/dist/svelte.d.cts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.cjs';
import { W as WindowAttachOptions, D as DesktopBinder, a as DesktopOptions } from './binder-Dq_AZRbo.cjs';
interface ReadableStore<T> {
subscribe(run: (value: T) => void): () => void;
}
interface ActionResult {
update?(params: WindowActionParams): void;
destroy(): void;
}
interface WindowActionParams extends WindowAttachOptions {
id: string;
}
declare function createManager(options?: ManagerOptions): WindowManager;
declare function wmStore(wm: WindowManager): ReadableStore<ManagerState>;
declare function wmWindowStore(wm: WindowManager, id: string): ReadableStore<WindowState | undefined>;
interface SvelteDesktop {
binder: DesktopBinder;
desktop(node: HTMLElement): ActionResult;
window(node: HTMLElement, params: WindowActionParams): ActionResult;
}
declare function createDesktop(wm: WindowManager, options?: DesktopOptions): SvelteDesktop;
export { type ActionResult, type ReadableStore, type SvelteDesktop, type WindowActionParams, createDesktop, createManager, wmStore, wmWindowStore };

24
web/node_modules/@surdeddd/wmkit/dist/svelte.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.js';
import { W as WindowAttachOptions, D as DesktopBinder, a as DesktopOptions } from './binder-0Oku22Nc.js';
interface ReadableStore<T> {
subscribe(run: (value: T) => void): () => void;
}
interface ActionResult {
update?(params: WindowActionParams): void;
destroy(): void;
}
interface WindowActionParams extends WindowAttachOptions {
id: string;
}
declare function createManager(options?: ManagerOptions): WindowManager;
declare function wmStore(wm: WindowManager): ReadableStore<ManagerState>;
declare function wmWindowStore(wm: WindowManager, id: string): ReadableStore<WindowState | undefined>;
interface SvelteDesktop {
binder: DesktopBinder;
desktop(node: HTMLElement): ActionResult;
window(node: HTMLElement, params: WindowActionParams): ActionResult;
}
declare function createDesktop(wm: WindowManager, options?: DesktopOptions): SvelteDesktop;
export { type ActionResult, type ReadableStore, type SvelteDesktop, type WindowActionParams, createDesktop, createManager, wmStore, wmWindowStore };

55
web/node_modules/@surdeddd/wmkit/dist/svelte.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
import { createWindowManager, createDesktopBinder } from './chunk-YCHJXSTC.js';
// src/adapters/svelte.ts
function createManager(options) {
return createWindowManager(options);
}
function wmStore(wm) {
return {
subscribe(run) {
run(wm.getState());
return wm.subscribe(run);
}
};
}
function wmWindowStore(wm, id) {
return {
subscribe(run) {
run(wm.get(id));
let last = wm.get(id);
return wm.subscribe(() => {
const next = wm.get(id);
if (next !== last) {
last = next;
run(next);
}
});
}
};
}
function createDesktop(wm, options) {
const binder = createDesktopBinder(wm, options);
return {
binder,
desktop(node) {
const unbind = binder.bindDesktop(node);
return { destroy: unbind };
},
window(node, params) {
let unbind = binder.bindWindow(params.id, node, params);
return {
update(next) {
unbind();
unbind = binder.bindWindow(next.id, node, next);
},
destroy() {
unbind();
}
};
}
};
}
export { createDesktop, createManager, wmStore, wmWindowStore };
//# sourceMappingURL=svelte.js.map
//# sourceMappingURL=svelte.js.map

1
web/node_modules/@surdeddd/wmkit/dist/svelte.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/adapters/svelte.ts"],"names":[],"mappings":";;;AAkBO,SAAS,cAAc,OAAA,EAAyC;AACrE,EAAA,OAAO,oBAAoB,OAAO,CAAA;AACpC;AAEO,SAAS,QAAQ,EAAA,EAAgD;AACtE,EAAA,OAAO;AAAA,IACL,UAAU,GAAA,EAAK;AACb,MAAA,GAAA,CAAI,EAAA,CAAG,UAAU,CAAA;AACjB,MAAA,OAAO,EAAA,CAAG,UAAU,GAAG,CAAA;AAAA,IACzB;AAAA,GACF;AACF;AAEO,SAAS,aAAA,CACd,IACA,EAAA,EACwC;AACxC,EAAA,OAAO;AAAA,IACL,UAAU,GAAA,EAAK;AACb,MAAA,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,EAAE,CAAC,CAAA;AACd,MAAA,IAAI,IAAA,GAAO,EAAA,CAAG,GAAA,CAAI,EAAE,CAAA;AACpB,MAAA,OAAO,EAAA,CAAG,UAAU,MAAM;AACxB,QAAA,MAAM,IAAA,GAAO,EAAA,CAAG,GAAA,CAAI,EAAE,CAAA;AACtB,QAAA,IAAI,SAAS,IAAA,EAAM;AACjB,UAAA,IAAA,GAAO,IAAA;AACP,UAAA,GAAA,CAAI,IAAI,CAAA;AAAA,QACV;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;AAQO,SAAS,aAAA,CAAc,IAAmB,OAAA,EAAyC;AACxF,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAC9C,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,QAAQ,IAAA,EAAM;AACZ,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,WAAA,CAAY,IAAI,CAAA;AACtC,MAAA,OAAO,EAAE,SAAS,MAAA,EAAO;AAAA,IAC3B,CAAA;AAAA,IACA,MAAA,CAAO,MAAM,MAAA,EAAQ;AACnB,MAAA,IAAI,SAAS,MAAA,CAAO,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,MAAM,MAAM,CAAA;AACtD,MAAA,OAAO;AAAA,QACL,OAAO,IAAA,EAAM;AACX,UAAA,MAAA,EAAO;AACP,UAAA,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,EAAA,EAAI,MAAM,IAAI,CAAA;AAAA,QAChD,CAAA;AAAA,QACA,OAAA,GAAU;AACR,UAAA,MAAA,EAAO;AAAA,QACT;AAAA,OACF;AAAA,IACF;AAAA,GACF;AACF","file":"svelte.js","sourcesContent":["import { 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\nexport interface ReadableStore<T> {\n subscribe(run: (value: T) => void): () => void\n}\n\nexport interface ActionResult {\n update?(params: WindowActionParams): void\n destroy(): void\n}\n\nexport interface WindowActionParams extends WindowAttachOptions {\n id: string\n}\n\nexport function createManager(options?: ManagerOptions): WindowManager {\n return createWindowManager(options)\n}\n\nexport function wmStore(wm: WindowManager): ReadableStore<ManagerState> {\n return {\n subscribe(run) {\n run(wm.getState())\n return wm.subscribe(run)\n },\n }\n}\n\nexport function wmWindowStore(\n wm: WindowManager,\n id: string,\n): ReadableStore<WindowState | undefined> {\n return {\n subscribe(run) {\n run(wm.get(id))\n let last = wm.get(id)\n return wm.subscribe(() => {\n const next = wm.get(id)\n if (next !== last) {\n last = next\n run(next)\n }\n })\n },\n }\n}\n\nexport interface SvelteDesktop {\n binder: DesktopBinder\n desktop(node: HTMLElement): ActionResult\n window(node: HTMLElement, params: WindowActionParams): ActionResult\n}\n\nexport function createDesktop(wm: WindowManager, options?: DesktopOptions): SvelteDesktop {\n const binder = createDesktopBinder(wm, options)\n return {\n binder,\n desktop(node) {\n const unbind = binder.bindDesktop(node)\n return { destroy: unbind }\n },\n window(node, params) {\n let unbind = binder.bindWindow(params.id, node, params)\n return {\n update(next) {\n unbind()\n unbind = binder.bindWindow(next.id, node, next)\n },\n destroy() {\n unbind()\n },\n }\n },\n }\n}\n"]}

202
web/node_modules/@surdeddd/wmkit/dist/themes/glass.css generated vendored Normal file
View File

@@ -0,0 +1,202 @@
[data-wm-desktop] {
--wm-radius: 14px;
--wm-bg: rgba(22, 24, 34, 0.55);
--wm-bg-focused: rgba(26, 28, 40, 0.68);
--wm-border: rgba(255, 255, 255, 0.09);
--wm-border-focused: rgba(255, 255, 255, 0.22);
--wm-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
--wm-shadow-focused: 0 18px 48px rgba(0, 0, 0, 0.5);
--wm-titlebar-bg: rgba(255, 255, 255, 0.04);
--wm-text: rgba(240, 242, 250, 0.92);
--wm-text-dim: rgba(240, 242, 250, 0.55);
--wm-accent: #7c6cff;
--wm-blur: 22px;
--wm-transition: 240ms cubic-bezier(0.32, 0.72, 0, 1);
position: relative;
overflow: hidden;
}
[data-wm-window] {
display: flex;
flex-direction: column;
box-sizing: border-box;
color: var(--wm-text);
background: var(--wm-bg);
-webkit-backdrop-filter: blur(var(--wm-blur)) saturate(1.4);
backdrop-filter: blur(var(--wm-blur)) saturate(1.4);
border: 1px solid var(--wm-border);
border-radius: var(--wm-radius);
box-shadow: var(--wm-shadow);
outline: none;
contain: layout style;
transition:
transform var(--wm-transition),
width var(--wm-transition),
height var(--wm-transition),
box-shadow 180ms ease,
border-color 180ms ease,
opacity 180ms ease;
animation: wm-window-in 220ms cubic-bezier(0.32, 0.72, 0, 1);
}
[data-wm-window][hidden] {
display: none;
}
[data-wm-window][data-wm-focused] {
background: var(--wm-bg-focused);
border-color: var(--wm-border-focused);
box-shadow: var(--wm-shadow-focused);
}
[data-wm-window][data-wm-dragging],
[data-wm-window][data-wm-resizing] {
transition:
box-shadow 180ms ease,
border-color 180ms ease;
user-select: none;
-webkit-user-select: none;
}
[data-wm-window][data-wm-stage="maximized"],
[data-wm-window][data-wm-stage="snapped"] {
border-radius: 0;
}
[data-wm-window][data-wm-flash] {
animation: wm-flash 320ms ease;
}
[data-wm-window] [data-wm-drag] {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
background: var(--wm-titlebar-bg);
border-bottom: 1px solid var(--wm-border);
border-radius: var(--wm-radius) var(--wm-radius) 0 0;
cursor: default;
user-select: none;
-webkit-user-select: none;
flex-shrink: 0;
}
[data-wm-window][data-wm-stage="maximized"] [data-wm-drag],
[data-wm-window][data-wm-stage="snapped"] [data-wm-drag] {
border-radius: 0;
}
[data-wm-window] [data-wm-title] {
flex: 1;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.01em;
color: var(--wm-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
[data-wm-window] [data-wm-controls] {
display: flex;
gap: 8px;
align-items: center;
}
[data-wm-window] [data-wm-close],
[data-wm-window] [data-wm-minimize],
[data-wm-window] [data-wm-maximize] {
width: 13px;
height: 13px;
border-radius: 50%;
border: none;
padding: 0;
cursor: pointer;
transition:
filter 120ms ease,
transform 120ms ease;
}
[data-wm-window] [data-wm-close]:hover,
[data-wm-window] [data-wm-minimize]:hover,
[data-wm-window] [data-wm-maximize]:hover {
filter: brightness(1.25);
transform: scale(1.12);
}
[data-wm-window] [data-wm-close]:focus-visible,
[data-wm-window] [data-wm-minimize]:focus-visible,
[data-wm-window] [data-wm-maximize]:focus-visible {
outline: 2px solid var(--wm-accent);
outline-offset: 2px;
}
[data-wm-window] [data-wm-close] {
background: #ff5f57;
}
[data-wm-window] [data-wm-minimize] {
background: #febc2e;
}
[data-wm-window] [data-wm-maximize] {
background: #28c840;
}
[data-wm-window] [data-wm-content] {
flex: 1;
overflow: auto;
padding: 14px;
font-size: 14px;
line-height: 1.55;
}
[data-wm-snap-preview] {
background: color-mix(in srgb, var(--wm-accent) 18%, transparent);
border: 1.5px solid color-mix(in srgb, var(--wm-accent) 55%, transparent);
border-radius: var(--wm-radius);
-webkit-backdrop-filter: blur(4px);
backdrop-filter: blur(4px);
transition:
transform 140ms cubic-bezier(0.32, 0.72, 0, 1),
width 140ms ease,
height 140ms ease;
}
@keyframes wm-window-in {
from {
opacity: 0;
scale: 0.96;
}
to {
opacity: 1;
scale: 1;
}
}
@keyframes wm-flash {
0%,
100% {
translate: 0 0;
}
20% {
translate: -6px 0;
}
45% {
translate: 5px 0;
}
70% {
translate: -3px 0;
}
90% {
translate: 2px 0;
}
}
@media (prefers-reduced-motion: reduce) {
[data-wm-window],
[data-wm-snap-preview] {
transition: none;
animation: none;
}
}

202
web/node_modules/@surdeddd/wmkit/dist/themes/light.css generated vendored Normal file
View File

@@ -0,0 +1,202 @@
[data-wm-desktop] {
--wm-radius: 12px;
--wm-bg: rgba(255, 255, 255, 0.78);
--wm-bg-focused: rgba(255, 255, 255, 0.94);
--wm-border: rgba(15, 23, 42, 0.1);
--wm-border-focused: rgba(15, 23, 42, 0.22);
--wm-shadow: 0 6px 22px rgba(15, 23, 42, 0.12);
--wm-shadow-focused: 0 16px 44px rgba(15, 23, 42, 0.2);
--wm-titlebar-bg: rgba(15, 23, 42, 0.03);
--wm-text: rgba(15, 23, 42, 0.92);
--wm-text-dim: rgba(15, 23, 42, 0.55);
--wm-accent: #4f46e5;
--wm-blur: 18px;
--wm-transition: 240ms cubic-bezier(0.32, 0.72, 0, 1);
position: relative;
overflow: hidden;
}
[data-wm-window] {
display: flex;
flex-direction: column;
box-sizing: border-box;
color: var(--wm-text);
background: var(--wm-bg);
-webkit-backdrop-filter: blur(var(--wm-blur)) saturate(1.2);
backdrop-filter: blur(var(--wm-blur)) saturate(1.2);
border: 1px solid var(--wm-border);
border-radius: var(--wm-radius);
box-shadow: var(--wm-shadow);
outline: none;
contain: layout style;
transition:
transform var(--wm-transition),
width var(--wm-transition),
height var(--wm-transition),
box-shadow 180ms ease,
border-color 180ms ease,
opacity 180ms ease;
animation: wm-window-in 220ms cubic-bezier(0.32, 0.72, 0, 1);
}
[data-wm-window][hidden] {
display: none;
}
[data-wm-window][data-wm-focused] {
background: var(--wm-bg-focused);
border-color: var(--wm-border-focused);
box-shadow: var(--wm-shadow-focused);
}
[data-wm-window][data-wm-dragging],
[data-wm-window][data-wm-resizing] {
transition:
box-shadow 180ms ease,
border-color 180ms ease;
user-select: none;
-webkit-user-select: none;
}
[data-wm-window][data-wm-stage="maximized"],
[data-wm-window][data-wm-stage="snapped"] {
border-radius: 0;
}
[data-wm-window][data-wm-flash] {
animation: wm-flash 320ms ease;
}
[data-wm-window] [data-wm-drag] {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
background: var(--wm-titlebar-bg);
border-bottom: 1px solid var(--wm-border);
border-radius: var(--wm-radius) var(--wm-radius) 0 0;
cursor: default;
user-select: none;
-webkit-user-select: none;
flex-shrink: 0;
}
[data-wm-window][data-wm-stage="maximized"] [data-wm-drag],
[data-wm-window][data-wm-stage="snapped"] [data-wm-drag] {
border-radius: 0;
}
[data-wm-window] [data-wm-title] {
flex: 1;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.01em;
color: var(--wm-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
[data-wm-window] [data-wm-controls] {
display: flex;
gap: 8px;
align-items: center;
}
[data-wm-window] [data-wm-close],
[data-wm-window] [data-wm-minimize],
[data-wm-window] [data-wm-maximize] {
width: 13px;
height: 13px;
border-radius: 50%;
border: none;
padding: 0;
cursor: pointer;
transition:
filter 120ms ease,
transform 120ms ease;
}
[data-wm-window] [data-wm-close]:hover,
[data-wm-window] [data-wm-minimize]:hover,
[data-wm-window] [data-wm-maximize]:hover {
filter: brightness(1.1);
transform: scale(1.12);
}
[data-wm-window] [data-wm-close]:focus-visible,
[data-wm-window] [data-wm-minimize]:focus-visible,
[data-wm-window] [data-wm-maximize]:focus-visible {
outline: 2px solid var(--wm-accent);
outline-offset: 2px;
}
[data-wm-window] [data-wm-close] {
background: #ff5f57;
}
[data-wm-window] [data-wm-minimize] {
background: #febc2e;
}
[data-wm-window] [data-wm-maximize] {
background: #28c840;
}
[data-wm-window] [data-wm-content] {
flex: 1;
overflow: auto;
padding: 14px;
font-size: 14px;
line-height: 1.55;
}
[data-wm-snap-preview] {
background: color-mix(in srgb, var(--wm-accent) 12%, transparent);
border: 1.5px solid color-mix(in srgb, var(--wm-accent) 45%, transparent);
border-radius: var(--wm-radius);
-webkit-backdrop-filter: blur(4px);
backdrop-filter: blur(4px);
transition:
transform 140ms cubic-bezier(0.32, 0.72, 0, 1),
width 140ms ease,
height 140ms ease;
}
@keyframes wm-window-in {
from {
opacity: 0;
scale: 0.96;
}
to {
opacity: 1;
scale: 1;
}
}
@keyframes wm-flash {
0%,
100% {
translate: 0 0;
}
20% {
translate: -6px 0;
}
45% {
translate: 5px 0;
}
70% {
translate: -3px 0;
}
90% {
translate: 2px 0;
}
}
@media (prefers-reduced-motion: reduce) {
[data-wm-window],
[data-wm-snap-preview] {
transition: none;
animation: none;
}
}

152
web/node_modules/@surdeddd/wmkit/dist/themes/retro.css generated vendored Normal file
View File

@@ -0,0 +1,152 @@
[data-wm-desktop] {
--wm-face: #c0c0c0;
--wm-face-light: #ffffff;
--wm-face-dark: #808080;
--wm-face-darker: #404040;
--wm-title-active-a: #000080;
--wm-title-active-b: #1084d0;
--wm-title-inactive: #808080;
--wm-text: #000000;
--wm-title-text: #ffffff;
position: relative;
overflow: hidden;
background: #008080;
}
[data-wm-window] {
display: flex;
flex-direction: column;
box-sizing: border-box;
color: var(--wm-text);
background: var(--wm-face);
border: 2px solid;
border-color: var(--wm-face-light) var(--wm-face-darker) var(--wm-face-darker)
var(--wm-face-light);
box-shadow: 1px 1px 0 var(--wm-face-dark);
outline: none;
contain: layout style;
font-family: "Pixelated MS Sans Serif", "MS Sans Serif", Tahoma, sans-serif;
}
[data-wm-window][hidden] {
display: none;
}
[data-wm-window][data-wm-flash] {
animation: wm-flash 320ms ease;
}
[data-wm-window] [data-wm-drag] {
display: flex;
align-items: center;
gap: 6px;
padding: 3px 4px;
margin: 2px;
background: linear-gradient(90deg, var(--wm-title-inactive), #b5b5b5);
cursor: default;
user-select: none;
-webkit-user-select: none;
flex-shrink: 0;
}
[data-wm-window][data-wm-focused] [data-wm-drag] {
background: linear-gradient(90deg, var(--wm-title-active-a), var(--wm-title-active-b));
}
[data-wm-window] [data-wm-title] {
flex: 1;
font-size: 12px;
font-weight: 700;
color: var(--wm-title-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
letter-spacing: 0;
}
[data-wm-window] [data-wm-controls] {
display: flex;
gap: 2px;
align-items: center;
}
[data-wm-window] [data-wm-close],
[data-wm-window] [data-wm-minimize],
[data-wm-window] [data-wm-maximize] {
width: 16px;
height: 14px;
border: 1px solid;
border-color: var(--wm-face-light) var(--wm-face-darker) var(--wm-face-darker)
var(--wm-face-light);
background: var(--wm-face);
padding: 0;
cursor: pointer;
font-size: 9px;
line-height: 1;
color: var(--wm-text);
}
[data-wm-window] [data-wm-close]:active,
[data-wm-window] [data-wm-minimize]:active,
[data-wm-window] [data-wm-maximize]:active {
border-color: var(--wm-face-darker) var(--wm-face-light) var(--wm-face-light)
var(--wm-face-darker);
}
[data-wm-window] [data-wm-close]:focus-visible,
[data-wm-window] [data-wm-minimize]:focus-visible,
[data-wm-window] [data-wm-maximize]:focus-visible {
outline: 1px dotted var(--wm-text);
outline-offset: -3px;
}
[data-wm-window] [data-wm-minimize]::after {
content: "_";
font-weight: 700;
}
[data-wm-window] [data-wm-maximize]::after {
content: "□";
font-weight: 700;
}
[data-wm-window] [data-wm-close]::after {
content: "✕";
font-weight: 700;
}
[data-wm-window] [data-wm-content] {
flex: 1;
overflow: auto;
padding: 8px;
margin: 0 2px 2px;
font-size: 12px;
line-height: 1.4;
background: var(--wm-face);
border: 1px solid;
border-color: var(--wm-face-dark) var(--wm-face-light) var(--wm-face-light) var(--wm-face-dark);
}
[data-wm-snap-preview] {
background: transparent;
border: 2px dashed var(--wm-face-darker);
}
@keyframes wm-flash {
0%,
100% {
translate: 0 0;
}
20% {
translate: -6px 0;
}
45% {
translate: 5px 0;
}
70% {
translate: -3px 0;
}
90% {
translate: 2px 0;
}
}

View File

@@ -0,0 +1,180 @@
interface Size {
width: number;
height: number;
}
interface Bounds {
x: number;
y: number;
width: number;
height: number;
}
type WindowStage = 'normal' | 'minimized' | 'maximized' | 'snapped';
type WindowLayer = 'normal' | 'floating' | 'modal';
type ArrangeMode = 'cascade' | 'tile';
type SnapZone = 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
interface WindowFlags {
draggable: boolean;
resizable: boolean;
closable: boolean;
minimizable: boolean;
maximizable: boolean;
snappable: boolean;
}
interface WindowState extends WindowFlags {
id: string;
title: string;
bounds: Bounds;
restoreBounds: Bounds | null;
restoreStage: WindowStage | null;
stage: WindowStage;
snapZone: SnapZone | null;
layer: WindowLayer;
minSize: Size;
maxSize: Size | null;
openedSeq: number;
meta: Record<string, unknown>;
}
interface WindowInit extends Partial<WindowFlags> {
id?: string;
title?: string;
x?: number;
y?: number;
width?: number;
height?: number;
minWidth?: number;
minHeight?: number;
maxWidth?: number;
maxHeight?: number;
stage?: WindowStage;
layer?: WindowLayer;
meta?: Record<string, unknown>;
}
interface HistoryEntry {
windows: Readonly<Record<string, WindowState>>;
order: readonly string[];
focusedId: string | null;
}
interface ManagerState {
windows: Readonly<Record<string, WindowState>>;
order: readonly string[];
focusedId: string | null;
viewport: Size;
}
interface SerializedMaxSize {
width: number | null;
height: number | null;
}
interface SerializedWindowState extends Omit<WindowState, 'maxSize'> {
maxSize: SerializedMaxSize | null;
}
interface SerializedState {
version: 1;
windows: SerializedWindowState[];
order: string[];
focusedId: string | null;
}
interface ManagerEvents {
open: {
window: WindowState;
};
close: {
window: WindowState;
};
focus: {
window: WindowState;
previous: string | null;
};
move: {
window: WindowState;
};
resize: {
window: WindowState;
};
stage: {
window: WindowState;
previous: WindowStage;
};
update: {
window: WindowState;
};
order: {
order: readonly string[];
};
modalblocked: {
window: WindowState;
};
change: {
state: ManagerState;
};
}
interface ManagerOptions {
viewport?: Size;
keepInViewport?: boolean;
minVisible?: number;
defaultSize?: Size;
cascadeOffset?: number;
cascadeOrigin?: {
x: number;
y: number;
};
idPrefix?: string;
historyLimit?: number;
}
interface WindowUpdate {
title?: string;
layer?: WindowLayer;
minSize?: Size;
maxSize?: Size | null;
meta?: Record<string, unknown>;
draggable?: boolean;
resizable?: boolean;
closable?: boolean;
minimizable?: boolean;
maximizable?: boolean;
snappable?: boolean;
}
interface WindowManager {
open(init?: WindowInit): WindowState;
close(id: string): boolean;
closeAll(): void;
focus(id: string): boolean;
blur(): void;
cycleFocus(direction?: 1 | -1): string | null;
minimize(id: string): boolean;
maximize(id: string): boolean;
toggleMaximize(id: string): boolean;
restore(id: string): boolean;
restoreTo(id: string, bounds: Bounds): boolean;
snap(id: string, zone: SnapZone): boolean;
move(id: string, x: number, y: number): boolean;
moveBy(id: string, dx: number, dy: number): boolean;
resize(id: string, patch: Partial<Bounds>): boolean;
update(id: string, patch: WindowUpdate): boolean;
get(id: string): WindowState | undefined;
getState(): ManagerState;
minimized(): readonly WindowState[];
setViewport(viewport: Size): void;
batch(run: () => void): void;
serialize(): SerializedState;
hydrate(data: SerializedState): boolean;
undo(): boolean;
redo(): boolean;
canUndo(): boolean;
canRedo(): boolean;
beginInteraction(): void;
endInteraction(): void;
saveLayout(name: string): SerializedState;
loadLayout(name: string): boolean;
getLayout(name: string): SerializedState | undefined;
setLayout(name: string, data: SerializedState): boolean;
deleteLayout(name: string): boolean;
layoutNames(): string[];
arrange(mode: ArrangeMode): void;
minimizeAll(): void;
restoreAll(): void;
subscribe(listener: (state: ManagerState) => void): () => void;
on<K extends keyof ManagerEvents>(event: K, listener: (payload: ManagerEvents[K]) => void): () => void;
destroy(): void;
}
export type { ArrangeMode as A, Bounds as B, HistoryEntry as H, ManagerOptions as M, SerializedMaxSize as S, WindowManager as W, ManagerState as a, WindowState as b, ManagerEvents as c, SerializedState as d, SerializedWindowState as e, Size as f, SnapZone as g, WindowFlags as h, WindowInit as i, WindowLayer as j, WindowStage as k, WindowUpdate as l };

View File

@@ -0,0 +1,180 @@
interface Size {
width: number;
height: number;
}
interface Bounds {
x: number;
y: number;
width: number;
height: number;
}
type WindowStage = 'normal' | 'minimized' | 'maximized' | 'snapped';
type WindowLayer = 'normal' | 'floating' | 'modal';
type ArrangeMode = 'cascade' | 'tile';
type SnapZone = 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
interface WindowFlags {
draggable: boolean;
resizable: boolean;
closable: boolean;
minimizable: boolean;
maximizable: boolean;
snappable: boolean;
}
interface WindowState extends WindowFlags {
id: string;
title: string;
bounds: Bounds;
restoreBounds: Bounds | null;
restoreStage: WindowStage | null;
stage: WindowStage;
snapZone: SnapZone | null;
layer: WindowLayer;
minSize: Size;
maxSize: Size | null;
openedSeq: number;
meta: Record<string, unknown>;
}
interface WindowInit extends Partial<WindowFlags> {
id?: string;
title?: string;
x?: number;
y?: number;
width?: number;
height?: number;
minWidth?: number;
minHeight?: number;
maxWidth?: number;
maxHeight?: number;
stage?: WindowStage;
layer?: WindowLayer;
meta?: Record<string, unknown>;
}
interface HistoryEntry {
windows: Readonly<Record<string, WindowState>>;
order: readonly string[];
focusedId: string | null;
}
interface ManagerState {
windows: Readonly<Record<string, WindowState>>;
order: readonly string[];
focusedId: string | null;
viewport: Size;
}
interface SerializedMaxSize {
width: number | null;
height: number | null;
}
interface SerializedWindowState extends Omit<WindowState, 'maxSize'> {
maxSize: SerializedMaxSize | null;
}
interface SerializedState {
version: 1;
windows: SerializedWindowState[];
order: string[];
focusedId: string | null;
}
interface ManagerEvents {
open: {
window: WindowState;
};
close: {
window: WindowState;
};
focus: {
window: WindowState;
previous: string | null;
};
move: {
window: WindowState;
};
resize: {
window: WindowState;
};
stage: {
window: WindowState;
previous: WindowStage;
};
update: {
window: WindowState;
};
order: {
order: readonly string[];
};
modalblocked: {
window: WindowState;
};
change: {
state: ManagerState;
};
}
interface ManagerOptions {
viewport?: Size;
keepInViewport?: boolean;
minVisible?: number;
defaultSize?: Size;
cascadeOffset?: number;
cascadeOrigin?: {
x: number;
y: number;
};
idPrefix?: string;
historyLimit?: number;
}
interface WindowUpdate {
title?: string;
layer?: WindowLayer;
minSize?: Size;
maxSize?: Size | null;
meta?: Record<string, unknown>;
draggable?: boolean;
resizable?: boolean;
closable?: boolean;
minimizable?: boolean;
maximizable?: boolean;
snappable?: boolean;
}
interface WindowManager {
open(init?: WindowInit): WindowState;
close(id: string): boolean;
closeAll(): void;
focus(id: string): boolean;
blur(): void;
cycleFocus(direction?: 1 | -1): string | null;
minimize(id: string): boolean;
maximize(id: string): boolean;
toggleMaximize(id: string): boolean;
restore(id: string): boolean;
restoreTo(id: string, bounds: Bounds): boolean;
snap(id: string, zone: SnapZone): boolean;
move(id: string, x: number, y: number): boolean;
moveBy(id: string, dx: number, dy: number): boolean;
resize(id: string, patch: Partial<Bounds>): boolean;
update(id: string, patch: WindowUpdate): boolean;
get(id: string): WindowState | undefined;
getState(): ManagerState;
minimized(): readonly WindowState[];
setViewport(viewport: Size): void;
batch(run: () => void): void;
serialize(): SerializedState;
hydrate(data: SerializedState): boolean;
undo(): boolean;
redo(): boolean;
canUndo(): boolean;
canRedo(): boolean;
beginInteraction(): void;
endInteraction(): void;
saveLayout(name: string): SerializedState;
loadLayout(name: string): boolean;
getLayout(name: string): SerializedState | undefined;
setLayout(name: string, data: SerializedState): boolean;
deleteLayout(name: string): boolean;
layoutNames(): string[];
arrange(mode: ArrangeMode): void;
minimizeAll(): void;
restoreAll(): void;
subscribe(listener: (state: ManagerState) => void): () => void;
on<K extends keyof ManagerEvents>(event: K, listener: (payload: ManagerEvents[K]) => void): () => void;
destroy(): void;
}
export type { ArrangeMode as A, Bounds as B, HistoryEntry as H, ManagerOptions as M, SerializedMaxSize as S, WindowManager as W, ManagerState as a, WindowState as b, ManagerEvents as c, SerializedState as d, SerializedWindowState as e, Size as f, SnapZone as g, WindowFlags as h, WindowInit as i, WindowLayer as j, WindowStage as k, WindowUpdate as l };

54
web/node_modules/@surdeddd/wmkit/dist/vue.cjs generated vendored Normal file
View File

@@ -0,0 +1,54 @@
'use strict';
var chunkB35DANTX_cjs = require('./chunk-B35DANTX.cjs');
var vue = require('vue');
function disposeWithScope(dispose) {
if (vue.getCurrentScope()) vue.onScopeDispose(dispose);
}
function useWindowManager(options) {
const wm = chunkB35DANTX_cjs.createWindowManager(options);
disposeWithScope(() => wm.destroy());
return wm;
}
function useWmState(wm) {
const state = vue.shallowRef(wm.getState());
disposeWithScope(
wm.subscribe((next) => {
state.value = next;
})
);
return state;
}
function useWmWindow(wm, id) {
const state = useWmState(wm);
return vue.computed(() => state.value.windows[vue.toValue(id)]);
}
function useDesktop(wm, target, options) {
const binder = chunkB35DANTX_cjs.createDesktopBinder(wm, options);
vue.watch(
target,
(element, _previous, onCleanup) => {
if (element) onCleanup(binder.bindDesktop(element));
},
{ immediate: true, flush: "post" }
);
return binder;
}
function useWmWindowEl(binder, id, target, options) {
vue.watch(
[target, () => vue.toValue(id)],
([element, windowId], _previous, onCleanup) => {
if (element && windowId) onCleanup(binder.bindWindow(windowId, element, options));
},
{ immediate: true, flush: "post" }
);
}
exports.useDesktop = useDesktop;
exports.useWindowManager = useWindowManager;
exports.useWmState = useWmState;
exports.useWmWindow = useWmWindow;
exports.useWmWindowEl = useWmWindowEl;
//# sourceMappingURL=vue.cjs.map
//# sourceMappingURL=vue.cjs.map

1
web/node_modules/@surdeddd/wmkit/dist/vue.cjs.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/adapters/vue.ts"],"names":["getCurrentScope","onScopeDispose","createWindowManager","shallowRef","computed","toValue","createDesktopBinder","watch"],"mappings":";;;;;AAiBA,SAAS,iBAAiB,OAAA,EAA2B;AACnD,EAAA,IAAIA,mBAAA,EAAgB,EAAGC,kBAAA,CAAe,OAAO,CAAA;AAC/C;AAEO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM,EAAA,GAAKC,sCAAoB,OAAO,CAAA;AACtC,EAAA,gBAAA,CAAiB,MAAM,EAAA,CAAG,OAAA,EAAS,CAAA;AACnC,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,WAAW,EAAA,EAA6C;AACtE,EAAA,MAAM,KAAA,GAAQC,cAAA,CAAW,EAAA,CAAG,QAAA,EAAU,CAAA;AACtC,EAAA,gBAAA;AAAA,IACE,EAAA,CAAG,SAAA,CAAU,CAAC,IAAA,KAAS;AACrB,MAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AAAA,IAChB,CAAC;AAAA,GACH;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,WAAA,CACd,IACA,EAAA,EACsC;AACtC,EAAA,MAAM,KAAA,GAAQ,WAAW,EAAE,CAAA;AAC3B,EAAA,OAAOC,YAAA,CAAS,MAAM,KAAA,CAAM,KAAA,CAAM,QAAQC,WAAA,CAAQ,EAAE,CAAC,CAAC,CAAA;AACxD;AAEO,SAAS,UAAA,CACd,EAAA,EACA,MAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,MAAA,GAASC,qCAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAC9C,EAAAC,SAAA;AAAA,IACE,MAAA;AAAA,IACA,CAAC,OAAA,EAAS,SAAA,EAAW,SAAA,KAAc;AACjC,MAAA,IAAI,OAAA,EAAS,SAAA,CAAU,MAAA,CAAO,WAAA,CAAY,OAAO,CAAC,CAAA;AAAA,IACpD,CAAA;AAAA,IACA,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,MAAA;AAAO,GACnC;AACA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,aAAA,CACd,MAAA,EACA,EAAA,EACA,MAAA,EACA,OAAA,EACM;AACN,EAAAA,SAAA;AAAA,IACE,CAAC,MAAA,EAAQ,MAAMF,WAAA,CAAQ,EAAE,CAAC,CAAA;AAAA,IAC1B,CAAC,CAAC,OAAA,EAAS,QAAQ,CAAA,EAAG,WAAW,SAAA,KAAc;AAC7C,MAAA,IAAI,OAAA,IAAW,UAAU,SAAA,CAAU,MAAA,CAAO,WAAW,QAAA,EAAU,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,IAClF,CAAA;AAAA,IACA,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,MAAA;AAAO,GACnC;AACF","file":"vue.cjs","sourcesContent":["import {\n type ComputedRef,\n computed,\n getCurrentScope,\n type MaybeRefOrGetter,\n onScopeDispose,\n type Ref,\n type ShallowRef,\n shallowRef,\n toValue,\n watch,\n} from 'vue'\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 disposeWithScope(dispose: () => void): void {\n if (getCurrentScope()) onScopeDispose(dispose)\n}\n\nexport function useWindowManager(options?: ManagerOptions): WindowManager {\n const wm = createWindowManager(options)\n disposeWithScope(() => wm.destroy())\n return wm\n}\n\nexport function useWmState(wm: WindowManager): ShallowRef<ManagerState> {\n const state = shallowRef(wm.getState())\n disposeWithScope(\n wm.subscribe((next) => {\n state.value = next\n }),\n )\n return state\n}\n\nexport function useWmWindow(\n wm: WindowManager,\n id: MaybeRefOrGetter<string>,\n): ComputedRef<WindowState | undefined> {\n const state = useWmState(wm)\n return computed(() => state.value.windows[toValue(id)])\n}\n\nexport function useDesktop(\n wm: WindowManager,\n target: Ref<HTMLElement | null | undefined>,\n options?: DesktopOptions,\n): DesktopBinder {\n const binder = createDesktopBinder(wm, options)\n watch(\n target,\n (element, _previous, onCleanup) => {\n if (element) onCleanup(binder.bindDesktop(element))\n },\n { immediate: true, flush: 'post' },\n )\n return binder\n}\n\nexport function useWmWindowEl(\n binder: DesktopBinder,\n id: MaybeRefOrGetter<string>,\n target: Ref<HTMLElement | null | undefined>,\n options?: WindowAttachOptions,\n): void {\n watch(\n [target, () => toValue(id)],\n ([element, windowId], _previous, onCleanup) => {\n if (element && windowId) onCleanup(binder.bindWindow(windowId, element, options))\n },\n { immediate: true, flush: 'post' },\n )\n}\n"]}

11
web/node_modules/@surdeddd/wmkit/dist/vue.d.cts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
import { Ref, ShallowRef, MaybeRefOrGetter, ComputedRef } from 'vue';
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.cjs';
import { a as DesktopOptions, D as DesktopBinder, W as WindowAttachOptions } from './binder-Dq_AZRbo.cjs';
declare function useWindowManager(options?: ManagerOptions): WindowManager;
declare function useWmState(wm: WindowManager): ShallowRef<ManagerState>;
declare function useWmWindow(wm: WindowManager, id: MaybeRefOrGetter<string>): ComputedRef<WindowState | undefined>;
declare function useDesktop(wm: WindowManager, target: Ref<HTMLElement | null | undefined>, options?: DesktopOptions): DesktopBinder;
declare function useWmWindowEl(binder: DesktopBinder, id: MaybeRefOrGetter<string>, target: Ref<HTMLElement | null | undefined>, options?: WindowAttachOptions): void;
export { useDesktop, useWindowManager, useWmState, useWmWindow, useWmWindowEl };

11
web/node_modules/@surdeddd/wmkit/dist/vue.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
import { Ref, ShallowRef, MaybeRefOrGetter, ComputedRef } from 'vue';
import { W as WindowManager, M as ManagerOptions, a as ManagerState, b as WindowState } from './types-DdCtDHgt.js';
import { a as DesktopOptions, D as DesktopBinder, W as WindowAttachOptions } from './binder-0Oku22Nc.js';
declare function useWindowManager(options?: ManagerOptions): WindowManager;
declare function useWmState(wm: WindowManager): ShallowRef<ManagerState>;
declare function useWmWindow(wm: WindowManager, id: MaybeRefOrGetter<string>): ComputedRef<WindowState | undefined>;
declare function useDesktop(wm: WindowManager, target: Ref<HTMLElement | null | undefined>, options?: DesktopOptions): DesktopBinder;
declare function useWmWindowEl(binder: DesktopBinder, id: MaybeRefOrGetter<string>, target: Ref<HTMLElement | null | undefined>, options?: WindowAttachOptions): void;
export { useDesktop, useWindowManager, useWmState, useWmWindow, useWmWindowEl };

48
web/node_modules/@surdeddd/wmkit/dist/vue.js generated vendored Normal file
View File

@@ -0,0 +1,48 @@
import { createWindowManager, createDesktopBinder } from './chunk-YCHJXSTC.js';
import { shallowRef, computed, toValue, watch, getCurrentScope, onScopeDispose } from 'vue';
function disposeWithScope(dispose) {
if (getCurrentScope()) onScopeDispose(dispose);
}
function useWindowManager(options) {
const wm = createWindowManager(options);
disposeWithScope(() => wm.destroy());
return wm;
}
function useWmState(wm) {
const state = shallowRef(wm.getState());
disposeWithScope(
wm.subscribe((next) => {
state.value = next;
})
);
return state;
}
function useWmWindow(wm, id) {
const state = useWmState(wm);
return computed(() => state.value.windows[toValue(id)]);
}
function useDesktop(wm, target, options) {
const binder = createDesktopBinder(wm, options);
watch(
target,
(element, _previous, onCleanup) => {
if (element) onCleanup(binder.bindDesktop(element));
},
{ immediate: true, flush: "post" }
);
return binder;
}
function useWmWindowEl(binder, id, target, options) {
watch(
[target, () => toValue(id)],
([element, windowId], _previous, onCleanup) => {
if (element && windowId) onCleanup(binder.bindWindow(windowId, element, options));
},
{ immediate: true, flush: "post" }
);
}
export { useDesktop, useWindowManager, useWmState, useWmWindow, useWmWindowEl };
//# sourceMappingURL=vue.js.map
//# sourceMappingURL=vue.js.map

1
web/node_modules/@surdeddd/wmkit/dist/vue.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/adapters/vue.ts"],"names":[],"mappings":";;;AAiBA,SAAS,iBAAiB,OAAA,EAA2B;AACnD,EAAA,IAAI,eAAA,EAAgB,EAAG,cAAA,CAAe,OAAO,CAAA;AAC/C;AAEO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM,EAAA,GAAK,oBAAoB,OAAO,CAAA;AACtC,EAAA,gBAAA,CAAiB,MAAM,EAAA,CAAG,OAAA,EAAS,CAAA;AACnC,EAAA,OAAO,EAAA;AACT;AAEO,SAAS,WAAW,EAAA,EAA6C;AACtE,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,EAAA,CAAG,QAAA,EAAU,CAAA;AACtC,EAAA,gBAAA;AAAA,IACE,EAAA,CAAG,SAAA,CAAU,CAAC,IAAA,KAAS;AACrB,MAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AAAA,IAChB,CAAC;AAAA,GACH;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,WAAA,CACd,IACA,EAAA,EACsC;AACtC,EAAA,MAAM,KAAA,GAAQ,WAAW,EAAE,CAAA;AAC3B,EAAA,OAAO,QAAA,CAAS,MAAM,KAAA,CAAM,KAAA,CAAM,QAAQ,OAAA,CAAQ,EAAE,CAAC,CAAC,CAAA;AACxD;AAEO,SAAS,UAAA,CACd,EAAA,EACA,MAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAC9C,EAAA,KAAA;AAAA,IACE,MAAA;AAAA,IACA,CAAC,OAAA,EAAS,SAAA,EAAW,SAAA,KAAc;AACjC,MAAA,IAAI,OAAA,EAAS,SAAA,CAAU,MAAA,CAAO,WAAA,CAAY,OAAO,CAAC,CAAA;AAAA,IACpD,CAAA;AAAA,IACA,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,MAAA;AAAO,GACnC;AACA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,aAAA,CACd,MAAA,EACA,EAAA,EACA,MAAA,EACA,OAAA,EACM;AACN,EAAA,KAAA;AAAA,IACE,CAAC,MAAA,EAAQ,MAAM,OAAA,CAAQ,EAAE,CAAC,CAAA;AAAA,IAC1B,CAAC,CAAC,OAAA,EAAS,QAAQ,CAAA,EAAG,WAAW,SAAA,KAAc;AAC7C,MAAA,IAAI,OAAA,IAAW,UAAU,SAAA,CAAU,MAAA,CAAO,WAAW,QAAA,EAAU,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,IAClF,CAAA;AAAA,IACA,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,MAAA;AAAO,GACnC;AACF","file":"vue.js","sourcesContent":["import {\n type ComputedRef,\n computed,\n getCurrentScope,\n type MaybeRefOrGetter,\n onScopeDispose,\n type Ref,\n type ShallowRef,\n shallowRef,\n toValue,\n watch,\n} from 'vue'\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 disposeWithScope(dispose: () => void): void {\n if (getCurrentScope()) onScopeDispose(dispose)\n}\n\nexport function useWindowManager(options?: ManagerOptions): WindowManager {\n const wm = createWindowManager(options)\n disposeWithScope(() => wm.destroy())\n return wm\n}\n\nexport function useWmState(wm: WindowManager): ShallowRef<ManagerState> {\n const state = shallowRef(wm.getState())\n disposeWithScope(\n wm.subscribe((next) => {\n state.value = next\n }),\n )\n return state\n}\n\nexport function useWmWindow(\n wm: WindowManager,\n id: MaybeRefOrGetter<string>,\n): ComputedRef<WindowState | undefined> {\n const state = useWmState(wm)\n return computed(() => state.value.windows[toValue(id)])\n}\n\nexport function useDesktop(\n wm: WindowManager,\n target: Ref<HTMLElement | null | undefined>,\n options?: DesktopOptions,\n): DesktopBinder {\n const binder = createDesktopBinder(wm, options)\n watch(\n target,\n (element, _previous, onCleanup) => {\n if (element) onCleanup(binder.bindDesktop(element))\n },\n { immediate: true, flush: 'post' },\n )\n return binder\n}\n\nexport function useWmWindowEl(\n binder: DesktopBinder,\n id: MaybeRefOrGetter<string>,\n target: Ref<HTMLElement | null | undefined>,\n options?: WindowAttachOptions,\n): void {\n watch(\n [target, () => toValue(id)],\n ([element, windowId], _previous, onCleanup) => {\n if (element && windowId) onCleanup(binder.bindWindow(windowId, element, options))\n },\n { immediate: true, flush: 'post' },\n )\n}\n"]}

284
web/node_modules/@surdeddd/wmkit/package.json generated vendored Normal file
View File

@@ -0,0 +1,284 @@
{
"name": "@surdeddd/wmkit",
"version": "0.3.0",
"description": "Headless, framework-agnostic window manager for the web — draggable, resizable, snappable windows with first-class accessibility and 60fps performance",
"keywords": [
"window-manager",
"windows",
"draggable",
"resizable",
"floating",
"snap",
"headless",
"desktop",
"taskbar",
"react",
"vue",
"svelte",
"solid"
],
"license": "MIT",
"author": "Maksim Kravcov (https://github.com/Surdeddd)",
"repository": {
"type": "git",
"url": "git+https://github.com/Surdeddd/wmkit.git"
},
"homepage": "https://surdeddd.github.io/wmkit/",
"bugs": "https://github.com/Surdeddd/wmkit/issues",
"publishConfig": {
"access": "public",
"provenance": true
},
"type": "module",
"sideEffects": [
"**/*.css"
],
"engines": {
"node": ">=20"
},
"packageManager": "pnpm@10.32.1",
"files": [
"dist"
],
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
},
"./react": {
"import": {
"types": "./dist/react.d.ts",
"default": "./dist/react.js"
},
"require": {
"types": "./dist/react.d.cts",
"default": "./dist/react.cjs"
}
},
"./vue": {
"import": {
"types": "./dist/vue.d.ts",
"default": "./dist/vue.js"
},
"require": {
"types": "./dist/vue.d.cts",
"default": "./dist/vue.cjs"
}
},
"./svelte": {
"import": {
"types": "./dist/svelte.d.ts",
"default": "./dist/svelte.js"
},
"require": {
"types": "./dist/svelte.d.cts",
"default": "./dist/svelte.cjs"
}
},
"./solid": {
"import": {
"types": "./dist/solid.d.ts",
"default": "./dist/solid.js"
},
"require": {
"types": "./dist/solid.d.cts",
"default": "./dist/solid.cjs"
}
},
"./angular": {
"import": {
"types": "./dist/angular.d.ts",
"default": "./dist/angular.js"
},
"require": {
"types": "./dist/angular.d.cts",
"default": "./dist/angular.cjs"
}
},
"./persist": {
"import": {
"types": "./dist/persist.d.ts",
"default": "./dist/persist.js"
},
"require": {
"types": "./dist/persist.d.cts",
"default": "./dist/persist.cjs"
}
},
"./popout": {
"import": {
"types": "./dist/popout.d.ts",
"default": "./dist/popout.js"
},
"require": {
"types": "./dist/popout.d.cts",
"default": "./dist/popout.cjs"
}
},
"./themes/*": "./dist/themes/*",
"./package.json": "./package.json"
},
"scripts": {
"build": "tsup",
"dev": "vite site",
"site:build": "vite build site",
"site:preview": "vite preview site",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"test:e2e": "playwright test",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"typecheck": "tsc --noEmit",
"size": "size-limit",
"attw": "attw --pack .",
"publint": "publint",
"prepublishOnly": "pnpm build",
"verify": "pnpm lint && pnpm typecheck && pnpm test:coverage && pnpm build && pnpm size && pnpm publint && pnpm attw && pnpm test:e2e",
"release": "semantic-release",
"bench": "vitest bench --run"
},
"peerDependencies": {
"@angular/core": ">=16",
"react": ">=18",
"solid-js": ">=1.8",
"svelte": ">=4",
"vue": ">=3.3"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"solid-js": {
"optional": true
},
"svelte": {
"optional": true
},
"vue": {
"optional": true
},
"@angular/core": {
"optional": true
}
},
"devDependencies": {
"@angular/core": "^20.3.26",
"@arethetypeswrong/cli": "^0.18.2",
"@axe-core/playwright": "^4.10.2",
"@biomejs/biome": "^2.0.0",
"@playwright/test": "^1.53.2",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@size-limit/preset-small-lib": "^11.2.0",
"@testing-library/react": "^16.3.0",
"@types/node": "^24.0.0",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitest/coverage-v8": "^3.2.4",
"jsdom": "^26.1.0",
"publint": "^0.3.12",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"semantic-release": "^25.0.6",
"size-limit": "^11.2.0",
"solid-js": "^1.9.7",
"svelte": "^5.35.2",
"tsup": "^8.5.0",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vitest": "^3.2.4",
"vue": "^3.5.17"
},
"size-limit": [
{
"name": "core",
"path": "dist/index.js",
"limit": "10 kB"
},
{
"name": "react adapter",
"path": "dist/react.js",
"limit": "10 kB",
"ignore": [
"react"
]
},
{
"name": "vue adapter",
"path": "dist/vue.js",
"limit": "10 kB",
"ignore": [
"vue"
]
},
{
"name": "svelte adapter",
"path": "dist/svelte.js",
"limit": "10 kB",
"ignore": [
"svelte"
]
},
{
"name": "solid adapter",
"path": "dist/solid.js",
"limit": "10 kB",
"ignore": [
"solid-js"
]
},
{
"name": "angular adapter",
"path": "dist/angular.js",
"limit": "10 kB",
"ignore": [
"@angular/core"
]
},
{
"name": "persist plugin",
"path": "dist/persist.js",
"limit": "1 kB"
},
{
"name": "popout plugin",
"path": "dist/popout.js",
"limit": "1 kB"
}
],
"typesVersions": {
"*": {
"react": [
"./dist/react.d.ts"
],
"vue": [
"./dist/vue.d.ts"
],
"svelte": [
"./dist/svelte.d.ts"
],
"solid": [
"./dist/solid.d.ts"
],
"persist": [
"./dist/persist.d.ts"
],
"popout": [
"./dist/popout.d.ts"
],
"angular": [
"./dist/angular.d.ts"
]
}
}
}