vintage-frames 0.12.1 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,30 @@
1
1
  import { LitElement, type PropertyValues } from 'lit';
2
2
  import './vf-scroll-area.js';
3
+ /** A box in viewport CSS px. A `DOMRect` is one; a zero-size box is a point. */
4
+ export interface VfViewportBox {
5
+ left: number;
6
+ top: number;
7
+ right: number;
8
+ bottom: number;
9
+ }
10
+ /** The options of {@link VfWindow.show}. */
11
+ export interface VfWindowShowOptions {
12
+ /**
13
+ * The box the window opens from, in viewport CSS px — an icon's
14
+ * `cellRect()`, a button's `getBoundingClientRect()`, any rect. Unset, the
15
+ * window shows at once.
16
+ */
17
+ from?: VfViewportBox | null;
18
+ }
19
+ /** The options of {@link VfWindow.hide}. */
20
+ export interface VfWindowHideOptions {
21
+ /**
22
+ * The box the window closes to, in viewport CSS px — an icon's
23
+ * `cellRect()`, a button's `getBoundingClientRect()`, any rect. Unset, the
24
+ * window hides at once.
25
+ */
26
+ to?: VfViewportBox | null;
27
+ }
3
28
  declare const VfWindow_base: (new (...args: any[]) => import("../size.js").VfSizedInterface) & (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
4
29
  /**
5
30
  * `<vf-window>` — the System 7 desktop-window shell.
@@ -29,6 +54,32 @@ declare const VfWindow_base: (new (...args: any[]) => import("../size.js").VfSiz
29
54
  * Unset, the window still renders — normal block layout, as before — and
30
55
  * says so once in the console.
31
56
  *
57
+ * **Opening from a rect.** {@link show} clears `hidden`, and given `from` — a
58
+ * box in viewport CSS px, an icon's `cellRect()` or a button's rect — opens
59
+ * the window from it: dotted rectangles grow from that box toward the
60
+ * window's frame, four on screen at a time, bunched at the box and opening
61
+ * out toward the window, drawn with the icon drag outline's XOR pen on the
62
+ * desktop's drag surface; the window draws once they have drained, eighteen
63
+ * steps later. Until then it matches `:state(opening)` and paints nothing —
64
+ * still laid out, focusable and a hit target, so a page can place it, raise
65
+ * it and focus into it at once, and a press finishes the rects and lands on
66
+ * the window. Under `prefers-reduced-motion`, with no `vf-desktop` on its
67
+ * path, or without `from`, the window shows at once.
68
+ *
69
+ * **Closing to a rect.** {@link hide} sets `hidden`, and given `to` closes
70
+ * the window to it: the same rectangles run the other way, from where the
71
+ * frame was in toward the box, the window gone from the first step. A press
72
+ * finishes them, and removing the window leaves them running. Under
73
+ * `prefers-reduced-motion`, with no `vf-desktop` on its path, or without
74
+ * `to`, the window hides at once. The window knows nothing about icons:
75
+ * `from` and `to` are any rect.
76
+ *
77
+ * **Dragging as an outline.** A `movable` window moves live under the
78
+ * pointer. With `outline-drag` a press on the title bar draws a dotted
79
+ * outline around the window on the desktop's drag surface instead, with the
80
+ * same pen; the drag moves the outline, held where the window can land, and
81
+ * the window moves there on the release. Escape cancels.
82
+ *
32
83
  * @slot - Default slot: window body content.
33
84
  * @slot header - Optional header content — a band between the title bar and
34
85
  * the body, the full width of the window (the Finder window's header
@@ -101,6 +152,16 @@ export declare class VfWindow extends VfWindow_base {
101
152
  zoomable: boolean;
102
153
  /** Allow dragging the window by its title bar. */
103
154
  movable: boolean;
155
+ /**
156
+ * Drag by the title bar as an outline: a press draws a dotted one-pixel
157
+ * rectangle around the window on the desktop's drag surface, with the
158
+ * icon drag outline's pen; the drag moves it, held where the window can
159
+ * land, and the window moves there on the release, in one write. Escape
160
+ * cancels and writes nothing, as does a release that never moved it.
161
+ * Unset, the window moves live under the pointer; with no `vf-desktop` on
162
+ * its path it moves live either way. Only matters with `movable`.
163
+ */
164
+ outlineDrag: boolean;
104
165
  /**
105
166
  * Show a grow box at the bottom-right corner for resizing. The drag is
106
167
  * bounded per axis by the sizeRect below.
@@ -217,6 +278,34 @@ export declare class VfWindow extends VfWindow_base {
217
278
  * `vf-scroll-area.measure()` is.
218
279
  */
219
280
  measure(): void;
281
+ /**
282
+ * Show the window: `hidden` cleared, and with `from` the window opens from
283
+ * that box — the zoom rects, grown from it toward the frame at the cadence
284
+ * in src/motion.ts (`WINDOW_RECT_*`), the window drawn once they have
285
+ * drained (see the class doc). A run in flight, a `show()` or a `hide()`,
286
+ * is finished first; a press anywhere or Escape finishes this one, and
287
+ * removing the window or a `hide()` takes it down. Resolves once the
288
+ * window draws: `true` when the rects ran, `false` when it showed at once
289
+ * — no `from`, `prefers-reduced-motion`, no `vf-desktop` on its path,
290
+ * nothing of the rects on the screen, or not in the DOM — or never drew.
291
+ * It raises and activates nothing: stacking stays the page's
292
+ * (`vf-desktop.bringToFront`).
293
+ */
294
+ show(options?: VfWindowShowOptions): Promise<boolean>;
295
+ /**
296
+ * Hide the window: `hidden` set, and with `to` the window closes to that
297
+ * box — the rects of {@link show} run the other way, from where the frame
298
+ * is drawn at the call in toward the box, the window gone from their first
299
+ * step. A `show()` still opening is taken down and says `false`; a second
300
+ * `hide()` finishes the first; a press anywhere or Escape finishes the
301
+ * rects; removing the window leaves them running, so a page can remove a
302
+ * window as it closes it. Resolves once the rects are done: `true` when
303
+ * they ran, `false` when the window hid at once — no `to`,
304
+ * `prefers-reduced-motion`, no `vf-desktop` on its path, nothing of the
305
+ * rects on the screen, not in the DOM, or no frame to close from: already
306
+ * hidden, or still opening.
307
+ */
308
+ hide(options?: VfWindowHideOptions): Promise<boolean>;
220
309
  /**
221
310
  * Say something the first time a window is opened without a width. The size
222
311
  * itself is written by VfSized's controller, from `width`/`height` — which
@@ -231,6 +320,7 @@ export declare class VfWindow extends VfWindow_base {
231
320
  * window content follow the grow box without a ResizeObserver.
232
321
  */
233
322
  protected updated(): void;
323
+ connectedCallback(): void;
234
324
  disconnectedCallback(): void;
235
325
  /** The `.empty` gate: the strip renders only while the slot is populated. */
236
326
  private _onStatusSlotChange;
@@ -1,58 +1,100 @@
1
1
  import { emit as e } from "../events.js";
2
2
  import { vfElement as t } from "../define.js";
3
- import { ScaleController as n, snapSys as r, sysLength as i, toSysExact as a } from "../scale.js";
4
- import o from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
5
- import { PlacementController as s, VfPositioned as c, placementIn as l, warnMovableContract as u } from "../position.js";
6
- import { vfBase as d } from "../styles/recipes/host.js";
7
- import { DOT_MOTIF as f, DOT_RECTS as p, DOT_SPAN as m, vfDots as h, vfStripes as g } from "../styles/recipes/pattern.js";
8
- import { vfChromeFrame as _ } from "../styles/recipes/surface.js";
9
- import { vfRule as v } from "../styles/recipes/rule.js";
10
- import { vfTitleBar as y, vfWindowWidgets as b } from "../styles/recipes/title-bar.js";
11
- import { vfFocus as x } from "../styles/recipes/focus.js";
12
- import { TileRasterCache as S, patternOverride as C, tileGrid as w, vfTileGrid as T } from "../tile-grid.js";
13
- import { GridSnapController as E } from "../grid-snap.js";
14
- import { VfSized as D } from "../size.js";
15
- import { DragController as O } from "../drag.js";
16
- import { TitleCenterController as k, chromeTitleBar as A, closeBox as j, widgetLabel as M, zoomBox as N } from "../chrome.js";
3
+ import { ScaleController as n, effectiveScale as r, snapSys as i, sysLength as a, toSysExact as o } from "../scale.js";
4
+ import s from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
5
+ import { PlacementController as c, VfPositioned as l, placementIn as u, warnMovableContract as d } from "../position.js";
6
+ import { vfBase as f } from "../styles/recipes/host.js";
7
+ import { DOT_MOTIF as p, DOT_RECTS as m, DOT_SPAN as h, vfDots as g, vfStripes as _ } from "../styles/recipes/pattern.js";
8
+ import { vfChromeFrame as v } from "../styles/recipes/surface.js";
9
+ import { vfRule as y } from "../styles/recipes/rule.js";
10
+ import { vfTitleBar as b, vfWindowWidgets as x } from "../styles/recipes/title-bar.js";
11
+ import { vfFocus as S } from "../styles/recipes/focus.js";
12
+ import { TileRasterCache as C, patternOverride as w, tileGrid as T, vfTileGrid as E } from "../tile-grid.js";
13
+ import { GridSnapController as D } from "../grid-snap.js";
14
+ import { DocumentListenersController as O } from "../document-listeners.js";
15
+ import { VfSized as k } from "../size.js";
16
+ import { DragController as A } from "../drag.js";
17
+ import { TitleCenterController as j, chromeTitleBar as M, closeBox as N, widgetLabel as P, zoomBox as F } from "../chrome.js";
18
+ import { prefersReducedMotion as I, windowRectFraction as L } from "../motion.js";
19
+ import { paintSelectionRect as R, penPhase as z, xorPenCanvas as B } from "../open-art.js";
17
20
  import "./vf-scroll-area.js";
18
- import { LitElement as P, css as F, html as I, nothing as L } from "lit";
19
- import { property as R, query as z, state as B } from "lit/decorators.js";
21
+ import { LitElement as V, css as H, html as U, nothing as W } from "lit";
22
+ import { property as G, query as K, state as q } from "lit/decorators.js";
20
23
  //#region src/components/vf-window.ts
21
- var V = 80, H = 54;
22
- function U(e, t, n) {
24
+ var J = 80, Y = 54;
25
+ function X(e, t, n) {
23
26
  let r = Math.max(t, e);
24
27
  return n == null ? r : Math.min(n, r);
25
28
  }
26
- var W = 24, G = 8, K = class extends D(c(P)) {
29
+ var Z = 24, Q = 8, $ = class extends k(l(V)) {
27
30
  constructor(...e) {
28
- super(...e), this.heading = "", this.active = !0, this.closable = !0, this.zoomable = !1, this.movable = !1, this.resizable = !1, this._hasHeader = !1, this._hasStatus = !1, this.scale = new n(this), this.gridSnap = new E(this), this.titleCenter = new k(this), this._dotsPattern = "", this.#e = new S(), this.#t = (e, t, n) => {
29
- let r = a(this.offsetWidth, this);
31
+ super(...e), this.heading = "", this.active = !0, this.closable = !0, this.zoomable = !1, this.movable = !1, this.outlineDrag = !1, this.resizable = !1, this._hasHeader = !1, this._hasStatus = !1, this.scale = new n(this), this.gridSnap = new D(this), this.titleCenter = new j(this), this._dotsPattern = "", this.#e = new C(), this.#t = (e, t, n) => {
32
+ let r = o(this.offsetWidth, this);
30
33
  return {
31
- x: Math.min(Math.max(e, W - r), n.width - W),
32
- y: Math.min(Math.max(t, 0), Math.max(0, n.height - W))
34
+ x: Math.min(Math.max(e, Z - r), n.width - Z),
35
+ y: Math.min(Math.max(t, 0), Math.max(0, n.height - Z))
33
36
  };
34
- }, this._placement = new s(this, (e, t, n) => this.#t(e, t, n)), this._drag = new O(this, {
35
- onDragStart: (e) => !this.movable || e.button !== 0 || e.composedPath().some((e) => e instanceof HTMLElement && e.classList.contains("box")) ? null : (this.#i(), this._placement.seed()),
36
- onDrag: (e, t) => this._placement.moveTo(e, t)
37
- }), this._resizeState = null, this.#n = !1, this.#r = !1;
37
+ }, this._placement = new c(this, (e, t, n) => this.#t(e, t, n)), this._drag = new A(this, {
38
+ onDragStart: (e) => {
39
+ if (!this.movable || e.button !== 0 || e.composedPath().some((e) => e instanceof HTMLElement && e.classList.contains("box"))) return null;
40
+ this.#S();
41
+ let t = this._placement.seed();
42
+ return this.#h(t), t;
43
+ },
44
+ onDrag: (e, t) => {
45
+ this.#f ? this.#g(e, t) : this._placement.moveTo(e, t);
46
+ },
47
+ onDragEnd: (e, t) => {
48
+ this.#y(t);
49
+ }
50
+ }), this._resizeState = null, this.#n = this.attachInternals(), this.#r = null, this.#i = new O(this, () => [[
51
+ document,
52
+ "pointerdown",
53
+ this.#a,
54
+ !0
55
+ ], [
56
+ document,
57
+ "keydown",
58
+ this.#o,
59
+ !0
60
+ ]]), this.#a = () => {
61
+ this.#s("finish");
62
+ }, this.#o = (e) => {
63
+ e.key !== "Escape" || !this.#r || (e.preventDefault(), e.stopPropagation(), this.#s("finish"));
64
+ }, this.#f = null, this.#p = new O(this, () => [[
65
+ document,
66
+ "keydown",
67
+ this.#m,
68
+ !0
69
+ ]]), this.#m = (e) => {
70
+ e.key !== "Escape" || !this.#f || (e.preventDefault(), e.stopPropagation(), this._drag.cancel());
71
+ }, this.#b = !1, this.#x = !1;
38
72
  }
