vintage-frames 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -183,6 +183,13 @@ export declare function cleanUp(grid: Lattice, positions: readonly Point[]): Poi
183
183
  * a bounded lattice is full.
184
184
  */
185
185
  export declare function nextFreeCell(grid: Lattice, taken: readonly Point[], cell?: number): Point;
186
+ /**
187
+ * The free cell nearest `at`: square rings out from its rounded, clamped
188
+ * cell, as Clean Up searches, a cell free where no icon at `taken` overlaps
189
+ * it. Of two as near, the later in fill order. The next free cell when the
190
+ * rings find none.
191
+ */
192
+ export declare function freeCellNear(grid: Lattice, at: Point, taken: readonly Point[], cell?: number): Point;
186
193
  /**
187
194
  * A folder's field: at least its viewport, grown to hold every icon at
188
195
  * `positions` (their top-lefts) plus the inset past it. The field's size is
@@ -221,7 +221,23 @@ function A(e, t, n = 64) {
221
221
  }
222
222
  return E(e, 0);
223
223
  }
224
- function j(e, t, { cell: n = 64, inset: r = 16 } = {}) {
224
+ function j(e, t, n, r = 64) {
225
+ let i = {
226
+ col: O((t.left - e.left) / e.dx, e.cols),
227
+ row: O((t.top - e.top) / e.dy, e.rows)
228
+ }, a = (e) => !n.some((t) => Math.abs(t.left - e.left) < r && Math.abs(t.top - e.top) < r), o = Math.min(e.cols, 2 * n.length + 1) + Math.min(e.rows, 2 * n.length + 1);
229
+ for (let n = 0; n <= o; n++) {
230
+ let r = null, o = Infinity;
231
+ for (let s = i.col - n; s <= i.col + n; s++) for (let c = i.row - n; c <= i.row + n; c++) {
232
+ if (Math.max(Math.abs(s - i.col), Math.abs(c - i.row)) !== n || s < 0 || c < 0 || s >= e.cols || c >= e.rows) continue;
233
+ let l = T(e, s, c), u = (l.left - t.left) ** 2 + (l.top - t.top) ** 2;
234
+ (u < o || u === o && D(e, l, r) > 0) && a(l) && (o = u, r = l);
235
+ }
236
+ if (r) return r;
237
+ }
238
+ return A(e, n, r);
239
+ }
240
+ function M(e, t, { cell: n = 64, inset: r = 16 } = {}) {
225
241
  let i = t.width, a = t.height;
226
242
  for (let t of e) i = Math.max(i, t.left + n + r), a = Math.max(a, t.top + n + r);
227
243
  return {
@@ -229,7 +245,7 @@ function j(e, t, { cell: n = 64, inset: r = 16 } = {}) {
229
245
  height: a
230
246
  };
231
247
  }
232
- function M(e) {
248
+ function N(e) {
233
249
  let t = /* @__PURE__ */ new Set();
