vintage-frames 0.12.2 → 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.
@@ -10,20 +10,20 @@ import { GridSnapController as p } from "../grid-snap.js";
10
10
  import { DocumentListenersController as m } from "../document-listeners.js";
11
11
  import { DragController as h } from "../drag.js";
12
12
  import { dragSlop as g, prefersReducedMotion as _, runOutlineTravel as v } from "../motion.js";
13
- import { FocusRuleController as y } from "../focus-modality.js";
14
- import { deriveDragOutline as b, deriveOpenArt as x, dotOutline as S, penPhase as C } from "../open-art.js";
15
- import { LitElement as w, css as T, html as E, nothing as D } from "lit";
16
- import { property as O, state as k } from "lit/decorators.js";
13
+ import { deriveDragOutline as y, deriveOpenArt as b, dotOutline as x, penPhase as S, xorPenCanvas as C } from "../open-art.js";
14
+ import { FocusRuleController as w } from "../focus-modality.js";
15
+ import { LitElement as T, css as E, html as D, nothing as O } from "lit";
16
+ import { property as k, state as A } from "lit/decorators.js";
17
17
  //#region src/components/vf-icon.ts
18
- var A, j = {
18
+ var j, M = {
19
19
  large: 32,
20
20
  small: 16
21
- }, M = 1, N = 8, P = (e, t) => t <= 0 ? Math.max(e, 0) : Math.min(Math.max(e, 0), t), F = class extends c(w) {
21
+ }, N = 1, P = 8, F = (e, t) => t <= 0 ? Math.max(e, 0) : Math.min(Math.max(e, 0), t), I = class extends c(T) {
22
22
  static {
23
- A = this;
23
+ j = this;
24
24
  }
25
25
  constructor(...t) {
26
- super(...t), this.label = "", this.size = "large", this.selectable = !1, this.selected = !1, this.target = !1, this.color = !1, this.open = !1, this.movable = !1, this.editable = !1, this.maxlength = 31, this.scale = new n(this), this.gridSnap = new p(this), this.focusRule = new y(this), this._editing = !1, this._draft = "", this.#e = 0, this._ghost = null, this.#t = null, this.#n = this.attachInternals(), this.#a = !1, this.#o = "", this.#s = "", this.#c = 0, this.#l = -Infinity, this.#u = !1, this.#d = null, this.#f = null, this.#p = new m(this, () => [[
26
+ super(...t), this.label = "", this.size = "large", this.selectable = !1, this.selected = !1, this.target = !1, this.color = !1, this.open = !1, this.movable = !1, this.editable = !1, this.maxlength = 31, this.scale = new n(this), this.gridSnap = new p(this), this.focusRule = new w(this), this._editing = !1, this._draft = "", this.#e = 0, this._ghost = null, this.#t = null, this.#n = this.attachInternals(), this.#a = !1, this.#o = "", this.#s = "", this.#c = 0, this.#l = -Infinity, this.#u = !1, this.#d = null, this.#f = null, this.#p = new m(this, () => [[
27
27
  document,
28
28
  "pointerdown",
29
29
  this.#te,
@@ -32,8 +32,8 @@ var A, j = {
32
32
  x: Math.max(e, 0),
33
33
  y: Math.max(t, 0)
34
34
  } : {
35
- x: P(e, n.width - a(this.offsetWidth, this)),
36
- y: P(t, n.height - a(this.offsetHeight, this))
35
+ x: F(e, n.width - a(this.offsetWidth, this)),
36
+ y: F(t, n.height - a(this.offsetHeight, this))
37
37
  }, this.#g = new s(this, (e, t, n) => this.#m(e, t, n)), this.#_ = null, this.#v = new h(this, {
38
38
  onDragStart: (e) => {
39
39
  if (!this.movable || e.button !== 0 || this._editing) return null;
@@ -119,7 +119,7 @@ var A, j = {
119
119
  if (t.includes(this) || (this.#G(), this.#f = null, e.shiftKey || e.metaKey)) return;
120
120
  let n = this.#i;
121
121
  if (n !== null) {
122
- let e = t.find((e) => e instanceof A);
122
+ let e = t.find((e) => e instanceof j);
123
123
  if (e?.selected && e.#i === n) return;
124
124
  }
125
125
  this.#X(!1);
@@ -158,7 +158,7 @@ var A, j = {
158
158
  case "ArrowDown": {
159
159
  if (!this.movable) return;
160
160
  t.preventDefault(), this.focusRule.reveal();
161
- let e = t.shiftKey ? N : M, n = t.key === "ArrowLeft" ? -e : t.key === "ArrowRight" ? e : 0, r = t.key === "ArrowUp" ? -e : t.key === "ArrowDown" ? e : 0;
161
+ let e = t.shiftKey ? P : N, n = t.key === "ArrowLeft" ? -e : t.key === "ArrowRight" ? e : 0, r = t.key === "ArrowUp" ? -e : t.key === "ArrowDown" ? e : 0;
162
162
  this.#L();
163
163
  let i = this.#g.seed();
164
164
  this.#g.moveTo(i.x + n, i.y + r);
@@ -168,7 +168,7 @@ var A, j = {
168
168
  };
169
169
  }
170
170
  static {
171
- this.styles = [d, T`
171
+ this.styles = [d, E`
172
172
  :host {
173
173
  display: inline-block;
174
174
  cursor: var(--vf-cursor, default);
@@ -553,7 +553,7 @@ var A, j = {
553
553
  y: Math.round((e.top - u) / o),
554
554
  width: Math.round(e.width / o),
555
555
  height: Math.round(e.height / o)
556
- }), m = Math.round((d - l) / o), h = Math.round((f - u) / o), g = this.open && this._ghost ? this._ghost : this.#t, _ = g != null && (g instanceof HTMLCanvasElement ? g.width > 0 : g.complete && g.naturalWidth > 0), v = _ ? g.getBoundingClientRect() : null, y = b(_ ? g : null, {
556
+ }), m = Math.round((d - l) / o), h = Math.round((f - u) / o), g = this.open && this._ghost ? this._ghost : this.#t, _ = g != null && (g instanceof HTMLCanvasElement ? g.width > 0 : g.complete && g.naturalWidth > 0), v = _ ? g.getBoundingClientRect() : null, b = y(_ ? g : null, {
557
557
  width: m,
558
558
  height: h,
559
559
  art: v && v.width > 0 ? p(v) : null,
@@ -565,27 +565,25 @@ var A, j = {
565
565
  },
566
566
  plate: c ? p(c) : null
567
567
  });
568
- if (!y) return null;
569
- let x = document.createElement("canvas");
570
- x.className = "drag-outline";
571
- let S = x.style;
572
- S.position = "absolute", S.display = "block", S.pointerEvents = "none", S.filter = "invert(1)", S.mixBlendMode = "difference", S.imageRendering = "pixelated", S.width = i(y.width), S.height = i(y.height);
573
- let C = t ?? a, w = t ? t.getBoundingClientRect() : e, T = {
574
- x: Math.round((l - w.left) / o),
575
- y: Math.round((u - w.top) / o)
568
+ if (!b) return null;
569
+ let x = C("drag-outline"), S = x.style;
570
+ S.position = "absolute", S.width = i(b.width), S.height = i(b.height);
571
+ let w = t ?? a, T = t ? t.getBoundingClientRect() : e, E = {
572
+ x: Math.round((l - T.left) / o),
573
+ y: Math.round((u - T.top) / o)
576
574
  };
577
- return C.append(x), {
578
- ring: y,
575
+ return w.append(x), {
576
+ ring: b,
579
577
  canvas: x,
580
- base: T,
578
+ base: E,
581
579
  phase: -1
582
580
  };
583
581
  }
584
582
  #P(e, t, n) {
585
583
  let r = e.base.x + t, a = e.base.y + n;
586
584
  e.canvas.style.left = i(r), e.canvas.style.top = i(a);
587
- let o = C(r, a);
588
- o !== e.phase && (e.phase = o, S(e.ring, e.canvas, o));
585
+ let o = S(r, a);
586
+ o !== e.phase && (e.phase = o, x(e.ring, e.canvas, o));
589
587
  }
590
588
  #F(e) {
591
589
  let { left: t, top: n } = e.proposal ?? {
@@ -636,7 +634,7 @@ var A, j = {
636
634
  n.selectNodeContents(e), t = n.getBoundingClientRect().width, n.detach();
637
635
  }
638
636
  let n = t / r(this) + 2, i = Math.max(2, Math.ceil(n / 2) * 2);
639
- this.#e = this._editing && t === 0 ? Math.max(i, j[this.size]) : i, e.style.width = this.#z;
637
+ this.#e = this._editing && t === 0 ? Math.max(i, M[this.size]) : i, e.style.width = this.#z;
640
638
  }
641
639
  get #z() {
642
640
  return this.#e ? `calc(var(--vf-scale, 1) * ${this.#e}px)` : "";
@@ -662,7 +660,7 @@ var A, j = {
662
660
  }
663
661
  let n = e instanceof HTMLImageElement ? `${this.size} ${e.currentSrc}` : "";
664
662
  if (n !== "" && n === this.#o && this._ghost) return;
665
- let r = x(e);
663
+ let r = b(e);
666
664
  if (r) {
667
665
  r.className = "ghost", r.style.width = `calc(var(--vf-scale, 1) * ${r.width}px)`, r.style.height = `calc(var(--vf-scale, 1) * ${r.height}px)`;
668
666
  let t = e instanceof HTMLImageElement ? e.alt : "";
@@ -703,7 +701,7 @@ var A, j = {
703
701
  }
704
702
  render() {
705
703
  let e = this._editing, t = e ? this._draft : this.label, n = this.focusRule.marked && !e, r = t !== "" || e, i = `caption${e ? " editing" : ""}${n && t ? " focus-rule" : ""}`, a = `art${this.open && this._ghost ? " open" : ""}${n && !t ? " focus-rule" : ""}`, o = this.width ? `width: calc(var(--vf-scale, 1) * ${this.width}px)` : "";
706
- return E`<div
704
+ return D`<div
707
705
  class="frame vf-snap"
708
706
  part="frame"
709
707
  style=${o}
@@ -714,9 +712,9 @@ var A, j = {
714
712
  @dblclick=${this.#Q}
715
713
  >
716
714
  <div class=${a} part="icon">
717
- ${this.size === "small" ? E`<slot name="small" @slotchange=${this.#B}></slot>` : E`<slot name="large" @slotchange=${this.#B}></slot>`}${this._ghost ?? D}
715
+ ${this.size === "small" ? D`<slot name="small" @slotchange=${this.#B}></slot>` : D`<slot name="large" @slotchange=${this.#B}></slot>`}${this._ghost ?? O}
718
716
  </div>
719
- ${r ? E`<div class=${i}>
717
+ ${r ? D`<div class=${i}>
720
718
  <!-- No whitespace around the span: it is the measured run, and a
721
719
  stray space would widen it. -->
722
720
  <div class="label" part="label"><span
@@ -725,7 +723,7 @@ var A, j = {
725
723
  style=${this.#e ? `width: ${this.#z}` : ""}
726
724
  >${t}</span
727
725
  ></div>
728
- ${e ? E`<div class="rename-box">
726
+ ${e ? D`<div class="rename-box">
729
727
  <input
730
728
  class="rename"
731
729
  part="input"
@@ -737,8 +735,8 @@ var A, j = {
737
735
  @keydown=${this.#ae}
738
736
  @blur=${this.commitEditing}
739
737
  />
740
- </div>` : D}
741
- </div>` : D}
738
+ </div>` : O}
739
+ </div>` : O}
742
740
  </div>`;
743
741
  }
744
742
  #K() {
@@ -778,6 +776,9 @@ var A, j = {
778
776
  }
779
777
  return !1;
780
778
  }
779
+ cellRect() {
780
+ return this.checkVisibility() ? this.renderRoot?.querySelector(".art")?.getBoundingClientRect() ?? this.getBoundingClientRect() : null;
781
+ }
781
782
  moveTo(e, t) {
782
783
  this.#x?.finish(), this.#L(), this.#g.seed(), this.#g.moveTo(e, t);
783
784
  }
@@ -816,27 +817,27 @@ var A, j = {
816
817
  #ae;
817
818
  #oe;
818
819
  };
819
- o([O()], F.prototype, "label", void 0), o([O({ reflect: !0 })], F.prototype, "size", void 0), o([O({
820
+ o([k()], I.prototype, "label", void 0), o([k({ reflect: !0 })], I.prototype, "size", void 0), o([k({
820
821
  type: Boolean,
821
822
  reflect: !0
822
- })], F.prototype, "selectable", void 0), o([O({
823
+ })], I.prototype, "selectable", void 0), o([k({
823
824
  type: Boolean,
824
825
  reflect: !0
825
- })], F.prototype, "selected", void 0), o([O({
826
+ })], I.prototype, "selected", void 0), o([k({
826
827
  type: Boolean,
827
828
  reflect: !0
828
- })], F.prototype, "target", void 0), o([O({
829
+ })], I.prototype, "target", void 0), o([k({
829
830
  type: Boolean,
830
831
  reflect: !0
831
- })], F.prototype, "color", void 0), o([O({
832
+ })], I.prototype, "color", void 0), o([k({
832
833
  type: Boolean,
833
834
  reflect: !0
834
- })], F.prototype, "open", void 0), o([O({
835
+ })], I.prototype, "open", void 0), o([k({
835
836
  type: Boolean,
836
837
  reflect: !0
837
- })], F.prototype, "movable", void 0), o([O({
838
+ })], I.prototype, "movable", void 0), o([k({
838
839
  type: Boolean,
839
840
  reflect: !0
840
- })], F.prototype, "editable", void 0), o([O({ type: Number })], F.prototype, "width", void 0), o([O({ type: Number })], F.prototype, "maxlength", void 0), o([k()], F.prototype, "_editing", void 0), o([k()], F.prototype, "_draft", void 0), o([k()], F.prototype, "_ghost", void 0), F = A = o([t("vf-icon")], F);
841
+ })], I.prototype, "editable", void 0), o([k({ type: Number })], I.prototype, "width", void 0), o([k({ type: Number })], I.prototype, "maxlength", void 0), o([A()], I.prototype, "_editing", void 0), o([A()], I.prototype, "_draft", void 0), o([A()], I.prototype, "_ghost", void 0), I = j = o([t("vf-icon")], I);
841
842
  //#endregion
842
- export { F as VfIcon };
843
+ export { I as VfIcon };
@@ -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;