vintage-frames 0.12.2 → 0.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A web component kit that rebuilds the classic Apple System 7 interface elements.
4
4
 
5
- View the [Examples Page](https://aportilla.github.io/vintage-frames/) to see every element live, with its full API.
5
+ View the [Examples Page](https://vintage-frames.portill.io/) to see every element live, with its full API.
6
6
 
7
7
  ```sh
8
8
  npm install vintage-frames
@@ -2453,7 +2453,7 @@
2453
2453
  "declarations": [
2454
2454
  {
2455
2455
  "kind": "class",
2456
- "description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its four corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, one whole-surface raster at one image px per system px, 1-bit at\nevery density and zoom (src/pattern-fill.ts).\n\n**The drag surface.** The Finder dragged an icon as a dotted outline drawn\non the *screen*, clipped at its edge and phase-locked to its raster, so\nthe screen hosts the layer that outline draws on: a full-bleed child of\nthe screen, `pointer-events: none` (never a hit for the page's\n`elementsFromPoint`), whose children paint one tier above the menu bar\nand under the corner mask — the layer itself is deliberately no stacking\ncontext, since a blend inside one would composite against nothing. An\nicon reaches it without an import, the menu-handshake idiom: on a drag's\nfirst step it dispatches `vf-drag-surface-request` (bubbles, non-composed,\n`detail.surface` null), and the nearest desktop on its light-DOM path\nfills the detail with the layer. Not the top layer: stable Safari cannot\nblend an element there against the page (src/cursor.ts), and a second\nkit entry in the top layer would need a re-promotion handshake.\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).",
2456
+ "description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its four corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, one whole-surface raster at one image px per system px, 1-bit at\nevery density and zoom (src/pattern-fill.ts).\n\n**The drag surface.** The Finder dragged an icon as a dotted outline drawn\non the *screen*, clipped at its edge and phase-locked to its raster, so\nthe screen hosts the layer that outline draws on: a full-bleed child of\nthe screen, `pointer-events: none` (never a hit for the page's\n`elementsFromPoint`), whose children paint one tier above the menu bar\nand under the corner mask — the layer itself is deliberately no stacking\ncontext, since a blend inside one would composite against nothing. An\nicon reaches it without an import, the menu-handshake idiom: on a drag's\nfirst step it dispatches `vf-drag-surface-request` (bubbles, non-composed,\n`detail.surface` null), and the nearest desktop on its light-DOM path\nfills the detail with the layer. A window asks the same way and draws\nthere with the same pen: its zoom rects when it opens from a rect\n(`vf-window.show({ from })`), its outline under an `outline-drag`. Not the\ntop layer: stable Safari cannot\nblend an element there against the page (src/cursor.ts), and a second\nkit entry in the top layer would need a re-promotion handshake.\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).",
2457
2457
  "name": "VfDesktop",
2458
2458
  "cssProperties": [
2459
2459
  {
@@ -2856,7 +2856,7 @@
2856
2856
  "kind": "field",
2857
2857
  "name": "_onDragSurfaceRequest",
2858
2858
  "privacy": "private",
2859
- "description": "A dragged icon asking for the screen's drag surface (see the class\ndoc). Non-composed, so it reaches here only through the light-DOM path\nthe icon is slotted on — a window body included. The nearest desktop\nanswers; an outer one leaves a filled detail alone."
2859
+ "description": "A dragged icon, or a window opening from a rect, asking for the screen's\ndrag surface (see the class doc). Non-composed, so it reaches here only\nthrough the light-DOM path the asker is slotted on — a window body\nincluded. The nearest desktop answers; an outer one leaves a filled\ndetail alone."
2860
2860
  },
2861
2861
  {
2862
2862
  "kind": "field",
@@ -6106,6 +6106,16 @@
6106
6106
  ],
6107
6107
  "description": "Whether a viewport box (CSS px) touches the icon the way the Finder's\nselection rectangle asked: its art cell or its name plate. The empty\ncell around narrower art and the frame's margin beside the plate count\nfor nothing — a rectangle dragged through the gap between two icons\nselects neither. `vf-icon-field`'s rubber band reads it."
6108
6108
  },
6109
+ {
6110
+ "kind": "method",
6111
+ "name": "cellRect",
6112
+ "return": {
6113
+ "type": {
6114
+ "text": "DOMRect | null"
6115
+ }
6116
+ },
6117
+ "description": "The reserved art cell's box in the viewport, CSS px: 32×32 system px, or\n16×16 under `size=\"small\"`, centered at the top of the frame — the same\nbox whatever the art, the name, `width`, `open` or `selected`. The\nslotted art is no stand-in for it: `open` hides the slot, so the art\nmeasures nothing. The box to hand anything that opens from the icon or\ncloses to it. Null while the icon is not rendered — out of the\ndocument, or under `display: none`, inside a hidden window say. Before\nthe first render, the host's box."
6118
+ },
6109
6119
  {
6110
6120
  "kind": "method",
6111
6121
  "name": "moveTo",
@@ -19971,7 +19981,7 @@
19971
19981
  "declarations": [
19972
19982
  {
19973
19983
  "kind": "class",
19974
- "description": "`<vf-window>` — the System 7 desktop-window shell.\n\nStriped title bar with optional close box (left) and zoom box (right), a\nsolid-white frame with a hard offset shadow, an optional grow box for\nresizing, optional edge scroll rails (`scrollbars`), and the slim windoid\nchrome (`variant=\"utility\"`). The HIG's window archetypes are parameter\nrecipes over this shell rather than fixed anatomies — the component enables\nHIG compliance, it doesn't enforce it (see docs/LAYOUT.md \"Window archetypes\"):\nthe full document window is `closable zoomable movable resizable\nscrollbars=\"both\"`, a modeless dialog box is `closable movable`, a utility\nwindow is `variant=\"utility\" movable`. Place inside `<vf-desktop>` to get\nclick-to-front stacking and automatic `active` management (utility windows\nfloat above the document tier).\n\nEvery recipe also declares `width` AND `height` (VfSized), in whole\nsystem px — the art's own unit, so the window keeps its proportions to the\nchrome inside it at every display density (a CSS-px size stays put while\nthe components in it triple). A window is a fixed box in both axes, the way\nthe WIND resource carried it: left to layout it takes whatever its\ncontainer or content hands it, which is how a title bar ends up wider than\nthe screen or a dialog reflows as it moves — and a window that grows with\nits body is one the user can neither predict nor (via the grow box) own.\nContent taller than the declared box is clipped at the frame the way the\nclassic content region was; `scrollbars` lets the user reach the rest.\nUnset, the window still renders — normal block layout, as before — and\nsays so once in the console.",
19984
+ "description": "`<vf-window>` — the System 7 desktop-window shell.\n\nStriped title bar with optional close box (left) and zoom box (right), a\nsolid-white frame with a hard offset shadow, an optional grow box for\nresizing, optional edge scroll rails (`scrollbars`), and the slim windoid\nchrome (`variant=\"utility\"`). The HIG's window archetypes are parameter\nrecipes over this shell rather than fixed anatomies — the component enables\nHIG compliance, it doesn't enforce it (see docs/LAYOUT.md \"Window archetypes\"):\nthe full document window is `closable zoomable movable resizable\nscrollbars=\"both\"`, a modeless dialog box is `closable movable`, a utility\nwindow is `variant=\"utility\" movable`. Place inside `<vf-desktop>` to get\nclick-to-front stacking and automatic `active` management (utility windows\nfloat above the document tier).\n\nEvery recipe also declares `width` AND `height` (VfSized), in whole\nsystem px — the art's own unit, so the window keeps its proportions to the\nchrome inside it at every display density (a CSS-px size stays put while\nthe components in it triple). A window is a fixed box in both axes, the way\nthe WIND resource carried it: left to layout it takes whatever its\ncontainer or content hands it, which is how a title bar ends up wider than\nthe screen or a dialog reflows as it moves — and a window that grows with\nits body is one the user can neither predict nor (via the grow box) own.\nContent taller than the declared box is clipped at the frame the way the\nclassic content region was; `scrollbars` lets the user reach the rest.\nUnset, the window still renders — normal block layout, as before — and\nsays so once in the console.\n\n**Opening from a rect.** show clears `hidden`, and given `from` — a\nbox in viewport CSS px, an icon's `cellRect()` or a button's rect — opens\nthe window from it: dotted rectangles grow from that box toward the\nwindow's frame, four on screen at a time, bunched at the box and opening\nout toward the window, drawn with the icon drag outline's XOR pen on the\ndesktop's drag surface; the window draws once they have drained, eighteen\nsteps later. Until then it matches `:state(opening)` and paints nothing —\nstill laid out, focusable and a hit target, so a page can place it, raise\nit and focus into it at once, and a press finishes the rects and lands on\nthe window. Under `prefers-reduced-motion`, with no `vf-desktop` on its\npath, or without `from`, the window shows at once.\n\n**Closing to a rect.** hide sets `hidden`, and given `to` closes\nthe window to it: the same rectangles run the other way, from where the\nframe was in toward the box, the window gone from the first step. A press\nfinishes them, and removing the window leaves them running. Under\n`prefers-reduced-motion`, with no `vf-desktop` on its path, or without\n`to`, the window hides at once. The window knows nothing about icons:\n`from` and `to` are any rect.\n\n**Dragging as an outline.** A `movable` window moves live under the\npointer. With `outline-drag` a press on the title bar draws a dotted\noutline around the window on the desktop's drag surface instead, with the\nsame pen; the drag moves the outline, held where the window can land, and\nthe window moves there on the release. Escape cancels.",
19975
19985
  "name": "VfWindow",
19976
19986
  "cssProperties": [
19977
19987
  {
@@ -20119,6 +20129,17 @@
20119
20129
  "attribute": "movable",
20120
20130
  "reflects": true
20121
20131
  },
20132
+ {
20133
+ "kind": "field",
20134
+ "name": "outlineDrag",
20135
+ "type": {
20136
+ "text": "boolean"
20137
+ },
20138
+ "default": "false",
20139
+ "description": "Drag by the title bar as an outline: a press draws a dotted one-pixel\nrectangle around the window on the desktop's drag surface, with the\nicon drag outline's pen; the drag moves it, held where the window can\nland, and the window moves there on the release, in one write. Escape\ncancels and writes nothing, as does a release that never moved it.\nUnset, the window moves live under the pointer; with no `vf-desktop` on\nits path it moves live either way. Only matters with `movable`.",
20140
+ "attribute": "outline-drag",
20141
+ "reflects": true
20142
+ },
20122
20143
  {
20123
20144
  "kind": "field",
20124
20145
  "name": "resizable",
@@ -20297,7 +20318,7 @@
20297
20318
  "name": "_drag",
20298
20319
  "privacy": "private",
20299
20320
  "readonly": true,
20300
- "default": "new DragController(this, { onDragStart: (event: PointerEvent): { x: number; y: number } | null => { if (!this.movable || event.button !== 0) return null // Ignore drags that start on the close/zoom widgets. if ( event .composedPath() .some( (node) => node instanceof HTMLElement && node.classList.contains('box') ) ) { return null } this.#warnIfUnplaced() return this._placement.seed() }, onDrag: (x: number, y: number): void => this._placement.moveTo(x, y), })",
20321
+ "default": "new DragController(this, { onDragStart: (event: PointerEvent): { x: number; y: number } | null => { if (!this.movable || event.button !== 0) return null // Ignore drags that start on the close/zoom widgets. if ( event .composedPath() .some( (node) => node instanceof HTMLElement && node.classList.contains('box') ) ) { return null } this.#warnIfUnplaced() const origin = this._placement.seed() this.#startOutlineDrag(origin) return origin }, onDrag: (x: number, y: number): void => { if (this.#outlineDrag) this.#dragOutlineTo(x, y) else this._placement.moveTo(x, y) }, onDragEnd: (_event: PointerEvent | undefined, cancelled: boolean): void => { this.#endOutlineDrag(cancelled) }, })",
20301
20322
  "description": "Title-bar drag-to-move (shared with `vf-dialog` via DragController).\nThe controller owns the pointer bookkeeping and hands over system px; the\nplacement controller seeds the origin and writes the result."
20302
20323
  },
20303
20324
  {
@@ -20350,6 +20371,312 @@
20350
20371
  },
20351
20372
  "description": "Re-measure the built-in scroll area's overflow and re-sync its rails —\na no-op without `scrollbars`. The area re-measures by itself on its\ncontent's box, its slot and every placement write; this is the escape\nhatch for a scroll range that changes with none of those, the way\n`vf-scroll-area.measure()` is."
20352
20373
  },
20374
+ {
20375
+ "kind": "method",
20376
+ "name": "show",
20377
+ "return": {
20378
+ "type": {
20379
+ "text": "Promise<boolean>"
20380
+ }
20381
+ },
20382
+ "parameters": [
20383
+ {
20384
+ "name": "options",
20385
+ "default": "{}",
20386
+ "type": {
20387
+ "text": "VfWindowShowOptions"
20388
+ }
20389
+ }
20390
+ ],
20391
+ "description": "Show the window: `hidden` cleared, and with `from` the window opens from\nthat box — the zoom rects, grown from it toward the frame at the cadence\nin src/motion.ts (`WINDOW_RECT_*`), the window drawn once they have\ndrained (see the class doc). A run in flight, a `show()` or a `hide()`,\nis finished first; a press anywhere or Escape finishes this one, and\nremoving the window or a `hide()` takes it down. Resolves once the\nwindow draws: `true` when the rects ran, `false` when it showed at once\n— no `from`, `prefers-reduced-motion`, no `vf-desktop` on its path,\nnothing of the rects on the screen, or not in the DOM — or never drew.\nIt raises and activates nothing: stacking stays the page's\n(`vf-desktop.bringToFront`)."
20392
+ },
20393
+ {
20394
+ "kind": "method",
20395
+ "name": "hide",
20396
+ "return": {
20397
+ "type": {
20398
+ "text": "Promise<boolean>"
20399
+ }
20400
+ },
20401
+ "parameters": [
20402
+ {
20403
+ "name": "options",
20404
+ "default": "{}",
20405
+ "type": {
20406
+ "text": "VfWindowHideOptions"
20407
+ }
20408
+ }
20409
+ ],
20410
+ "description": "Hide the window: `hidden` set, and with `to` the window closes to that\nbox — the rects of show run the other way, from where the frame\nis drawn at the call in toward the box, the window gone from their first\nstep. A `show()` still opening is taken down and says `false`; a second\n`hide()` finishes the first; a press anywhere or Escape finishes the\nrects; removing the window leaves them running, so a page can remove a\nwindow as it closes it. Resolves once the rects are done: `true` when\nthey ran, `false` when the window hid at once — no `to`,\n`prefers-reduced-motion`, no `vf-desktop` on its path, nothing of the\nrects on the screen, not in the DOM, or no frame to close from: already\nhidden, or still opening."
20411
+ },
20412
+ {
20413
+ "kind": "field",
20414
+ "name": "#internals",
20415
+ "privacy": "private",
20416
+ "readonly": true,
20417
+ "description": "Internals, for the `opening` custom state."
20418
+ },
20419
+ {
20420
+ "kind": "field",
20421
+ "name": "#rectsRun",
20422
+ "privacy": "private",
20423
+ "type": {
20424
+ "text": "RectsRun | null"
20425
+ },
20426
+ "default": "null",
20427
+ "description": "The `show({ from })` or `hide({ to })` in flight, or null."
20428
+ },
20429
+ {
20430
+ "kind": "field",
20431
+ "name": "#interrupt",
20432
+ "privacy": "private",
20433
+ "readonly": true,
20434
+ "default": "new DocumentListenersController(this, () => [ [document, 'pointerdown', this.#onRectsPress, true], [document, 'keydown', this.#onRectsKeyDown, true], ])",
20435
+ "description": "A press anywhere, or Escape, finishes the rects: an opening window draws\nat once, and the press lands on it. Scoped to the run, on the document,\ncapture phase, Escape stopped there — the walk's rule (`vf-icon.dragTo`),\nfor the same reasons."
20436
+ },
20437
+ {
20438
+ "kind": "field",
20439
+ "name": "#onRectsPress",
20440
+ "privacy": "private"
20441
+ },
20442
+ {
20443
+ "kind": "field",
20444
+ "name": "#onRectsKeyDown",
20445
+ "privacy": "private"
20446
+ },
20447
+ {
20448
+ "kind": "method",
20449
+ "name": "#stopRects",
20450
+ "privacy": "private",
20451
+ "return": {
20452
+ "type": {
20453
+ "text": "void"
20454
+ }
20455
+ },
20456
+ "parameters": [
20457
+ {
20458
+ "name": "how",
20459
+ "type": {
20460
+ "text": "'finish' | 'cancel'"
20461
+ }
20462
+ }
20463
+ ],
20464
+ "description": "End the run in flight now: its rects finished — its call says they ran,\nand an opening window draws at once — or cancelled, when it says they\ndid not. A run whose rects have not started says `false`."
20465
+ },
20466
+ {
20467
+ "kind": "method",
20468
+ "name": "#endRects",
20469
+ "privacy": "private",
20470
+ "return": {
20471
+ "type": {
20472
+ "text": "void"
20473
+ }
20474
+ },
20475
+ "description": "The run over, the window drawn if it was opening, the finishers gone."
20476
+ },
20477
+ {
20478
+ "kind": "method",
20479
+ "name": "#playOut",
20480
+ "privacy": "private",
20481
+ "return": {
20482
+ "type": {
20483
+ "text": "Promise<boolean>"
20484
+ }
20485
+ },
20486
+ "parameters": [
20487
+ {
20488
+ "name": "run",
20489
+ "type": {
20490
+ "text": "RectsRun"
20491
+ }
20492
+ },
20493
+ {
20494
+ "name": "rects",
20495
+ "type": {
20496
+ "text": "Rects"
20497
+ }
20498
+ }
20499
+ ],
20500
+ "description": "Wait out a run's rects, then take their canvases down: finished —\ndrained, or a press, Escape or the next call — they ran; cancelled,\nthey did not."
20501
+ },
20502
+ {
20503
+ "kind": "method",
20504
+ "name": "#animateRects",
20505
+ "privacy": "private",
20506
+ "return": {
20507
+ "type": {
20508
+ "text": "Rects | null"
20509
+ }
20510
+ },
20511
+ "parameters": [
20512
+ {
20513
+ "name": "box",
20514
+ "type": {
20515
+ "text": "VfViewportBox"
20516
+ }
20517
+ },
20518
+ {
20519
+ "name": "frame",
20520
+ "type": {
20521
+ "text": "VfViewportBox"
20522
+ }
20523
+ },
20524
+ {
20525
+ "name": "closing",
20526
+ "type": {
20527
+ "text": "boolean"
20528
+ }
20529
+ }
20530
+ ],
20531
+ "description": "The rects between `box` and the window's `frame`, on the desktop's drag\nsurface — the one the `vf-drag-surface-request` handshake finds, as a\ndragged icon's outline does. Both in whole system px from the corner of\nits screen; every edge of rect k sits its fraction of the way from the\nbox to the frame (windowRectFraction), the delta truncated toward\nzero. Each rect is a canvas of its own, framed once with the XOR pen at\nits phase on the screen (penPhase) and hidden, with an animation\nthat shows it for WINDOW_RECTS_VISIBLE steps: from step k opening,\nout from the box, and from step 13 − k closing, in toward it. Where two\nrects share a pixel the later one inverts it back: the surface is no\nstacking context, so each canvas blends over the ones before it as well\nas the screen. Null with no desktop on the path, or none of the rects on\nthe screen."
20532
+ },
20533
+ {
20534
+ "kind": "method",
20535
+ "name": "#requestSurface",
20536
+ "privacy": "private",
20537
+ "return": {
20538
+ "type": {
20539
+ "text": "HTMLElement | null"
20540
+ }
20541
+ },
20542
+ "description": "The handshake a dragged icon's outline uses: a desktop on the light-DOM\npath hands over its drag surface. Null with no desktop."
20543
+ },
20544
+ {
20545
+ "kind": "field",
20546
+ "name": "#outlineDrag",
20547
+ "privacy": "private",
20548
+ "type": {
20549
+ "text": "OutlineDrag | null"
20550
+ },
20551
+ "default": "null",
20552
+ "description": "The outline drag in flight, or null — a live drag keeps none."
20553
+ },
20554
+ {
20555
+ "kind": "field",
20556
+ "name": "#dragEscape",
20557
+ "privacy": "private",
20558
+ "readonly": true,
20559
+ "default": "new DocumentListenersController(this, () => [ [document, 'keydown', this.#onDragKeyDown, true], ])",
20560
+ "description": "Escape mid outline-drag cancels it: a document listener scoped to the\ngesture, capture phase, the key stopped there — the icon drag's rule, so\nan enclosing dialog never reads it as a dismissal."
20561
+ },
20562
+ {
20563
+ "kind": "field",
20564
+ "name": "#onDragKeyDown",
20565
+ "privacy": "private"
20566
+ },
20567
+ {
20568
+ "kind": "method",
20569
+ "name": "#startOutlineDrag",
20570
+ "privacy": "private",
20571
+ "return": {
20572
+ "type": {
20573
+ "text": "void"
20574
+ }
20575
+ },
20576
+ "parameters": [
20577
+ {
20578
+ "name": "origin",
20579
+ "type": {
20580
+ "text": "{ x: number; y: number }"
20581
+ }
20582
+ }
20583
+ ],
20584
+ "description": "The press of an outline drag: the outline drawn around the window at\nonce, and Escape armed. A window without `outline-drag`, or with no\ndesktop to draw on, keeps no outline drag, and the gesture moves it live."
20585
+ },
20586
+ {
20587
+ "kind": "method",
20588
+ "name": "#dragOutlineTo",
20589
+ "privacy": "private",
20590
+ "return": {
20591
+ "type": {
20592
+ "text": "void"
20593
+ }
20594
+ },
20595
+ "parameters": [
20596
+ {
20597
+ "name": "x",
20598
+ "type": {
20599
+ "text": "number"
20600
+ }
20601
+ },
20602
+ {
20603
+ "name": "y",
20604
+ "type": {
20605
+ "text": "number"
20606
+ }
20607
+ }
20608
+ ],
20609
+ "description": "A step of an outline drag: the outline to where the release would land\n— the step clamped as a live drag is (PlacementController.resolve)."
20610
+ },
20611
+ {
20612
+ "kind": "method",
20613
+ "name": "#placeOutline",
20614
+ "privacy": "private",
20615
+ "return": {
20616
+ "type": {
20617
+ "text": "void"
20618
+ }
20619
+ },
20620
+ "parameters": [
20621
+ {
20622
+ "name": "outline",
20623
+ "type": {
20624
+ "text": "WindowOutline"
20625
+ }
20626
+ },
20627
+ {
20628
+ "name": "dx",
20629
+ "type": {
20630
+ "text": "number"
20631
+ }
20632
+ },
20633
+ {
20634
+ "name": "dy",
20635
+ "type": {
20636
+ "text": "number"
20637
+ }
20638
+ }
20639
+ ],
20640
+ "description": "Put the outline its delta from where the press drew it, whole system px\nfrom the desktop's screen, re-dotted when its phase on the screen changes."
20641
+ },
20642
+ {
20643
+ "kind": "method",
20644
+ "name": "#buildOutline",
20645
+ "privacy": "private",
20646
+ "return": {
20647
+ "type": {
20648
+ "text": "WindowOutline | null"
20649
+ }
20650
+ },
20651
+ "parameters": [
20652
+ {
20653
+ "name": "frame",
20654
+ "type": {
20655
+ "text": "DOMRect"
20656
+ }
20657
+ }
20658
+ ],
20659
+ "description": "The outline an outline drag moves: the window's box at the press — its\nframe, border included, shadow not — as a one-pixel ring on the\ndesktop's drag surface, with the drag outline's pen. Null with no desktop."
20660
+ },
20661
+ {
20662
+ "kind": "method",
20663
+ "name": "#endOutlineDrag",
20664
+ "privacy": "private",
20665
+ "return": {
20666
+ "type": {
20667
+ "text": "void"
20668
+ }
20669
+ },
20670
+ "parameters": [
20671
+ {
20672
+ "name": "cancelled",
20673
+ "type": {
20674
+ "text": "boolean"
20675
+ }
20676
+ }
20677
+ ],
20678
+ "description": "The end of an outline drag: the outline down and, released rather than\ncancelled, the window written where it was — one write, one\n`vf-placement-change`. A press released without a step writes nothing."
20679
+ },
20353
20680
  {
20354
20681
  "kind": "field",
20355
20682
  "name": "#warnedNoSize",
@@ -20655,6 +20982,15 @@
20655
20982
  "description": "Allow dragging the window by its title bar.",
20656
20983
  "fieldName": "movable"
20657
20984
  },
20985
+ {
20986
+ "name": "outline-drag",
20987
+ "type": {
20988
+ "text": "boolean"
20989
+ },
20990
+ "default": "false",
20991
+ "description": "Drag by the title bar as an outline: a press draws a dotted one-pixel\nrectangle around the window on the desktop's drag surface, with the\nicon drag outline's pen; the drag moves it, held where the window can\nland, and the window moves there on the release, in one write. Escape\ncancels and writes nothing, as does a release that never moved it.\nUnset, the window moves live under the pointer; with no `vf-desktop` on\nits path it moves live either way. Only matters with `movable`.",
20992
+ "fieldName": "outlineDrag"
20993
+ },
20658
20994
  {
20659
20995
  "name": "resizable",
20660
20996
  "type": {
@@ -65,7 +65,10 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
65
65
  * icon reaches it without an import, the menu-handshake idiom: on a drag's
66
66
  * first step it dispatches `vf-drag-surface-request` (bubbles, non-composed,
67
67
  * `detail.surface` null), and the nearest desktop on its light-DOM path
68
- * fills the detail with the layer. Not the top layer: stable Safari cannot
68
+ * fills the detail with the layer. A window asks the same way and draws
69
+ * there with the same pen: its zoom rects when it opens from a rect
70
+ * (`vf-window.show({ from })`), its outline under an `outline-drag`. Not the
71
+ * top layer: stable Safari cannot
69
72
  * blend an element there against the page (src/cursor.ts), and a second
70
73
  * kit entry in the top layer would need a re-promotion handshake.
71
74
  *
@@ -307,10 +310,11 @@ export declare class VfDesktop extends VfDesktop_base {
307
310
  */
308
311
  private _onGestureEnd;
309
312
  /**
310
- * A dragged icon asking for the screen's drag surface (see the class
311
- * doc). Non-composed, so it reaches here only through the light-DOM path
312
- * the icon is slotted on — a window body included. The nearest desktop
313
- * answers; an outer one leaves a filled detail alone.
313
+ * A dragged icon, or a window opening from a rect, asking for the screen's
314
+ * drag surface (see the class doc). Non-composed, so it reaches here only
315
+ * through the light-DOM path the asker is slotted on — a window body
316
+ * included. The nearest desktop answers; an outer one leaves a filled
317
+ * detail alone.
314
318
  */
315
319
  private _onDragSurfaceRequest;
316
320
  /**
@@ -7,13 +7,13 @@ import { vfBase as o } from "../styles/recipes/host.js";
7
7
  import { DocumentListenersController as s } from "../document-listeners.js";
8
8
  import { VfSized as c } from "../size.js";
9
9
  import "../motion.js";
10
- import { paintSelectionRect as l, penPhase as u } from "../open-art.js";
11
- import { LitElement as d, css as f, html as p } from "lit";
12
- import { property as m } from "lit/decorators.js";
10
+ import { paintSelectionRect as l, penPhase as u, xorPenCanvas as d } from "../open-art.js";
11
+ import { LitElement as f, css as p, html as m } from "lit";
12
+ import { property as h } from "lit/decorators.js";
13
13
  //#region src/components/vf-icon-field.ts
14
- var h = (e, t, n) => Math.min(Math.max(e, t), n), g = class extends c(a(d)) {
14
+ var g = (e, t, n) => Math.min(Math.max(e, t), n), _ = class extends c(a(f)) {
15
15
  static {
16
- this.styles = [o, f`
16
+ this.styles = [o, p`
17
17
  :host {
18
18
  /* A block that shrink-wraps: the field is exactly as big as what it
19
19
  holds in flow — nothing, for a field of placed icons — so it can
@@ -137,8 +137,8 @@ var h = (e, t, n) => Math.min(Math.max(e, t), n), g = class extends c(a(d)) {
137
137
  }
138
138
  #h(e, t, n, r) {
139
139
  return {
140
- x: h(Math.round((e.clientX - t.left) / n), r.minX, r.maxX),
141
- y: h(Math.round((e.clientY - t.top) / n), r.minY, r.maxY)
140
+ x: g(Math.round((e.clientX - t.left) / n), r.minX, r.maxX),
141
+ y: g(Math.round((e.clientY - t.top) / n), r.minY, r.maxY)
142
142
  };
143
143
  }
144
144
  #g(e, t) {
@@ -172,10 +172,8 @@ var h = (e, t, n) => Math.min(Math.max(e, t), n), g = class extends c(a(d)) {
172
172
  };
173
173
  }
174
174
  #v() {
175
- let e = document.createElement("canvas");
176
- e.className = "selection-rect";
177
- let t = e.style;
178
- return t.position = "fixed", t.display = "block", t.pointerEvents = "none", t.filter = "invert(1)", t.mixBlendMode = "difference", t.imageRendering = "pixelated", e;
175
+ let e = d("selection-rect");
176
+ return e.style.position = "fixed", e;
179
177
  }
180
178
  #y(e, t) {
181
179
  let { rect: n, canvas: r } = e;
@@ -238,9 +236,9 @@ var h = (e, t, n) => Math.min(Math.max(e, t), n), g = class extends c(a(d)) {
238
236
  e.finished || (e.finished = !0, this.#r === e && (this.#r = null, this.#i.detach()), e.settle());
239
237
  }
240
238
  render() {
241
- return p`<slot @slotchange=${this.#s}></slot>`;
239
+ return m`<slot @slotchange=${this.#s}></slot>`;
242
240
  }
243
241
  };
244
- i([m()], g.prototype, "label", void 0), i([m({ reflect: !0 })], g.prototype, "size", void 0), g = i([t("vf-icon-field")], g);
242
+ i([h()], _.prototype, "label", void 0), i([h({ reflect: !0 })], _.prototype, "size", void 0), _ = i([t("vf-icon-field")], _);
245
243
  //#endregion
246
- export { g as VfIconField };
244
+ export { _ as VfIconField };
@@ -626,6 +626,17 @@ export declare class VfIcon extends VfIcon_base {
626
626
  right: number;
627
627
  bottom: number;
628
628
  }): boolean;
629
+ /**
630
+ * The reserved art cell's box in the viewport, CSS px: 32×32 system px, or
631
+ * 16×16 under `size="small"`, centered at the top of the frame — the same
632
+ * box whatever the art, the name, `width`, `open` or `selected`. The
633
+ * slotted art is no stand-in for it: `open` hides the slot, so the art
634
+ * measures nothing. The box to hand anything that opens from the icon or
635
+ * closes to it. Null while the icon is not rendered — out of the
636
+ * document, or under `display: none`, inside a hidden window say. Before
637
+ * the first render, the host's box.
638
+ */
639
+ cellRect(): DOMRect | null;
629
640
  /**
630
641
  * Place the icon as a drop would: the stated pair — the origin point
631
642
  * under an `origin`, the corner without one — clamped whole in the