vintage-frames 0.17.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.
- package/README.md +1 -1
- package/custom-elements.json +96 -7
- package/dist/build/app-file.d.ts +2 -2
- package/dist/build/app-file.js +1 -0
- package/dist/build/box.d.ts +3 -1
- package/dist/build/box.js +6 -3
- package/dist/build/frame.js +19 -17
- package/dist/build/plugins.d.ts +5 -4
- package/dist/build/plugins.js +69 -64
- package/dist/components/vf-icon.d.ts +7 -0
- package/dist/components/vf-icon.js +101 -81
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -14
- package/dist/modal-dialog.d.ts +7 -6
- package/dist/modal-dialog.js +30 -22
- package/dist/shell/app-file.d.ts +43 -5
- package/dist/shell/app-file.js +90 -62
- package/dist/shell/catalog.d.ts +41 -1
- package/dist/shell/catalog.js +174 -153
- package/dist/shell/finder.d.ts +27 -9
- package/dist/shell/finder.js +335 -277
- 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 +144 -117
- 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 +2 -2
- package/editor/vscode.html-custom-data.json +5 -0
- package/editor/web-types.json +11 -1
- 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, 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, 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, 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 };
|
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, 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, 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 };
|
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, 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
|
|
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,29 +136,29 @@ 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));
|
|
146
149
|
};
|
|
147
|
-
t.addEventListener("vf-close", n)
|
|
150
|
+
t.show(), t.addEventListener("vf-close", n);
|
|
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,106 @@ 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 = () => {
|
|
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 (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
|
187
|
-
if (
|
|
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 =
|
|
215
|
+
let n = E.itemOf(e);
|
|
190
216
|
if (n == null) continue;
|
|
191
|
-
let r =
|
|
192
|
-
r ? (
|
|
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
|
|
196
|
-
desktop:
|
|
197
|
-
windows:
|
|
198
|
-
catalog:
|
|
199
|
-
apps:
|
|
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
|
|
203
|
-
for (let { item: e, app: t } of
|
|
204
|
-
let e =
|
|
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 =
|
|
207
|
-
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 (
|
|
211
|
-
let e =
|
|
212
|
-
windows:
|
|
213
|
-
active:
|
|
214
|
-
pattern:
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
...
|
|
244
|
+
E.onLayout(e),
|
|
245
|
+
E.onWindows(e),
|
|
246
|
+
...j ? [j.subscribe(e)] : []
|
|
220
247
|
];
|
|
221
|
-
|
|
248
|
+
p.addEventListener("vf-activate", e);
|
|
222
249
|
let n = new MutationObserver(e);
|
|
223
|
-
return n.observe(
|
|
250
|
+
return n.observe(p, {
|
|
224
251
|
attributes: !0,
|
|
225
252
|
attributeFilter: ["pattern"]
|
|
226
253
|
}), () => {
|
|
227
254
|
for (let e of t) e();
|
|
228
|
-
|
|
255
|
+
p.removeEventListener("vf-activate", e), n.disconnect();
|
|
229
256
|
};
|
|
230
257
|
});
|
|
231
|
-
|
|
258
|
+
x.push(e), y.release();
|
|
232
259
|
}
|
|
233
260
|
}
|
|
234
261
|
})(),
|
|
235
262
|
dispose() {
|
|
236
|
-
for (let e of
|
|
237
|
-
if (
|
|
238
|
-
|
|
239
|
-
for (let e of
|
|
240
|
-
|
|
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 {
|
|
272
|
+
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.0";
|
package/dist/shell/version.js
CHANGED