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.
- package/README.md +1 -1
- package/custom-elements.json +39 -0
- 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/index.d.ts +1 -0
- package/dist/index.js +15 -14
- package/dist/shell/app-file.d.ts +20 -4
- package/dist/shell/app-file.js +65 -53
- 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 +143 -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 +1 -1
- package/editor/vscode.html-custom-data.json +5 -0
- package/editor/web-types.json +11 -1
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ There is no need to import a stylesheet. The components carry their styles with
|
|
|
25
25
|
|
|
26
26
|
## The shell
|
|
27
27
|
|
|
28
|
-
`vintage-frames/shell` is an experimental second entry point that runs applications over one desktop: a window manager, a menu bar that shows the front application's menus, and a Finder with folders, filing, Clean Up and the Trash.
|
|
28
|
+
`vintage-frames/shell` is an experimental second entry point that runs applications over one desktop: a window manager, a menu bar that shows the front application's menus, and a Finder with folders, aliases, filing, Clean Up and the Trash. A System Folder's contents set the Apple menu and what opens at startup.
|
|
29
29
|
|
|
30
30
|
```ts
|
|
31
31
|
import 'vintage-frames'
|
package/custom-elements.json
CHANGED
|
@@ -5681,6 +5681,17 @@
|
|
|
5681
5681
|
"attribute": "open",
|
|
5682
5682
|
"reflects": true
|
|
5683
5683
|
},
|
|
5684
|
+
{
|
|
5685
|
+
"kind": "field",
|
|
5686
|
+
"name": "alias",
|
|
5687
|
+
"type": {
|
|
5688
|
+
"text": "boolean"
|
|
5689
|
+
},
|
|
5690
|
+
"default": "false",
|
|
5691
|
+
"description": "The icon is an alias, an item standing for another: its name is set in\nitalics, the body face's own, and the plate widens to the slant's last\npixel.",
|
|
5692
|
+
"attribute": "alias",
|
|
5693
|
+
"reflects": true
|
|
5694
|
+
},
|
|
5684
5695
|
{
|
|
5685
5696
|
"kind": "field",
|
|
5686
5697
|
"name": "movable",
|
|
@@ -6272,6 +6283,25 @@
|
|
|
6272
6283
|
},
|
|
6273
6284
|
"description": "Size the plate to a whole, EVEN number of system pixels.\n\nThis is the whole alignment argument, so it is worth stating plainly. The\nframe centers two things over one axis — the art cell and the name — and a\ncentered child's offset is `(box − child) / 2`. That is a whole number\nexactly when the box and the child have the SAME PARITY. The cell is 32 or\n16 and a declared `width` is required even, so if the plate is even too,\nevery offset in the component is whole by construction: no correction, no\nsnapping, nothing for the compositor to round.\n\nThe text is measured rather than the plate, with a Range over its own\ncontents — the plate already carries the width this computed last time, so\nreading the element back would just return it. The measurement is in\nsystem px and so is scale-invariant: the same name is the same number of\nart pixels wide at every display density, which is why nothing here\nre-runs when the scale changes.\n\nRounding UP to even (never down) means the plate never clips the run it\nwas measured from; the leftover is at most one system pixel of extra plate\nafter the text, since the embedded faces advance in whole pixels and only\na fallback face measures fractionally."
|
|
6274
6285
|
},
|
|
6286
|
+
{
|
|
6287
|
+
"kind": "method",
|
|
6288
|
+
"name": "#lean",
|
|
6289
|
+
"privacy": "private",
|
|
6290
|
+
"return": {
|
|
6291
|
+
"type": {
|
|
6292
|
+
"text": "number"
|
|
6293
|
+
}
|
|
6294
|
+
},
|
|
6295
|
+
"parameters": [
|
|
6296
|
+
{
|
|
6297
|
+
"name": "plate",
|
|
6298
|
+
"type": {
|
|
6299
|
+
"text": "HTMLElement"
|
|
6300
|
+
}
|
|
6301
|
+
}
|
|
6302
|
+
],
|
|
6303
|
+
"description": "How far an alias's italic name runs past its advance, in whole system px:\nthe slant leans the tops of the last letters right, by up to 5. Read off\nthe glyphs' ink, in a canvas set in the plate's own font."
|
|
6304
|
+
},
|
|
6275
6305
|
{
|
|
6276
6306
|
"kind": "field",
|
|
6277
6307
|
"name": "#plateWidthCss",
|
|
@@ -6769,6 +6799,15 @@
|
|
|
6769
6799
|
"description": "The icon's window is on screen, so the art paints as the Finder's open\nghost — outline held, interior re-filled with the kit's loose dither —\nderived in the client from the slotted art itself (see the class doc).\nSet it when handling `vf-open`, clear it when the window goes away.\nSelection inverts the ghost exactly as it inverts the art.",
|
|
6770
6800
|
"fieldName": "open"
|
|
6771
6801
|
},
|
|
6802
|
+
{
|
|
6803
|
+
"name": "alias",
|
|
6804
|
+
"type": {
|
|
6805
|
+
"text": "boolean"
|
|
6806
|
+
},
|
|
6807
|
+
"default": "false",
|
|
6808
|
+
"description": "The icon is an alias, an item standing for another: its name is set in\nitalics, the body face's own, and the plate widens to the slant's last\npixel.",
|
|
6809
|
+
"fieldName": "alias"
|
|
6810
|
+
},
|
|
6772
6811
|
{
|
|
6773
6812
|
"name": "movable",
|
|
6774
6813
|
"type": {
|
package/dist/build/app-file.d.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
import type { AppManifest } from '../shell/app-file.js';
|
|
7
7
|
/** What {@link packApp} packs. */
|
|
8
8
|
export interface PackAppInput {
|
|
9
|
-
/** The manifest's fields but its format and icon, which the packer fills in. */
|
|
10
|
-
manifest: Omit<AppManifest, 'format' | 'icon'>;
|
|
9
|
+
/** The manifest's fields but its format, app API and icon, which the packer fills in. */
|
|
10
|
+
manifest: Omit<AppManifest, 'format' | 'api' | 'icon'>;
|
|
11
11
|
/** The icon's PNG, 32 × 32. */
|
|
12
12
|
icon: Uint8Array;
|
|
13
13
|
/** The application's code: one ES module whose default export is its factory. */
|
package/dist/build/app-file.js
CHANGED
package/dist/build/plugins.d.ts
CHANGED
|
@@ -32,8 +32,8 @@ export interface AppFileOptions {
|
|
|
32
32
|
export declare function appFile(options: AppFileOptions): Plugin;
|
|
33
33
|
/**
|
|
34
34
|
* Builds app files into a site. An import of `*.png?app` reads the file and
|
|
35
|
-
* refuses one that isn't an app file, or
|
|
36
|
-
*
|
|
35
|
+
* refuses one that isn't an app file, or one this kit doesn't run
|
|
36
|
+
* (`appRuns`). Its default export is the application's factory,
|
|
37
37
|
* its definition given the manifest's icon, and `manifest` is the manifest.
|
|
38
38
|
* The code imports the kit by name, so the page keeps one copy of it. A new
|
|
39
39
|
* file reloads the dev server's page.
|
package/dist/build/plugins.js
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { packApp as
|
|
4
|
-
import { mkdir as
|
|
5
|
-
import { join as
|
|
1
|
+
import { VERSION as e } from "../shell/version.js";
|
|
2
|
+
import { appRuns as t, inspectAppFile as n, isVersion as r, satisfies as i } from "../shell/app-file.js";
|
|
3
|
+
import { packApp as a } from "./app-file.js";
|
|
4
|
+
import { mkdir as o, readFile as s, writeFile as c } from "node:fs/promises";
|
|
5
|
+
import { join as l, relative as u, resolve as d } from "node:path";
|
|
6
6
|
//#region src/build/plugins.ts
|
|
7
|
-
var
|
|
7
|
+
var f = [
|
|
8
8
|
"vintage-frames",
|
|
9
9
|
"vintage-frames/shell",
|
|
10
10
|
"vintage-frames/shell/pure"
|
|
11
|
-
],
|
|
12
|
-
function
|
|
11
|
+
], p = "app-code";
|
|
12
|
+
function m(e) {
|
|
13
13
|
let t = e.match(/(?<=[\\/]node_modules[\\/])(?:@[^\\/]+[\\/])?[^\\/]+/g)?.at(-1)?.replace("\\", "/");
|
|
14
14
|
return t === "vintage-frames" ? "a copy of vintage-frames" : t && /^(?:lit|lit-html|lit-element|@lit\/.+|@lit-labs\/.+)$/.test(t) ? `Lit (${t})` : null;
|
|
15
15
|
}
|
|
16
|
-
async function
|
|
17
|
-
let n = JSON.parse(await
|
|
16
|
+
async function h(t) {
|
|
17
|
+
let n = JSON.parse(await s(l(t, "package.json"), "utf8")), i = n.devDependencies?.["vintage-frames"] ?? n.dependencies?.["vintage-frames"];
|
|
18
18
|
if (typeof i != "string") throw Error("package.json has no vintage-frames dev dependency");
|
|
19
|
-
if (!i.startsWith("^") || !
|
|
19
|
+
if (!i.startsWith("^") || !r(i.slice(1))) throw Error(`package.json's vintage-frames range is "${i}", and an app file requires a caret range: ^${e}`);
|
|
20
20
|
return i;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
let { app:
|
|
22
|
+
function g(t) {
|
|
23
|
+
let { app: n, entry: u, icon: p, artwork: g, copyTo: _ } = t;
|
|
24
24
|
for (let e of [
|
|
25
25
|
"id",
|
|
26
26
|
"name",
|
|
27
27
|
"version",
|
|
28
28
|
"author"
|
|
29
|
-
]) if (typeof
|
|
30
|
-
if (!
|
|
31
|
-
if (!
|
|
32
|
-
let v = `${
|
|
29
|
+
]) if (typeof n?.[e] != "string" || !n[e]) throw Error(`vintage-frames appFile(): app.${e} is missing`);
|
|
30
|
+
if (!r(n.version)) throw Error(`vintage-frames appFile(): app.version, ${n.version}, is not a version`);
|
|
31
|
+
if (!u || !p) throw Error(`vintage-frames appFile(): ${u ? "icon" : "entry"} is missing`);
|
|
32
|
+
let v = `${n.name.replace(/[\\/:*?"<>|]/g, "-")}.png`, y = "", b = null;
|
|
33
33
|
return {
|
|
34
34
|
name: "vintage-frames:app-file",
|
|
35
35
|
apply: "build",
|
|
36
36
|
config: () => ({ build: {
|
|
37
37
|
lib: {
|
|
38
|
-
entry:
|
|
38
|
+
entry: u,
|
|
39
39
|
formats: ["es"],
|
|
40
40
|
fileName: "app"
|
|
41
41
|
},
|
|
@@ -50,44 +50,44 @@ function h(e) {
|
|
|
50
50
|
},
|
|
51
51
|
buildStart() {
|
|
52
52
|
for (let e of [
|
|
53
|
-
|
|
53
|
+
p,
|
|
54
54
|
g,
|
|
55
55
|
"package.json"
|
|
56
|
-
]) e && this.addWatchFile(
|
|
56
|
+
]) e && this.addWatchFile(d(y, e));
|
|
57
57
|
},
|
|
58
58
|
generateBundle: {
|
|
59
59
|
order: "post",
|
|
60
|
-
async handler(
|
|
61
|
-
let
|
|
62
|
-
|
|
63
|
-
let [
|
|
64
|
-
(!
|
|
65
|
-
for (let e of Object.keys(
|
|
66
|
-
let t =
|
|
67
|
-
t && this.error(`${
|
|
60
|
+
async handler(t, r) {
|
|
61
|
+
let o = Object.values(r), c = o.filter((e) => e.type === "chunk"), l = o.filter((e) => e.type === "asset").map((e) => e.fileName);
|
|
62
|
+
l.length && this.error(`${n.name} emits ${l.join(", ")} beside its code, and an app file holds one module: no CSS import, no source map file, its art inlined.`);
|
|
63
|
+
let [u] = c;
|
|
64
|
+
(!u || c.length > 1) && this.error(`${n.name} builds to ${c.length} modules, and an app file holds one.`);
|
|
65
|
+
for (let e of Object.keys(u.modules)) {
|
|
66
|
+
let t = m(e);
|
|
67
|
+
t && this.error(`${n.name} bundles ${t}. It composes the page's kit and brings none of its own.`);
|
|
68
68
|
}
|
|
69
|
-
let _ = [...
|
|
70
|
-
_.length && this.error(`${
|
|
69
|
+
let _ = [...u.imports, ...u.dynamicImports].filter((e) => !f.includes(e));
|
|
70
|
+
_.length && this.error(`${n.name} imports ${_.join(", ")}. An application imports ${f.join(", ")} and its own files.`);
|
|
71
71
|
try {
|
|
72
|
-
let
|
|
73
|
-
if (!
|
|
74
|
-
b = await
|
|
72
|
+
let t = await h(y);
|
|
73
|
+
if (!i("0.19.0", t)) throw Error(`package.json requires vintage-frames ${t}, and the build is on ${e}: move the range`);
|
|
74
|
+
b = await a({
|
|
75
75
|
manifest: {
|
|
76
|
-
id:
|
|
77
|
-
name:
|
|
78
|
-
version:
|
|
79
|
-
requires:
|
|
80
|
-
author:
|
|
81
|
-
description:
|
|
76
|
+
id: n.id,
|
|
77
|
+
name: n.name,
|
|
78
|
+
version: n.version,
|
|
79
|
+
requires: t,
|
|
80
|
+
author: n.author,
|
|
81
|
+
description: n.description
|
|
82
82
|
},
|
|
83
|
-
icon: new Uint8Array(await
|
|
84
|
-
code:
|
|
85
|
-
artwork: g ? new Uint8Array(await
|
|
83
|
+
icon: new Uint8Array(await s(d(y, p))),
|
|
84
|
+
code: u.code,
|
|
85
|
+
artwork: g ? new Uint8Array(await s(d(y, g))) : void 0
|
|
86
86
|
});
|
|
87
87
|
} catch (e) {
|
|
88
|
-
this.error(`${
|
|
88
|
+
this.error(`${n.name}: ${e.message}`);
|
|
89
89
|
}
|
|
90
|
-
delete
|
|
90
|
+
delete r[u.fileName], this.emitFile({
|
|
91
91
|
type: "asset",
|
|
92
92
|
fileName: v,
|
|
93
93
|
source: b
|
|
@@ -96,31 +96,34 @@ function h(e) {
|
|
|
96
96
|
},
|
|
97
97
|
async writeBundle() {
|
|
98
98
|
if (!_ || !b) return;
|
|
99
|
-
let e =
|
|
100
|
-
await
|
|
99
|
+
let e = d(y, _);
|
|
100
|
+
await o(e, { recursive: !0 }), await c(l(e, v), b);
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
|
-
function
|
|
105
|
-
|
|
104
|
+
function _(t) {
|
|
105
|
+
return t.api === void 0 ? `requires vintage-frames ${t.requires}, and this site has ${e}` : `is built for app API ${t.api}, and this site's kit runs app API 2`;
|
|
106
|
+
}
|
|
107
|
+
function v() {
|
|
108
|
+
let r = "";
|
|
106
109
|
return {
|
|
107
110
|
name: "vintage-frames:app-files",
|
|
108
111
|
enforce: "pre",
|
|
109
112
|
configResolved(e) {
|
|
110
|
-
|
|
113
|
+
r = e.root;
|
|
111
114
|
},
|
|
112
115
|
async load(i) {
|
|
113
116
|
let a = i.indexOf("?");
|
|
114
117
|
if (a < 0) return null;
|
|
115
|
-
let
|
|
116
|
-
if (!
|
|
117
|
-
this.addWatchFile(
|
|
118
|
-
let
|
|
119
|
-
typeof d == "string" && this.error(`${
|
|
120
|
-
let { manifest:
|
|
121
|
-
return c.has(
|
|
122
|
-
`import factory from ${JSON.stringify(`${
|
|
123
|
-
`export const manifest = ${JSON.stringify(
|
|
118
|
+
let o = i.slice(0, a), c = new URLSearchParams(i.slice(a + 1));
|
|
119
|
+
if (!o.endsWith(".png") || !(c.has("app") || c.has(p))) return null;
|
|
120
|
+
this.addWatchFile(o);
|
|
121
|
+
let l = u(r, o), d = await n(new Uint8Array(await s(o)));
|
|
122
|
+
typeof d == "string" && this.error(`${l} is not an app file: ${d}.`);
|
|
123
|
+
let { manifest: f, code: m } = d;
|
|
124
|
+
return c.has(p) ? m : (t(f) || this.error(`${l}: ${f.name} ${f.version} ${_(f)}. Build ${f.name} on ${e} and copy its app file in.`), [
|
|
125
|
+
`import factory from ${JSON.stringify(`${o}?${p}`)}`,
|
|
126
|
+
`export const manifest = ${JSON.stringify(f)}`,
|
|
124
127
|
"export default (...args) => ({ ...factory(...args), icon: manifest.icon })",
|
|
125
128
|
""
|
|
126
129
|
].join("\n"));
|
|
@@ -128,4 +131,4 @@ function g() {
|
|
|
128
131
|
};
|
|
129
132
|
}
|
|
130
133
|
//#endregion
|
|
131
|
-
export {
|
|
134
|
+
export { g as appFile, v as appFiles };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
|
+
import '../styles/body-italic-font.js';
|
|
2
3
|
/** Which member of the icon family paints — the two System 7 resource sizes. */
|
|
3
4
|
export type VfIconSize = 'large' | 'small';
|
|
4
5
|
/**
|
|
@@ -523,6 +524,12 @@ export declare class VfIcon extends VfIcon_base {
|
|
|
523
524
|
* Selection inverts the ghost exactly as it inverts the art.
|
|
524
525
|
*/
|
|
525
526
|
open: boolean;
|
|
527
|
+
/**
|
|
528
|
+
* The icon is an alias, an item standing for another: its name is set in
|
|
529
|
+
* italics, the body face's own, and the plate widens to the slant's last
|
|
530
|
+
* pixel.
|
|
531
|
+
*/
|
|
532
|
+
alias: boolean;
|
|
526
533
|
/**
|
|
527
534
|
* Drag to move — `movable`, never `draggable`, which is a platform attribute
|
|
528
535
|
* and accessor (see the class doc). Arrow keys move a focused icon too, which
|