234
250
  for (let n = 0; n < e.length; n++) for (let r = n + 1; r < e.length; r++) {
235
251
  let i = e[n], a = e[r];
@@ -238,4 +254,4 @@ function M(e) {
238
254
  return t;
239
255
  }
240
256
  //#endregion
241
- export { u as BAND, t as CASCADE_SLOTS, e as CASCADE_STEP, v as ICON_CELL, b as ICON_COLUMN, x as ICON_INSET, y as ICON_ROW, c as NEAR, n as WINDOW_ORIGIN, a as cascadeFrom, i as cascadeSlot, s as cascadedBox, o as centeredBox, k as cleanUp, M as collisions, S as desktopLattice, j as fieldExtent, D as fillOrder, w as folderLattice, d as frameOf, f as isPin, T as latticeCell, E as latticeSlot, l as nearBox, A as nextFreeCell, g as pinOf, _ as pinTo, C as trashCell, r as windowOrigin };
257
+ export { u as BAND, t as CASCADE_SLOTS, e as CASCADE_STEP, v as ICON_CELL, b as ICON_COLUMN, x as ICON_INSET, y as ICON_ROW, c as NEAR, n as WINDOW_ORIGIN, a as cascadeFrom, i as cascadeSlot, s as cascadedBox, o as centeredBox, k as cleanUp, N as collisions, S as desktopLattice, M as fieldExtent, D as fillOrder, w as folderLattice, d as frameOf, j as freeCellNear, f as isPin, T as latticeCell, E as latticeSlot, l as nearBox, A as nextFreeCell, g as pinOf, _ as pinTo, C as trashCell, r as windowOrigin };
@@ -17,14 +17,14 @@ export { finder, FINDER } from './finder.js';
17
17
  export type { FinderAlert, FinderAlertHandler, FinderAlerts, FinderApi, FinderArt, FinderCommand, FinderCommandSpec, FinderFailedAction, FinderMenu, FinderOpen, FinderOptions, } from './finder.js';
18
18
  export { fileByDrag } from './filing.js';
19
19
  export type { FilingOptions } from './filing.js';
20
- export { createCatalog, memoryStorage, appIdOf, childrenOf, containerOf, copyName, descendantsOf, enclosingFolders, isContainerKind, isInside, isTrashed, isVolume, itemCount, itemOf, nextFolderName, APP_KIND, DISK, FOLDER, TRASH, UNTITLED_FOLDER, } from './catalog.js';
21
- export type { Catalog, CatalogArchive, CatalogOptions, CatalogState, CatalogStorage, Item, KindHooks, NewItem, Volumes, } from './catalog.js';
20
+ export { createCatalog, memoryStorage, aliasName, appIdOf, appleMenuItemsOf, childrenOf, containerOf, copyName, descendantsOf, enclosingFolders, isContainerKind, isInside, isKept, isTrashed, isVolume, itemCount, itemOf, nextFolderName, originalOf, resolve, startupItemsOf, ALIAS_KIND, APPLE_MENU_ITEMS, APP_KIND, DISK, FOLDER, STARTUP_ITEMS, SYSTEM_FOLDER, TRASH, UNTITLED_FOLDER, } from './catalog.js';
21
+ export type { Catalog, CatalogArchive, CatalogOptions, CatalogState, CatalogStorage, Item, KindHooks, NewItem, SystemFolders, Volumes, } from './catalog.js';
22
22
  export { indexedDbStorage } from './storage.js';
23
23
  export { localStorageState, mergeSession, openWindowsOf, readSession } from './state.js';
24
24
  export type { LocalStorageStateOptions, SavedSession, SavedWindow, SessionSnapshot, ShellState } from './state.js';
25
- export { BAND, CASCADE_SLOTS, CASCADE_STEP, ICON_CELL, ICON_COLUMN, ICON_INSET, ICON_ROW, NEAR, WINDOW_ORIGIN, cascadedBox, cascadeFrom, cascadeSlot, centeredBox, cleanUp, collisions, desktopLattice, fieldExtent, fillOrder, folderLattice, frameOf, isPin, latticeCell, latticeSlot, nearBox, nextFreeCell, pinOf, pinTo, trashCell, windowOrigin, } from './geometry.js';
25
+ export { BAND, CASCADE_SLOTS, CASCADE_STEP, ICON_CELL, ICON_COLUMN, ICON_INSET, ICON_ROW, NEAR, WINDOW_ORIGIN, cascadedBox, cascadeFrom, cascadeSlot, centeredBox, cleanUp, collisions, desktopLattice, fieldExtent, fillOrder, folderLattice, frameOf, freeCellNear, isPin, latticeCell, latticeSlot, nearBox, nextFreeCell, pinOf, pinTo, trashCell, windowOrigin, } from './geometry.js';
26
26
  export type { Bands, Box, CascadeOptions, EdgePin, Frame, Lattice, LatticeOptions, Pin, Point, Policy, Size, } from './geometry.js';
27
27
  export { startClock, formatDate, formatTime, DATE_HOLD_MS } from './clock.js';
28
- export { APP_FILE_FORMAT, BOX_SCALE, compareVersions, inspectAppFile, readAppFile, satisfies } from './app-file.js';
28
+ export { APP_API, APP_API_OLDEST, APP_FILE_FORMAT, BOX_SCALE, appRuns, compareVersions, inspectAppFile, readAppFile, satisfies, } from './app-file.js';
29
29
  export type { AppFile, AppManifest } from './app-file.js';
30
30
  export { VERSION } from './version.js';
@@ -1,12 +1,12 @@
1
- import { APP_KIND as e, DISK as t, FOLDER as n, TRASH as r, UNTITLED_FOLDER as i, appIdOf as a, childrenOf as o, containerOf as s, copyName as c, createCatalog as l, descendantsOf as u, enclosingFolders as d, isContainerKind as f, isInside as p, isTrashed as m, isVolume as h, itemCount as g, itemOf as _, memoryStorage as v, nextFolderName as y } from "./catalog.js";
2
- import { BAND as b, CASCADE_SLOTS as x, CASCADE_STEP as S, ICON_CELL as C, ICON_COLUMN as w, ICON_INSET as T, ICON_ROW as E, NEAR as D, WINDOW_ORIGIN as O, cascadeFrom as k, cascadeSlot as A, cascadedBox as j, centeredBox as M, cleanUp as N, collisions as P, desktopLattice as F, fieldExtent as I, fillOrder as L, folderLattice as R, frameOf as z, isPin as B, latticeCell as V, latticeSlot as H, nearBox as U, nextFreeCell as W, pinOf as G, pinTo as K, trashCell as q, windowOrigin as J } from "./geometry.js";
3
- import { createWindowManager as Y, focusInto as X } from "./windows.js";
4
- import { localStorageState as Z, mergeSession as Q, openWindowsOf as $, readSession as ee } from "./state.js";
5
- import { DATE_HOLD_MS as te, formatDate as ne, formatTime as re, startClock as ie } from "./clock.js";
6
- import { createShell as ae, defineApp as oe } from "./shell.js";
7
- import { fileByDrag as se } from "./filing.js";
8
- import { FINDER as ce, finder as le } from "./finder.js";
9
- import { indexedDbStorage as ue } from "./storage.js";
10
- import { APP_FILE_FORMAT as de, BOX_SCALE as fe, compareVersions as pe, inspectAppFile as me, readAppFile as he, satisfies as ge } from "./app-file.js";
11
- import { VERSION as _e } from "./version.js";
12
- export { de as APP_FILE_FORMAT, e as APP_KIND, b as BAND, fe as BOX_SCALE, x as CASCADE_SLOTS, S as CASCADE_STEP, te as DATE_HOLD_MS, t as DISK, ce as FINDER, n as FOLDER, C as ICON_CELL, w as ICON_COLUMN, T as ICON_INSET, E as ICON_ROW, D as NEAR, r as TRASH, i as UNTITLED_FOLDER, _e as VERSION, O as WINDOW_ORIGIN, a as appIdOf, k as cascadeFrom, A as cascadeSlot, j as cascadedBox, M as centeredBox, o as childrenOf, N as cleanUp, P as collisions, pe as compareVersions, s as containerOf, c as copyName, l as createCatalog, ae as createShell, Y as createWindowManager, oe as defineApp, u as descendantsOf, F as desktopLattice, d as enclosingFolders, I as fieldExtent, se as fileByDrag, L as fillOrder, le as finder, X as focusInto, R as folderLattice, ne as formatDate, re as formatTime, z as frameOf, ue as indexedDbStorage, me as inspectAppFile, f as isContainerKind, p as isInside, B as isPin, m as isTrashed, h as isVolume, g as itemCount, _ as itemOf, V as latticeCell, H as latticeSlot, Z as localStorageState, v as memoryStorage, Q as mergeSession, U as nearBox, y as nextFolderName, W as nextFreeCell, $ as openWindowsOf, G as pinOf, K as pinTo, he as readAppFile, ee as readSession, ge as satisfies, ie as startClock, q as trashCell, J as windowOrigin };
1
+ import { ALIAS_KIND as e, APPLE_MENU_ITEMS as t, APP_KIND as n, DISK as r, FOLDER as i, STARTUP_ITEMS as a, SYSTEM_FOLDER as o, TRASH as s, UNTITLED_FOLDER as c, aliasName as l, appIdOf as u, appleMenuItemsOf as d, childrenOf as f, containerOf as p, copyName as m, createCatalog as h, descendantsOf as g, enclosingFolders as _, isContainerKind as v, isInside as y, isKept as b, isTrashed as x, isVolume as S, itemCount as C, itemOf as w, memoryStorage as T, nextFolderName as E, originalOf as D, resolve as O, startupItemsOf as k } from "./catalog.js";
2
+ import { BAND as A, CASCADE_SLOTS as j, CASCADE_STEP as M, ICON_CELL as N, ICON_COLUMN as P, ICON_INSET as F, ICON_ROW as I, NEAR as L, WINDOW_ORIGIN as R, cascadeFrom as z, cascadeSlot as B, cascadedBox as V, centeredBox as H, cleanUp as U, collisions as W, desktopLattice as G, fieldExtent as K, fillOrder as q, folderLattice as J, frameOf as Y, freeCellNear as X, isPin as Z, latticeCell as Q, latticeSlot as $, nearBox as ee, nextFreeCell as te, pinOf as ne, pinTo as re, trashCell as ie, windowOrigin as ae } from "./geometry.js";
3
+ import { createWindowManager as oe, focusInto as se } from "./windows.js";
4
+ import { localStorageState as ce, mergeSession as le, openWindowsOf as ue, readSession as de } from "./state.js";
5
+ import { DATE_HOLD_MS as fe, formatDate as pe, formatTime as me, startClock as he } from "./clock.js";
6
+ import { createShell as ge, defineApp as _e } from "./shell.js";
7
+ import { fileByDrag as ve } from "./filing.js";
8
+ import { FINDER as ye, finder as be } from "./finder.js";
9
+ import { indexedDbStorage as xe } from "./storage.js";
10
+ import { VERSION as Se } from "./version.js";
11
+ import { APP_API as Ce, APP_API_OLDEST as we, APP_FILE_FORMAT as Te, BOX_SCALE as Ee, appRuns as De, compareVersions as Oe, inspectAppFile as ke, readAppFile as Ae, satisfies as je } from "./app-file.js";
12
+ export { e as ALIAS_KIND, t as APPLE_MENU_ITEMS, Ce as APP_API, we as APP_API_OLDEST, Te as APP_FILE_FORMAT, n as APP_KIND, A as BAND, Ee as BOX_SCALE, j as CASCADE_SLOTS, M as CASCADE_STEP, fe as DATE_HOLD_MS, r as DISK, ye as FINDER, i as FOLDER, N as ICON_CELL, P as ICON_COLUMN, F as ICON_INSET, I as ICON_ROW, L as NEAR, a as STARTUP_ITEMS, o as SYSTEM_FOLDER, s as TRASH, c as UNTITLED_FOLDER, Se as VERSION, R as WINDOW_ORIGIN, l as aliasName, u as appIdOf, De as appRuns, d as appleMenuItemsOf, z as cascadeFrom, B as cascadeSlot, V as cascadedBox, H as centeredBox, f as childrenOf, U as cleanUp, W as collisions, Oe as compareVersions, p as containerOf, m as copyName, h as createCatalog, ge as createShell, oe as createWindowManager, _e as defineApp, g as descendantsOf, G as desktopLattice, _ as enclosingFolders, K as fieldExtent, ve as fileByDrag, q as fillOrder, be as finder, se as focusInto, J as folderLattice, pe as formatDate, me as formatTime, Y as frameOf, X as freeCellNear, xe as indexedDbStorage, ke as inspectAppFile, v as isContainerKind, y as isInside, b as isKept, Z as isPin, x as isTrashed, S as isVolume, C as itemCount, w as itemOf, Q as latticeCell, $ as latticeSlot, ce as localStorageState, T as memoryStorage, le as mergeSession, ee as nearBox, E as nextFolderName, te as nextFreeCell, ue as openWindowsOf, D as originalOf, ne as pinOf, re as pinTo, Ae as readAppFile, de as readSession, O as resolve, je as satisfies, he as startClock, k as startupItemsOf, ie as trashCell, ae as windowOrigin };
@@ -8,6 +8,6 @@
8
8
  export * from './catalog.js';
9
9
  export * from './geometry.js';
10
10
  export * from './state.js';
11
- export { APP_FILE_FORMAT, BOX_SCALE, compareVersions, inspectAppFile, readAppFile, satisfies } from './app-file.js';
11
+ export { APP_API, APP_API_OLDEST, APP_FILE_FORMAT, BOX_SCALE, appRuns, compareVersions, inspectAppFile, readAppFile, satisfies, } from './app-file.js';
12
12
  export type { AppFile, AppManifest } from './app-file.js';
13
13
  export { VERSION } from './version.js';
@@ -1,6 +1,6 @@
1
- import { APP_KIND as e, DISK as t, FOLDER as n, TRASH as r, UNTITLED_FOLDER as i, appIdOf as a, childrenOf as o, containerOf as s, copyName as c, createCatalog as l, descendantsOf as u, enclosingFolders as d, isContainerKind as f, isInside as p, isTrashed as m, isVolume as h, itemCount as g, itemOf as _, memoryStorage as v, nextFolderName as y } from "./catalog.js";
2
- import { BAND as b, CASCADE_SLOTS as x, CASCADE_STEP as S, ICON_CELL as C, ICON_COLUMN as w, ICON_INSET as T, ICON_ROW as E, NEAR as D, WINDOW_ORIGIN as O, cascadeFrom as k, cascadeSlot as A, cascadedBox as j, centeredBox as M, cleanUp as N, collisions as P, desktopLattice as F, fieldExtent as I, fillOrder as L, folderLattice as R, frameOf as z, isPin as B, latticeCell as V, latticeSlot as H, nearBox as U, nextFreeCell as W, pinOf as G, pinTo as K, trashCell as q, windowOrigin as J } from "./geometry.js";
3
- import { localStorageState as Y, mergeSession as X, openWindowsOf as Z, readSession as Q } from "./state.js";
4
- import { APP_FILE_FORMAT as $, BOX_SCALE as ee, compareVersions as te, inspectAppFile as ne, readAppFile as re, satisfies as ie } from "./app-file.js";
5
- import { VERSION as ae } from "./version.js";
6
- export { $ as APP_FILE_FORMAT, e as APP_KIND, b as BAND, ee as BOX_SCALE, x as CASCADE_SLOTS, S as CASCADE_STEP, t as DISK, n as FOLDER, C as ICON_CELL, w as ICON_COLUMN, T as ICON_INSET, E as ICON_ROW, D as NEAR, r as TRASH, i as UNTITLED_FOLDER, ae as VERSION, O as WINDOW_ORIGIN, a as appIdOf, k as cascadeFrom, A as cascadeSlot, j as cascadedBox, M as centeredBox, o as childrenOf, N as cleanUp, P as collisions, te as compareVersions, s as containerOf, c as copyName, l as createCatalog, u as descendantsOf, F as desktopLattice, d as enclosingFolders, I as fieldExtent, L as fillOrder, R as folderLattice, z as frameOf, ne as inspectAppFile, f as isContainerKind, p as isInside, B as isPin, m as isTrashed, h as isVolume, g as itemCount, _ as itemOf, V as latticeCell, H as latticeSlot, Y as localStorageState, v as memoryStorage, X as mergeSession, U as nearBox, y as nextFolderName, W as nextFreeCell, Z as openWindowsOf, G as pinOf, K as pinTo, re as readAppFile, Q as readSession, ie as satisfies, q as trashCell, J as windowOrigin };
1
+ import { ALIAS_KIND as e, APPLE_MENU_ITEMS as t, APP_KIND as n, DISK as r, FOLDER as i, STARTUP_ITEMS as a, SYSTEM_FOLDER as o, TRASH as s, UNTITLED_FOLDER as c, aliasName as l, appIdOf as u, appleMenuItemsOf as d, childrenOf as f, containerOf as p, copyName as m, createCatalog as h, descendantsOf as g, enclosingFolders as _, isContainerKind as v, isInside as y, isKept as b, isTrashed as x, isVolume as S, itemCount as C, itemOf as w, memoryStorage as T, nextFolderName as E, originalOf as D, resolve as O, startupItemsOf as k } from "./catalog.js";
2
+ import { BAND as A, CASCADE_SLOTS as j, CASCADE_STEP as M, ICON_CELL as N, ICON_COLUMN as P, ICON_INSET as F, ICON_ROW as I, NEAR as L, WINDOW_ORIGIN as R, cascadeFrom as z, cascadeSlot as B, cascadedBox as V, centeredBox as H, cleanUp as U, collisions as W, desktopLattice as G, fieldExtent as K, fillOrder as q, folderLattice as J, frameOf as Y, freeCellNear as X, isPin as Z, latticeCell as Q, latticeSlot as $, nearBox as ee, nextFreeCell as te, pinOf as ne, pinTo as re, trashCell as ie, windowOrigin as ae } from "./geometry.js";
3
+ import { localStorageState as oe, mergeSession as se, openWindowsOf as ce, readSession as le } from "./state.js";
4
+ import { VERSION as ue } from "./version.js";
5
+ import { APP_API as de, APP_API_OLDEST as fe, APP_FILE_FORMAT as pe, BOX_SCALE as me, appRuns as he, compareVersions as ge, inspectAppFile as _e, readAppFile as ve, satisfies as ye } from "./app-file.js";
6
+ export { e as ALIAS_KIND, t as APPLE_MENU_ITEMS, de as APP_API, fe as APP_API_OLDEST, pe as APP_FILE_FORMAT, n as APP_KIND, A as BAND, me as BOX_SCALE, j as CASCADE_SLOTS, M as CASCADE_STEP, r as DISK, i as FOLDER, N as ICON_CELL, P as ICON_COLUMN, F as ICON_INSET, I as ICON_ROW, L as NEAR, a as STARTUP_ITEMS, o as SYSTEM_FOLDER, s as TRASH, c as UNTITLED_FOLDER, ue as VERSION, R as WINDOW_ORIGIN, l as aliasName, u as appIdOf, he as appRuns, d as appleMenuItemsOf, z as cascadeFrom, B as cascadeSlot, V as cascadedBox, H as centeredBox, f as childrenOf, U as cleanUp, W as collisions, ge as compareVersions, p as containerOf, m as copyName, h as createCatalog, g as descendantsOf, G as desktopLattice, _ as enclosingFolders, K as fieldExtent, q as fillOrder, J as folderLattice, Y as frameOf, X as freeCellNear, _e as inspectAppFile, v as isContainerKind, y as isInside, b as isKept, Z as isPin, x as isTrashed, S as isVolume, C as itemCount, w as itemOf, Q as latticeCell, $ as latticeSlot, oe as localStorageState, T as memoryStorage, se as mergeSession, ee as nearBox, E as nextFolderName, te as nextFreeCell, ce as openWindowsOf, D as originalOf, ne as pinOf, re as pinTo, ve as readAppFile, le as readSession, O as resolve, ye as satisfies, k as startupItemsOf, ie as trashCell, ae as windowOrigin };
@@ -7,10 +7,13 @@
7
7
  * nodes come back each time it is front, so items keep their state. A menu
8
8
  * off the bar has no key equivalents, so only the front application's fire.
9
9
  * The bar's label is the front application's name.
10
+ * - The system menu is the page's own items, then what Apple Menu Items
11
+ * holds, by name, following the folder as it changes. Choosing an entry
12
+ * opens its item as a double-click would. No application adds to it.
10
13
  * - While an application's held dialog is open, the bar shows that
11
14
  * application's name and menus instead; nothing else changes.
12
15
  * - Each application's `init(ctx)` gets the desktop, the window manager, its
13
- * own menus, dialogs and window markup, the system menu, the other applications' actions
16
+ * own menus, dialogs and window markup, the other applications' actions
14
17
  * (read at the call), the catalog when a Finder runs, the site's services,
15
18
  * `ask()`, `gate()`, `onFront()` and `onDispose()`. Everything it sets up
16
19
  * comes down through `onDispose()`, and its dialogs with it, so a hot
@@ -19,11 +22,12 @@
19
22
  * and it closes when the item is removed.
20
23
  * - The boot waits for the desktop and its menu bar to render, reads the
21
24
  * catalog, seeds it once, reopens the last session's windows deepest
22
- * first and the active one last, then starts saving.
25
+ * first and the active one last, opens what Startup Items holds, then
26
+ * starts saving.
23
27
  */
24
28
  import { VfWindow } from '../index.js';
25
29
  import type { VfDesktop, VfDialog, VfMenu, VfMenuItem, VfModalDialog, VfViewportBox } from '../index.js';
26
- import type { Catalog, CatalogStorage, Item, Volumes } from './catalog.js';
30
+ import type { Catalog, CatalogStorage, Item, SystemFolders, Volumes } from './catalog.js';
27
31
  import type { WindowManager } from './windows.js';
28
32
  import type { ShellState } from './state.js';
29
33
  /** A kind of catalog item an application registers: how it looks and opens. */
@@ -45,10 +49,12 @@ export interface KindDefinition {
45
49
  /** The item on the system clipboard, as a file. */
46
50
  export?(item: Item): Promise<Blob | null>;
47
51
  }
48
- /** The catalog a Finder brings: where it is stored, its volumes and its seed. */
52
+ /** The catalog a Finder brings: where it is stored, its volumes, its System Folder and its seed. */
49
53
  export interface CatalogSetup {
50
54
  storage: CatalogStorage | null;
51
55
  volumes?: Volumes;
56
+ /** The System Folder, named; its folders drive the Apple menu and what opens at startup. */
57
+ system?: SystemFolders;
52
58
  /** Run once per storage, to store the site's defaults. */
53
59
  seed?: (catalog: Catalog) => void | Promise<void>;
54
60
  }
@@ -88,17 +94,15 @@ export interface AppContext {
88
94
  readonly windows: WindowManager;
89
95
  /** Its own menus, parsed from `menus`. */
90
96
  readonly menus: VfMenu[];
91
- /** The page's system menu, for the items applications install. */
92
- readonly systemMenu: VfMenu;
93
97
  /** Every application's actions by id, read at the call. */
94
98
  readonly apps: Record<string, any>;
95
- /** The catalog, when a Finder runs; read before the boot has refreshed it, it lists the volumes alone. */
99
+ /** The catalog, when a Finder runs; read before the boot has refreshed it, it lists the kept containers alone. */
96
100
  readonly catalog: Catalog | null;
97
101
  /** The site's own services. */
98
102
  readonly services: Record<string, any>;
99
103
  /** The saved session, or null. */
100
104
  readonly state: ShellState | null;
101
- /** Every kind the applications register, the shell's `app` kind included, in registration order. */
105
+ /** Every kind the applications register, the shell's `app` and `alias` kinds included, in registration order. */
102
106
  readonly kinds: ReadonlyMap<string, KindDefinition>;
103
107
  /** A kind's definition, or undefined. */
104
108
  kind(kind: string): KindDefinition | undefined;
@@ -110,8 +114,6 @@ export interface AppContext {
110
114
  item(value: string): VfMenuItem;
111
115
  /** Every pick from its menus — never while a modal is open. */
112
116
  onMenu(fn: (value: string, item: VfMenuItem) => void): void;
113
- /** Put an item in the system menu, which runs `fn` when picked. */
114
- systemItem(value: string, label: string, fn: () => void): VfMenuItem;
115
117
  /** One of its dialogs by `data-dialog`; throws when the markup drifts. */
116
118
  dialog<T extends HTMLElement = VfDialog>(name: string): T;
117
119
  /**
@@ -158,6 +160,8 @@ export interface ShellOptions {
158
160
  services?: Record<string, unknown>;
159
161
  /** The clock in the menu bar's `end` slot. Default true. */
160
162
  clock?: boolean;
163
+ /** Open what Startup Items holds once the session is back. Default true; false skips it for this boot. */
164
+ startup?: boolean;
161
165
  }
162
166
  /** A running shell. */
163
167
  export interface Shell {
@@ -1,101 +1,110 @@
1
1
  import { onScaleChange as e } from "../scale.js";
2
2
  import { VfWindow as t } from "../components/vf-window.js";
3
3
  import "../index.js";
4
- import { appIdOf as n, createCatalog as r } from "./catalog.js";
5
- import { createWindowManager as i, deepActiveElement as a, desktopRendered as o } from "./windows.js";
6
- import { openWindowsOf as s } from "./state.js";
7
- import { startClock as c } from "./clock.js";
4
+ import { ALIAS_KIND as n, appIdOf as r, appleMenuItemsOf as i, createCatalog as a, resolve as o, startupItemsOf as s } from "./catalog.js";
5
+ import { createWindowManager as c, deepActiveElement as l, desktopRendered as u } from "./windows.js";
6
+ import { openWindowsOf as d } from "./state.js";
7
+ import { startClock as f } from "./clock.js";
8
8
  //#region src/shell/shell.ts
9
- function l(e) {
9
+ function p(e) {
10
10
  return e;
11
11
  }
12
- var u = (e) => e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement || e?.isContentEditable === !0;
13
- function d(l, d) {
14
- let f = d.apps, p = f.find((e) => e.catalog), m = d.defaultApp ?? p?.id ?? f[0]?.id ?? "", h = d.state ?? null, g = d.services ?? {}, _ = [], v = l.querySelector(":scope > vf-menu-bar");
15
- if (!v) throw Error("vintage-frames/shell: the desktop has no vf-menu-bar");
16
- let y = v.querySelector(":scope > vf-menu");
17
- if (!y) throw Error("vintage-frames/shell: the menu bar has no system menu");
18
- v.shortcuts = !0;
19
- let b = h?.saved?.pattern;
20
- b && (l.pattern = b);
21
- let x = null;
22
- if (d.fit === "viewport") {
12
+ var m = (e) => e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement || e?.isContentEditable === !0;
13
+ function h(p, h) {
14
+ let g = h.apps, _ = g.find((e) => e.catalog), v = h.defaultApp ?? _?.id ?? g[0]?.id ?? "", y = h.state ?? null, b = h.services ?? {}, x = [], S = p.querySelector(":scope > vf-menu-bar");
15
+ if (!S) throw Error("vintage-frames/shell: the desktop has no vf-menu-bar");
16
+ let C = S.querySelector(":scope > vf-menu");
17
+ if (!C) throw Error("vintage-frames/shell: the menu bar has no system menu");
18
+ S.shortcuts = !0;
19
+ let w = y?.saved?.pattern;
20
+ w && (p.pattern = w);
21
+ let T = null;
22
+ if (h.fit === "viewport") {
23
23
  let t = () => {
24
24
  let e = {
25
- width: l.width,
26
- height: l.height
25
+ width: p.width,
26
+ height: p.height
27
27
  };
28
- l.fitWithin(document.documentElement.clientWidth, document.documentElement.clientHeight), x?.resized(e);
28
+ p.fitWithin(document.documentElement.clientWidth, document.documentElement.clientHeight), T?.resized(e);
29
29
  };
30
30
  t(), window.addEventListener("resize", t);
31
31
  let n = e(t);
32
- _.push(() => {
32
+ x.push(() => {
33
33
  window.removeEventListener("resize", t), n();
34
34
  });
35
35
  }
36
- let S = i(l, {
37
- defaultApp: m,
38
- savedPin: (e) => h?.pin(e) ?? null
36
+ let E = c(p, {
37
+ defaultApp: v,
38
+ savedPin: (e) => y?.pin(e) ?? null
39
39
  });
40
- x = S;
41
- let C = (e) => {
42
- e.target === l && l.clearActive();
40
+ T = E;
41
+ let D = (e) => {
42
+ e.target === p && p.clearActive();
43
43
  };
44
- l.addEventListener("pointerdown", C), _.push(() => l.removeEventListener("pointerdown", C));
45
- let w = {}, T = /* @__PURE__ */ new Map();
46
- T.set("app", {
47
- art: (e) => f.find((t) => t.id === n(e))?.icon ?? "",
48
- open: (e, t) => void w[n(e) ?? ""]?.open?.({ from: t }),
44
+ p.addEventListener("pointerdown", D), x.push(() => p.removeEventListener("pointerdown", D));
45
+ let O = {}, k = (e, t = null) => O[_?.id ?? ""]?.open?.({
46
+ item: e,
47
+ from: t
48
+ }), A = /* @__PURE__ */ new Map();
49
+ A.set("app", {
50
+ art: (e) => g.find((t) => t.id === r(e))?.icon ?? "",
51
+ open: (e, t) => void O[r(e) ?? ""]?.open?.({ from: t }),
49
52
  editable: !1
53
+ }), A.set(n, {
54
+ art: (e) => {
55
+ let t = j && o(j.get(), e.id), n = t && A.get(t.kind);
56
+ return !t || !n ? "" : typeof n.art == "function" ? n.art(t) : n.art;
57
+ },
58
+ open: (e, t) => void k(e.id, t)
50
59
  });
51
- for (let e of f) for (let [t, n] of Object.entries(e.kinds ?? {})) T.set(t, n);
52
- let E = p?.catalog ? r({
53
- storage: p.catalog.storage,
54
- volumes: p.catalog.volumes,
55
- listed: (e) => T.has(e),
56
- hooks: (e) => T.get(e)
57
- }) : null, D = () => !!document.querySelector("vf-dialog[open]"), O = () => u(a()), k = /* @__PURE__ */ new Map(), A = () => {
58
- for (let [e, t] of k) {
60
+ for (let e of g) for (let [t, n] of Object.entries(e.kinds ?? {})) A.set(t, n);
61
+ let j = _?.catalog ? a({
62
+ storage: _.catalog.storage,
63
+ volumes: _.catalog.volumes,
64
+ system: _.catalog.system,
65
+ listed: (e) => A.has(e),
66
+ hooks: (e) => A.get(e)
67
+ }) : null, M = () => !!document.querySelector("vf-dialog[open]"), N = () => m(l()), P = /* @__PURE__ */ new Map(), F = () => {
68
+ for (let [e, t] of P) {
59
69
  let n = !t();
60
70
  e.disabled !== n && (e.disabled = n);
61
71
  }
62
72
  };
63
- document.addEventListener("pointerdown", A, !0), document.addEventListener("keydown", A, !0), l.addEventListener("vf-select", A), l.addEventListener("vf-activate", A), _.push(() => document.removeEventListener("pointerdown", A, !0), () => document.removeEventListener("keydown", A, !0), () => l.removeEventListener("vf-select", A), () => l.removeEventListener("vf-activate", A), S.onWindows(A), S.onLayout(A)), E && _.push(E.subscribe(A));
64
- let j = (e) => {
73
+ document.addEventListener("pointerdown", F, !0), document.addEventListener("keydown", F, !0), p.addEventListener("vf-select", F), p.addEventListener("vf-activate", F), x.push(() => document.removeEventListener("pointerdown", F, !0), () => document.removeEventListener("keydown", F, !0), () => p.removeEventListener("vf-select", F), () => p.removeEventListener("vf-activate", F), E.onWindows(F), E.onLayout(F)), j && x.push(j.subscribe(F));
74
+ let I = (e) => {
65
75
  if (!e) return [];
66
76
  let t = document.createElement("div");
67
77
  t.innerHTML = e, customElements.upgrade(t);
68
78
  let n = [...t.children].filter((e) => e instanceof HTMLElement);
69
79
  for (let e of n) e.remove();
70
80
  return n;
71
- }, M = f.map((e) => ({
81
+ }, L = g.map((e) => ({
72
82
  def: e,
73
- menus: j(e.menus).filter((e) => e.localName === "vf-menu"),
74
- dialogs: j(e.dialogs).filter((e) => e.dataset.dialog != null),
83
+ menus: I(e.menus).filter((e) => e.localName === "vf-menu"),
84
+ dialogs: I(e.dialogs).filter((e) => e.dataset.dialog != null),
75
85
  windows: (() => {
76
86
  let t = document.createElement("template");
77
87
  return t.innerHTML = e.windows ?? "", t.content;
78
88
  })()
79
- })), N = [];
80
- for (let { def: e, menus: t, dialogs: n, windows: r } of M) {
89
+ })), R = [];
90
+ for (let { def: e, menus: t, dialogs: n, windows: r } of L) {
81
91
  let i = [], a = `vintage-frames/shell (${e.id})`, o = /* @__PURE__ */ new Set();
82
- for (let t of n) S.holdDialog(t, { app: e.id }), o.add(t);
92
+ for (let t of n) E.holdDialog(t, { app: e.id }), o.add(t);
83
93
  i.push(() => {
84
- for (let e of o) S.releaseDialog(e), e.remove();
94
+ for (let e of o) E.releaseDialog(e), e.remove();
85
95
  o.clear();
86
96
  });
87
97
  let s = {
88
- desktop: l,
89
- windows: S,
98
+ desktop: p,
99
+ windows: E,
90
100
  menus: t,
91
- systemMenu: y,
92
- apps: w,
93
- catalog: E,
94
- services: g,
95
- state: h,
96
- kinds: T,
97
- kind: (e) => T.get(e),
98
- app: (e) => f.find((t) => t.id === e),
101
+ apps: O,
102
+ catalog: j,
103
+ services: b,
104
+ state: y,
105
+ kinds: A,
106
+ kind: (e) => A.get(e),
107
+ app: (e) => g.find((t) => t.id === e),
99
108
  menu(e) {
100
109
  let n = t.find((t) => t.dataset.menu === e);
101
110
  if (!n) throw Error(`${a}: missing menu ${e}`);
@@ -110,17 +119,11 @@ function d(l, d) {
110
119
  },
111
120
  onMenu(e) {
112
121
  for (let n of t) s.on(n, "vf-menu-select", (t) => {
113
- if (D()) return;
122
+ if (M()) return;
114
123
  let { value: n, item: r } = t.detail;
115
124
  e(n, r);
116
125
  });
117
126
  },
118
- systemItem(e, t, n) {
119
- let r = document.createElement("vf-menu-item");
120
- return r.setAttribute("value", e), r.textContent = t, y.append(r), s.on(y, "vf-menu-select", (t) => {
121
- !D() && t.detail.value === e && n();
122
- }), i.push(() => r.remove()), r;
123
- },
124
127
  dialog(e) {
125
128
  let t = n.find((t) => t.dataset.dialog === e);
126
129
  if (!t) throw Error(`${a}: missing dialog ${e}`);
@@ -133,13 +136,13 @@ function d(l, d) {
133
136
  return customElements.upgrade(n), n;
134
137
  },
135
138
  hold(t) {
136
- return S.holdDialog(t, { app: e.id }), o.add(t), t;
139
+ return E.holdDialog(t, { app: e.id }), o.add(t), t;
137
140
  },
138
141
  release(e) {
139
- o.delete(e) && (S.releaseDialog(e), e.remove());
142
+ o.delete(e) && (E.releaseDialog(e), e.remove());
140
143
  },
141
144
  ask(t) {
142
- if (S.appOf(t) !== e.id) throw Error(`${a}: ask() takes a dialog the application holds`);
145
+ if (E.appOf(t) !== e.id) throw Error(`${a}: ask() takes a dialog the application holds`);
143
146
  return new Promise((e) => {
144
147
  let n = (r) => {
145
148
  r.target === t && (t.removeEventListener("vf-close", n), e(r.detail.returnValue));
@@ -148,14 +151,14 @@ function d(l, d) {
148
151
  });
149
152
  },
150
153
  gate(e, t) {
151
- k.set(e, t), i.push(() => k.delete(e));
154
+ P.set(e, t), i.push(() => P.delete(e));
152
155
  let n = !t();
153
156
  e.disabled !== n && (e.disabled = n);
154
157
  },
155
- typing: O,
156
- modalOpen: D,
158
+ typing: N,
159
+ modalOpen: M,
157
160
  onFront(t) {
158
- t(S.front === e.id), i.push(S.onFront((n) => t(n === e.id)));
161
+ t(E.front === e.id), i.push(E.onFront((n) => t(n === e.id)));
159
162
  },
160
163
  on(e, t, n, r) {
161
164
  e.addEventListener(t, n, r), i.push(() => e.removeEventListener(t, n, r));
@@ -164,82 +167,106 @@ function d(l, d) {
164
167
  i.push(e);
165
168
  }
166
169
  }, c = e.init(s);
167
- c && (w[e.id] = c), N.push(() => {
170
+ c && (O[e.id] = c), R.push(() => {
168
171
  for (let e of i.splice(0).reverse()) e();
169
172
  });
170
173
  }
171
- let P = null, F = () => {
172
- let e = S.asking ?? S.front, t = M.find((t) => t.def.id === e) ?? M.find((e) => e.def.id === m) ?? null;
173
- if (!(!t || t === P)) {
174
- if (P) for (let e of P.menus) e.remove();
175
- y.after(...t.menus), v.label = t.def.name, P = t, A();
174
+ let z = null, B = () => {
175
+ let e = E.asking ?? E.front, t = L.find((t) => t.def.id === e) ?? L.find((e) => e.def.id === v) ?? null;
176
+ if (!(!t || t === z)) {
177
+ if (z) for (let e of z.menus) e.remove();
178
+ C.after(...t.menus), S.label = t.def.name, z = t, F();
179
+ }
180
+ };
181
+ x.push(E.onFront(B), E.onDialogs(B)), B();
182
+ let V = /* @__PURE__ */ new Map(), H = () => {
183
+ let e = j ? i(j.get()) : [], t = [...V];
184
+ if (t.length === e.length && t.every(([, t], n) => t === e[n].id)) {
185
+ t.forEach(([t], n) => {
186
+ t.textContent !== e[n].name && (t.textContent = e[n].name);
187
+ });
188
+ return;
189
+ }
190
+ for (let [e] of t) e.remove();
191
+ V.clear();
192
+ for (let t of e) {
193
+ let e = document.createElement("vf-menu-item");
194
+ e.setAttribute("value", t.id), e.textContent = t.name, C.append(e), V.set(e, t.id);
176
195
  }
196
+ }, U = (e) => {
197
+ let t = V.get(e.detail.item);
198
+ t != null && !M() && k(t);
177
199
  };
178
- if (_.push(S.onFront(F), S.onDialogs(F)), F(), d.clock !== !1) {
179
- let e = v.querySelector(":scope > [slot=\"end\"]"), t = !e;
180
- e || (e = document.createElement("vf-label"), e.slot = "end", v.append(e));
181
- let n = c(e);
182
- _.push(() => {
200
+ if (C.addEventListener("vf-menu-select", U), x.push(() => {
201
+ C.removeEventListener("vf-menu-select", U);
202
+ for (let [e] of V) e.remove();
203
+ V.clear();
204
+ }), j && x.push(j.subscribe(H)), h.clock !== !1) {
205
+ let e = S.querySelector(":scope > [slot=\"end\"]"), t = !e;
206
+ e || (e = document.createElement("vf-label"), e.slot = "end", S.append(e));
207
+ let n = f(e);
208
+ x.push(() => {
183
209
  n(), t && e.remove();
184
210
  });
185
211
  }
186
- let I = /* @__PURE__ */ new WeakSet(), L = () => {
187
- if (E) for (let e of l.stackingOrder) {
212
+ let W = /* @__PURE__ */ new WeakSet(), G = () => {
213
+ if (j) for (let e of p.stackingOrder) {
188
214
  if (!(e instanceof t)) continue;
189
- let n = S.itemOf(e);
215
+ let n = E.itemOf(e);
190
216
  if (n == null) continue;
191
- let r = E.item(n);
192
- r ? (I.add(e), e.heading !== r.name && (e.heading = r.name)) : I.has(e) && E.get().available && S.close(e, { to: null });
217
+ let r = j.item(n);
218
+ r ? (W.add(e), e.heading !== r.name && (e.heading = r.name)) : W.has(e) && j.get().available && E.close(e, { to: null });
193
219
  }
194
220
  };
195
- return E && _.push(E.subscribe(L), S.onWindows(L)), h?.hold(), {
196
- desktop: l,
197
- windows: S,
198
- catalog: E,
199
- apps: w,
221
+ return j && x.push(j.subscribe(G), E.onWindows(G)), y?.hold(), {
222
+ desktop: p,
223
+ windows: E,
224
+ catalog: j,
225
+ apps: O,
200
226
  ready: (async () => {
201
227
  try {
202
- await o(l), E && (await E.refresh(), p?.catalog?.seed && await E.seed(p.catalog.seed));
203
- for (let { item: e, app: t } of s(h?.saved ?? null)) await w[t]?.open?.({ item: e });
204
- let e = h?.saved?.active;
228
+ await u(p), j && (await j.refresh(), _?.catalog?.seed && await j.seed(_.catalog.seed));
229
+ for (let { item: e, app: t } of d(y?.saved ?? null)) await O[t]?.open?.({ item: e });
230
+ let e = y?.saved?.active;
205
231
  if (e) {
206
- let t = S.windowFor(e);
207
- t && l.bringToFront(t);
232
+ let t = E.windowFor(e);
233
+ t && p.bringToFront(t);
208
234
  }
235
+ if (j && h.startup !== !1) for (let e of s(j.get())) await k(e.id);
209
236
  } finally {
210
- if (h) {
211
- let e = h.start(() => ({
212
- windows: S.snapshot(),
213
- active: S.itemOf(l.activeWindow),
214
- pattern: l.pattern ?? null
237
+ if (y) {
238
+ let e = y.start(() => ({
239
+ windows: E.snapshot(),
240
+ active: E.itemOf(p.activeWindow),
241
+ pattern: p.pattern ?? null
215
242
  }), (e) => {
216
243
  let t = [
217
- S.onLayout(e),
218
- S.onWindows(e),
219
- ...E ? [E.subscribe(e)] : []
244
+ E.onLayout(e),
245
+ E.onWindows(e),
246
+ ...j ? [j.subscribe(e)] : []
220
247
  ];
221
- l.addEventListener("vf-activate", e);
248
+ p.addEventListener("vf-activate", e);
222
249
  let n = new MutationObserver(e);
223
- return n.observe(l, {
250
+ return n.observe(p, {
224
251
  attributes: !0,
225
252
  attributeFilter: ["pattern"]
226
253
  }), () => {
227
254
  for (let e of t) e();
228
- l.removeEventListener("vf-activate", e), n.disconnect();
255
+ p.removeEventListener("vf-activate", e), n.disconnect();
229
256
  };
230
257
  });
231
- _.push(e), h.release();
258
+ x.push(e), y.release();
232
259
  }
233
260
  }
234
261
  })(),
235
262
  dispose() {
236
- for (let e of N.splice(0).reverse()) e();
237
- if (P) for (let e of P.menus) e.remove();
238
- P = null;
239
- for (let e of _.splice(0)) e();
240
- S.dispose(), E?.dispose();
263
+ for (let e of R.splice(0).reverse()) e();
264
+ if (z) for (let e of z.menus) e.remove();
265
+ z = null;
266
+ for (let e of x.splice(0)) e();
267
+ E.dispose(), j?.dispose();
241
268
  }
242
269
  };
243
270
  }
244
271
  //#endregion
245
- export { d as createShell, l as defineApp };
272
+ export { h as createShell, p as defineApp };
@@ -1,2 +1,2 @@
1
1
  /** The kit's version, as published: package.json's `version`. `npm version` rewrites it (the `version` script). */
2
- export declare const VERSION = "0.18.0";
2
+ export declare const VERSION = "0.19.0";
@@ -1,4 +1,4 @@
1
1
  //#region src/shell/version.ts
2
- var e = "0.18.0";
2
+ var e = "0.19.0";
3
3
  //#endregion
4
4
  export { e as VERSION };
@@ -0,0 +1,2 @@
1
+ /** Register the body face's italic on the document once (idempotent). */
2
+ export declare function registerBodyItalicFace(): void;