39
73
  static {
40
74
  this.styles = [
41
- d,
42
- g,
43
- h,
44
- T,
45
- x,
75
+ f,
46
76
  _,
77
+ g,
78
+ E,
79
+ S,
47
80
  v,
48
81
  y,
49
82
  b,
50
- F`
83
+ x,
84
+ H`
51
85
  :host {
52
86
  display: block;
53
87
  position: relative;
54
88
  --vf-surface: var(--vf-white, #ffffff);
55
89
  }
90
+ /* Opening from a rect (show): laid out, focusable and a hit target,
91
+ painting nothing until the rects have drained. Opacity rather than
92
+ visibility, which would drop focus and hand a press to whatever is
93
+ under the window. A rule of its own, never in an :is() list: an
94
+ engine that cannot parse :state() drops the whole list. */
95
+ :host(:state(opening)) {
96
+ opacity: 0;
97
+ }
56
98
  /* Skin from vfChromeFrame; the layout is the window's own — a full-size
57
99
  flex column so the body takes the slack the title bar and grow box
58
100
  don't. */
@@ -312,32 +354,152 @@ var W = 24, G = 8, K = class extends D(c(P)) {
312
354
  }
313
355
  #e;
314
356
  willUpdate(e) {
315
- super.willUpdate(e), this.variant === "utility" && (this._dotsPattern = C(this, "--vf-dots-pattern"));
357
+ super.willUpdate(e), this.variant === "utility" && (this._dotsPattern = w(this, "--vf-dots-pattern"));
316
358
  }
317
359
  _dotsTexture() {
318
360
  if (this.width == null) return;
319
361
  let e = Math.max(1, this.width - 2);
320
- if (this._dotsPattern) return w({
321
- cols: Math.ceil(e / m),
362
+ if (this._dotsPattern) return T({
363
+ cols: Math.ceil(e / h),
322
364
  rows: 1,
323
- tile: m
365
+ tile: h
324
366
  });
325
- let t = Math.ceil((e + f) / m) * m, n = G + f;
326
- return I`<div
367
+ let t = Math.ceil((e + p) / h) * h, n = Q + p;
368
+ return U`<div
327
369
  class="vf-tile-raster"
328
- style="width:${i(t)};height:${i(n)};background-image:${this.#e.for(f, f, p, t, n)}"
370
+ style="width:${a(t)};height:${a(n)};background-image:${this.#e.for(p, p, m, t, n)}"
329
371
  ></div>`;
330
372
  }
331
373
  #t;
332
374
  placementAt(e, t, n) {
333
375
  let r = this.scrollArea;
334
- return r ? r.placementAt(e, t, n) : l(this.body ?? this, e, t, this, n);
376
+ return r ? r.placementAt(e, t, n) : u(this.body ?? this, e, t, this, n);
335
377
  }
336
378
  measure() {
337
379
  this.scrollArea?.measure();
338
380
  }
381
+ async show(e = {}) {
382
+ this.#s("finish"), this.hidden = !1;
383
+ let t = e.from;
384
+ if (!t || I()) return !1;
385
+ let n = {
386
+ closing: !1,
387
+ animations: []
388
+ };
389
+ this.#r = n, this.#n.states?.add("opening"), this.#i.attach();
390
+ do
391
+ await this.updateComplete;
392
+ while (this.isUpdatePending && this.#r === n);
393
+ if (this.#r !== n) return !1;
394
+ let r = this.isConnected ? this.#u(t, this.getBoundingClientRect(), !1) : null;
395
+ return r ? (n.animations = r.animations, this.#l(n, r)) : (this.#c(), !1);
396
+ }
397
+ async hide(e = {}) {
398
+ let t = this.#r?.closing === !1, n = !this.hidden && !t;
399
+ this.#s(t ? "cancel" : "finish");
400
+ let r = e.to, i = r && n && this.isConnected && !I() ? this.#u(r, this.getBoundingClientRect(), !0) : null;
401
+ if (this.hidden = !0, !i) return !1;
402
+ let a = {
403
+ closing: !0,
404
+ animations: i.animations
405
+ };
406
+ return this.#r = a, this.#i.attach(), this.#l(a, i);
407
+ }
408
+ #n;
409
+ #r;
410
+ #i;
411
+ #a;
412
+ #o;
413
+ #s(e) {
414
+ let t = this.#r;
415
+ if (t) {
416
+ this.#c();
417
+ for (let n of t.animations) n[e]();
418
+ }
419
+ }
420
+ #c() {
421
+ this.#r = null, this.#n.states?.delete("opening"), this.#i.detach();
422
+ }
423
+ async #l(e, t) {
424
+ let n = await Promise.all(t.animations.map((e) => e.finished)).then(() => !0, () => !1);
425
+ for (let e of t.canvases) e.remove();
426
+ return this.#r === e && this.#c(), n;
427
+ }
428
+ #u(e, t, n) {
429
+ let i = this.#d();
430
+ if (!i) return null;
431
+ let o = r(this), s = i.getBoundingClientRect(), c = (e) => ({
432
+ left: Math.round((e.left - s.left) / o),
433
+ top: Math.round((e.top - s.top) / o),
434
+ right: Math.round((e.right - s.left) / o),
435
+ bottom: Math.round((e.bottom - s.top) / o)
436
+ }), l = c(e), u = c(t);
437
+ if (Math.max(l.right, u.right) <= 0 || Math.max(l.bottom, u.bottom) <= 0 || Math.min(l.left, u.left) >= Math.round(s.width / o) || Math.min(l.top, u.top) >= Math.round(s.height / o)) return null;
438
+ let d = {
439
+ canvases: [],
440
+ animations: []
441
+ };
442
+ for (let e = 0; e < 14; e++) {
443
+ let t = L(e), r = (e, n) => e + Math.trunc((n - e) * t), o = r(l.left, u.left), s = r(l.top, u.top), c = Math.max(1, r(l.right, u.right) - o), f = Math.max(1, r(l.bottom, u.bottom) - s), p = B("window-rect"), m = p.style;
444
+ m.position = "absolute", m.left = a(o), m.top = a(s), m.width = a(c), m.height = a(f), m.visibility = "hidden", R(p, c, f, z(o, s)), i.append(p), d.canvases.push(p);
445
+ let h = n ? 13 - e : e;
446
+ d.animations.push(p.animate([{ visibility: "visible" }, { visibility: "visible" }], {
447
+ delay: h * 17,
448
+ duration: 68,
449
+ endDelay: (14 - h) * 17
450
+ }));
451
+ }
452
+ return d;
453
+ }
454
+ #d() {
455
+ let t = { surface: null };
456
+ return e(this, "vf-drag-surface-request", t, { composed: !1 }), t.surface;
457
+ }
458
+ #f;
459
+ #p;
460
+ #m;
461
+ #h(e) {
462
+ if (this.#y(!0), !this.outlineDrag) return;
463
+ let t = this.#v(this.getBoundingClientRect());
464
+ t && (this.#f = {
465
+ origin: e,
466
+ outline: t,
467
+ landing: null
468
+ }, this.#_(t, 0, 0), this.#p.attach());
469
+ }
470
+ #g(e, t) {
471
+ let n = this.#f;
472
+ if (!n) return;
473
+ let r = this._placement.resolve(e, t);
474
+ n.landing = r, this.#_(n.outline, r.x - n.origin.x, r.y - n.origin.y);
475
+ }
476
+ #_(e, t, n) {
477
+ let r = e.base.x + t, i = e.base.y + n;
478
+ e.canvas.style.left = a(r), e.canvas.style.top = a(i);
479
+ let o = z(r, i);
480
+ o !== e.phase && (e.phase = o, R(e.canvas, e.width, e.height, o));
481
+ }
482
+ #v(e) {
483
+ let t = this.#d();
484
+ if (!t) return null;
485
+ let n = r(this), i = t.getBoundingClientRect(), o = Math.max(1, Math.round(e.width / n)), s = Math.max(1, Math.round(e.height / n)), c = B("drag-outline"), l = c.style;
486
+ return l.position = "absolute", l.width = a(o), l.height = a(s), t.append(c), {
487
+ canvas: c,
488
+ base: {
489
+ x: Math.round((e.left - i.left) / n),
490
+ y: Math.round((e.top - i.top) / n)
491
+ },
492
+ width: o,
493
+ height: s,
494
+ phase: -1
495
+ };
496
+ }
497
+ #y(e) {
498
+ let t = this.#f;
499
+ this.#f = null, t && (this.#p.detach(), t.outline.canvas.remove(), !e && t.landing && this._placement.moveTo(t.landing.x, t.landing.y));
500
+ }
339
501
  updated() {
340
- this.#a();
502
+ this.#C();
341
503
  let t = this._resizeState;
342
504
  t?.emitPending && (t.emitPending = !1, e(this, "vf-resize", {
343
505
  width: this.width,
@@ -345,18 +507,23 @@ var W = 24, G = 8, K = class extends D(c(P)) {
345
507
  commit: !1
346
508
  }));
347
509
  }
348
- #n;
349
- #r;
350
- #i() {
351
- this.#r ||= u(this, `vf-window${this.heading ? ` ("${this.heading}")` : ""}`, "<vf-window movable top=\"30\" left=\"40\" width=\"240\" height=\"176\">");
510
+ #b;
511
+ #x;
512
+ #S() {
513
+ this.#x ||= d(this, `vf-window${this.heading ? ` ("${this.heading}")` : ""}`, "<vf-window movable top=\"30\" left=\"40\" width=\"240\" height=\"176\">");
352
514
  }
353
- #a() {
354
- if (this.#n) return;
515
+ #C() {
516
+ if (this.#b) return;
355
517
  let e = [];
356
- this.width == null && this.style.width === "" && e.push("width (falling back to block layout)"), this.height == null && this.style.height === "" && e.push("height (falling back to the content)"), e.length !== 0 && (this.#n = !0, console.warn(`vf-window${this.heading ? ` ("${this.heading}")` : ""}: no ${e.join(", no ")}. A window owns its whole box — declare both in system px: <vf-window width="240" height="176">.`));
518
+ this.width == null && this.style.width === "" && e.push("width (falling back to block layout)"), this.height == null && this.style.height === "" && e.push("height (falling back to the content)"), e.length !== 0 && (this.#b = !0, console.warn(`vf-window${this.heading ? ` ("${this.heading}")` : ""}: no ${e.join(", no ")}. A window owns its whole box — declare both in system px: <vf-window width="240" height="176">.`));
519
+ }
520
+ connectedCallback() {
521
+ super.connectedCallback(), this.#r && this.#i.attach();
357
522
  }
358
523
  disconnectedCallback() {
359
- super.disconnectedCallback(), this._resizeState = null;
524
+ super.disconnectedCallback(), this._resizeState = null, this.#f?.outline.canvas.remove(), this.#f = null, this.#r && !this.#r.closing && queueMicrotask(() => {
525
+ !this.isConnected && this.#r?.closing === !1 && this.#s("cancel");
526
+ });
360
527
  }
361
528
  _onStatusSlotChange(e) {
362
529
  let t = e.target;
@@ -379,8 +546,8 @@ var W = 24, G = 8, K = class extends D(c(P)) {
379
546
  pointerId: e.pointerId,
380
547
  startX: e.clientX,
381
548
  startY: e.clientY,
382
- baseWidth: a(t.width, this),
383
- baseHeight: a(t.height, this),
549
+ baseWidth: o(t.width, this),
550
+ baseHeight: o(t.height, this),
384
551
  emitPending: !1,
385
552
  resized: !1
386
553
  }, e.currentTarget.setPointerCapture(e.pointerId), e.preventDefault();
@@ -388,8 +555,8 @@ var W = 24, G = 8, K = class extends D(c(P)) {
388
555
  _onGrowPointerMove(e) {
389
556
  let t = this._resizeState;
390
557
  if (!t || e.pointerId !== t.pointerId) return;
391
- let n = U(r(t.baseWidth + a(e.clientX - t.startX, this), this), this.minWidth ?? V, this.maxWidth), i = U(r(t.baseHeight + a(e.clientY - t.startY, this), this), this.minHeight ?? H, this.maxHeight);
392
- (n !== this.width || i !== this.height) && (t.emitPending = !0, t.resized = !0), this.width = n, this.height = i;
558
+ let n = X(i(t.baseWidth + o(e.clientX - t.startX, this), this), this.minWidth ?? J, this.maxWidth), r = X(i(t.baseHeight + o(e.clientY - t.startY, this), this), this.minHeight ?? Y, this.maxHeight);
559
+ (n !== this.width || r !== this.height) && (t.emitPending = !0, t.resized = !0), this.width = n, this.height = r;
393
560
  }
394
561
  _onGrowPointerEnd(t) {
395
562
  let n = this._resizeState;
@@ -403,42 +570,42 @@ var W = 24, G = 8, K = class extends D(c(P)) {
403
570
  });
404
571
  }
405
572
  render() {
406
- return I`
573
+ return U`
407
574
  <div
408
575
  class="vf-frame vf-snap"
409
576
  part="frame"
410
577
  role="group"
411
- aria-labelledby=${this.heading ? "title" : L}
578
+ aria-labelledby=${this.heading ? "title" : W}
412
579
  >
413
- ${A(this._drag, I`
414
- ${this.closable ? j(M("Close", this.heading), this._onCloseClick) : L}
580
+ ${M(this._drag, U`
581
+ ${this.closable ? N(P("Close", this.heading), this._onCloseClick) : W}
415
582
  <span class="vf-title" part="title" id="title">${this.heading}</span>
416
- ${this.zoomable ? N(M("Zoom", this.heading), this._onZoomClick) : L}
583
+ ${this.zoomable ? F(P("Zoom", this.heading), this._onZoomClick) : W}
417
584
  `, this.variant === "utility" ? "vf-dots" : "vf-stripes", this.variant === "utility" ? this._dotsTexture() : void 0)}
418
585
  <div
419
586
  class="header vf-rule-bottom ${this._hasHeader ? "" : "empty"}"
420
587
  part="header"
421
- style=${this.headerHeight == null ? L : `height:${i(this.headerHeight)}`}
588
+ style=${this.headerHeight == null ? W : `height:${a(this.headerHeight)}`}
422
589
  >
423
590
  <slot name="header" @slotchange=${this._onHeaderSlotChange}></slot>
424
591
  </div>
425
592
  <div class="body" part="body">
426
- ${this.scrollbars ? I`
593
+ ${this.scrollbars ? U`
427
594
  <vf-scroll-area
428
595
  class="edge-scroll"
429
596
  axis=${this.scrollbars}
430
597
  ?corner=${this.resizable && !this._hasStatus}
431
- label=${this.heading || L}
598
+ label=${this.heading || W}
432
599
  exportparts="viewport"
433
600
  >
434
601
  <slot></slot>
435
602
  </vf-scroll-area>
436
- ` : I`<slot></slot>`}
603
+ ` : U`<slot></slot>`}
437
604
  </div>
438
605
  <div class="status vf-rule-top ${this._hasStatus ? "" : "empty"}" part="status-bar">
439
606
  <slot name="status" @slotchange=${this._onStatusSlotChange}></slot>
440
607
  </div>
441
- ${this.resizable ? I`
608
+ ${this.resizable ? U`
442
609
  <div
443
610
  class="grow"
444
611
  part="grow-box"
@@ -448,41 +615,45 @@ var W = 24, G = 8, K = class extends D(c(P)) {
448
615
  @pointercancel=${this._onGrowPointerEnd}
449
616
  @lostpointercapture=${this._onGrowPointerEnd}
450
617
  ></div>
451
- ` : L}
618
+ ` : W}
452
619
  </div>
453
620
  `;
454
621
  }
455
622
  };
456
- o([R({ reflect: !0 })], K.prototype, "variant", void 0), o([R()], K.prototype, "heading", void 0), o([R({
623
+ s([G({ reflect: !0 })], $.prototype, "variant", void 0), s([G()], $.prototype, "heading", void 0), s([G({
457
624
  type: Boolean,
458
625
  reflect: !0
459
- })], K.prototype, "active", void 0), o([R({
626
+ })], $.prototype, "active", void 0), s([G({
460
627
  type: Boolean,
461
628
  reflect: !0
462
- })], K.prototype, "closable", void 0), o([R({
629
+ })], $.prototype, "closable", void 0), s([G({
463
630
  type: Boolean,
464
631
  reflect: !0
465
- })], K.prototype, "zoomable", void 0), o([R({
632
+ })], $.prototype, "zoomable", void 0), s([G({
466
633
  type: Boolean,
467
634
  reflect: !0
468
- })], K.prototype, "movable", void 0), o([R({
635
+ })], $.prototype, "movable", void 0), s([G({
636
+ type: Boolean,
637
+ reflect: !0,
638
+ attribute: "outline-drag"
639
+ })], $.prototype, "outlineDrag", void 0), s([G({
469
640
  type: Boolean,
470
641
  reflect: !0
471
- })], K.prototype, "resizable", void 0), o([R({
642
+ })], $.prototype, "resizable", void 0), s([G({
472
643
  type: Number,
473
644
  attribute: "min-width"
474
- })], K.prototype, "minWidth", void 0), o([R({
645
+ })], $.prototype, "minWidth", void 0), s([G({
475
646
  type: Number,
476
647
  attribute: "min-height"
477
- })], K.prototype, "minHeight", void 0), o([R({
648
+ })], $.prototype, "minHeight", void 0), s([G({
478
649
  type: Number,
479
650
  attribute: "max-width"
480
- })], K.prototype, "maxWidth", void 0), o([R({
651
+ })], $.prototype, "maxWidth", void 0), s([G({
481
652
  type: Number,
482
653
  attribute: "max-height"
483
- })], K.prototype, "maxHeight", void 0), o([R({ reflect: !0 })], K.prototype, "scrollbars", void 0), o([R({
654
+ })], $.prototype, "maxHeight", void 0), s([G({ reflect: !0 })], $.prototype, "scrollbars", void 0), s([G({
484
655
  type: Number,
485
656
  attribute: "header-height"
486
- })], K.prototype, "headerHeight", void 0), o([B()], K.prototype, "_hasHeader", void 0), o([B()], K.prototype, "_hasStatus", void 0), o([z(".body")], K.prototype, "body", void 0), o([z("vf-scroll-area")], K.prototype, "scrollArea", void 0), K = o([t("vf-window")], K);
657
+ })], $.prototype, "headerHeight", void 0), s([q()], $.prototype, "_hasHeader", void 0), s([q()], $.prototype, "_hasStatus", void 0), s([K(".body")], $.prototype, "body", void 0), s([K("vf-scroll-area")], $.prototype, "scrollArea", void 0), $ = s([t("vf-window")], $);
487
658
  //#endregion
488
- export { K as VfWindow };
659
+ export { $ as VfWindow };
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@
12
12
  */
13
13
  export { VfDesktop } from './components/vf-desktop.js';
14
14
  export { VfWindow } from './components/vf-window.js';
15
+ export type { VfViewportBox, VfWindowHideOptions, VfWindowShowOptions, } from './components/vf-window.js';
15
16
  export { VfDialog } from './components/vf-dialog.js';
16
17
  export { VfSeparator } from './components/vf-separator.js';
17
18
  export { VfButton } from './components/vf-button.js';
@@ -143,7 +144,7 @@ export type { DocumentListenerSpec } from './document-listeners.js';
143
144
  export { focusModality, trackFocusModality, FocusRuleController } from './focus-modality.js';
144
145
  export type { FocusModality } from './focus-modality.js';
145
146
  export { emit } from './events.js';
146
- export { prefersReducedMotion, runSelectionBlink, runOutlineTravel, BLINK_INTERVAL_MS, BLINK_FLIPS, PRESS_HOLD_MS, RENAME_DELAY_MS, WALK_STEP_PX, WALK_STEP_MS, WALK_BEAT_MS, } from './motion.js';
147
+ export { prefersReducedMotion, runSelectionBlink, runOutlineTravel, BLINK_INTERVAL_MS, BLINK_FLIPS, PRESS_HOLD_MS, RENAME_DELAY_MS, TAP_PAIR_MS, TAP_PAIR_SLOP_PX, DRAG_SLOP_PX, DRAG_SLOP_COARSE_PX, dragSlop, WALK_STEP_PX, WALK_STEP_MS, WALK_BEAT_MS, windowRectFraction, WINDOW_RECT_STEPS, WINDOW_RECTS_VISIBLE, WINDOW_RECT_RATIO, WINDOW_RECT_STEP_MS, } from './motion.js';
147
148
  export type { BlinkHandle, TravelHandle } from './motion.js';
148
149
  /**
149
150
  * Element registration. `vfElement` is the kit's `@customElement`: it registers