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.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/custom-elements.json +96 -7
  3. package/dist/build/app-file.d.ts +2 -2
  4. package/dist/build/app-file.js +1 -0
  5. package/dist/build/box.d.ts +3 -1
  6. package/dist/build/box.js +6 -3
  7. package/dist/build/frame.js +19 -17
  8. package/dist/build/plugins.d.ts +5 -4
  9. package/dist/build/plugins.js +69 -64
  10. package/dist/components/vf-icon.d.ts +7 -0
  11. package/dist/components/vf-icon.js +101 -81
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.js +15 -14
  14. package/dist/modal-dialog.d.ts +7 -6
  15. package/dist/modal-dialog.js +30 -22
  16. package/dist/shell/app-file.d.ts +43 -5
  17. package/dist/shell/app-file.js +90 -62
  18. package/dist/shell/catalog.d.ts +41 -1
  19. package/dist/shell/catalog.js +174 -153
  20. package/dist/shell/finder.d.ts +27 -9
  21. package/dist/shell/finder.js +335 -277
  22. package/dist/shell/geometry.d.ts +7 -0
  23. package/dist/shell/geometry.js +19 -3
  24. package/dist/shell/index.d.ts +4 -4
  25. package/dist/shell/index.js +12 -12
  26. package/dist/shell/pure.d.ts +1 -1
  27. package/dist/shell/pure.js +6 -6
  28. package/dist/shell/shell.d.ts +14 -10
  29. package/dist/shell/shell.js +144 -117
  30. package/dist/shell/version.d.ts +1 -1
  31. package/dist/shell/version.js +1 -1
  32. package/dist/styles/body-italic-font.d.ts +2 -0
  33. package/dist/styles/body-italic-font.js +10 -0
  34. package/dist/styles/register-embedded-font.d.ts +5 -4
  35. package/dist/styles/register-embedded-font.js +11 -10
  36. package/docs/SPEC.md +2 -2
  37. package/editor/vscode.html-custom-data.json +5 -0
  38. package/editor/web-types.json +11 -1
  39. package/package.json +7 -3
@@ -1,289 +1,310 @@
1
1
  //#region src/shell/catalog.ts
