vintage-frames 0.18.0 → 0.19.1
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 +1 -1
- package/custom-elements.json +278 -51
- package/dist/build/app-file.d.ts +2 -2
- package/dist/build/app-file.js +1 -0
- package/dist/build/plugins.d.ts +2 -2
- package/dist/build/plugins.js +62 -59
- package/dist/components/vf-icon.d.ts +7 -0
- package/dist/components/vf-icon.js +101 -81
- package/dist/components/vf-menu-bar.d.ts +6 -4
- package/dist/components/vf-menu-bar.js +26 -56
- package/dist/components/vf-menu-item.d.ts +33 -5
- package/dist/components/vf-menu-item.js +128 -61
- package/dist/components/vf-menu.d.ts +35 -0
- package/dist/components/vf-menu.js +171 -111
- package/dist/glyphs.d.ts +6 -0
- package/dist/glyphs.js +18 -14
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -14
- package/dist/menu-navigation.d.ts +34 -0
- package/dist/menu-navigation.js +53 -0
- package/dist/menu-press.d.ts +25 -7
- package/dist/menu-press.js +78 -44
- package/dist/motion.d.ts +10 -0
- package/dist/shell/app-file.d.ts +20 -4
- package/dist/shell/app-file.js +65 -53
- package/dist/shell/catalog.d.ts +79 -1
- package/dist/shell/catalog.js +206 -153
- package/dist/shell/finder.d.ts +28 -9
- package/dist/shell/finder.js +339 -267
- package/dist/shell/geometry.d.ts +7 -0
- package/dist/shell/geometry.js +19 -3
- package/dist/shell/index.d.ts +4 -4
- package/dist/shell/index.js +12 -12
- package/dist/shell/pure.d.ts +1 -1
- package/dist/shell/pure.js +6 -6
- package/dist/shell/shell.d.ts +14 -10
- package/dist/shell/shell.js +148 -116
- package/dist/shell/version.d.ts +1 -1
- package/dist/shell/version.js +1 -1
- package/dist/styles/body-italic-font.d.ts +2 -0
- package/dist/styles/body-italic-font.js +10 -0
- package/dist/styles/register-embedded-font.d.ts +5 -4
- package/dist/styles/register-embedded-font.js +11 -10
- package/docs/SPEC.md +11 -7
- package/editor/vscode.html-custom-data.json +15 -5
- package/editor/web-types.json +55 -9
- package/package.json +7 -3
package/dist/shell/geometry.d.ts
CHANGED
|
@@ -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
|
package/dist/shell/geometry.js
CHANGED
|
@@ -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,
|
|
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
|
|
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,
|
|
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 };
|
package/dist/shell/index.d.ts
CHANGED
|
@@ -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, appleMenuOf, canAlias, childrenOf, containerOf, copyName, descendantsOf, dropTargetOf, 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 { AppleMenuEntry, Catalog, CatalogArchive, CatalogOptions, CatalogState, CatalogStorage, DropTarget, 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';
|
package/dist/shell/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { BAND as
|
|
3
|
-
import { createWindowManager as
|
|
4
|
-
import { localStorageState as
|
|
5
|
-
import { DATE_HOLD_MS as
|
|
6
|
-
import { createShell as
|
|
7
|
-
import { fileByDrag as
|
|
8
|
-
import { FINDER as
|
|
9
|
-
import { indexedDbStorage as
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
export {
|
|
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, appleMenuOf as f, canAlias as p, childrenOf as m, containerOf as h, copyName as g, createCatalog as _, descendantsOf as v, dropTargetOf as y, enclosingFolders as b, isContainerKind as x, isInside as S, isKept as C, isTrashed as w, isVolume as T, itemCount as E, itemOf as D, memoryStorage as O, nextFolderName as k, originalOf as A, resolve as j, startupItemsOf as M } from "./catalog.js";
|
|
2
|
+
import { BAND as N, CASCADE_SLOTS as P, CASCADE_STEP as F, ICON_CELL as I, ICON_COLUMN as L, ICON_INSET as R, ICON_ROW as z, NEAR as B, WINDOW_ORIGIN as V, cascadeFrom as H, cascadeSlot as U, cascadedBox as W, centeredBox as G, cleanUp as K, collisions as q, desktopLattice as J, fieldExtent as Y, fillOrder as X, folderLattice as Z, frameOf as Q, freeCellNear as $, isPin as ee, latticeCell as te, latticeSlot as ne, nearBox as re, nextFreeCell as ie, pinOf as ae, pinTo as oe, trashCell as se, windowOrigin as ce } from "./geometry.js";
|
|
3
|
+
import { createWindowManager as le, focusInto as ue } from "./windows.js";
|
|
4
|
+
import { localStorageState as de, mergeSession as fe, openWindowsOf as pe, readSession as me } from "./state.js";
|
|
5
|
+
import { DATE_HOLD_MS as he, formatDate as ge, formatTime as _e, startClock as ve } from "./clock.js";
|
|
6
|
+
import { createShell as ye, defineApp as be } from "./shell.js";
|
|
7
|
+
import { fileByDrag as xe } from "./filing.js";
|
|
8
|
+
import { FINDER as Se, finder as Ce } from "./finder.js";
|
|
9
|
+
import { indexedDbStorage as we } from "./storage.js";
|
|
10
|
+
import { VERSION as Te } from "./version.js";
|
|
11
|
+
import { APP_API as Ee, APP_API_OLDEST as De, APP_FILE_FORMAT as Oe, BOX_SCALE as ke, appRuns as Ae, compareVersions as je, inspectAppFile as Me, readAppFile as Ne, satisfies as Pe } from "./app-file.js";
|
|
12
|
+
export { e as ALIAS_KIND, t as APPLE_MENU_ITEMS, Ee as APP_API, De as APP_API_OLDEST, Oe as APP_FILE_FORMAT, n as APP_KIND, N as BAND, ke as BOX_SCALE, P as CASCADE_SLOTS, F as CASCADE_STEP, he as DATE_HOLD_MS, r as DISK, Se as FINDER, i as FOLDER, I as ICON_CELL, L as ICON_COLUMN, R as ICON_INSET, z as ICON_ROW, B as NEAR, a as STARTUP_ITEMS, o as SYSTEM_FOLDER, s as TRASH, c as UNTITLED_FOLDER, Te as VERSION, V as WINDOW_ORIGIN, l as aliasName, u as appIdOf, Ae as appRuns, d as appleMenuItemsOf, f as appleMenuOf, p as canAlias, H as cascadeFrom, U as cascadeSlot, W as cascadedBox, G as centeredBox, m as childrenOf, K as cleanUp, q as collisions, je as compareVersions, h as containerOf, g as copyName, _ as createCatalog, ye as createShell, le as createWindowManager, be as defineApp, v as descendantsOf, J as desktopLattice, y as dropTargetOf, b as enclosingFolders, Y as fieldExtent, xe as fileByDrag, X as fillOrder, Ce as finder, ue as focusInto, Z as folderLattice, ge as formatDate, _e as formatTime, Q as frameOf, $ as freeCellNear, we as indexedDbStorage, Me as inspectAppFile, x as isContainerKind, S as isInside, C as isKept, ee as isPin, w as isTrashed, T as isVolume, E as itemCount, D as itemOf, te as latticeCell, ne as latticeSlot, de as localStorageState, O as memoryStorage, fe as mergeSession, re as nearBox, k as nextFolderName, ie as nextFreeCell, pe as openWindowsOf, A as originalOf, ae as pinOf, oe as pinTo, Ne as readAppFile, me as readSession, j as resolve, Pe as satisfies, ve as startClock, M as startupItemsOf, se as trashCell, ce as windowOrigin };
|
package/dist/shell/pure.d.ts
CHANGED
|
@@ -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';
|
package/dist/shell/pure.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { BAND as
|
|
3
|
-
import { localStorageState as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
export {
|
|
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, appleMenuOf as f, canAlias as p, childrenOf as m, containerOf as h, copyName as g, createCatalog as _, descendantsOf as v, dropTargetOf as y, enclosingFolders as b, isContainerKind as x, isInside as S, isKept as C, isTrashed as w, isVolume as T, itemCount as E, itemOf as D, memoryStorage as O, nextFolderName as k, originalOf as A, resolve as j, startupItemsOf as M } from "./catalog.js";
|
|
2
|
+
import { BAND as N, CASCADE_SLOTS as P, CASCADE_STEP as F, ICON_CELL as I, ICON_COLUMN as L, ICON_INSET as R, ICON_ROW as z, NEAR as B, WINDOW_ORIGIN as V, cascadeFrom as H, cascadeSlot as U, cascadedBox as W, centeredBox as G, cleanUp as K, collisions as q, desktopLattice as J, fieldExtent as Y, fillOrder as X, folderLattice as Z, frameOf as Q, freeCellNear as $, isPin as ee, latticeCell as te, latticeSlot as ne, nearBox as re, nextFreeCell as ie, pinOf as ae, pinTo as oe, trashCell as se, windowOrigin as ce } from "./geometry.js";
|
|
3
|
+
import { localStorageState as le, mergeSession as ue, openWindowsOf as de, readSession as fe } from "./state.js";
|
|
4
|
+
import { VERSION as pe } from "./version.js";
|
|
5
|
+
import { APP_API as me, APP_API_OLDEST as he, APP_FILE_FORMAT as ge, BOX_SCALE as _e, appRuns as ve, compareVersions as ye, inspectAppFile as be, readAppFile as xe, satisfies as Se } from "./app-file.js";
|
|
6
|
+
export { e as ALIAS_KIND, t as APPLE_MENU_ITEMS, me as APP_API, he as APP_API_OLDEST, ge as APP_FILE_FORMAT, n as APP_KIND, N as BAND, _e as BOX_SCALE, P as CASCADE_SLOTS, F as CASCADE_STEP, r as DISK, i as FOLDER, I as ICON_CELL, L as ICON_COLUMN, R as ICON_INSET, z as ICON_ROW, B as NEAR, a as STARTUP_ITEMS, o as SYSTEM_FOLDER, s as TRASH, c as UNTITLED_FOLDER, pe as VERSION, V as WINDOW_ORIGIN, l as aliasName, u as appIdOf, ve as appRuns, d as appleMenuItemsOf, f as appleMenuOf, p as canAlias, H as cascadeFrom, U as cascadeSlot, W as cascadedBox, G as centeredBox, m as childrenOf, K as cleanUp, q as collisions, ye as compareVersions, h as containerOf, g as copyName, _ as createCatalog, v as descendantsOf, J as desktopLattice, y as dropTargetOf, b as enclosingFolders, Y as fieldExtent, X as fillOrder, Z as folderLattice, Q as frameOf, $ as freeCellNear, be as inspectAppFile, x as isContainerKind, S as isInside, C as isKept, ee as isPin, w as isTrashed, T as isVolume, E as itemCount, D as itemOf, te as latticeCell, ne as latticeSlot, le as localStorageState, O as memoryStorage, ue as mergeSession, re as nearBox, k as nextFolderName, ie as nextFreeCell, de as openWindowsOf, A as originalOf, ae as pinOf, oe as pinTo, xe as readAppFile, fe as readSession, j as resolve, Se as satisfies, M as startupItemsOf, se as trashCell, ce as windowOrigin };
|
package/dist/shell/shell.d.ts
CHANGED
|
@@ -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
|
|
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,
|
|
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
|
|
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`
|
|
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 {
|
package/dist/shell/shell.js
CHANGED
|
@@ -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 {
|
|
5
|
-
import { createWindowManager as
|
|
6
|
-
import { openWindowsOf as
|
|
7
|
-
import { startClock as
|
|
4
|
+
import { ALIAS_KIND as n, appIdOf as r, appleMenuOf 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
|
|
9
|
+
function p(e) {
|
|
10
10
|
return e;
|
|
11
11
|
}
|
|
12
|
-
var
|
|
13
|
-
function
|
|
14
|
-
let
|
|
15
|
-
if (!
|
|
16
|
-
let
|
|
17
|
-
if (!
|
|
18
|
-
|
|
19
|
-
let
|
|
20
|
-
|
|
21
|
-
let
|
|
22
|
-
if (
|
|
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:
|
|
26
|
-
height:
|
|
25
|
+
width: p.width,
|
|
26
|
+
height: p.height
|
|
27
27
|
};
|
|
28
|
-
|
|
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
|
-
|
|
32
|
+
x.push(() => {
|
|
33
33
|
window.removeEventListener("resize", t), n();
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
-
let
|
|
37
|
-
defaultApp:
|
|
38
|
-
savedPin: (e) =>
|
|
36
|
+
let E = c(p, {
|
|
37
|
+
defaultApp: v,
|
|
38
|
+
savedPin: (e) => y?.pin(e) ?? null
|
|
39
39
|
});
|
|
40
|
-
|
|
41
|
-
let
|
|
42
|
-
e.target ===
|
|
40
|
+
T = E;
|
|
41
|
+
let D = (e) => {
|
|
42
|
+
e.target === p && p.clearActive();
|
|
43
43
|
};
|
|
44
|
-
|
|
45
|
-
let
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
|
52
|
-
let
|
|
53
|
-
storage:
|
|
54
|
-
volumes:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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",
|
|
64
|
-
let
|
|
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
|
-
},
|
|
81
|
+
}, L = g.map((e) => ({
|
|
72
82
|
def: e,
|
|
73
|
-
menus:
|
|
74
|
-
dialogs:
|
|
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
|
-
})),
|
|
80
|
-
for (let { def: e, menus: t, dialogs: n, windows: r } of
|
|
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)
|
|
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)
|
|
94
|
+
for (let e of o) E.releaseDialog(e), e.remove();
|
|
85
95
|
o.clear();
|
|
86
96
|
});
|
|
87
97
|
let s = {
|
|
88
|
-
desktop:
|
|
89
|
-
windows:
|
|
98
|
+
desktop: p,
|
|
99
|
+
windows: E,
|
|
90
100
|
menus: t,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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 (
|
|
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
|
|
139
|
+
return E.holdDialog(t, { app: e.id }), o.add(t), t;
|
|
137
140
|
},
|
|
138
141
|
release(e) {
|
|
139
|
-
o.delete(e) && (
|
|
142
|
+
o.delete(e) && (E.releaseDialog(e), e.remove());
|
|
140
143
|
},
|
|
141
144
|
ask(t) {
|
|
142
|
-
if (
|
|
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
|
-
|
|
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:
|
|
156
|
-
modalOpen:
|
|
158
|
+
typing: N,
|
|
159
|
+
modalOpen: M,
|
|
157
160
|
onFront(t) {
|
|
158
|
-
t(
|
|
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,111 @@ function d(l, d) {
|
|
|
164
167
|
i.push(e);
|
|
165
168
|
}
|
|
166
169
|
}, c = e.init(s);
|
|
167
|
-
c && (
|
|
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
|
|
172
|
-
let e =
|
|
173
|
-
if (!(!t || t ===
|
|
174
|
-
if (
|
|
175
|
-
|
|
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 = [], U = "", W = (e) => e.map((e) => e.entries ? `${e.item.id}(${W(e.entries)})` : e.item.id).join(","), G = (e) => e.flatMap((e) => [e.item, ...e.entries ? G(e.entries) : []]), K = (e, t) => {
|
|
183
|
+
for (let { item: n, entries: r } of e) {
|
|
184
|
+
let e = document.createElement("vf-menu-item");
|
|
185
|
+
if (e.setAttribute("value", n.id), e.append(n.name), t.append(e), V.set(e, n.id), H.push(e), r) {
|
|
186
|
+
let t = document.createElement("vf-menu");
|
|
187
|
+
t.slot = "submenu", e.append(t), K(r, t);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}, q = () => {
|
|
191
|
+
let e = j ? i(j.get()) : [], t = W(e);
|
|
192
|
+
if (t === U) {
|
|
193
|
+
G(e).forEach((e, t) => {
|
|
194
|
+
let n = H[t];
|
|
195
|
+
n.labelText !== e.name && n.firstChild.replaceWith(e.name);
|
|
196
|
+
});
|
|
197
|
+
return;
|
|
176
198
|
}
|
|
199
|
+
for (let [e] of V) e.remove();
|
|
200
|
+
V.clear(), H = [], U = t, K(e, C);
|
|
201
|
+
}, J = (e) => {
|
|
202
|
+
let t = V.get(e.detail.item);
|
|
203
|
+
t != null && !M() && k(t);
|
|
177
204
|
};
|
|
178
|
-
if (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
205
|
+
if (C.addEventListener("vf-menu-select", J), x.push(() => {
|
|
206
|
+
C.removeEventListener("vf-menu-select", J);
|
|
207
|
+
for (let [e] of V) e.remove();
|
|
208
|
+
V.clear();
|
|
209
|
+
}), j && x.push(j.subscribe(q)), h.clock !== !1) {
|
|
210
|
+
let e = S.querySelector(":scope > [slot=\"end\"]"), t = !e;
|
|
211
|
+
e || (e = document.createElement("vf-label"), e.slot = "end", S.append(e));
|
|
212
|
+
let n = f(e);
|
|
213
|
+
x.push(() => {
|
|
183
214
|
n(), t && e.remove();
|
|
184
215
|
});
|
|
185
216
|
}
|
|
186
|
-
let
|
|
187
|
-
if (
|
|
217
|
+
let Y = /* @__PURE__ */ new WeakSet(), X = () => {
|
|
218
|
+
if (j) for (let e of p.stackingOrder) {
|
|
188
219
|
if (!(e instanceof t)) continue;
|
|
189
|
-
let n =
|
|
220
|
+
let n = E.itemOf(e);
|
|
190
221
|
if (n == null) continue;
|
|
191
|
-
let r =
|
|
192
|
-
r ? (
|
|
222
|
+
let r = j.item(n);
|
|
223
|
+
r ? (Y.add(e), e.heading !== r.name && (e.heading = r.name)) : Y.has(e) && j.get().available && E.close(e, { to: null });
|
|
193
224
|
}
|
|
194
225
|
};
|
|
195
|
-
return
|
|
196
|
-
desktop:
|
|
197
|
-
windows:
|
|
198
|
-
catalog:
|
|
199
|
-
apps:
|
|
226
|
+
return j && x.push(j.subscribe(X), E.onWindows(X)), y?.hold(), {
|
|
227
|
+
desktop: p,
|
|
228
|
+
windows: E,
|
|
229
|
+
catalog: j,
|
|
230
|
+
apps: O,
|
|
200
231
|
ready: (async () => {
|
|
201
232
|
try {
|
|
202
|
-
await
|
|
203
|
-
for (let { item: e, app: t } of
|
|
204
|
-
let e =
|
|
233
|
+
await u(p), j && (await j.refresh(), _?.catalog?.seed && await j.seed(_.catalog.seed));
|
|
234
|
+
for (let { item: e, app: t } of d(y?.saved ?? null)) await O[t]?.open?.({ item: e });
|
|
235
|
+
let e = y?.saved?.active;
|
|
205
236
|
if (e) {
|
|
206
|
-
let t =
|
|
207
|
-
t &&
|
|
237
|
+
let t = E.windowFor(e);
|
|
238
|
+
t && p.bringToFront(t);
|
|
208
239
|
}
|
|
240
|
+
if (j && h.startup !== !1) for (let e of s(j.get())) await k(e.id);
|
|
209
241
|
} finally {
|
|
210
|
-
if (
|
|
211
|
-
let e =
|
|
212
|
-
windows:
|
|
213
|
-
active:
|
|
214
|
-
pattern:
|
|
242
|
+
if (y) {
|
|
243
|
+
let e = y.start(() => ({
|
|
244
|
+
windows: E.snapshot(),
|
|
245
|
+
active: E.itemOf(p.activeWindow),
|
|
246
|
+
pattern: p.pattern ?? null
|
|
215
247
|
}), (e) => {
|
|
216
248
|
let t = [
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
...
|
|
249
|
+
E.onLayout(e),
|
|
250
|
+
E.onWindows(e),
|
|
251
|
+
...j ? [j.subscribe(e)] : []
|
|
220
252
|
];
|
|
221
|
-
|
|
253
|
+
p.addEventListener("vf-activate", e);
|
|
222
254
|
let n = new MutationObserver(e);
|
|
223
|
-
return n.observe(
|
|
255
|
+
return n.observe(p, {
|
|
224
256
|
attributes: !0,
|
|
225
257
|
attributeFilter: ["pattern"]
|
|
226
258
|
}), () => {
|
|
227
259
|
for (let e of t) e();
|
|
228
|
-
|
|
260
|
+
p.removeEventListener("vf-activate", e), n.disconnect();
|
|
229
261
|
};
|
|
230
262
|
});
|
|
231
|
-
|
|
263
|
+
x.push(e), y.release();
|
|
232
264
|
}
|
|
233
265
|
}
|
|
234
266
|
})(),
|
|
235
267
|
dispose() {
|
|
236
|
-
for (let e of
|
|
237
|
-
if (
|
|
238
|
-
|
|
239
|
-
for (let e of
|
|
240
|
-
|
|
268
|
+
for (let e of R.splice(0).reverse()) e();
|
|
269
|
+
if (z) for (let e of z.menus) e.remove();
|
|
270
|
+
z = null;
|
|
271
|
+
for (let e of x.splice(0)) e();
|
|
272
|
+
E.dispose(), j?.dispose();
|
|
241
273
|
}
|
|
242
274
|
};
|
|
243
275
|
}
|
|
244
276
|
//#endregion
|
|
245
|
-
export {
|
|
277
|
+
export { h as createShell, p as defineApp };
|
package/dist/shell/version.d.ts
CHANGED
|
@@ -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.
|
|
2
|
+
export declare const VERSION = "0.19.1";
|
package/dist/shell/version.js
CHANGED