vintage-frames 0.14.1 → 0.16.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 (55) hide show
  1. package/custom-elements.json +770 -74
  2. package/dist/chrome.d.ts +10 -1
  3. package/dist/chrome.js +8 -3
  4. package/dist/components/vf-button.d.ts +5 -1
  5. package/dist/components/vf-button.js +1 -1
  6. package/dist/components/vf-desktop.d.ts +5 -2
  7. package/dist/components/vf-desktop.js +5 -5
  8. package/dist/components/vf-dialog.d.ts +13 -2
  9. package/dist/components/vf-dialog.js +27 -27
  10. package/dist/components/vf-menu-bar.js +9 -10
  11. package/dist/components/vf-menu-item.js +18 -13
  12. package/dist/components/vf-menu.d.ts +8 -3
  13. package/dist/components/vf-menu.js +85 -61
  14. package/dist/components/vf-number-field.d.ts +4 -0
  15. package/dist/components/vf-number-field.js +28 -25
  16. package/dist/components/vf-paragraph.d.ts +3 -1
  17. package/dist/components/vf-paragraph.js +7 -0
  18. package/dist/components/vf-scroll-area.d.ts +16 -1
  19. package/dist/components/vf-scroll-area.js +39 -29
  20. package/dist/components/vf-select.d.ts +5 -4
  21. package/dist/components/vf-select.js +26 -17
  22. package/dist/components/vf-text-field.d.ts +5 -5
  23. package/dist/components/vf-text-field.js +1 -1
  24. package/dist/components/vf-window.d.ts +22 -5
  25. package/dist/components/vf-window.js +113 -98
  26. package/dist/cursor.d.ts +8 -0
  27. package/dist/cursor.js +70 -73
  28. package/dist/events.d.ts +3 -2
  29. package/dist/events.js +3 -3
  30. package/dist/index.d.ts +2 -1
  31. package/dist/modal-dialog.d.ts +49 -4
  32. package/dist/modal-dialog.js +115 -87
  33. package/dist/position.js +25 -20
  34. package/dist/shell/alert.d.ts +17 -9
  35. package/dist/shell/alert.js +25 -28
  36. package/dist/shell/catalog.d.ts +1 -1
  37. package/dist/shell/catalog.js +32 -18
  38. package/dist/shell/finder.d.ts +46 -1
  39. package/dist/shell/finder.js +166 -126
  40. package/dist/shell/index.d.ts +2 -4
  41. package/dist/shell/index.js +5 -6
  42. package/dist/shell/pure.d.ts +10 -0
  43. package/dist/shell/pure.js +4 -0
  44. package/dist/shell/shell.d.ts +40 -13
  45. package/dist/shell/shell.js +87 -51
  46. package/dist/shell/windows.d.ts +69 -12
  47. package/dist/shell/windows.js +245 -144
  48. package/dist/text-control.d.ts +30 -1
  49. package/dist/text-control.js +27 -6
  50. package/dist/top-layer.d.ts +13 -0
  51. package/dist/top-layer.js +16 -0
  52. package/docs/SPEC.md +25 -24
  53. package/editor/vscode.html-custom-data.json +22 -12
  54. package/editor/web-types.json +58 -25
  55. package/package.json +5 -1
@@ -4,10 +4,17 @@ import { windowChrome as r } from "../window-chrome.js";
4
4
  import "../index.js";
5
5
  import { FOLDER as i, TRASH as a, childrenOf as o, enclosingFolders as s, isContainerKind as c, isInside as l, isTrashed as u, isVolume as d, itemCount as f } from "./catalog.js";
6
6
  import { cleanUp as ee, collisions as te, desktopLattice as ne, fieldExtent as re, fillOrder as ie, folderLattice as ae, frameOf as oe, nextFreeCell as se, pinOf as ce, pinTo as le, trashCell as ue } from "./geometry.js";
7
- import { appIdOf as de, defineApp as p } from "./shell.js";
8
- import { fileByDrag as fe } from "./filing.js";
7
+ import { desktopRendered as de } from "./windows.js";
8
+ import { appIdOf as fe, defineApp as p } from "./shell.js";
9
+ import { fileByDrag as pe } from "./filing.js";
10
+ import { composeAlert as me } from "./alert.js";
9
11
  //#region src/shell/finder.ts