2
- var e = "trash", t = "disk", n = "folder", r = "app", i = "untitled folder", a = "#seeded", o = (e) => e === "folder" || e === "trash" || e === "disk", s = (e) => e === "trash" || e === "disk";
3
- function c(e) {
2
+ var e = "trash", t = "disk", n = "system-folder", r = "apple-menu-items", i = "startup-items", a = "folder", o = "app", s = "alias", c = "untitled folder", l = "#seeded", u = (e) => e === "folder" || e === "trash" || e === "disk", d = (e) => e === "trash" || e === "disk", f = (e) => d(e) || e === "system-folder" || e === "apple-menu-items" || e === "startup-items";
3
+ function p(e) {
4
4
  let t = e.data;
5
5
  return typeof t?.app == "string" ? t.app : null;
6
6
  }
7
- function l(e, t) {
7
+ function m(e) {
8
+ if (e.kind !== "alias") return null;
9
+ let t = e.data;
10
+ return typeof t?.original == "string" ? t.original : null;
11
+ }
12
+ function h(e, t) {
8
13
  return t == null ? null : e.items.find((e) => e.id === t) ?? null;
9
14
  }
10
- function u(e, t) {
11
- let n = l(e, t);
12
- return n && o(n.kind) ? n.id : null;
15
+ function g(e, t) {
16
+ let n = /* @__PURE__ */ new Set(), r = h(e, t);
17
+ for (; r?.kind === s;) {
18
+ if (n.has(r.id)) return null;
19
+ n.add(r.id), r = h(e, m(r));
20
+ }
21
+ return r;
13
22
  }
14
- function d(e, t) {
15
- let n = u(e, t);
16
- return e.items.filter((t) => t.id !== n && u(e, t.parent) === n);
23
+ function _(e, t) {
24
+ let n = h(e, t);
25
+ return n && u(n.kind) ? n.id : null;
17
26
  }
18
- function f(e, t) {
19
- return d(e, t).length;
27
+ function v(e, t) {
28
+ let n = _(e, t);
29
+ return e.items.filter((t) => t.id !== n && _(e, t.parent) === n);
20
30
  }
21
- var p = (e, t) => u(e, l(e, t)?.parent ?? null);
22
- function m(e, t, n) {
23
- let r = /* @__PURE__ */ new Set(), i = p(e, t);
31
+ function y(e, t) {
32
+ return v(e, t).length;
33
+ }
34
+ var b = (e, t) => _(e, h(e, t)?.parent ?? null);
35
+ function x(e, t, n) {
36
+ let r = /* @__PURE__ */ new Set(), i = b(e, t);
24
37
  for (; i != null && !r.has(i);) {
25
38
  if (i === n) return !0;
26
- r.add(i), i = p(e, i);
39
+ r.add(i), i = b(e, i);
27
40
  }
28
41
  return !1;
29
42
  }
30
- function h(e, t) {
31
- let n = [], r = /* @__PURE__ */ new Set(), i = u(e, t ?? null);
32
- for (; i != null && !r.has(i);) n.push(i), r.add(i), i = p(e, i);
43
+ function S(e, t) {
44
+ let n = [], r = /* @__PURE__ */ new Set(), i = _(e, t ?? null);
45
+ for (; i != null && !r.has(i);) n.push(i), r.add(i), i = b(e, i);
33
46
  return n;
34
47
  }
35
- function g(e, t) {
36
- return t == null ? !1 : t === "trash" || m(e, t, "trash");
48
+ function C(e, t) {
49
+ return t == null ? !1 : t === "trash" || x(e, t, "trash");
37
50
  }
38
- function _(e, t) {
51
+ function w(e, t) {
39
52
  let n = [], r = /* @__PURE__ */ new Set(), i = (t) => {
40
- for (let a of d(e, t)) r.has(a.id) || (r.add(a.id), n.push(a), o(a.kind) && i(a.id));
53
+ for (let a of v(e, t)) r.has(a.id) || (r.add(a.id), n.push(a), u(a.kind) && i(a.id));
41
54
  };
42
- return i(u(e, t)), n;
55
+ return i(_(e, t)), n;
43
56
  }
44
- function v(e, t) {
45
- let r = new Set(d(e, t).filter((e) => e.kind === n).map((e) => e.name));
46
- if (!r.has("untitled folder")) return i;
57
+ function T(e, t) {
58
+ let n = new Set(v(e, t).filter((e) => e.kind === a).map((e) => e.name));
59
+ if (!n.has("untitled folder")) return c;
47
60
  for (let e = 2;; e++) {
48
- let t = `${i} ${e}`;
49
- if (!r.has(t)) return t;
61
+ let t = `${c} ${e}`;
62
+ if (!n.has(t)) return t;
50
63
  }
51
64
  }
52
- var y = (e) => e.replace(/ copy( \d+)?$/, "");
53
- function b(e, t, n, r) {
54
- let i = new Set(d(e, t).filter((e) => e.kind === r).map((e) => e.name));
65
+ var E = (e) => e.replace(/ copy( \d+)?$/, "");
66
+ function D(e, t, n, r) {
67
+ let i = new Set(v(e, t).filter((e) => e.kind === r).map((e) => e.name));
55
68
  if (!i.has(n)) return n;
56
- let a = y(n);
69
+ let a = E(n);
57
70
  if (!i.has(`${a} copy`)) return `${a} copy`;
58
71
  for (let e = 2;; e++) {
59
72
  let t = `${a} copy ${e}`;
60
73
  if (!i.has(t)) return t;
61
74
  }
62
75
  }
63
- var x = (e, t) => e.createdAt - t.createdAt || (e.id < t.id ? -1 : 1);
64
- function S(e, t) {
76
+ function O(e, t, n) {
77
+ let r = new Set(v(e, t).filter((e) => e.kind === s).map((e) => e.name)), i = `${n} alias`;
78
+ if (!r.has(i)) return i;
79
+ for (let e = 2;; e++) {
80
+ let t = `${i} ${e}`;
81
+ if (!r.has(t)) return t;
82
+ }
83
+ }
84
+ var k = new Intl.Collator("en");
85
+ function A(e, t) {
86
+ return h(e, t) ? v(e, t).sort((e, t) => k.compare(e.name, t.name) || N(e, t)) : [];
87
+ }
88
+ var j = (e) => A(e, r), M = (e) => A(e, i), N = (e, t) => e.createdAt - t.createdAt || (e.id < t.id ? -1 : 1);
89
+ function P(e, t) {
65
90
  let n = { ...e };
66
91
  return t ? (n.left = t.left, n.top = t.top) : (delete n.left, delete n.top), n;
67
92
  }
68
- function C(n) {
69
- let { storage: r, volumes: i = {}, listed: c = () => !0, hooks: d = () => void 0, placeDelay: f = 400 } = n, p = () => (n.now ?? Date.now)(), h = () => n.newId ? n.newId() : crypto.randomUUID(), y = [];
70
- i.disk && y.push({
71
- id: t,
72
- name: i.disk,
73
- kind: t,
74
- parent: null,
75
- createdAt: 0,
76
- modifiedAt: 0
77
- }), i.trash !== !1 && y.push({
93
+ function F(o) {
94
+ let { storage: s, volumes: c = {}, system: d, listed: p = () => !0, hooks: g = () => void 0, placeDelay: v = 400 } = o, y = () => (o.now ?? Date.now)(), b = () => o.newId ? o.newId() : crypto.randomUUID(), S = [], E = (e, t, n, r) => S.push({
78
95
  id: e,
79
- name: i.trash ?? "Trash",
80
- kind: e,
81
- parent: null,
96
+ name: t,
97
+ kind: n,
98
+ parent: r,
82
99
  createdAt: 0,
83
100
  modifiedAt: 0
84
101
  });
85
- let C = /* @__PURE__ */ new Map(), w = !1, T = !1, E = O(), D = /* @__PURE__ */ new Set();
86
- function O() {
87
- let e = y.map((e) => {
88
- let t = C.get(e.id);
102
+ c.disk && E(t, c.disk, t, null), c.trash !== !1 && E(e, c.trash ?? "Trash", e, null), d && (E(n, d.folder, a, c.disk ? t : null), E(r, d.appleMenu, a, n), E(i, d.startup, a, n));
103
+ let O = /* @__PURE__ */ new Map(), k = !1, A = !1, j = F(), M = /* @__PURE__ */ new Set();
104
+ function F() {
105
+ let e = S.map((e) => {
106
+ let t = O.get(e.id);
89
107
  return t?.left != null && t.top != null ? {
90
108
  ...e,
91
109
  left: t.left,
92
110
  top: t.top
93
111
  } : e;
94
- }), t = [...C.values()].filter((e) => !s(e.id) && (e.kind === "folder" || c(e.kind))).sort(x);
112
+ }), t = [...O.values()].filter((e) => !f(e.id) && (e.kind === "folder" || p(e.kind))).sort(N);
95
113
  return {
96
- available: w,
114
+ available: k,
97
115
  items: [...e, ...t]
98
116
  };
99
117
  }
100
- function k() {
101
- E = O();
102
- for (let e of [...D]) e(E);
118
+ function I() {
119
+ j = F();
120
+ for (let e of [...M]) e(j);
103
121
  }
104
- let A = () => {
105
- if (!r) throw Error("storage is unavailable");
106
- return r;
122
+ let L = () => {
123
+ if (!s) throw Error("storage is unavailable");
124
+ return s;
107
125
  };
108
- async function j(e) {
109
- await A().put(e), C.set(e.id, e);
126
+ async function R(e) {
127
+ await L().put(e), O.set(e.id, e);
110
128
  }
111
- let M = /* @__PURE__ */ new Set(), N = null;
112
- async function P() {
113
- N && clearTimeout(N), N = null;
114
- let e = [...M];
115
- if (M.clear(), !(!r || !w)) for (let t of e) {
116
- let e = C.get(t);
117
- e && await r.put(e).catch(() => {});
129
+ let z = /* @__PURE__ */ new Set(), B = null;
130
+ async function V() {
131
+ B && clearTimeout(B), B = null;
132
+ let e = [...z];
133
+ if (z.clear(), !(!s || !k)) for (let t of e) {
134
+ let e = O.get(t);
135
+ e && await s.put(e).catch(() => {});
118
136
  }
119
137
  }
120
- let F = (e) => {
121
- let t = y.find((t) => t.id === e);
122
- return C.get(e) ?? {
138
+ let H = (e) => {
139
+ let t = S.find((t) => t.id === e);
140
+ return O.get(e) ?? {
123
141
  ...t,
124
142
  name: ""
125
143
  };
126
144
  };
127
- async function I() {
128
- M.clear();
129
- for (let e of await A().list()) e.id !== a && (await A().remove(e.id), C.delete(e.id));
130
- C = /* @__PURE__ */ new Map();
145
+ async function U() {
146
+ z.clear();
147
+ for (let e of await L().list()) e.id !== l && (await L().remove(e.id), O.delete(e.id));
148
+ O = /* @__PURE__ */ new Map();
131
149
  }
132
- let L = {
133
- get: () => E,
150
+ let W = {
151
+ get: () => j,
134
152
  subscribe(e) {
135
- return D.add(e), () => {
136
- D.delete(e);
153
+ return M.add(e), () => {
154
+ M.delete(e);
137
155
  };
138
156
  },
139
- item: (e) => l(E, e),
157
+ item: (e) => h(j, e),
140
158
  async refresh() {
141
- if (!r) {
142
- C = /* @__PURE__ */ new Map(), w = !1, k();
159
+ if (!s) {
160
+ O = /* @__PURE__ */ new Map(), k = !1, I();
143
161
  return;
144
162
  }
145
163
  try {
146
- let e = await r.list();
147
- C = /* @__PURE__ */ new Map(), T = !1;
148
- for (let t of e) t.id === a ? T = !0 : C.set(t.id, t);
149
- w = !0;
164
+ let e = await s.list();
165
+ O = /* @__PURE__ */ new Map(), A = !1;
166
+ for (let t of e) t.id === l ? A = !0 : O.set(t.id, t);
167
+ k = !0;
150
168
  } catch (e) {
151
- console.warn("vintage-frames/shell: the catalog could not be read —", e), C = /* @__PURE__ */ new Map(), w = !1;
169
+ console.warn("vintage-frames/shell: the catalog could not be read —", e), O = /* @__PURE__ */ new Map(), k = !1;
152
170
  }
153
- k();
171
+ I();
154
172
  },
155
173
  async seed(e) {
156
- return !r || !w || T ? !1 : (await e(L), await r.put({
157
- id: a,
174
+ return !s || !k || A ? !1 : (await e(W), await s.put({
175
+ id: l,
158
176
  name: "",
159
- kind: a,
177
+ kind: l,
160
178
  parent: null,
161
- createdAt: p(),
162
- modifiedAt: p()
163
- }), T = !0, !0);
179
+ createdAt: y(),
180
+ modifiedAt: y()
181
+ }), A = !0, !0);
164
182
  },
165
183
  async create(e = {}) {
166
- let t = u(E, e.parent ?? null);
167
- if (g(E, t)) return null;
168
- let n = e.kind ?? "folder", r = e.at ?? p(), i = {
169
- id: h(),
170
- name: e.name ?? (n === "folder" ? v(E, t) : "untitled"),
184
+ let t = _(j, e.parent ?? null);
185
+ if (C(j, t)) return null;
186
+ let n = e.kind ?? "folder", r = e.at ?? y(), i = {
187
+ id: b(),
188
+ name: e.name ?? (n === "folder" ? T(j, t) : "untitled"),
171
189
  kind: n,
172
190
  parent: t,
173
191
  createdAt: r,
174
192
  modifiedAt: r
175
193
  };
176
- return e.data !== void 0 && (i.data = e.data), e.left != null && e.top != null && (i = S(i, {
194
+ return e.data !== void 0 && (i.data = e.data), e.left != null && e.top != null && (i = P(i, {
177
195
  left: e.left,
178
196
  top: e.top
179
- })), await j(i), k(), i;
197
+ })), await R(i), I(), i;
180
198
  },
181
199
  async rename(e, t) {
182
- let n = C.get(e);
183
- return !n || s(e) || n.name === t ? !1 : (await j({
200
+ let n = O.get(e);
201
+ return !n || f(e) || n.name === t ? !1 : (await R({
184
202
  ...n,
185
203
  name: t,
186
- modifiedAt: p()
187
- }), k(), !0);
204
+ modifiedAt: y()
205
+ }), I(), !0);
188
206
  },
189
207
  async update(e, t) {
190
- let n = C.get(e);
191
- return !n || s(e) ? !1 : (await j({
208
+ let n = O.get(e);
209
+ return !n || f(e) ? !1 : (await R({
192
210
  ...n,
193
211
  data: t,
194
- modifiedAt: p()
195
- }), k(), !0);
212
+ modifiedAt: y()
213
+ }), I(), !0);
196
214
  },
197
215
  async move(e, t, n) {
198
- let r = u(E, t), i = [];
216
+ let r = _(j, t), i = [];
199
217
  for (let t of e) {
200
- let e = C.get(t);
201
- !e || s(t) || r === t || r != null && o(e.kind) && m(E, r, t) || u(E, e.parent) !== r && (M.delete(t), await j(S({
218
+ let e = O.get(t);
219
+ !e || f(t) || r === t || r != null && u(e.kind) && x(j, r, t) || _(j, e.parent) !== r && (z.delete(t), await R(P({
202
220
  ...e,
203
221
  parent: r
204
222
  }, n?.get(t) ?? null)), i.push(t));
205
223
  }
206
- return i.length && k(), i;
224
+ return i.length && I(), i;
207
225
  },
208
226
  place(e) {
209
227
  let t = !1;
210
228
  for (let [n, r] of e) {
211
- let e = s(n) ? y.some((e) => e.id === n) ? F(n) : null : C.get(n);
212
- !e || e.left === r.left && e.top === r.top || (C.set(n, S(e, r)), M.add(n), t = !0);
229
+ let e = f(n) ? S.some((e) => e.id === n) ? H(n) : null : O.get(n);
230
+ !e || e.left === r.left && e.top === r.top || (O.set(n, P(e, r)), z.add(n), t = !0);
213
231
  }
214
- t && (k(), N && clearTimeout(N), N = setTimeout(() => void P(), f));
232
+ t && (I(), B && clearTimeout(B), B = setTimeout(() => void V(), v));
215
233
  },
216
- flush: P,
234
+ flush: V,
217
235
  async copy(e, t) {
218
- let n = u(E, t);
219
- if (g(E, n)) return [];
236
+ let n = _(j, t);
237
+ if (C(j, n)) return [];
220
238
  let r = [];
221
239
  for (let t of e) {
222
- let e = l(E, t);
223
- if (!e || s(t)) continue;
224
- let i = o(e.kind) ? _(E, t) : [], a = /* @__PURE__ */ new Map(), c = async (e, t, n) => {
225
- let r = p(), i = {
240
+ let e = h(j, t);
241
+ if (!e || f(t)) continue;
242
+ let i = u(e.kind) ? w(j, t) : [], a = /* @__PURE__ */ new Map(), o = async (e, t, n) => {
243
+ let r = y(), i = {
226
244
  ...e,
227
- id: h(),
228
- name: n ? b(E, t, e.name, e.kind) : e.name,
245
+ id: b(),
246
+ name: n ? D(j, t, e.name, e.kind) : e.name,
229
247
  parent: t,
230
248
  createdAt: r,
231
249
  modifiedAt: r
232
250
  };
233
- return n && (i = S(i, null)), a.set(e.id, i.id), await j(i), await d(e.kind)?.copy?.(e, i), i;
251
+ return n && (i = P(i, null)), a.set(e.id, i.id), await R(i), await g(e.kind)?.copy?.(e, i), i;
234
252
  };
235
- r.push(await c(e, n, !0));
236
- for (let e of i) await c(e, a.get(u(E, e.parent) ?? "") ?? null, !1);
237
- k();
253
+ r.push(await o(e, n, !0));
254
+ for (let e of i) await o(e, a.get(_(j, e.parent) ?? "") ?? null, !1);
255
+ I();
238
256
  }
239
257
  return r;
240
258
  },
241
259
  async emptyTrash() {
242
- let t = _(E, e);
243
- for (let e of t) await A().remove(e.id), C.delete(e.id), M.delete(e.id), await d(e.kind)?.onRemove?.(e);
244
- return t.length && k(), t;
260
+ let t = w(j, e);
261
+ for (let e of t) await L().remove(e.id), O.delete(e.id), z.delete(e.id), await g(e.kind)?.onRemove?.(e);
262
+ return t.length && I(), t;
245
263
  },
246
264
  trashSize() {
247
- return _(E, e).reduce((e, t) => e + (d(t.kind)?.size?.(t) ?? 0), 0);
265
+ return w(j, e).reduce((e, t) => e + (g(t.kind)?.size?.(t) ?? 0), 0);
248
266
  },
249
267
  dump() {
250
- return { items: [...C.values()] };
268
+ return { items: [...O.values()] };
251
269
  },
252
270
  async clear() {
253
- if (r) try {
254
- await I();
271
+ if (s) try {
272
+ await U();
255
273
  } finally {
256
- k();
274
+ I();
257
275
  }
258
276
  },
259
277
  async import(e, { mode: t = "merge" } = {}) {
260
- let n = /* @__PURE__ */ new Map(), i = e.items.filter((e) => e.id !== a && !s(e.id));
261
- if (!i.length || !r) return n;
262
- let o = t === "replace", c = /* @__PURE__ */ new Map();
263
- for (let e of i) c.set(e.id, o ? e.id : h());
264
- let l = (e) => e == null || s(e) ? e : c.get(e) ?? null;
278
+ let n = /* @__PURE__ */ new Map(), r = e.items.filter((e) => e.id !== l && !f(e.id));
279
+ if (!r.length || !s) return n;
280
+ let i = t === "replace", a = /* @__PURE__ */ new Map();
281
+ for (let e of r) a.set(e.id, i ? e.id : b());
282
+ let o = (e) => e == null || f(e) ? e : a.get(e) ?? null;
265
283
  try {
266
- o && await I();
267
- for (let e of i) {
284
+ i && await U();
285
+ for (let e of r) {
268
286
  let t = {
269
287
  ...e,
270
- id: c.get(e.id),
271
- parent: l(e.parent)
272
- };
273
- await j(t), n.set(e.id, t);
288
+ id: a.get(e.id),
289
+ parent: o(e.parent)
290
+ }, r = m(e);
291
+ r != null && a.has(r) && (t.data = {
292
+ ...e.data,
293
+ original: a.get(r)
294
+ }), await R(t), n.set(e.id, t);
274
295
  }
275
296
  } finally {
276
- k();
297
+ I();
277
298
  }
278
299
  return n;
279
300
  },
280
301
  async dispose() {
281
- await P(), D.clear();
302
+ await V(), M.clear();
282
303
  }
283
304
  };
284
- return L;
305
+ return W;
285
306
  }
286
- function w(e = []) {
307
+ function I(e = []) {
287
308
  let t = new Map(e.map((e) => [e.id, e]));
288
309
  return {
289
310
  records: t,
@@ -293,4 +314,4 @@ function w(e = []) {
293
314
  };
294
315
  }
295
316
  //#endregion
296
- export { r as APP_KIND, t as DISK, n as FOLDER, e as TRASH, i as UNTITLED_FOLDER, c as appIdOf, d as childrenOf, u as containerOf, b as copyName, C as createCatalog, _ as descendantsOf, h as enclosingFolders, o as isContainerKind, m as isInside, g as isTrashed, s as isVolume, f as itemCount, l as itemOf, w as memoryStorage, v as nextFolderName };
317
+ export { s as ALIAS_KIND, r as APPLE_MENU_ITEMS, o as APP_KIND, t as DISK, a as FOLDER, i as STARTUP_ITEMS, n as SYSTEM_FOLDER, e as TRASH, c as UNTITLED_FOLDER, O as aliasName, p as appIdOf, j as appleMenuItemsOf, v as childrenOf, _ as containerOf, D as copyName, F as createCatalog, w as descendantsOf, S as enclosingFolders, u as isContainerKind, x as isInside, f as isKept, C as isTrashed, d as isVolume, y as itemCount, h as itemOf, I as memoryStorage, T as nextFolderName, m as originalOf, g as resolve, M as startupItemsOf };
@@ -19,16 +19,19 @@
19
19
  * around it. An application's icon stands for the application: it is drawn
20
20
  * open while the application has a window open, and the application's own
21
21
  * windows close into it.
22
- * - Menus: File (Open, New Folder, Close), Edit (Copy, Paste, Select All),
23
- * View (Arrange Windows), Special (Clean Up, Empty Trash…), each disabled
24
- * while it has nothing to act on. A site switches commands off and adds
25
- * its own.
22
+ * - An alias wears its original's art with its name in italics, and opens
23
+ * its original; with the original gone, an alert says so. Make Alias makes
24
+ * one beside each selected application or document.
25
+ * - Menus: File (Open, New Folder, Close, Make Alias), Edit (Copy, Paste,
26
+ * Select All), View (Arrange Windows), Special (Clean Up, Empty Trash…),
27
+ * each disabled while it has nothing to act on. A site switches commands
28
+ * off and adds its own.
26
29
  * - Alerts are the Finder's own, composed with the site's caution art and
27
30
  * held by it while they are up. A site answers any of them with its own
28
31
  * dialog through `alertWith`.
29
32
  */
30
33
  import type { VfIcon, VfMenuItem, VfViewportBox } from '../index.js';
31
- import type { Catalog, CatalogStorage, Item, Volumes } from './catalog.js';
34
+ import type { Catalog, CatalogStorage, Item, SystemFolders, Volumes } from './catalog.js';
32
35
  import type { LatticeOptions, Size } from './geometry.js';
33
36
  import type { AppContext, AppDefinition } from './shell.js';
34
37
  /** The Finder's application id. */
@@ -44,13 +47,17 @@ export interface FinderArt {
44
47
  document: string;
45
48
  /** The startup disk; the folder's art without it. */
46
49
  disk?: string;
50
+ /** The System Folder and its two folders; the folder's art without them. */
51
+ systemFolder?: string;
52
+ appleMenuItems?: string;
53
+ startupItems?: string;
47
54
  /** 12×12: the mark before the item count in the Trash's window and trashed folders. */
48
55
  trashMark?: string;
49
56
  /** 32×32: beside the message in the Finder's alerts. Without it they have no art. */
50
57
  caution?: string;
51
58
  }
52
59
  /** What a failed command was, in the `failed` alert. */
53
- export type FinderFailedAction = 'new-folder' | 'empty-trash' | 'paste' | 'add-file';
60
+ export type FinderFailedAction = 'new-folder' | 'empty-trash' | 'paste' | 'add-file' | 'make-alias';
54
61
  /** The Finder's alerts, by id, with the details each one's handler gets. */
55
62
  export interface FinderAlerts {
56
63
  /** Special → Empty Trash…: an answer of `'ok'` empties the Trash. */
@@ -70,7 +77,11 @@ export interface FinderAlerts {
70
77
  'move-failed': {
71
78
  error: Error;
72
79
  };
73
- /** New Folder, Empty Trash, Paste or a dropped file failed. */
80
+ /** Opening an alias whose original is gone. */
81
+ 'original-missing': {
82
+ alias: Item;
83
+ };
84
+ /** New Folder, Empty Trash, Paste, Make Alias or a dropped file failed. */
74
85
  failed: {
75
86
  action: FinderFailedAction;
76
87
  error: Error;
@@ -81,7 +92,7 @@ export type FinderAlert = keyof FinderAlerts;
81
92
  /** Answers one of the Finder's alerts: resolves the answer, or null. */
82
93
  export type FinderAlertHandler<K extends FinderAlert> = (details: FinderAlerts[K]) => string | null | Promise<string | null>;
83
94
  /** The Finder's own commands, each of which a site can switch off. */
84
- export type FinderCommand = 'open' | 'new-folder' | 'close' | 'copy' | 'paste' | 'select-all' | 'arrange' | 'clean-up' | 'empty-trash';
95
+ export type FinderCommand = 'open' | 'new-folder' | 'close' | 'make-alias' | 'copy' | 'paste' | 'select-all' | 'arrange' | 'clean-up' | 'empty-trash';
85
96
  /** The Finder's menus, by `data-menu`. */
86
97
  export type FinderMenu = 'file' | 'edit' | 'view' | 'special';
87
98
  /** A command a site adds to the Finder's menus. */
@@ -135,10 +146,17 @@ export interface FinderOptions {
135
146
  art: FinderArt;
136
147
  /** The volumes: the Trash by default, and a startup disk when named. */
137
148
  volumes?: Volumes;
149
+ /**
150
+ * The System Folder and its folders, named: what Apple Menu Items holds is
151
+ * the Apple menu, and what Startup Items holds opens at startup. Unset, none.
152
+ */
153
+ system?: SystemFolders;
138
154
  /**
139
155
  * What the catalog starts with, stored once per storage: `'markup'` reads
140
156
  * the `<vf-icon data-app>` and `<template data-folder="Name">` the page
141
- * put in the desktop's field; a function stores the site's defaults.
157
+ * put in the desktop's field, and a `<template data-system="apple-menu-items">`
158
+ * files what it holds in that folder of the System Folder; a function
159
+ * stores the site's defaults.
142
160
  */
143
161
  seed?: 'markup' | ((catalog: Catalog) => void | Promise<void>);
144
162
  /** The lattices' cells, pitches and insets (default: 64px cells, 80px columns, 72px rows, 16px insets). */