10
- var m = "finder", pe = 306, me = 300, he = 20, ge = 18, h = {
12
+ var m = "finder", he = 306, ge = 300, _e = {
13
+ "new-folder": "New Folder",
14
+ "empty-trash": "Empty Trash",
15
+ paste: "Paste",
16
+ "add-file": "Adding the file"
17
+ }, ve = 20, ye = 18, h = {
11
18
  left: 8,
12
19
  top: 2
13
20
  }, g = {
@@ -16,7 +23,7 @@ var m = "finder", pe = 306, me = 300, he = 20, ge = 18, h = {
16
23
  }, _ = {
17
24
  left: h.left - 1,
18
25
  top: h.top
19
- }, _e = {
26
+ }, be = {
20
27
  left: _.left + g.width + 3,
21
28
  top: h.top
22
29
  }, v = [
@@ -79,17 +86,17 @@ function y(e) {
79
86
  return i.length ? `<vf-menu data-menu="${t}" label="${n}">${i.join("")}</vf-menu>` : "";
80
87
  }).join("");
81
88
  }
82
- var ve = (e) => e.localName === "vf-icon" && e.dataset.app != null || e instanceof HTMLTemplateElement && e.dataset.folder != null;
83
- function ye(e) {
89
+ var xe = (e) => e.localName === "vf-icon" && e.dataset.app != null || e instanceof HTMLTemplateElement && e.dataset.folder != null;
90
+ function Se(e) {
84
91
  let t = (e, t) => e != null && t != null && Number.isFinite(+e) && Number.isFinite(+t) ? {
85
92
  left: +e,
86
93
  top: +t
87
94
  } : void 0, n = [];
88
- for (let r of [...e.children].filter(ve)) r instanceof HTMLTemplateElement ? n.push({
95
+ for (let r of [...e.children].filter(xe)) r instanceof HTMLTemplateElement ? n.push({
89
96
  kind: i,
90
97
  name: r.dataset.folder ?? null,
91
98
  at: t(r.dataset.left, r.dataset.top),
92
- children: ye(r.content)
99
+ children: Se(r.content)
93
100
  }) : n.push({
94
101
  kind: "app",
95
102
  name: r.getAttribute("label"),
@@ -100,12 +107,12 @@ function ye(e) {
100
107
  return n;
101
108
  }
102
109
  function b(i) {
103
- let b = i.volumes?.trash !== !1, x = (e) => i.commands?.[e] !== !1 && (e !== "empty-trash" || b), be = [], xe = (e) => e, S = i.seed === "markup" ? async (e) => {
110
+ let b = i.volumes?.trash !== !1, x = (e) => i.commands?.[e] !== !1 && (e !== "empty-trash" || b), Ce = [], we = (e) => e, S = i.seed === "markup" ? async (e) => {
104
111
  let t = Date.now(), n = async (r, i) => {
105
112
  for (let a of r) {
106
113
  let r = await e.create({
107
114
  kind: a.kind,
108
- name: a.name ?? (a.app == null ? void 0 : xe(a.app)),
115
+ name: a.name ?? (a.app == null ? void 0 : we(a.app)),
109
116
  parent: i,
110
117
  ...a.at,
111
118
  ...a.app == null ? {} : { data: { app: a.app } },
@@ -114,12 +121,13 @@ function b(i) {
114
121
  r && a.children.length && await n(a.children, r.id);
115
122
  }
116
123
  };
117
- await n(be, null);
124
+ await n(Ce, null);
118
125
  } : i.seed;
119
126
  return p({
120
127
  id: m,
121
128
  name: "Finder",
122
129
  menus: y(x),
130
+ dialogs: i.dialogs,
123
131
  catalog: {
124
132
  storage: i.storage,
125
133
  volumes: i.volumes,
@@ -127,53 +135,76 @@ function b(i) {
127
135
  },
128
136
  init(p) {
129
137
  let { desktop: y, windows: S } = p, C = p.catalog, w = i.art;
130
- xe = (e) => p.app(e)?.name ?? e;
131
- let T = i.lattice?.desktop?.cell ?? 64, Se = i.lattice?.folder?.cell ?? 64, Ce = i.window ?? {
138
+ we = (e) => p.app(e)?.name ?? e;
139
+ let T = i.lattice?.desktop?.cell ?? 64, Te = i.lattice?.folder?.cell ?? 64, Ee = i.window ?? {
132
140
  width: 320,
133
141
  height: 223
134
142
  }, E = r({
135
143
  scrollbars: "both",
136
- headerHeight: he
137
- }), D = (e) => (t) => void p.alert(`${e} failed: ${t.message}.`), O = y.querySelector(":scope > vf-icon-field"), we = !O;
138
- if (!O) {
139
- O = document.createElement("vf-icon-field"), O.label = "Desktop", O.toggleAttribute("fill-width", !0), O.toggleAttribute("fill-height", !0);
144
+ headerHeight: ve
145
+ }), De = /* @__PURE__ */ new Map();
146
+ async function D(e, t, n, r = {}) {
147
+ let i = De.get(e);
148
+ if (i) return i(t);
149
+ let a = me(n, {
150
+ art: w.caution ?? null,
151
+ ...r
152
+ });
153
+ p.hold(a.dialog);
154
+ try {
155
+ await a.rendered();
156
+ let e = p.ask(a.dialog);
157
+ return a.fit(), await e;
158
+ } finally {
159
+ p.release(a.dialog);
160
+ }
161
+ }
162
+ let O = (e) => (t) => {
163
+ let n = t;
164
+ D("failed", {
165
+ action: e,
166
+ error: n
167
+ }, `${_e[e]} failed: ${n.message}.`);
168
+ }, k = y.querySelector(":scope > vf-icon-field"), Oe = !k;
169
+ if (!k) {
170
+ k = document.createElement("vf-icon-field"), k.label = "Desktop", k.toggleAttribute("fill-width", !0), k.toggleAttribute("fill-height", !0);
140
171
  let e = y.querySelector(":scope > vf-menu-bar");
141
- e ? e.after(O) : y.prepend(O);
172
+ e ? e.after(k) : y.prepend(k);
142
173
  }
143
- let k = O, Te = [...k.children].filter(ve);
144
- be = ye(k);
145
- for (let e of Te) e.remove();
146
- let A = () => S.windowsOf(m).map((e) => [S.itemOf(e), e]).filter((e) => e[0] != null), j = (e) => e.querySelector(":scope > vf-icon-field"), M = () => [[null, k], ...A().flatMap(([e, t]) => {
174
+ let A = k, ke = [...A.children].filter(xe);
175
+ Ce = Se(A);
176
+ for (let e of ke) e.remove();
177
+ let Ae = () => S.windowsOf(m).map((e) => [S.itemOf(e), e]).filter((e) => e[0] != null), j = (e) => e.querySelector(":scope > vf-icon-field"), M = () => [[null, A], ...Ae().flatMap(([e, t]) => {
147
178
  let n = j(t);
148
179
  return n ? [[e, n]] : [];
149
- })], Ee = (e) => M().find(([t]) => t === e)?.[1] ?? null, N = (e) => [...e.querySelectorAll(":scope > vf-icon[data-id]")], P = () => M().flatMap(([, e]) => N(e)), F = (e) => e.dataset.id, I = (e) => P().find((t) => F(t) === e) ?? null, L = (e) => ({
180
+ })], je = (e) => M().find(([t]) => t === e)?.[1] ?? null, N = (e) => [...e.querySelectorAll(":scope > vf-icon[data-id]")], P = () => M().flatMap(([, e]) => N(e)), F = (e) => e.dataset.id, I = (e) => P().find((t) => F(t) === e) ?? null, L = (e) => ({
150
181
  left: e.left ?? 0,
151
182
  top: e.top ?? 0
152
- }), De = (e) => S.itemOf(e.closest("vf-window")), Oe = (e) => ({
183
+ }), Me = (e) => S.itemOf(e.closest("vf-window")), Ne = (e) => ({
153
184
  width: Math.max(0, (e.width ?? 0) - E.left - E.right),
154
185
  height: Math.max(0, (e.height ?? 0) - E.top - E.bottom)
155
- }), ke = (e) => {
186
+ }), Pe = (e) => {
156
187
  if (e == null) return ne(y.workArea, i.lattice?.desktop);
157
188
  let t = S.windowFor(e);
158
- return ae(t ? Oe(t).width : 0, i.lattice?.folder);
159
- }, Ae = (e) => {
189
+ return ae(t ? Ne(t).width : 0, i.lattice?.folder);
190
+ }, Fe = (e) => {
160
191
  let t = S.windowFor(e), n = t && j(t);
161
192
  if (!t || !n) return;
162
- let r = re(N(n).map(L), Oe(t), { cell: Se });
193
+ let r = re(N(n).map(L), Ne(t), { cell: Te });
163
194
  n.width !== r.width && (n.width = r.width), n.height !== r.height && (n.height = r.height);
164
- }, je = (n, r, i) => {
195
+ }, Ie = (n, r, i) => {
165
196
  if (r == null) {
166
197
  let r = y.workArea, a = t(n), o = (e) => Math.floor(e / a) * a, s = Math.ceil(r.top / a) * a, c = Math.max(r.left, o(r.left + r.width - T)), l = Math.max(s, o(r.top + r.height - T));
167
198
  n.left = Math.min(Math.max(e(i.left, n), r.left), c), n.top = Math.min(Math.max(e(i.top, n), s), l);
168
199
  } else n.left = e(Math.max(0, i.left), n), n.top = e(Math.max(0, i.top), n);
169
- }, Me = (e) => {
200
+ }, Le = (e) => {
170
201
  if (e.kind === "folder") return w.folder;
171
202
  if (e.kind === "trash") return f(C.get(), "trash") ? w.trashFull : w.trash;
172
203
  if (e.kind === "disk") return w.disk ?? w.folder;
173
204
  let t = p.kind(e.kind);
174
205
  return (typeof t?.art == "function" ? t.art(e) : t?.art) || w.document;
175
206
  };
176
- function Ne(e, t) {
207
+ function Re(e, t) {
177
208
  let n = e.querySelector(":scope > vf-img > img");
178
209
  if (!n) {
179
210
  let t = document.createElement("vf-img");
@@ -181,52 +212,52 @@ function b(i) {
181
212
  }
182
213
  n.getAttribute("src") !== t && (n.src = t);
183
214
  }
184
- function Pe(e) {
215
+ function ze(e) {
185
216
  let t = document.createElement("vf-icon");
186
217
  return t.dataset.id = e.id, t.label = e.name, t.width = T, t.selectable = !0, t.movable = !0, c(e.kind) && (t.dataset.folder = e.id), t;
187
218
  }
188
219
  let R = /* @__PURE__ */ new Set(), z = /* @__PURE__ */ new WeakMap();
189
- function Fe(e, t, n, r) {
220
+ function Be(e, t, n, r) {
190
221
  if (t.left != null && t.top != null) {
191
222
  let r = `${t.left},${t.top}`;
192
223
  if (z.get(e) === r) return;
193
- z.set(e, r), (e.left !== t.left || e.top !== t.top) && je(e, n, {
224
+ z.set(e, r), (e.left !== t.left || e.top !== t.top) && Ie(e, n, {
194
225
  left: t.left,
195
226
  top: t.top
196
227
  });
197
228
  return;
198
229
  }
199
- let a = N(r).filter((t) => t !== e && t.left != null && t.top != null).map(L), o = n == null && t.id === "trash" ? ue(y.workArea, i.lattice?.desktop) : se(ke(n), a, n == null ? T : Se);
200
- je(e, n, o), R.add(e);
230
+ let a = N(r).filter((t) => t !== e && t.left != null && t.top != null).map(L), o = n == null && t.id === "trash" ? ue(y.workArea, i.lattice?.desktop) : se(Pe(n), a, n == null ? T : Te);
231
+ Ie(e, n, o), R.add(e);
201
232
  }
202
- let B = !1;
233
+ let Ve = !1, B = !1;
203
234
  function V() {
204
- if (!B) {
235
+ if (!(B || !Ve)) {
205
236
  B = !0;
206
237
  try {
207
238
  let e = C.get(), t = new Map(P().map((e) => [F(e), e])), n = /* @__PURE__ */ new Set(), r = [], i = [];
208
239
  for (let [a, s] of M()) for (let c of o(e, a)) {
209
- let e = t.get(c.id) ?? Pe(c);
210
- e.parentElement !== s && (s.append(e), e.left = void 0, e.top = void 0, z.delete(e)), n.add(e), e.label !== c.name && (e.label = c.name), e.editable = !d(c.id) && p.kind(c.kind)?.editable !== !1, Ne(e, Me(c));
211
- let o = c.kind === "app" ? S.hasWindows(de(c) ?? "") : S.isOpen(c.id);
240
+ let e = t.get(c.id) ?? ze(c);
241
+ e.parentElement !== s && (s.append(e), e.left = void 0, e.top = void 0, z.delete(e)), n.add(e), e.label !== c.name && (e.label = c.name), e.editable = !d(c.id) && p.kind(c.kind)?.editable !== !1, Re(e, Le(c));
242
+ let o = c.kind === "app" ? S.hasWindows(fe(c) ?? "") : S.isOpen(c.id);
212
243
  e.open !== o && (e.open = o);
213
- let l = () => Fe(e, c, a, s);
244
+ let l = () => Be(e, c, a, s);
214
245
  c.left != null && c.top != null ? r.push(l) : i.push(l);
215
246
  }
216
247
  for (let e of t.values()) n.has(e) || e.remove();
217
248
  for (let e of [...r, ...i]) e();
218
- for (let [e, t] of A()) {
249
+ for (let [e, t] of Ae()) {
219
250
  let n = j(t), r = C.item(e)?.name;
220
- n && r != null && n.label !== r && (n.label = r), Re(e), Ae(e);
251
+ n && r != null && n.label !== r && (n.label = r), We(e), Fe(e);
221
252
  }
222
253
  } finally {
223
254
  B = !1;
224
255
  }
225
- Ie();
256
+ He();
226
257
  }
227
258
  }
228
259
  let H = !1;
229
- function Ie() {
260
+ function He() {
230
261
  if (H = !1, !R.size) return;
231
262
  let e = /* @__PURE__ */ new Map();
232
263
  for (let t of R) t.isConnected && t.left != null && t.top != null && e.set(F(t), L(t));
@@ -234,29 +265,29 @@ function b(i) {
234
265
  }
235
266
  p.on(y, "vf-placement-change", (e) => {
236
267
  let t = e.target;
237
- t.localName === "vf-icon" && t.dataset.id != null && (R.add(t), !H && (H = !0, queueMicrotask(Ie)));
268
+ t.localName === "vf-icon" && t.dataset.id != null && (R.add(t), !H && (H = !0, queueMicrotask(He)));
238
269
  }), p.onDispose(C.subscribe(V)), p.onDispose(S.onWindows(V));
239
- function Le() {
270
+ function Ue() {
240
271
  let e = document.createElement("vf-img");
241
272
  e.dataset.trashMark = "", e.width = g.width, e.height = g.height, e.left = _.left, e.top = _.top;
242
273
  let t = document.createElement("img");
243
274
  return t.alt = "in the Trash", t.src = w.trashMark, e.append(t), e;
244
275
  }
245
- function Re(e) {
276
+ function We(e) {
246
277
  let t = S.windowFor(e)?.querySelector(":scope > [slot=\"header\"]"), n = t?.querySelector(":scope > vf-label[data-count]");
247
278
  if (!t || !n) return;
248
279
  let r = C.get(), i = f(r, e), a = `${i} item${i === 1 ? "" : "s"}`;
249
280
  n.textContent !== a && (n.textContent = a);
250
281
  let o = !!w.trashMark && u(r, e), s = t.querySelector(":scope > vf-img[data-trash-mark]");
251
- o && !s ? t.prepend(Le()) : !o && s && s.remove();
252
- let c = o ? _e : h;
282
+ o && !s ? t.prepend(Ue()) : !o && s && s.remove();
283
+ let c = o ? be : h;
253
284
  n.left !== c.left && (n.left = c.left);
254
285
  }
255
- function ze(e) {
286
+ function Ge(e) {
256
287
  let t = C.item(e)?.name ?? "", n = document.createElement("vf-window");
257
- n.heading = t, n.movable = !0, n.outlineDrag = !0, n.resizable = !0, n.scrollbars = "both", n.headerHeight = he, n.width = Ce.width, n.height = Ce.height;
288
+ n.heading = t, n.closable = !0, n.movable = !0, n.outlineDrag = !0, n.resizable = !0, n.scrollbars = "both", n.headerHeight = ve, n.width = Ee.width, n.height = Ee.height;
258
289
  let r = document.createElement("vf-container");
259
- r.slot = "header", r.toggleAttribute("fill-width", !0), r.height = ge, r.rule = "bottom";
290
+ r.slot = "header", r.toggleAttribute("fill-width", !0), r.height = ye, r.rule = "bottom";
260
291
  let i = document.createElement("vf-label");
261
292
  i.face = "body", i.dataset.count = "", i.left = h.left, i.top = h.top, r.append(i);
262
293
  let a = document.createElement("vf-icon-field");
@@ -265,7 +296,7 @@ function b(i) {
265
296
  p.on(y, "vf-resize", (e) => {
266
297
  if (!e.detail?.commit || S.appOf(e.target) !== "finder") return;
267
298
  let t = S.itemOf(e.target);
268
- t != null && Ae(t);
299
+ t != null && Fe(t);
269
300
  });
270
301
  function U(e, t) {
271
302
  let n = C.item(e);
@@ -273,19 +304,19 @@ function b(i) {
273
304
  app: m,
274
305
  item: e,
275
306
  from: t,
276
- create: () => ze(e)
307
+ create: () => Ge(e)
277
308
  }) : p.kind(n.kind)?.open(n, t));
278
309
  }
279
310
  p.on(y, "vf-open", (e) => {
280
311
  let t = e.target;
281
- t.localName === "vf-icon" && t.dataset.id != null && (t.selected && q().length > 1 ? Ue() : U(F(t), t.cellRect()));
312
+ t.localName === "vf-icon" && t.dataset.id != null && (t.selected && q().length > 1 ? Ye() : U(F(t), t.cellRect()));
282
313
  });
283
- let Be = (e) => {
284
- let t = C.get().items.filter((t) => t.kind === "app" && de(t) === e);
314
+ let Ke = (e) => {
315
+ let t = C.get().items.filter((t) => t.kind === "app" && fe(t) === e);
285
316
  return t.find((e) => I(e.id)) ?? t[0] ?? null;
286
- }, Ve = (e, t) => C.item(e) ?? (t == null ? null : Be(t));
317
+ }, qe = (e, t) => C.item(e) ?? (t == null ? null : Ke(t));
287
318
  p.onDispose(S.setHome((e, t) => {
288
- let n = Ve(e, t);
319
+ let n = qe(e, t);
289
320
  if (!n) return null;
290
321
  let r = I(n.id)?.cellRect();
291
322
  if (r) return r;
@@ -295,9 +326,9 @@ function b(i) {
295
326
  }
296
327
  return null;
297
328
  }, (e, t) => {
298
- let n = e == null && t == null ? null : Ve(e, t), r = N(k), i = n ? I(n.id) : r.find((e) => e.selected) ?? r[0] ?? null;
329
+ let n = e == null && t == null ? null : qe(e, t), r = N(A), i = n ? I(n.id) : r.find((e) => e.selected) ?? r[0] ?? null;
299
330
  return i?.checkVisibility() ? (i.focus({ preventScroll: !0 }), !0) : !1;
300
- })), p.on(k, "pointerdown", () => y.clearActive());
331
+ })), p.on(A, "pointerdown", () => y.clearActive());
301
332
  let W = (e) => {
302
333
  let t = e.target;
303
334
  return t.localName === "vf-icon" && t.dataset.id != null;
@@ -314,15 +345,15 @@ function b(i) {
314
345
  if (!W(e) || G) return;
315
346
  G = !0;
316
347
  let { limit: t } = e.detail;
317
- p.alert(`That name is too long. A name can have up to ${t} characters.`).finally(() => {
348
+ D("name-too-long", { limit: t }, `That name is too long. A name can have up to ${t} characters.`).finally(() => {
318
349
  G = !1;
319
350
  });
320
351
  }), p.on(y, "vf-name-rejected", (e) => {
321
- W(e) && p.alert("An item needs a name.");
322
- }), p.onDispose(fe(y, {
352
+ W(e) && D("name-rejected", {}, "An item needs a name.");
353
+ }), p.onDispose(pe(y, {
323
354
  folderOfWindow: (e) => S.appOf(e) === "finder" ? S.itemOf(e) ?? void 0 : void 0,
324
355
  folderOfIcon: (e) => e.dataset.folder,
325
- containerOf: (e) => e.dataset.id == null ? void 0 : De(e),
356
+ containerOf: (e) => e.dataset.id == null ? void 0 : Me(e),
326
357
  canFile: (e, t) => {
327
358
  let n = C.get();
328
359
  return e.every((e) => {
@@ -333,34 +364,34 @@ function b(i) {
333
364
  file: (e, t, n) => {
334
365
  let r = new Map([...n].map(([e, t]) => [F(e), t]));
335
366
  C.move(e.map(F), t, r).catch((e) => {
336
- p.alert(`The items couldn’t be moved: ${e.message}.`);
367
+ D("move-failed", { error: e }, `The items couldn’t be moved: ${e.message}.`);
337
368
  });
338
369
  }
339
370
  }));
340
- let He = /* @__PURE__ */ new WeakMap(), K = 0;
371
+ let Je = /* @__PURE__ */ new WeakMap(), K = 0;
341
372
  p.onDispose(S.onRaster((t, n) => {
342
- k.dragIcons([]);
373
+ A.dragIcons([]);
343
374
  let r = {
344
375
  width: T,
345
376
  height: T
346
377
  }, a = oe(y.workArea.top);
347
- for (let i of N(k)) {
378
+ for (let i of N(A)) {
348
379
  let o = {
349
380
  ...L(i),
350
381
  ...r
351
- }, s = He.get(i), c = !s || s.left !== o.left || s.top !== o.top ? ce(o, t, a) : s.pin, l = le(c, n, a, { size: r });
352
- i.left = e(l.left, i), i.top = e(l.top, i), He.set(i, {
382
+ }, s = Je.get(i), c = !s || s.left !== o.left || s.top !== o.top ? ce(o, t, a) : s.pin, l = le(c, n, a, { size: r });
383
+ i.left = e(l.left, i), i.top = e(l.top, i), Je.set(i, {
353
384
  pin: c,
354
385
  left: i.left,
355
386
  top: i.top
356
387
  });
357
388
  }
358
389
  i.cleanUpAfterResize && (window.clearTimeout(K), K = window.setTimeout(() => {
359
- K = 0, te(N(k).map((e) => ({
390
+ K = 0, te(N(A).map((e) => ({
360
391
  ...L(e),
361
392
  ...r
362
393
  }))).size && X(null);
363
- }, me));
394
+ }, ge));
364
395
  })), p.onDispose(() => window.clearTimeout(K));
365
396
  let q = () => {
366
397
  let e = new Set(P().filter((e) => e.selected).map(F));
@@ -373,33 +404,36 @@ function b(i) {
373
404
  return e && S.appOf(e) === "finder" ? S.itemOf(e) : null;
374
405
  };
375
406
  async function X(e) {
376
- let t = Ee(e);
407
+ let t = je(e);
377
408
  if (!t) return;
378
- let n = ke(e), r = N(t), i = ee(n, r.map(L)), a = r.map((e, t) => ({
409
+ let n = Pe(e), r = N(t), i = ee(n, r.map(L)), a = r.map((e, t) => ({
379
410
  icon: e,
380
411
  ...i[t]
381
412
  })).sort((e, t) => ie(n, e, t));
382
413
  await t.dragIcons(a);
383
414
  }
384
- async function Ue() {
385
- let e = n() ? 0 : pe;
415
+ async function Ye() {
416
+ let e = n() ? 0 : he;
386
417
  for (let [t, n] of q().entries()) t && e && await new Promise((t) => setTimeout(t, e)), U(n.id, I(n.id)?.cellRect() ?? null);
387
418
  }
388
- async function We(e) {
419
+ async function Xe(e) {
389
420
  let t = I(e);
390
421
  t && (J([e]), await t.updateComplete, t.startEditing());
391
422
  }
392
- let Z = () => C.get().available ? !0 : (p.alert("Files can’t be saved in this browser session. A private window, perhaps.", { label: "Storage Unavailable" }), !1);
393
- async function Ge() {
423
+ let Z = () => C.get().available ? !0 : (D("storage-unavailable", {}, "Files can’t be saved in this browser session. A private window, perhaps.", { label: "Storage Unavailable" }), !1);
424
+ async function Ze() {
394
425
  if (!Z()) return;
395
- let e = await C.create({ parent: Y() }).catch(D("New Folder"));
396
- e && await We(e.id);
426
+ let e = await C.create({ parent: Y() }).catch(O("new-folder"));
427
+ e && await Xe(e.id);
397
428
  }
398
- async function Ke() {
429
+ async function Qe() {
399
430
  let e = f(C.get(), a);
400
431
  if (!b || !e) return;
401
- let t = Math.ceil(C.trashSize() / 1024), n = e === 1 ? `The Trash contains 1 item, which uses ${t}K of disk space. Are you sure you want to permanently remove it?` : `The Trash contains ${e} items, which use ${t}K of disk space. Are you sure you want to permanently remove these items?`;
402
- await p.alert(n, {
432
+ let t = C.trashSize(), n = Math.ceil(t / 1024), r = e === 1 ? `The Trash contains 1 item, which uses ${n}K of disk space. Are you sure you want to permanently remove it?` : `The Trash contains ${e} items, which use ${n}K of disk space. Are you sure you want to permanently remove these items?`;
433
+ await D("empty-trash", {
434
+ count: e,
435
+ bytes: t
436
+ }, r, {
403
437
  label: "Empty Trash",
404
438
  buttons: [{
405
439
  label: "Cancel",
@@ -409,13 +443,13 @@ function b(i) {
409
443
  value: "ok",
410
444
  default: !0
411
445
  }]
412
- }) === "ok" && await C.emptyTrash().catch(D("Empty Trash"));
446
+ }) === "ok" && await C.emptyTrash().catch(O("empty-trash"));
413
447
  }
414
448
  let Q = {
415
449
  ids: [],
416
450
  text: ""
417
- }, qe = (e) => e.replace(/\r\n?/g, "\n").trimEnd();
418
- async function Je() {
451
+ }, $e = (e) => e.replace(/\r\n?/g, "\n").trimEnd();
452
+ async function et() {
419
453
  let e = q().filter((e) => !d(e.id));
420
454
  if (!e.length) return;
421
455
  let t = e.map((e) => e.name).join("\n");
@@ -438,12 +472,12 @@ function b(i) {
438
472
  await navigator.clipboard?.writeText(t);
439
473
  } catch {}
440
474
  }
441
- async function Ye(e, t) {
475
+ async function tt(e, t) {
442
476
  for (let n of p.kinds.values()) if (n.claim && await n.claim(e, t)) return !0;
443
477
  return !1;
444
478
  }
445
- let Xe = () => [...p.kinds.values()].some((e) => e.claim);
446
- async function Ze() {
479
+ let nt = () => [...p.kinds.values()].some((e) => e.claim);
480
+ async function rt() {
447
481
  try {
448
482
  if (navigator.clipboard?.read) {
449
483
  let e = null, t = [];
@@ -463,59 +497,57 @@ function b(i) {
463
497
  } catch {}
464
498
  return null;
465
499
  }
466
- async function Qe(e) {
500
+ async function it(e) {
467
501
  if (!Z()) return;
468
502
  let t = Y();
469
503
  if (u(C.get(), t)) return;
470
- let n = e === void 0 ? await Ze() : e, r = Q.ids.length > 0 && (n == null || n.text != null && qe(n.text) === qe(Q.text));
504
+ let n = e === void 0 ? await rt() : e, r = Q.ids.length > 0 && (n == null || n.text != null && $e(n.text) === $e(Q.text));
471
505
  try {
472
506
  if (r) {
473
507
  let e = await C.copy(Q.ids, t);
474
508
  e.length && J(e.map((e) => e.id));
475
- } else for (let e of n?.files ?? []) await Ye(e, t);
509
+ } else for (let e of n?.files ?? []) await tt(e, t);
476
510
  } catch (e) {
477
- D("Paste")(e);
511
+ O("paste")(e);
478
512
  }
479
513
  }
480
514
  p.on(document, "paste", (e) => {
481
515
  if (!x("paste") || S.front !== "finder" || p.modalOpen() || p.typing()) return;
482
516
  let t = e.clipboardData;
483
- t && (e.preventDefault(), Qe({
517
+ t && (e.preventDefault(), it({
484
518
  text: t.getData("text/plain") || null,
485
519
  files: [...t.files]
486
520
  }));
487
521
  });
488
- let $e = (e) => [...e.dataTransfer?.types ?? []].includes("Files");
522
+ let at = (e) => [...e.dataTransfer?.types ?? []].includes("Files");
489
523
  p.on(y, "dragover", (e) => {
490
- $e(e) && Xe() && e.preventDefault();
524
+ at(e) && nt() && e.preventDefault();
491
525
  }), p.on(y, "drop", (e) => {
492
- if (!$e(e) || !Xe()) return;
526
+ if (!at(e) || !nt()) return;
493
527
  e.preventDefault();
494
- let t = e, n = [...t.dataTransfer?.files ?? []];
495
- if (!Z()) return;
496
- let r = document.elementsFromPoint(t.clientX, t.clientY).find((e) => e.localName === "vf-window");
497
- if (r && S.appOf(r) !== "finder") return;
528
+ let t = e, n = [...t.dataTransfer?.files ?? []], r = document.elementsFromPoint(t.clientX, t.clientY).find((e) => e.localName === "vf-window");
529
+ if (r && S.appOf(r) !== "finder" || (r ? y.bringToFront(r) : y.clearActive(), !Z())) return;
498
530
  let i = r ? S.itemOf(r) : null;
499
531
  u(C.get(), i) || (async () => {
500
- for (let e of n) await Ye(e, i);
501
- })().catch(D("Adding the file"));
532
+ for (let e of n) await tt(e, i);
533
+ })().catch(O("add-file"));
502
534
  });
503
- let et = {
504
- open: () => void Ue(),
505
- "new-folder": () => void Ge(),
535
+ let ot = {
536
+ open: () => void Ye(),
537
+ "new-folder": () => void Ze(),
506
538
  close: () => {
507
539
  let e = Y(), t = e == null ? null : S.windowFor(e);
508
540
  t && S.requestClose(t);
509
541
  },
510
- copy: () => void Je(),
511
- paste: () => void Qe(),
542
+ copy: () => void et(),
543
+ paste: () => void it(),
512
544
  "select-all": () => {
513
- let e = Ee(Y());
545
+ let e = je(Y());
514
546
  e && J(N(e).map(F));
515
547
  },
516
548
  arrange: () => S.arrange(),
517
549
  "clean-up": () => void X(Y()),
518
- "empty-trash": () => void Ke()
550
+ "empty-trash": () => void Qe()
519
551
  }, $ = (e, t) => {
520
552
  x(e) && p.gate(p.item(e), t);
521
553
  };
@@ -526,15 +558,15 @@ function b(i) {
526
558
  return e.textContent !== t && (e.textContent = t), !0;
527
559
  });
528
560
  }
529
- let tt = !0, nt = (e) => {
561
+ let st = !0, ct = (e) => {
530
562
  let t = p.menus.find((t) => t.dataset.menu === e);
531
563
  if (t) return t;
532
- if (!tt) throw Error(`vintage-frames/shell (finder): no ${e} menu; add to it from extend`);
564
+ if (!st) throw Error(`vintage-frames/shell (finder): no ${e} menu; add to it from extend`);
533
565
  let n = document.createElement("vf-menu");
534
566
  n.dataset.menu = e, n.label = v.find((t) => t.menu === e).label;
535
567
  let r = v.map((e) => e.menu), i = p.menus.findIndex((t) => r.indexOf(t.dataset.menu) > r.indexOf(e));
536
568
  return p.menus.splice(i < 0 ? p.menus.length : i, 0, n), n;
537
- }, rt = {
569
+ }, lt = {
538
570
  catalog: C,
539
571
  selection: q,
540
572
  select: J,
@@ -542,21 +574,29 @@ function b(i) {
542
574
  open: ({ item: e, from: t = null } = {}) => {
543
575
  e != null && U(e, t);
544
576
  },
545
- rename: We,
577
+ rename: Xe,
546
578
  cleanUp: X,
547
579
  iconFor: I,
548
580
  addCommand(e) {
549
- let t = nt(e.menu);
581
+ let t = ct(e.menu);
550
582
  e.separator && t.append(document.createElement("vf-separator"));
551
583
  let n = document.createElement("vf-menu-item");
552
- return n.setAttribute("value", e.value), e.shortcut && n.setAttribute("shortcut", e.shortcut), n.textContent = e.label, t.append(n), et[e.value] = e.run, e.enabled && p.gate(n, e.enabled), n;
553
- }
584
+ return n.setAttribute("value", e.value), e.shortcut && n.setAttribute("shortcut", e.shortcut), n.textContent = e.label, t.append(n), ot[e.value] = e.run, e.enabled && p.gate(n, e.enabled), n;
585
+ },
586
+ alertWith(e, t) {
587
+ De.set(e, t);
588
+ },
589
+ storageReady: Z
554
590
  };
555
- return i.extend?.(rt, p), tt = !1, p.onMenu((e) => et[e]?.()), p.onDispose(() => {
556
- for (let [, e] of A()) e.remove();
557
- for (let e of N(k)) e.remove();
558
- we ? k.remove() : k.append(...Te);
559
- }), V(), rt;
591
+ i.extend?.(lt, p), st = !1, p.onMenu((e) => ot[e]?.());
592
+ let ut = !1;
593
+ return p.onDispose(() => {
594
+ ut = !0;
595
+ for (let e of N(A)) e.remove();
596
+ Oe ? A.remove() : A.append(...ke);
597
+ }), de(y).then(() => {
598
+ ut || (Ve = !0, V());
599
+ }), lt;
560
600
  }
561
601
  });
562
602
  }
@@ -12,9 +12,9 @@
12
12
  export { createShell, defineApp, appIdOf, APP_KIND } from './shell.js';
13
13
  export type { AppContext, AppDefinition, CatalogSetup, KindDefinition, Shell, ShellOptions } from './shell.js';
14
14
  export { createWindowManager, focusInto } from './windows.js';
15
- export type { AdoptOptions, ArrangeGroup, BoxInput, FocusHome, HomeBox, OpenOptions, PlacePolicy, Placed, WindowManager, WindowManagerOptions, } from './windows.js';
15
+ export type { AdoptOptions, ArrangeGroup, BoxInput, CloseHandler, FocusHome, HomeBox, OpenOptions, PlacePolicy, Placed, WindowManager, WindowManagerOptions, } from './windows.js';
16
16
  export { finder, FINDER } from './finder.js';
17
- export type { FinderApi, FinderArt, FinderCommand, FinderCommandSpec, FinderMenu, FinderOpen, FinderOptions, } from './finder.js';
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
20
  export { createCatalog, memoryStorage, childrenOf, containerOf, copyName, descendantsOf, enclosingFolders, isContainerKind, isInside, isTrashed, isVolume, itemCount, itemOf, nextFolderName, DISK, FOLDER, TRASH, UNTITLED_FOLDER, } from './catalog.js';
@@ -25,5 +25,3 @@ export type { LocalStorageStateOptions, SavedSession, SavedWindow, SessionSnapsh
25
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';
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 { showAlert } from './alert.js';
29
- export type { AlertButton, AlertOptions } from './alert.js';
@@ -3,9 +3,8 @@ import { BAND as v, CASCADE_SLOTS as y, CASCADE_STEP as b, ICON_CELL as x, ICON_
3
3
  import { createWindowManager as q, focusInto as J } from "./windows.js";
4
4
  import { localStorageState as Y, mergeSession as X, openWindowsOf as Z, readSession as Q } from "./state.js";
5
5
  import { DATE_HOLD_MS as $, formatDate as ee, formatTime as te, startClock as ne } from "./clock.js";
6
- import { showAlert as re } from "./alert.js";
7
- import { APP_KIND as ie, appIdOf as ae, createShell as oe, defineApp as se } from "./shell.js";
8
- import { fileByDrag as ce } from "./filing.js";
9
- import { FINDER as le, finder as ue } from "./finder.js";
10
- import { indexedDbStorage as de } from "./storage.js";
11
- export { ie as APP_KIND, v as BAND, y as CASCADE_SLOTS, b as CASCADE_STEP, $ as DATE_HOLD_MS, e as DISK, le as FINDER, t as FOLDER, x as ICON_CELL, S as ICON_COLUMN, C as ICON_INSET, w as ICON_ROW, T as NEAR, n as TRASH, r as UNTITLED_FOLDER, E as WINDOW_ORIGIN, ae as appIdOf, D as cascadeFrom, O as cascadeSlot, k as cascadedBox, A as centeredBox, i as childrenOf, j as cleanUp, M as collisions, a as containerOf, o as copyName, s as createCatalog, oe as createShell, q as createWindowManager, se as defineApp, c as descendantsOf, N as desktopLattice, l as enclosingFolders, P as fieldExtent, ce as fileByDrag, F as fillOrder, ue as finder, J as focusInto, I as folderLattice, ee as formatDate, te as formatTime, L as frameOf, de as indexedDbStorage, u as isContainerKind, d as isInside, R as isPin, f as isTrashed, p as isVolume, m as itemCount, h as itemOf, z as latticeCell, B as latticeSlot, Y as localStorageState, g as memoryStorage, X as mergeSession, V as nearBox, _ as nextFolderName, H as nextFreeCell, Z as openWindowsOf, U as pinOf, W as pinTo, Q as readSession, re as showAlert, ne as startClock, G as trashCell, K as windowOrigin };
6
+ import { APP_KIND as re, appIdOf as ie, createShell as ae, defineApp as oe } from "./shell.js";
7
+ import { fileByDrag as se } from "./filing.js";
8
+ import { FINDER as ce, finder as le } from "./finder.js";
9
+ import { indexedDbStorage as ue } from "./storage.js";
10
+ export { re as APP_KIND, v as BAND, y as CASCADE_SLOTS, b as CASCADE_STEP, $ as DATE_HOLD_MS, e as DISK, ce as FINDER, t as FOLDER, x as ICON_CELL, S as ICON_COLUMN, C as ICON_INSET, w as ICON_ROW, T as NEAR, n as TRASH, r as UNTITLED_FOLDER, E as WINDOW_ORIGIN, ie as appIdOf, D as cascadeFrom, O as cascadeSlot, k as cascadedBox, A as centeredBox, i as childrenOf, j as cleanUp, M as collisions, a as containerOf, o as copyName, s as createCatalog, ae as createShell, q as createWindowManager, oe as defineApp, c as descendantsOf, N as desktopLattice, l as enclosingFolders, P as fieldExtent, se as fileByDrag, F as fillOrder, le as finder, J as focusInto, I as folderLattice, ee as formatDate, te as formatTime, L as frameOf, ue as indexedDbStorage, u as isContainerKind, d as isInside, R as isPin, f as isTrashed, p as isVolume, m as itemCount, h as itemOf, z as latticeCell, B as latticeSlot, Y as localStorageState, g as memoryStorage, X as mergeSession, V as nearBox, _ as nextFolderName, H as nextFreeCell, Z as openWindowsOf, U as pinOf, W as pinTo, Q as readSession, ne as startClock, G as trashCell, K as windowOrigin };